]>
git.saurik.com Git - cycript.git/blob - sig/parse.cpp
f1e63ff7e75f1671835789e9f1aeb7e9c9827a58
   1 /* Cycript - Optimizing JavaScript Compiler/Runtime 
   2  * Copyright (C) 2009-2014  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
);