]>
git.saurik.com Git - cycript.git/blob - sig/parse.cpp
1 /* Cycript - Remove Execution Server and Disassembler
2 * Copyright (C) 2009 Jay Freeman (saurik)
5 /* Modified BSD License {{{ */
7 * Redistribution and use in source and binary
8 * forms, with or without modification, are permitted
9 * provided that the following conditions are met:
11 * 1. Redistributions of source code must retain the
12 * above copyright notice, this list of conditions
13 * and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the
15 * above copyright notice, this list of conditions
16 * and the following disclaimer in the documentation
17 * and/or other materials provided with the
19 * 3. The name of the author may not be used to endorse
20 * or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS''
24 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
25 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
34 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
36 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44 #include "minimal/stdlib.h"
46 #include <apr-1/apr_strings.h>
50 #include "sig/parse.hpp"
54 void Parse_(apr_pool_t
*pool
, struct Signature
*signature
, const char **name
, char eos
, Callback callback
);
55 struct Type
*Parse_(apr_pool_t
*pool
, const char **name
, char eos
, bool named
, Callback callback
);
58 /* XXX: I really screwed up this time */
59 void *prealloc_(apr_pool_t
*pool
, void *odata
, size_t osize
, size_t nsize
) {
60 void *ndata
= apr_palloc(pool
, nsize
);
61 memcpy(ndata
, odata
, osize
);
65 void Parse_(apr_pool_t
*pool
, struct Signature
*signature
, const char **name
, char eos
, Callback callback
) {
66 _assert(*name
!= NULL
);
68 // XXX: this is just a stupid check :(
69 bool named(**name
== '"');
71 signature
->elements
= NULL
;
80 signature
->elements
= (struct Element
*) prealloc_(pool
, signature
->elements
, signature
->count
* sizeof(struct Element
), (signature
->count
+ 1) * sizeof(struct Element
));
81 _assert(signature
->elements
!= NULL
);
83 struct Element
*element
= &signature
->elements
[signature
->count
++];
88 char *quote
= strchr(++*name
, '"');
89 element
->name
= apr_pstrmemdup(pool
, *name
, quote
- *name
);
93 element
->type
= Parse_(pool
, name
, eos
, named
, callback
);
95 if (**name
< '0' || **name
> '9')
96 element
->offset
= _not(size_t);
101 element
->offset
= element
->offset
* 10 + (*(*name
)++ - '0');
102 while (**name
>= '0' && **name
<= '9');
107 struct Type
*Parse_(apr_pool_t
*pool
, const char **name
, char eos
, bool named
, Callback callback
) {
108 char next
= *(*name
)++;
112 struct Type
*type
= (struct Type
*) apr_palloc(pool
, sizeof(struct Type
));
113 _assert(type
!= NULL
);
114 memset(type
, 0, sizeof(struct Type
));
118 case '#': type
->primitive
= typename_P
; break;
121 if (type
->data
.signature
.count
< 2)
122 type
->primitive
= struct_P
;
124 type
->primitive
= union_P
;
128 case '*': type
->primitive
= string_P
; break;
129 case ':': type
->primitive
= selector_P
; break;
133 char *quote
= strchr(*name
+ 1, '"');
134 if (!named
|| quote
[1] == eos
|| quote
[1] == '"') {
135 type
->name
= apr_pstrmemdup(pool
, *name
+ 1, quote
- *name
- 1);
140 type
->primitive
= object_P
;
143 case 'B': type
->primitive
= boolean_P
; break;
144 case 'C': type
->primitive
= uchar_P
; break;
145 case 'I': type
->primitive
= uint_P
; break;
146 case 'L': type
->primitive
= ulong_P
; break;
147 case 'Q': type
->primitive
= ulonglong_P
; break;
148 case 'S': type
->primitive
= ushort_P
; break;
151 type
->primitive
= array_P
;
152 type
->data
.data
.size
= strtoul(*name
, (char **) name
, 10);
153 type
->data
.data
.type
= Parse_(pool
, name
, eos
, false, callback
);
155 printf("']' != \"%s\"\n", *name
);
162 type
->primitive
= pointer_P
;
164 type
->data
.data
.type
= NULL
;
166 type
->data
.data
.type
= Parse_(pool
, name
, eos
, named
, callback
);
167 sig::Type
*&target(type
->data
.data
.type
);
168 if (target
!= NULL
&& target
->primitive
== void_P
)
174 type
->primitive
= bit_P
;
175 type
->data
.data
.size
= strtoul(*name
, (char **) name
, 10);
178 case 'c': type
->primitive
= char_P
; break;
179 case 'd': type
->primitive
= double_P
; break;
180 case 'f': type
->primitive
= float_P
; break;
181 case 'i': type
->primitive
= int_P
; break;
182 case 'l': type
->primitive
= long_P
; break;
183 case 'q': type
->primitive
= longlong_P
; break;
184 case 's': type
->primitive
= short_P
; break;
185 case 'v': type
->primitive
= void_P
; break;
188 type
->primitive
= struct_P
;
194 const char *begin
= *name
;
195 do next
= *(*name
)++;
200 size_t length
= *name
- begin
- 1;
201 if (strncmp(begin
, "?", length
) != 0)
202 type
->name
= (char *) apr_pstrmemdup(pool
, begin
, length
);
206 // XXX: this types thing is a throwback to JocStrap
212 const char *temp(*name
);
213 Parse_(pool
, &type
->data
.signature
, name
, end
, callback
);
214 types
= (char *) apr_pstrmemdup(pool
, temp
, *name
- temp
- 1);
217 if (callback
!= NULL
)
218 (*callback
)(pool
, type
->name
, types
, type
);
221 case 'N': type
->flags
|= JOC_TYPE_INOUT
; goto next
;
222 case 'n': type
->flags
|= JOC_TYPE_IN
; goto next
;
223 case 'O': type
->flags
|= JOC_TYPE_BYCOPY
; goto next
;
224 case 'o': type
->flags
|= JOC_TYPE_OUT
; goto next
;
225 case 'R': type
->flags
|= JOC_TYPE_BYREF
; goto next
;
226 case 'r': type
->flags
|= JOC_TYPE_CONST
; goto next
;
227 case 'V': type
->flags
|= JOC_TYPE_ONEWAY
; goto next
;
235 printf("invalid type character: '%c' {%s}\n", next
, *name
- 10);
242 void Parse(apr_pool_t
*pool
, struct Signature
*signature
, const char *name
, Callback callback
) {
243 const char *temp
= name
;
244 Parse_(pool
, signature
, &temp
, '\0', callback
);
245 _assert(temp
[-1] == '\0');
248 const char *Unparse(apr_pool_t
*pool
, struct Signature
*signature
) {
249 const char *value
= "";
252 for (offset
= 0; offset
!= signature
->count
; ++offset
) {
253 const char *type
= Unparse(pool
, signature
->elements
[offset
].type
);
254 value
= apr_pstrcat(pool
, value
, type
, NULL
);
260 const char *Unparse(apr_pool_t
*pool
, struct Type
*type
) {
263 else switch (type
->primitive
) {
264 case typename_P
: return "#";
265 case union_P
: return apr_psprintf(pool
, "(%s)", Unparse(pool
, &type
->data
.signature
));
266 case string_P
: return "*";
267 case selector_P
: return ":";
268 case object_P
: return type
->name
== NULL
? "@" : apr_psprintf(pool
, "@\"%s\"", type
->name
);
269 case boolean_P
: return "B";
270 case uchar_P
: return "C";
271 case uint_P
: return "I";
272 case ulong_P
: return "L";
273 case ulonglong_P
: return "Q";
274 case ushort_P
: return "S";
277 const char *value
= Unparse(pool
, type
->data
.data
.type
);
278 return apr_psprintf(pool
, "[%lu%s]", type
->data
.data
.size
, value
);
281 case pointer_P
: return apr_psprintf(pool
, "^%s", type
->data
.data
.type
== NULL
? "" : Unparse(pool
, type
->data
.data
.type
));
282 case bit_P
: return apr_psprintf(pool
, "b%zu", type
->data
.data
.size
);
283 case char_P
: return "c";
284 case double_P
: return "d";
285 case float_P
: return "f";
286 case int_P
: return "i";
287 case long_P
: return "l";
288 case longlong_P
: return "q";
289 case short_P
: return "s";
290 case void_P
: return "v";
291 case struct_P
: return apr_psprintf(pool
, "{%s=%s}", type
->name
== NULL
? "?" : type
->name
, Unparse(pool
, &type
->data
.signature
));