X-Git-Url: https://git.saurik.com/cycript.git/blobdiff_plain/ea2d184cbcdf25cfa51727f175356fe2ee211136..dc81e1c20b268c419fa88f8dd17fb92191a7ce1b:/sig/parse.cpp?ds=sidebyside diff --git a/sig/parse.cpp b/sig/parse.cpp index cf628a8..2f007de 100644 --- a/sig/parse.cpp +++ b/sig/parse.cpp @@ -1,3 +1,42 @@ +/* Cycript - Remove Execution Server and Disassembler + * Copyright (C) 2009 Jay Freeman (saurik) +*/ + +/* Modified BSD License {{{ */ +/* + * Redistribution and use in source and binary + * forms, with or without modification, are permitted + * provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the + * above copyright notice, this list of conditions + * and the following disclaimer. + * 2. Redistributions in binary form must reproduce the + * above copyright notice, this list of conditions + * and the following disclaimer in the documentation + * and/or other materials provided with the + * distribution. + * 3. The name of the author may not be used to endorse + * or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/* }}} */ + #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif @@ -12,7 +51,9 @@ namespace sig { -void (*sig_aggregate)(apr_pool_t *pool, enum Primitive primitive, const char *name, struct Signature *signature, const char *types) = NULL; +void Parse_(apr_pool_t *pool, struct Signature *signature, const char **name, char eos, Callback callback); +struct Type *Parse_(apr_pool_t *pool, const char **name, char eos, bool named, Callback callback); + /* XXX: I really screwed up this time */ void *prealloc_(apr_pool_t *pool, void *odata, size_t osize, size_t nsize) { @@ -21,10 +62,11 @@ void *prealloc_(apr_pool_t *pool, void *odata, size_t osize, size_t nsize) { return ndata; } -void sig_parse_signature(apr_pool_t *pool, struct Signature *signature, const char **name, char eos) { +void Parse_(apr_pool_t *pool, struct Signature *signature, const char **name, char eos, Callback callback) { _assert(*name != NULL); - bool named = **name == '"'; + // XXX: this is just a stupid check :( + bool named(**name == '"'); signature->elements = NULL; signature->count = 0; @@ -48,7 +90,7 @@ void sig_parse_signature(apr_pool_t *pool, struct Signature *signature, const ch *name = quote + 1; } - element->type = sig_parse_type(pool, name, eos, named); + element->type = Parse_(pool, name, eos, named, callback); if (**name < '0' || **name > '9') element->offset = _not(size_t); @@ -62,7 +104,7 @@ void sig_parse_signature(apr_pool_t *pool, struct Signature *signature, const ch } } -struct Type *sig_parse_type(apr_pool_t *pool, const char **name, char eos, bool named) { +struct Type *Parse_(apr_pool_t *pool, const char **name, char eos, bool named, Callback callback) { char next = *(*name)++; if (next == '?') return NULL; @@ -76,7 +118,10 @@ struct Type *sig_parse_type(apr_pool_t *pool, const char **name, char eos, bool case '#': type->primitive = typename_P; break; case '(': - type->primitive = union_P; + if (type->data.signature.count < 2) + type->primitive = struct_P; + else + type->primitive = union_P; next = ')'; goto aggregate; @@ -105,7 +150,7 @@ struct Type *sig_parse_type(apr_pool_t *pool, const char **name, char eos, bool case '[': type->primitive = array_P; type->data.data.size = strtoul(*name, (char **) name, 10); - type->data.data.type = sig_parse_type(pool, name, eos, false); + type->data.data.type = Parse_(pool, name, eos, false, callback); if (**name != ']') { printf("']' != \"%s\"\n", *name); _assert(false); @@ -115,13 +160,13 @@ struct Type *sig_parse_type(apr_pool_t *pool, const char **name, char eos, bool case '^': type->primitive = pointer_P; - if (**name == 'v') { - type->data.data.type = NULL; - ++*name; - } else if (**name == '"') { + if (**name == '"') { type->data.data.type = NULL; } else { - type->data.data.type = sig_parse_type(pool, name, eos, named); + type->data.data.type = Parse_(pool, name, eos, named, callback); + sig::Type *&target(type->data.data.type); + if (target != NULL && target->primitive == void_P) + target = NULL; } break; @@ -158,24 +203,19 @@ struct Type *sig_parse_type(apr_pool_t *pool, const char **name, char eos, bool else type->name = NULL; + // XXX: this types thing is a throwback to JocStrap + char *types; - if (next != '=') + if (next != '=') { types = NULL; - else { - const char *temp = *name; - sig_parse_signature(pool, &type->data.signature, name, end); + } else { + const char *temp(*name); + Parse_(pool, &type->data.signature, name, end, callback); types = (char *) apr_pstrmemdup(pool, temp, *name - temp - 1); } - if (type->name != NULL && sig_aggregate != NULL) { - char *angle = strchr(type->name, '<'); - if (angle == NULL) - (*sig_aggregate)(pool, type->primitive, type->name, &type->data.signature, types); - else { - angle = (char *) apr_pstrmemdup(pool, type->name, angle - type->name); - (*sig_aggregate)(pool, type->primitive, angle, &type->data.signature, types); - } - } + if (callback != NULL) + (*callback)(pool, type->name, types, type); } break; case 'N': type->flags |= JOC_TYPE_INOUT; goto next; @@ -199,30 +239,30 @@ struct Type *sig_parse_type(apr_pool_t *pool, const char **name, char eos, bool return type; } -void Parse(apr_pool_t *pool, struct Signature *signature, const char *name) { +void Parse(apr_pool_t *pool, struct Signature *signature, const char *name, Callback callback) { const char *temp = name; - sig_parse_signature(pool, signature, &temp, '\0'); + Parse_(pool, signature, &temp, '\0', callback); _assert(temp[-1] == '\0'); } -const char *sig_unparse_signature(apr_pool_t *pool, struct Signature *signature) { +const char *Unparse(apr_pool_t *pool, struct Signature *signature) { const char *value = ""; size_t offset; for (offset = 0; offset != signature->count; ++offset) { - const char *type = sig_unparse_type(pool, signature->elements[offset].type); + const char *type = Unparse(pool, signature->elements[offset].type); value = apr_pstrcat(pool, value, type, NULL); } return value; } -const char *sig_unparse_type(apr_pool_t *pool, struct Type *type) { +const char *Unparse(apr_pool_t *pool, struct Type *type) { if (type == NULL) return "?"; else switch (type->primitive) { case typename_P: return "#"; - case union_P: return apr_psprintf(pool, "(%s)", sig_unparse_signature(pool, &type->data.signature)); + case union_P: return apr_psprintf(pool, "(%s)", Unparse(pool, &type->data.signature)); case string_P: return "*"; case selector_P: return ":"; case object_P: return type->name == NULL ? "@" : apr_psprintf(pool, "@\"%s\"", type->name); @@ -234,11 +274,11 @@ const char *sig_unparse_type(apr_pool_t *pool, struct Type *type) { case ushort_P: return "S"; case array_P: { - const char *value = sig_unparse_type(pool, type->data.data.type); + const char *value = Unparse(pool, type->data.data.type); return apr_psprintf(pool, "[%lu%s]", type->data.data.size, value); } break; - case pointer_P: return apr_psprintf(pool, "^%s", type->data.data.type == NULL ? "" : sig_unparse_type(pool, type->data.data.type)); + case pointer_P: return apr_psprintf(pool, "^%s", type->data.data.type == NULL ? "" : Unparse(pool, type->data.data.type)); case bit_P: return apr_psprintf(pool, "b%zu", type->data.data.size); case char_P: return "c"; case double_P: return "d"; @@ -248,7 +288,7 @@ const char *sig_unparse_type(apr_pool_t *pool, struct Type *type) { case longlong_P: return "q"; case short_P: return "s"; case void_P: return "v"; - case struct_P: return apr_psprintf(pool, "{%s=%s}", type->name == NULL ? "?" : type->name, sig_unparse_signature(pool, &type->data.signature)); + case struct_P: return apr_psprintf(pool, "{%s=%s}", type->name == NULL ? "?" : type->name, Unparse(pool, &type->data.signature)); } _assert(false);