]>
git.saurik.com Git - cycript.git/blob - sig/parse.cpp
1 /* Cycript - Optimizing JavaScript Compiler/Runtime
2 * Copyright (C) 2009-2015 Jay Freeman (saurik)
5 /* GNU Affero General Public License, Version 3 {{{ */
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "sig/parse.hpp"
32 void Parse_(CYPool
&pool
, struct Signature
*signature
, const char **name
, char eos
, Callback callback
);
33 struct Type
*Parse_(CYPool
&pool
, const char **name
, char eos
, bool named
, Callback callback
);
36 /* XXX: I really screwed up this time */
37 void *prealloc_(CYPool
&pool
, void *odata
, size_t osize
, size_t nsize
) {
38 void *ndata(pool
.malloc
<void>(nsize
));
39 memcpy(ndata
, odata
, osize
);
43 void Parse_(CYPool
&pool
, struct Signature
*signature
, const char **name
, char eos
, Callback callback
) {
44 _assert(*name
!= NULL
);
46 // XXX: this is just a stupid check :(
47 bool named(**name
== '"');
49 signature
->elements
= NULL
;
58 signature
->elements
= (struct Element
*) prealloc_(pool
, signature
->elements
, signature
->count
* sizeof(struct Element
), (signature
->count
+ 1) * sizeof(struct Element
));
59 _assert(signature
->elements
!= NULL
);
61 struct Element
*element
= &signature
->elements
[signature
->count
++];
66 const char *quote
= strchr(++*name
, '"');
67 element
->name
= pool
.strmemdup(*name
, quote
- *name
);
71 element
->type
= Parse_(pool
, name
, eos
, named
, callback
);
73 if (**name
< '0' || **name
> '9')
74 element
->offset
= _not(size_t);
79 element
->offset
= element
->offset
* 10 + (*(*name
)++ - '0');
80 while (**name
>= '0' && **name
<= '9');
85 Type
*Parse_(CYPool
&pool
, const char **name
, char eos
, bool named
, Callback callback
) {
86 char next
= *(*name
)++;
88 Type
*type(new(pool
) Type());
89 _assert(type
!= NULL
);
90 memset(type
, 0, sizeof(Type
));
94 case '?': type
->primitive
= unknown_P
; break;
95 case '#': type
->primitive
= typename_P
; break;
98 if (type
->data
.signature
.count
< 2)
99 type
->primitive
= struct_P
;
101 type
->primitive
= union_P
;
105 case '*': type
->primitive
= string_P
; break;
106 case ':': type
->primitive
= selector_P
; break;
112 type
->primitive
= block_P
;
115 type
->primitive
= object_P
;
118 const char *quote
= strchr(*name
+ 1, '"');
120 printf("unterminated specific id type {%s}\n", *name
- 10);
122 } else if (!named
|| quote
[1] == eos
|| quote
[1] == '"') {
123 type
->name
= pool
.strmemdup(*name
+ 1, quote
- *name
- 1);
131 case 'B': type
->primitive
= boolean_P
; break;
132 case 'C': type
->primitive
= uchar_P
; break;
133 case 'I': type
->primitive
= uint_P
; break;
134 case 'L': type
->primitive
= ulong_P
; break;
135 case 'Q': type
->primitive
= ulonglong_P
; break;
136 case 'S': type
->primitive
= ushort_P
; break;
139 type
->primitive
= array_P
;
140 type
->data
.data
.size
= strtoul(*name
, (char **) name
, 10);
141 type
->data
.data
.type
= Parse_(pool
, name
, eos
, false, callback
);
143 printf("']' != \"%s\"\n", *name
);
150 type
->primitive
= pointer_P
;
152 // XXX: why is this here?
153 type
->data
.data
.type
= NULL
;
155 type
->data
.data
.type
= Parse_(pool
, name
, eos
, named
, callback
);
159 type
->primitive
= bit_P
;
160 type
->data
.data
.size
= strtoul(*name
, (char **) name
, 10);
163 case 'c': type
->primitive
= char_P
; break;
164 case 'd': type
->primitive
= double_P
; break;
165 case 'f': type
->primitive
= float_P
; break;
166 case 'i': type
->primitive
= int_P
; break;
167 case 'l': type
->primitive
= long_P
; break;
168 case 'q': type
->primitive
= longlong_P
; break;
169 case 's': type
->primitive
= short_P
; break;
170 case 'v': type
->primitive
= void_P
; break;
173 case 'F': type
->primitive
= double_P
; break;
175 case 'F': type
->primitive
= float_P
; break;
179 type
->primitive
= struct_P
;
185 const char *begin
= *name
;
186 do next
= *(*name
)++;
191 size_t length
= *name
- begin
- 1;
192 if (strncmp(begin
, "?", length
) != 0)
193 type
->name
= (char *) pool
.strmemdup(begin
, length
);
197 // XXX: this types thing is a throwback to JocStrap
200 Parse_(pool
, &type
->data
.signature
, name
, end
, callback
);
203 case 'N': type
->flags
|= JOC_TYPE_INOUT
; goto next
;
204 case 'n': type
->flags
|= JOC_TYPE_IN
; goto next
;
205 case 'O': type
->flags
|= JOC_TYPE_BYCOPY
; goto next
;
206 case 'o': type
->flags
|= JOC_TYPE_OUT
; goto next
;
207 case 'R': type
->flags
|= JOC_TYPE_BYREF
; goto next
;
208 case 'r': type
->flags
|= JOC_TYPE_CONST
; goto next
;
209 case 'V': type
->flags
|= JOC_TYPE_ONEWAY
; goto next
;
217 printf("invalid type character: '%c' {%s}\n", next
, *name
- 10);
221 if (callback
!= NULL
)
222 (*callback
)(pool
, type
);
227 void Parse(CYPool
&pool
, struct Signature
*signature
, const char *name
, Callback callback
) {
228 const char *temp
= name
;
229 Parse_(pool
, signature
, &temp
, '\0', callback
);
230 _assert(temp
[-1] == '\0');
233 const char *Unparse(CYPool
&pool
, struct Signature
*signature
) {
234 const char *value
= "";
237 for (offset
= 0; offset
!= signature
->count
; ++offset
) {
238 const char *type
= Unparse(pool
, signature
->elements
[offset
].type
);
239 value
= pool
.strcat(value
, type
, NULL
);
245 const char *Unparse_(CYPool
&pool
, struct Type
*type
) {
246 switch (type
->primitive
) {
248 if (type
->data
.signature
.count
== 0)
250 std::ostringstream out
;
251 for (size_t i(0); i
!= type
->data
.signature
.count
; ++i
) {
252 Element
&element(type
->data
.signature
.elements
[i
]);
253 out
<< Unparse(pool
, element
.type
);
254 if (element
.offset
!= _not(size_t))
255 out
<< pool
.itoa(element
.offset
);
257 return pool
.strdup(out
.str().c_str());
260 case unknown_P
: return "?";
261 case typename_P
: return "#";
262 case union_P
: return pool
.strcat("(", Unparse(pool
, &type
->data
.signature
), ")", NULL
);
263 case string_P
: return "*";
264 case selector_P
: return ":";
265 case block_P
: return "@?";
266 case object_P
: return type
->name
== NULL
? "@" : pool
.strcat("@\"", type
->name
, "\"", NULL
);
267 case boolean_P
: return "B";
268 case uchar_P
: return "C";
269 case uint_P
: return "I";
270 case ulong_P
: return "L";
271 case ulonglong_P
: return "Q";
272 case ushort_P
: return "S";
275 const char *value
= Unparse(pool
, type
->data
.data
.type
);
276 return pool
.strcat("[", pool
.itoa(type
->data
.data
.size
), value
, "]", NULL
);
280 // XXX: protect against the weird '"' check in Parse_
281 _assert(type
->data
.data
.type
!= NULL
);
282 if (type
->data
.data
.type
->primitive
== function_P
)
285 return pool
.strcat("^", Unparse(pool
, type
->data
.data
.type
), NULL
);
288 case bit_P
: return pool
.strcat("b", pool
.itoa(type
->data
.data
.size
), NULL
);
289 case char_P
: return "c";
290 case double_P
: return "d";
291 case float_P
: return "f";
292 case int_P
: return "i";
293 case long_P
: return "l";
294 case longlong_P
: return "q";
295 case short_P
: return "s";
296 case void_P
: return "v";
297 case struct_P
: return pool
.strcat("{", type
->name
== NULL
? "?" : type
->name
, "=", Unparse(pool
, &type
->data
.signature
), "}", NULL
);
304 const char *Unparse(CYPool
&pool
, struct Type
*type
) {
308 const char *base(Unparse_(pool
, type
));
309 if (type
->flags
== 0)
312 #define iovec_(base, size) \
313 (struct iovec) {const_cast<char *>(base), size}
315 size_t size(strlen(base
));
316 char buffer
[7 + size
];
319 if ((type
->flags
& JOC_TYPE_INOUT
) != 0)
320 buffer
[offset
++] = 'N';
321 if ((type
->flags
& JOC_TYPE_IN
) != 0)
322 buffer
[offset
++] = 'n';
323 if ((type
->flags
& JOC_TYPE_BYCOPY
) != 0)
324 buffer
[offset
++] = 'O';
325 if ((type
->flags
& JOC_TYPE_OUT
) != 0)
326 buffer
[offset
++] = 'o';
327 if ((type
->flags
& JOC_TYPE_BYREF
) != 0)
328 buffer
[offset
++] = 'R';
329 if ((type
->flags
& JOC_TYPE_CONST
) != 0)
330 buffer
[offset
++] = 'r';
331 if ((type
->flags
& JOC_TYPE_ONEWAY
) != 0)
332 buffer
[offset
++] = 'V';
334 memcpy(buffer
+ offset
, base
, size
);
335 return pool
.strmemdup(buffer
, offset
+ size
);