]>
git.saurik.com Git - cycript.git/blob - sig/parse.cpp
9eac602be37620ec19185e049c9221b7d748e9e9
   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. 
  40 #include <apr_strings.h> 
  41 #include "sig/parse.hpp" 
  50 void Parse_(apr_pool_t 
*pool
, struct Signature 
*signature
, const char **name
, char eos
, Callback callback
); 
  51 struct Type 
*Parse_(apr_pool_t 
*pool
, const char **name
, char eos
, bool named
, Callback callback
); 
  54 /* XXX: I really screwed up this time */ 
  55 void *prealloc_(apr_pool_t 
*pool
, void *odata
, size_t osize
, size_t nsize
) { 
  56     void *ndata 
= apr_palloc(pool
, nsize
); 
  57     memcpy(ndata
, odata
, osize
); 
  61 void Parse_(apr_pool_t 
*pool
, struct Signature 
*signature
, const char **name
, char eos
, Callback callback
) { 
  62     _assert(*name 
!= NULL
); 
  64     // XXX: this is just a stupid check :( 
  65     bool named(**name 
== '"'); 
  67     signature
->elements 
= NULL
; 
  76         signature
->elements 
= (struct Element 
*) prealloc_(pool
, signature
->elements
, signature
->count 
* sizeof(struct Element
), (signature
->count 
+ 1) * sizeof(struct Element
)); 
  77         _assert(signature
->elements 
!= NULL
); 
  79         struct Element 
*element 
= &signature
->elements
[signature
->count
++]; 
  84             char *quote 
= strchr(++*name
, '"'); 
  85             element
->name 
= apr_pstrmemdup(pool
, *name
, quote 
- *name
); 
  89         element
->type 
= Parse_(pool
, name
, eos
, named
, callback
); 
  91         if (**name 
< '0' || **name 
> '9') 
  92             element
->offset 
= _not(size_t); 
  97                 element
->offset 
= element
->offset 
* 10 + (*(*name
)++ - '0'); 
  98             while (**name 
>= '0' && **name 
<= '9'); 
 103 struct Type 
*Parse_(apr_pool_t 
*pool
, const char **name
, char eos
, bool named
, Callback callback
) { 
 104     char next 
= *(*name
)++; 
 108     struct Type 
*type 
= (struct Type 
*) apr_palloc(pool
, sizeof(struct Type
)); 
 109     _assert(type 
!= NULL
); 
 110     memset(type
, 0, sizeof(struct Type
)); 
 114         case '#': type
->primitive 
= typename_P
; break; 
 117             if (type
->data
.signature
.count 
< 2) 
 118                 type
->primitive 
= struct_P
; 
 120                 type
->primitive 
= union_P
; 
 124         case '*': type
->primitive 
= string_P
; break; 
 125         case ':': type
->primitive 
= selector_P
; break; 
 129                 char *quote 
= strchr(*name 
+ 1, '"'); 
 130                 if (!named 
|| quote
[1] == eos 
|| quote
[1] == '"') { 
 131                     type
->name 
= apr_pstrmemdup(pool
, *name 
+ 1, quote 
- *name 
- 1); 
 136             type
->primitive 
= object_P
; 
 139         case 'B': type
->primitive 
= boolean_P
; break; 
 140         case 'C': type
->primitive 
= uchar_P
; break; 
 141         case 'I': type
->primitive 
= uint_P
; break; 
 142         case 'L': type
->primitive 
= ulong_P
; break; 
 143         case 'Q': type
->primitive 
= ulonglong_P
; break; 
 144         case 'S': type
->primitive 
= ushort_P
; break; 
 147             type
->primitive 
= array_P
; 
 148             type
->data
.data
.size 
= strtoul(*name
, (char **) name
, 10); 
 149             type
->data
.data
.type 
= Parse_(pool
, name
, eos
, false, callback
); 
 151                 printf("']' != \"%s\"\n", *name
); 
 158             type
->primitive 
= pointer_P
; 
 160                 type
->data
.data
.type 
= NULL
; 
 162                 type
->data
.data
.type 
= Parse_(pool
, name
, eos
, named
, callback
); 
 163                 sig::Type 
*&target(type
->data
.data
.type
); 
 164                 if (target 
!= NULL 
&& target
->primitive 
== void_P
) 
 170             type
->primitive 
= bit_P
; 
 171             type
->data
.data
.size 
= strtoul(*name
, (char **) name
, 10); 
 174         case 'c': type
->primitive 
= char_P
; break; 
 175         case 'd': type
->primitive 
= double_P
; break; 
 176         case 'f': type
->primitive 
= float_P
; break; 
 177         case 'i': type
->primitive 
= int_P
; break; 
 178         case 'l': type
->primitive 
= long_P
; break; 
 179         case 'q': type
->primitive 
= longlong_P
; break; 
 180         case 's': type
->primitive 
= short_P
; break; 
 181         case 'v': type
->primitive 
= void_P
; break; 
 184             type
->primitive 
= struct_P
; 
 190             const char *begin 
= *name
; 
 191             do next 
= *(*name
)++; 
 196             size_t length 
= *name 
- begin 
- 1; 
 197             if (strncmp(begin
, "?", length
) != 0) 
 198                 type
->name 
= (char *) apr_pstrmemdup(pool
, begin
, length
); 
 202             // XXX: this types thing is a throwback to JocStrap 
 205                 Parse_(pool
, &type
->data
.signature
, name
, end
, callback
); 
 208         case 'N': type
->flags 
|= JOC_TYPE_INOUT
; goto next
; 
 209         case 'n': type
->flags 
|= JOC_TYPE_IN
; goto next
; 
 210         case 'O': type
->flags 
|= JOC_TYPE_BYCOPY
; goto next
; 
 211         case 'o': type
->flags 
|= JOC_TYPE_OUT
; goto next
; 
 212         case 'R': type
->flags 
|= JOC_TYPE_BYREF
; goto next
; 
 213         case 'r': type
->flags 
|= JOC_TYPE_CONST
; goto next
; 
 214         case 'V': type
->flags 
|= JOC_TYPE_ONEWAY
; goto next
; 
 222             printf("invalid type character: '%c' {%s}\n", next
, *name 
- 10); 
 226     if (callback 
!= NULL
) 
 227         (*callback
)(pool
, type
); 
 232 void Parse(apr_pool_t 
*pool
, struct Signature 
*signature
, const char *name
, Callback callback
) { 
 233     const char *temp 
= name
; 
 234     Parse_(pool
, signature
, &temp
, '\0', callback
); 
 235     _assert(temp
[-1] == '\0'); 
 238 const char *Unparse(apr_pool_t 
*pool
, struct Signature 
*signature
) { 
 239     const char *value 
= ""; 
 242     for (offset 
= 0; offset 
!= signature
->count
; ++offset
) { 
 243         const char *type 
= Unparse(pool
, signature
->elements
[offset
].type
); 
 244         value 
= apr_pstrcat(pool
, value
, type
, NULL
); 
 250 const char *Unparse(apr_pool_t 
*pool
, struct Type 
*type
) { 
 253     else switch (type
->primitive
) { 
 254         case typename_P
: return "#"; 
 255         case union_P
: return apr_psprintf(pool
, "(%s)", Unparse(pool
, &type
->data
.signature
)); 
 256         case string_P
: return "*"; 
 257         case selector_P
: return ":"; 
 258         case object_P
: return type
->name 
== NULL 
? "@" : apr_psprintf(pool
, "@\"%s\"", type
->name
); 
 259         case boolean_P
: return "B"; 
 260         case uchar_P
: return "C"; 
 261         case uint_P
: return "I"; 
 262         case ulong_P
: return "L"; 
 263         case ulonglong_P
: return "Q"; 
 264         case ushort_P
: return "S"; 
 267             const char *value 
= Unparse(pool
, type
->data
.data
.type
); 
 268             return apr_psprintf(pool
, "[%zu%s]", type
->data
.data
.size
, value
); 
 271         case pointer_P
: return apr_psprintf(pool
, "^%s", type
->data
.data
.type 
== NULL 
? "v" : Unparse(pool
, type
->data
.data
.type
)); 
 272         case bit_P
: return apr_psprintf(pool
, "b%zu", type
->data
.data
.size
); 
 273         case char_P
: return "c"; 
 274         case double_P
: return "d"; 
 275         case float_P
: return "f"; 
 276         case int_P
: return "i"; 
 277         case long_P
: return "l"; 
 278         case longlong_P
: return "q"; 
 279         case short_P
: return "s"; 
 280         case void_P
: return "v"; 
 281         case struct_P
: return apr_psprintf(pool
, "{%s=%s}", type
->name 
== NULL 
? "?" : type
->name
, Unparse(pool
, &type
->data
.signature
));