X-Git-Url: https://git.saurik.com/cycript.git/blobdiff_plain/51a72a9d652bf1b478bffc842feb68dee5d8744e..a14eb7025a69e6ed6fab72d4bb4eb8ed24cfff1f:/Library.cpp diff --git a/Library.cpp b/Library.cpp index cbeeb2a..2289e37 100644 --- a/Library.cpp +++ b/Library.cpp @@ -145,7 +145,7 @@ _finline size_t iconv_(size_t (*iconv)(iconv_t, Type_, size_t *, char **, size_t return iconv(cd, const_cast(inbuf), inbytesleft, outbuf, outbytesleft); } -static CYUTF8String CYPoolUTF8String(apr_pool_t *pool, JSContextRef context, JSStringRef value) { +CYUTF8String CYPoolUTF8String(apr_pool_t *pool, JSContextRef context, JSStringRef value) { _assert(pool != NULL); CYUTF16String utf16(CYCastUTF16String(value)); @@ -186,19 +186,25 @@ const char *CYPoolCString(apr_pool_t *pool, JSContextRef context, JSValueRef val /* Index Offsets {{{ */ size_t CYGetIndex(const CYUTF8String &value) { if (value.data[0] != '0') { - char *end; - size_t index(strtoul(value.data, &end, 10)); - if (value.data + value.size == end) - return index; - } else if (value.data[1] == '\0') + size_t index(0); + for (size_t i(0); i != value.size; ++i) { + if (!DigitRange_[value.data[i]]) + return _not(size_t); + index *= 10; + index += value.data[i] - '0'; + } + return index; + } else if (value.size == 1) return 0; - return _not(size_t); + else + return _not(size_t); } size_t CYGetIndex(apr_pool_t *pool, JSContextRef context, JSStringRef value) { return CYGetIndex(CYPoolUTF8String(pool, context, value)); } +// XXX: this isn't actually right bool CYGetOffset(const char *value, ssize_t &index) { if (value[0] != '0') { char *end; @@ -334,8 +340,19 @@ struct CStringMapLess : } }; -void Structor_(apr_pool_t *pool, const char *name, const char *types, sig::Type *&type) { - if (name == NULL) +void Structor_(apr_pool_t *pool, sig::Type *&type) { + if ( + type->primitive == sig::pointer_P && + type->data.data.type != NULL && + type->data.data.type->primitive == sig::struct_P && + strcmp(type->data.data.type->name, "_objc_class") == 0 + ) { + type->primitive = sig::typename_P; + type->data.data.type = NULL; + return; + } + + if (type->primitive != sig::struct_P || type->name == NULL) return; sqlite3_stmt *statement; @@ -351,7 +368,7 @@ void Structor_(apr_pool_t *pool, const char *name, const char *types, sig::Type " limit 1" , -1, &statement, NULL)); - _sqlcall(sqlite3_bind_text(statement, 1, name, -1, SQLITE_STATIC)); + _sqlcall(sqlite3_bind_text(statement, 1, type->name, -1, SQLITE_STATIC)); int mode; const char *value; @@ -522,7 +539,7 @@ static size_t Nonce_(0); static JSValueRef $cyq(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYPool pool; - const char *name(apr_psprintf(pool, "%s%zu", CYPoolCString(pool, context, arguments[0]), Nonce_++)); + const char *name(apr_psprintf(pool, "%s%"APR_SIZE_T_FMT"", CYPoolCString(pool, context, arguments[0]), Nonce_++)); return CYCastJSValue(context, name); } @@ -799,8 +816,7 @@ JSValueRef CYFromFFI(JSContextRef context, sig::Type *type, ffi_type *ffi, void if (JSValueRef value = (*hooks_->FromFFI)(context, type, ffi, data, initialize, owner)) return value; - fprintf(stderr, "CYFromFFI(%c)\n", type->primitive); - _assert(false); + CYThrow("failed conversion from FFI format: '%c'\n", type->primitive); } } @@ -1021,7 +1037,7 @@ static void Struct_getPropertyNames(JSContextRef context, JSObjectRef object, JS name = elements[index].name; if (name == NULL) { - sprintf(number, "%lu", index); + sprintf(number, "%zu", index); name = number; } @@ -1118,17 +1134,21 @@ static JSValueRef Runtime_getProperty(JSContextRef context, JSObjectRef object, case 0: return JSEvaluateScript(CYGetJSContext(), CYJSString(value), NULL, NULL, 0, NULL); - case 1: - return CYMakeFunctor(context, reinterpret_cast(CYCastSymbol(name.data)), value); - case 2: { - // XXX: this is horrendously inefficient - sig::Signature signature; - sig::Parse(pool, &signature, value, &Structor_); - ffi_cif cif; - sig::sig_ffi_cif(pool, &sig::ObjectiveC, &signature, &cif); - return CYFromFFI(context, signature.elements[0].type, cif.rtype, CYCastSymbol(name.data)); - } + case 1: + if (void (*symbol)() = reinterpret_cast(CYCastSymbol(name.data))) + return CYMakeFunctor(context, symbol, value); + else return NULL; + + case 2: + if (void *symbol = CYCastSymbol(name.data)) { + // XXX: this is horrendously inefficient + sig::Signature signature; + sig::Parse(pool, &signature, value, &Structor_); + ffi_cif cif; + sig::sig_ffi_cif(pool, &sig::ObjectiveC, &signature, &cif); + return CYFromFFI(context, signature.elements[0].type, cif.rtype, symbol); + } else return NULL; // XXX: implement case 3 case 4: @@ -1302,19 +1322,24 @@ static JSStaticFunction Type_staticFunctions[4] = { {NULL, NULL, 0} }; +static JSObjectRef (*JSObjectMakeArray$)(JSContextRef, size_t, const JSValueRef[], JSValueRef *); + void CYSetArgs(int argc, const char *argv[]) { JSContextRef context(CYGetJSContext()); JSValueRef args[argc]; for (int i(0); i != argc; ++i) args[i] = CYCastJSValue(context, argv[i]); -#ifdef __APPLE__ - JSValueRef exception(NULL); - JSObjectRef array(JSObjectMakeArray(context, argc, args, &exception)); - CYThrow(context, exception); -#else - JSValueRef value(CYCallAsFunction(context, Array_, NULL, argc, args)); - JSObjectRef array(CYCastJSObject(context, value)); -#endif + + JSObjectRef array; + if (JSObjectMakeArray$ != NULL) { + JSValueRef exception(NULL); + array = (*JSObjectMakeArray$)(context, argc, args, &exception); + CYThrow(context, exception); + } else { + JSValueRef value(CYCallAsFunction(context, Array_, NULL, argc, args)); + array = CYCastJSObject(context, value); + } + CYSetProperty(context, System_, CYJSString("args"), array); } @@ -1376,6 +1401,8 @@ void CYInitialize() { _aprcall(apr_initialize()); _aprcall(apr_pool_create(&Pool_, NULL)); _sqlcall(sqlite3_open("/usr/lib/libcycript.db", &Bridge_)); + + JSObjectMakeArray$ = reinterpret_cast(dlsym(RTLD_DEFAULT, "JSObjectMakeArray")); } apr_pool_t *CYGetGlobalPool() { @@ -1420,8 +1447,18 @@ CYPoolError::CYPoolError(const char *format, va_list args) { message_ = apr_pvsprintf(pool_, format, args); } +JSValueRef CYCastJSError(JSContextRef context, const char *message) { + JSValueRef arguments[1] = {CYCastJSValue(context, message)}; + + JSValueRef exception(NULL); + JSValueRef value(JSObjectCallAsConstructor(context, Error_, 1, arguments, &exception)); + CYThrow(context, exception); + + return value; +} + JSValueRef CYPoolError::CastJSValue(JSContextRef context) const { - return CYCastJSValue(context, message_); + return CYCastJSError(context, message_); } CYJSError::CYJSError(JSContextRef context, const char *format, ...) { @@ -1435,15 +1472,9 @@ CYJSError::CYJSError(JSContextRef context, const char *format, ...) { const char *message(apr_pvsprintf(pool, format, args)); va_end (args); - JSValueRef arguments[1] = {CYCastJSValue(context, CYJSString(message))}; - - JSValueRef exception(NULL); - value_ = JSObjectCallAsConstructor(context, Error_, 1, arguments, &exception); - CYThrow(context, exception); + value_ = CYCastJSError(context, message); } -void CYObjectiveC(JSContextRef context, JSObjectRef global); - JSGlobalContextRef CYGetJSContext() { CYInitialize(); @@ -1562,10 +1593,8 @@ JSGlobalContextRef CYGetJSContext() { Result_ = JSStringCreateWithUTF8CString("_"); -// XXX: this is very wrong and sad -#ifdef __APPLE__ - CYObjectiveC(context, global); -#endif + if (hooks_ != NULL && hooks_->SetupContext != NULL) + (*hooks_->SetupContext)(context); } return Context_;