]> git.saurik.com Git - cycript.git/blobdiff - Execute.cpp
Forgot earlier yy modification: CYTypeArrayOf type.
[cycript.git] / Execute.cpp
index 0abf7f66d46b50aed93cc07752e5ab98631897ba..dd258265db86cd6cbbb74ae69b9bad7cd77f4f09 100644 (file)
@@ -131,7 +131,7 @@ size_t CYGetIndex(apr_pool_t *pool, JSContextRef context, JSStringRef value) {
 
 static JSClassRef All_;
 static JSClassRef Context_;
-static JSClassRef Functor_;
+JSClassRef Functor_;
 static JSClassRef Global_;
 static JSClassRef Pointer_;
 static JSClassRef Struct_;
@@ -257,6 +257,10 @@ JSObjectRef CYMakeStruct(JSContextRef context, void *data, sig::Type *type, ffi_
     return JSObjectMake(context, Struct_, internal);
 }
 
+static void *CYCastSymbol(const char *name) {
+    return dlsym(RTLD_DEFAULT, name);
+}
+
 JSValueRef CYCastJSValue(JSContextRef context, bool value) {
     return JSValueMakeBoolean(context, value);
 }
@@ -493,21 +497,24 @@ JSObjectRef CYMakePointer(JSContextRef context, void *pointer, size_t length, si
     return JSObjectMake(context, Pointer_, internal);
 }
 
-static JSObjectRef CYMakeFunctor(JSContextRef context, void (*function)(), const char *type, void **cache = NULL) {
-    cy::Functor *internal;
+static JSObjectRef CYMakeFunctor(JSContextRef context, void (*function)(), const char *type) {
+    return JSObjectMake(context, Functor_, new cy::Functor(type, function));
+}
 
-    if (cache != NULL && *cache != NULL) {
+static JSObjectRef CYMakeFunctor(JSContextRef context, const char *symbol, const char *type, void **cache) {
+    cy::Functor *internal;
+    if (*cache != NULL)
         internal = reinterpret_cast<cy::Functor *>(*cache);
-        ++internal->count_;
-    } else {
-        internal = new cy::Functor(type, function);
+    else {
+        void (*function)()(reinterpret_cast<void (*)()>(CYCastSymbol(symbol)));
+        if (function == NULL)
+            return NULL;
 
-        if (cache != NULL) {
-            *cache = internal;
-            ++internal->count_;
-        }
+        internal = new cy::Functor(type, function);
+        *cache = internal;
     }
 
+    ++internal->count_;
     return JSObjectMake(context, Functor_, internal);
 }
 
@@ -685,7 +692,7 @@ JSValueRef CYFromFFI(JSContextRef context, sig::Type *type, ffi_type *ffi, void
     }
 }
 
-static void FunctionClosure_(ffi_cif *cif, void *result, void **arguments, void *arg) {
+void CYExecuteClosure(ffi_cif *cif, void *result, void **arguments, void *arg, JSValueRef (*adapter)(JSContextRef, size_t, JSValueRef[], JSObjectRef)) {
     Closure_privateData *internal(reinterpret_cast<Closure_privateData *>(arg));
 
     JSContextRef context(internal->context_);
@@ -696,10 +703,18 @@ static void FunctionClosure_(ffi_cif *cif, void *result, void **arguments, void
     for (size_t index(0); index != count; ++index)
         values[index] = CYFromFFI(context, internal->signature_.elements[1 + index].type, internal->cif_.arg_types[index], arguments[index]);
 
-    JSValueRef value(CYCallAsFunction(context, internal->function_, NULL, count, values));
+    JSValueRef value(adapter(context, count, values, internal->function_));
     CYPoolFFI(NULL, context, internal->signature_.elements[0].type, internal->cif_.rtype, result, value);
 }
 
+static JSValueRef FunctionAdapter_(JSContextRef context, size_t count, JSValueRef values[], JSObjectRef function) {
+    return CYCallAsFunction(context, function, NULL, count, values);
+}
+
+static void FunctionClosure_(ffi_cif *cif, void *result, void **arguments, void *arg) {
+    CYExecuteClosure(cif, result, arguments, arg, &FunctionAdapter_);
+}
+
 Closure_privateData *CYMakeFunctor_(JSContextRef context, JSObjectRef function, const char *type, void (*callback)(ffi_cif *, void *, void **, void *)) {
     // XXX: in case of exceptions this will leak
     // XXX: in point of fact, this may /need/ to leak :(
@@ -957,10 +972,6 @@ JSObjectRef CYMakeType(JSContextRef context, sig::Type *type) {
     return JSObjectMake(context, Type_privateData::Class_, internal);
 }
 
-static void *CYCastSymbol(const char *name) {
-    return dlsym(RTLD_DEFAULT, name);
-}
-
 static JSValueRef All_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
     JSObjectRef global(CYGetGlobalObject(context));
     JSObjectRef cycript(CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Cycript"))));
@@ -990,9 +1001,7 @@ static JSValueRef All_getProperty(JSContextRef context, JSObjectRef object, JSSt
                     return JSEvaluateScript(CYGetJSContext(context), CYJSString(entry->value_), NULL, NULL, 0, NULL);
 
                 case '1':
-                    if (void (*symbol)() = reinterpret_cast<void (*)()>(CYCastSymbol(name.data)))
-                        return CYMakeFunctor(context, symbol, entry->value_, &entry->cache_);
-                    else return NULL;
+                    return CYMakeFunctor(context, name.data, entry->value_, &entry->cache_);
 
                 case '2':
                     if (void *symbol = CYCastSymbol(name.data)) {
@@ -1071,6 +1080,16 @@ static JSValueRef Type_callAsFunction_arrayOf(JSContextRef context, JSObjectRef
     return CYMakeType(context, &type);
 } CYCatch }
 
+static JSValueRef Type_callAsFunction_constant(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
+    if (count != 0)
+        throw CYJSError(context, "incorrect number of arguments to Type.constant");
+    Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(_this)));
+
+    sig::Type type(*internal->type_);
+    type.flags |= JOC_TYPE_CONST;
+    return CYMakeType(context, &type);
+} CYCatch }
+
 static JSValueRef Type_callAsFunction_pointerTo(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
     if (count != 0)
         throw CYJSError(context, "incorrect number of arguments to Type.pointerTo");
@@ -1087,6 +1106,19 @@ static JSValueRef Type_callAsFunction_pointerTo(JSContextRef context, JSObjectRe
     return CYMakeType(context, &type);
 } CYCatch }
 
+static JSValueRef Type_callAsFunction_withName(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
+    if (count != 1)
+        throw CYJSError(context, "incorrect number of arguments to Type.withName");
+    Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(_this)));
+
+    CYPool pool;
+    const char *name(CYPoolCString(pool, context, arguments[0]));
+
+    sig::Type type(*internal->type_);
+    type.name = name;
+    return CYMakeType(context, &type);
+} CYCatch }
+
 static JSValueRef Type_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
     if (count != 1)
         throw CYJSError(context, "incorrect number of arguments to type cast function");
@@ -1147,7 +1179,7 @@ static JSValueRef CYValue_callAsFunction_toCYON(JSContextRef context, JSObjectRe
 static JSValueRef Pointer_callAsFunction_toCYON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
     Pointer *internal(reinterpret_cast<Pointer *>(JSObjectGetPrivate(_this)));
     if (internal->length_ != _not(size_t)) {
-        JSObjectRef Array(CYGetCachedObject(context, Array_s));
+        JSObjectRef Array(CYGetCachedObject(context, CYJSString("Array_prototype")));
         JSObjectRef toCYON(CYCastJSObject(context, CYGetProperty(context, Array, toCYON_s)));
         return CYCallAsFunction(context, toCYON, _this, count, arguments);
     } else {
@@ -1162,6 +1194,11 @@ static JSValueRef Type_getProperty_alignment(JSContextRef context, JSObjectRef o
     return CYCastJSValue(context, internal->GetFFI()->alignment);
 }
 
+static JSValueRef Type_getProperty_name(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) {
+    Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(object)));
+    return CYCastJSValue(context, internal->type_->name);
+}
+
 static JSValueRef Type_getProperty_size(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) {
     Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(object)));
     return CYCastJSValue(context, internal->GetFFI()->size);
@@ -1178,13 +1215,9 @@ static JSValueRef Type_callAsFunction_toCYON(JSContextRef context, JSObjectRef o
     Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(_this)));
     CYPool pool;
     const char *type(sig::Unparse(pool, internal->type_));
-    size_t size(strlen(type));
-    char *cyon(new(pool) char[12 + size + 1]);
-    memcpy(cyon, "new Type(\"", 10);
-    cyon[12 + size] = '\0';
-    cyon[12 + size - 2] = '"';
-    cyon[12 + size - 1] = ')';
-    memcpy(cyon + 10, type, size);
+    std::ostringstream str;
+    CYStringify(str, type, strlen(type));
+    char *cyon(apr_pstrcat(pool, "new Type(", str.str().c_str(), ")", NULL));
     return CYCastJSValue(context, CYJSString(cyon));
 } CYCatch }
 
@@ -1215,15 +1248,18 @@ namespace cy {
     JSStaticFunction const * const Functor::StaticFunctions = Functor_staticFunctions;
 }
 
-static JSStaticValue Type_staticValues[3] = {
+static JSStaticValue Type_staticValues[4] = {
     {"alignment", &Type_getProperty_alignment, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
+    {"name", &Type_getProperty_name, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
     {"size", &Type_getProperty_size, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
     {NULL, NULL, NULL, 0}
 };
 
-static JSStaticFunction Type_staticFunctions[6] = {
+static JSStaticFunction Type_staticFunctions[8] = {
     {"arrayOf", &Type_callAsFunction_arrayOf, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
+    {"constant", &Type_callAsFunction_constant, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
     {"pointerTo", &Type_callAsFunction_pointerTo, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
+    {"withName", &Type_callAsFunction_withName, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
     {"toCYON", &Type_callAsFunction_toCYON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
     {"toJSON", &Type_callAsFunction_toJSON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
     {"toString", &Type_callAsFunction_toString, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
@@ -1516,6 +1552,9 @@ extern "C" void CYSetupContext(JSGlobalContextRef context) {
     //CYSetProperty(context, System, CYJSString("global"), global);
     CYSetProperty(context, System, CYJSString("print"), &System_print);
 
+    if (CYBridgeEntry *entry = CYBridgeHash("1dlerror", 8))
+        entry->cache_ = new cy::Functor(entry->value_, reinterpret_cast<void (*)()>(&dlerror));
+
     if (hooks_ != NULL && hooks_->SetupContext != NULL)
         (*hooks_->SetupContext)(context);