From 574d47203e63ac4a85f0d609098118d19e6bbf09 Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Tue, 29 Dec 2015 19:22:58 -0800 Subject: [PATCH] Move x.type() to typeid(x) and implement variadic. --- Decode.cpp | 26 +++--- Execute.cpp | 135 ++++++++++++++++++++--------- Internal.hpp | 17 ++-- JavaScript.hpp | 4 +- ObjectiveC/Library.mm | 109 ++++++++++++----------- ObjectiveC/Syntax.hpp | 3 +- Output.cpp | 8 +- Parser.ypp.in | 31 ++++--- Replace.cpp | 17 ++-- Scanner.lpp.in | 1 + Syntax.hpp | 15 +++- config.h.in | 3 + configure | 84 +++++++++++++++++- configure.ac | 5 +- libcycript.cy | 6 ++ modules/com/saurik/substrate/MS.cy | 2 +- sig/copy.cpp | 2 +- sig/ffi_type.cpp | 46 +++++----- sig/ffi_type.hpp | 9 +- sig/types.hpp | 14 ++- 20 files changed, 358 insertions(+), 179 deletions(-) diff --git a/Decode.cpp b/Decode.cpp index 2187f26..8bda223 100644 --- a/Decode.cpp +++ b/Decode.cpp @@ -150,26 +150,26 @@ CYTypedIdentifier *Aggregate::Decode(CYPool &pool) const { return $ CYTypedIdentifier($ CYTypeStruct(identifier, $ CYStructTail(fields))); } -CYTypedIdentifier *Function::Decode(CYPool &pool) const { +CYTypedIdentifier *Callable::Decode(CYPool &pool) const { _assert(signature.count != 0); - CYTypedParameter *parameter(NULL); + CYTypedParameter *parameters(NULL); for (size_t i(signature.count - 1); i != 0; --i) - parameter = $ CYTypedParameter(CYDecodeType(pool, signature.elements[i].type), parameter); - return CYDecodeType(pool, signature.elements[0].type)->Modify($ CYTypeFunctionWith(parameter)); + parameters = $ CYTypedParameter(CYDecodeType(pool, signature.elements[i].type), parameters); + return Modify(pool, CYDecodeType(pool, signature.elements[0].type), parameters); +} + +CYTypedIdentifier *Function::Modify(CYPool &pool, CYTypedIdentifier *result, CYTypedParameter *parameters) const { + return result->Modify($ CYTypeFunctionWith(variadic, parameters)); +} + +CYTypedIdentifier *Block::Modify(CYPool &pool, CYTypedIdentifier *result, CYTypedParameter *parameters) const { + return result->Modify($ CYTypeBlockWith(parameters)); } CYTypedIdentifier *Block::Decode(CYPool &pool) const { if (signature.count == 0) return $ CYTypedIdentifier($ CYTypeVariable("NSBlock"), $ CYTypePointerTo()); - else { - _assert(signature.count != 1); - _assert(dynamic_cast(signature.elements[1].type) != NULL); - - CYTypedParameter *parameter(NULL); - for (size_t i(signature.count - 1); i != 0; --i) - parameter = $ CYTypedParameter(CYDecodeType(pool, signature.elements[i].type), parameter); - return CYDecodeType(pool, signature.elements[0].type)->Modify($ CYTypeBlockWith(parameter)); - } + return Callable::Decode(pool); } } diff --git a/Execute.cpp b/Execute.cpp index 7875d88..d25f7b6 100644 --- a/Execute.cpp +++ b/Execute.cpp @@ -178,6 +178,7 @@ static JSClassRef Struct_; JSStringRef Array_s; JSStringRef cy_s; JSStringRef cyi_s; +JSStringRef cyt_s; JSStringRef length_s; JSStringRef message_s; JSStringRef name_s; @@ -649,8 +650,8 @@ JSObjectRef CYMakePointer(JSContextRef context, void *pointer, const char *encod return JSObjectMake(context, Pointer_, internal); } -static JSObjectRef CYMakeFunctor(JSContextRef context, void (*function)(), const sig::Signature &signature) { - return JSObjectMake(context, Functor_, new cy::Functor(signature, function)); +static JSObjectRef CYMakeFunctor(JSContextRef context, void (*function)(), bool variadic, const sig::Signature &signature) { + return JSObjectMake(context, Functor_, new cy::Functor(function, variadic, signature)); } static JSObjectRef CYMakeFunctor(JSContextRef context, const char *symbol, const char *encoding) { @@ -658,7 +659,7 @@ static JSObjectRef CYMakeFunctor(JSContextRef context, const char *symbol, const if (function == NULL) return NULL; - cy::Functor *internal(new cy::Functor(encoding, function)); + cy::Functor *internal(new cy::Functor(function, encoding)); ++internal->count_; return JSObjectMake(context, Functor_, internal); } @@ -876,7 +877,7 @@ JSValueRef Aggregate::FromFFI(JSContextRef context, ffi_type *ffi, void *data, b } JSValueRef Function::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const { - return CYMakeFunctor(context, reinterpret_cast(data), signature); + return CYMakeFunctor(context, reinterpret_cast(data), variadic, signature); } } @@ -959,7 +960,7 @@ JSObjectRef CYGetCachedObject(JSContextRef context, JSStringRef name) { return CYCastJSObject(context, CYGetCachedValue(context, name)); } -static JSObjectRef CYMakeFunctor(JSContextRef context, JSValueRef value, const sig::Signature &signature) { +static JSObjectRef CYMakeFunctor(JSContextRef context, JSValueRef value, bool variadic, const sig::Signature &signature) { JSObjectRef Function(CYGetCachedObject(context, CYJSString("Function"))); bool function(_jsccall(JSValueIsInstanceOfConstructor, context, value, Function)); @@ -968,7 +969,7 @@ static JSObjectRef CYMakeFunctor(JSContextRef context, JSValueRef value, const s return CYMakeFunctor(context, function, signature); } else { void (*function)()(CYCastPointer(context, value)); - return CYMakeFunctor(context, function, signature); + return CYMakeFunctor(context, function, variadic, signature); } } @@ -1097,7 +1098,7 @@ static JSValueRef Pointer_getProperty(JSContextRef context, JSObjectRef object, if (sig::Function *function = dynamic_cast(typical->type_)) { if (!JSStringIsEqualToUTF8CString(property, "$cyi")) return NULL; - return CYMakeFunctor(context, reinterpret_cast(internal->value_), function->signature); + return CYMakeFunctor(context, reinterpret_cast(internal->value_), function->variadic, function->signature); } JSObjectRef owner(internal->GetOwner() ?: object); @@ -1117,7 +1118,7 @@ static JSValueRef Struct_callAsFunction_$cya(JSContextRef context, JSObjectRef o return CYMakePointer(context, internal->value_, *typical->type_, typical->ffi_, _this); } CYCatch(NULL) } -static JSValueRef Struct_getProperty_type(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { +static JSValueRef Struct_getProperty_$cyt(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { Struct_privateData *internal(reinterpret_cast(JSObjectGetPrivate(object))); return CYMakeType(context, *internal->type_->type_); } CYCatch(NULL) } @@ -1181,23 +1182,62 @@ static void Struct_getPropertyNames(JSContextRef context, JSObjectRef object, JS } } +static sig::Void Void_; +static sig::Pointer PointerToVoid_(Void_); + +static sig::Type *CYGetType(CYPool &pool, JSContextRef context, JSValueRef value) { + if (JSValueIsNull(context, value)) + return &PointerToVoid_; + JSObjectRef object(CYCastJSObject(context, value)); + JSObjectRef type(CYCastJSObject(context, CYGetProperty(context, object, cyt_s))); + _assert(JSValueIsObjectOfClass(context, type, Type_privateData::Class_)); + Type_privateData *internal(reinterpret_cast(JSObjectGetPrivate(type))); + return internal->type_; +} + void CYCallFunction(CYPool &pool, JSContextRef context, ffi_cif *cif, void (*function)(), void *value, void **values) { ffi_call(cif, function, value, values); } -JSValueRef CYCallFunction(CYPool &pool, JSContextRef context, size_t setups, void *setup[], size_t count, const JSValueRef arguments[], bool initialize, sig::Signature *signature, ffi_cif *cif, void (*function)()) { - if (setups + count != signature->count - 1) - throw CYJSError(context, "incorrect number of arguments to ffi function"); +JSValueRef CYCallFunction(CYPool &pool, JSContextRef context, size_t setups, void *setup[], size_t count, const JSValueRef arguments[], bool initialize, bool variadic, const sig::Signature &signature, ffi_cif *cif, void (*function)()) { + size_t have(setups + count); + size_t need(signature.count - 1); + + if (have < need) + throw CYJSError(context, "insufficient number of arguments to ffi function"); + + ffi_cif corrected; + sig::Element *elements(signature.elements); + + if (have > need) { + if (!variadic) + throw CYJSError(context, "exorbitant number of arguments to ffi function"); + + elements = new (pool) sig::Element[have + 1]; + memcpy(elements, signature.elements, sizeof(sig::Element) * (need + 1)); + + for (size_t index(need); index != have; ++index) { + sig::Element &element(elements[index + 1]); + element.name = NULL; + element.offset = _not(size_t); + element.type = CYGetType(pool, context, arguments[index - setups]); + } + + sig::Signature extended; + extended.elements = elements; + extended.count = have + 1; + sig::sig_ffi_cif(pool, signature.count, extended, &corrected); + cif = &corrected; + } - size_t size(setups + count); - void *values[size]; + void *values[have]; memcpy(values, setup, sizeof(void *) * setups); - for (size_t index(setups); index != size; ++index) { - sig::Element *element(&signature->elements[index + 1]); + for (size_t index(setups); index != have; ++index) { + sig::Element &element(elements[index + 1]); ffi_type *ffi(cif->arg_types[index]); values[index] = pool.malloc(ffi->size, ffi->alignment); - element->type->PoolFFI(&pool, context, ffi, values[index], arguments[index - setups]); + element.type->PoolFFI(&pool, context, ffi, values[index], arguments[index - setups]); } uint8_t value[cif->rtype->size]; @@ -1209,13 +1249,13 @@ JSValueRef CYCallFunction(CYPool &pool, JSContextRef context, size_t setups, voi call = hook->CallFunction; call(pool, context, cif, function, value, values); - return signature->elements[0].type->FromFFI(context, cif->rtype, value, initialize); + return signature.elements[0].type->FromFFI(context, cif->rtype, value, initialize); } static JSValueRef Functor_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { CYPool pool; cy::Functor *internal(reinterpret_cast(JSObjectGetPrivate(object))); - return CYCallFunction(pool, context, 0, NULL, count, arguments, false, &internal->signature_, &internal->cif_, internal->GetValue()); + return CYCallFunction(pool, context, 0, NULL, count, arguments, false, internal->variadic_, internal->signature_, &internal->cif_, internal->GetValue()); } CYCatch(NULL) } static JSValueRef Pointer_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { @@ -1231,13 +1271,6 @@ JSObjectRef CYMakeType(JSContextRef context, const sig::Type &type) { return JSObjectMake(context, Type_privateData::Class_, internal); } -JSObjectRef CYMakeType(JSContextRef context, sig::Signature *signature) { - CYPool pool; - sig::Function type; - sig::Copy(pool, type.signature, *signature); - return CYMakeType(context, type); -} - extern "C" bool CYBridgeHash(CYPool &pool, CYUTF8String name, const char *&code, unsigned &flags) { sqlite3_stmt *statement; @@ -1499,8 +1532,9 @@ static JSValueRef Type_callAsFunction_constant(JSContextRef context, JSObjectRef } CYCatch(NULL) } static JSValueRef Type_callAsFunction_functionWith(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { - sig::Function type; - return Type_callAsFunction_$With(context, object, _this, count, arguments, type, exception); + bool variadic(count != 0 && JSValueIsNull(context, arguments[count - 1])); + sig::Function type(variadic); + return Type_callAsFunction_$With(context, object, _this, variadic ? count - 1 : count, arguments, type, exception); } static JSValueRef Type_callAsFunction_pointerTo(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { @@ -1529,14 +1563,23 @@ static JSValueRef Type_callAsFunction(JSContextRef context, JSObjectRef object, Type_privateData *internal(reinterpret_cast(JSObjectGetPrivate(object))); if (sig::Function *function = dynamic_cast(internal->type_)) - return CYMakeFunctor(context, arguments[0], function->signature); + return CYMakeFunctor(context, arguments[0], function->variadic, function->signature); CYPool pool; sig::Type *type(internal->type_); ffi_type *ffi(internal->GetFFI()); - void *value(pool.malloc(ffi->size, ffi->alignment)); - type->PoolFFI(&pool, context, ffi, value, arguments[0]); - return type->FromFFI(context, ffi, value); + + void *data(pool.malloc(ffi->size, ffi->alignment)); + type->PoolFFI(&pool, context, ffi, data, arguments[0]); + JSValueRef value(type->FromFFI(context, ffi, data)); + + if (JSValueGetType(context, value) == kJSTypeNumber) { + JSObjectRef typed(_jsccall(JSObjectCallAsConstructor, context, CYGetCachedObject(context, CYJSString("Number")), 1, &value)); + CYSetProperty(context, typed, cyt_s, object, kJSPropertyAttributeDontEnum); + value = typed; + } + + return value; } CYCatch(NULL) } static JSObjectRef Type_callAsConstructor(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { @@ -1559,7 +1602,7 @@ static JSObjectRef Functor_new(JSContextRef context, JSObjectRef object, size_t const char *encoding(CYPoolCString(pool, context, arguments[1])); sig::Signature signature; sig::Parse(pool, &signature, encoding, &Structor_); - return CYMakeFunctor(context, arguments[0], signature); + return CYMakeFunctor(context, arguments[0], false, signature); } CYCatch(NULL) } static JSValueRef CArray_callAsFunction_toPointer(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { @@ -1578,7 +1621,7 @@ static JSValueRef Functor_callAsFunction_$cya(JSContextRef context, JSObjectRef CYPool pool; cy::Functor *internal(reinterpret_cast(JSObjectGetPrivate(_this))); - sig::Function type; + sig::Function type(internal->variadic_); sig::Copy(pool, type.signature, internal->signature_); return CYMakePointer(context, internal->value_, type, NULL, NULL); @@ -1650,17 +1693,17 @@ static JSValueRef CString_getProperty_length(JSContextRef context, JSObjectRef o return CYCastJSValue(context, strlen(string)); } CYCatch(NULL) } -static JSValueRef CString_getProperty_type(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { +static JSValueRef CString_getProperty_$cyt(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { return CYMakeType(context, sig::String()); } CYCatch(NULL) } -static JSValueRef CArray_getProperty_type(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { +static JSValueRef CArray_getProperty_$cyt(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { CArray *internal(reinterpret_cast(JSObjectGetPrivate(object))); sig::Array type(*internal->type_->type_, internal->length_); return CYMakeType(context, type); } CYCatch(NULL) } -static JSValueRef Pointer_getProperty_type(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { +static JSValueRef Pointer_getProperty_$cyt(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { Pointer *internal(reinterpret_cast(JSObjectGetPrivate(object))); sig::Pointer type(*internal->type_->type_); return CYMakeType(context, type); @@ -1686,9 +1729,12 @@ static JSValueRef CString_callAsFunction_toString(JSContextRef context, JSObject return CYCastJSValue(context, string); } CYCatch(NULL) } -static JSValueRef Functor_getProperty_type(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { +static JSValueRef Functor_getProperty_$cyt(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { cy::Functor *internal(reinterpret_cast(JSObjectGetPrivate(object))); - return CYMakeType(context, &internal->signature_); + CYPool pool; + sig::Function type(internal->variadic_); + sig::Copy(pool, type.signature, internal->signature_); + return CYMakeType(context, type); } CYCatch(NULL) } static JSValueRef Type_getProperty_alignment(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { @@ -1740,7 +1786,7 @@ static JSStaticFunction CArray_staticFunctions[4] = { }; static JSStaticValue CArray_staticValues[2] = { - {"type", &CArray_getProperty_type, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {"$cyt", &CArray_getProperty_$cyt, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {NULL, NULL, NULL, 0} }; @@ -1755,7 +1801,7 @@ static JSStaticFunction CString_staticFunctions[6] = { static JSStaticValue CString_staticValues[3] = { {"length", &CString_getProperty_length, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, - {"type", &CString_getProperty_type, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {"$cyt", &CString_getProperty_$cyt, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {NULL, NULL, NULL, 0} }; @@ -1768,7 +1814,7 @@ static JSStaticFunction Pointer_staticFunctions[5] = { }; static JSStaticValue Pointer_staticValues[2] = { - {"type", &Pointer_getProperty_type, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {"$cyt", &Pointer_getProperty_$cyt, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {NULL, NULL, NULL, 0} }; @@ -1778,7 +1824,7 @@ static JSStaticFunction Struct_staticFunctions[2] = { }; static JSStaticValue Struct_staticValues[2] = { - {"type", &Struct_getProperty_type, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {"$cyt", &Struct_getProperty_$cyt, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {NULL, NULL, NULL, 0} }; @@ -1795,7 +1841,7 @@ namespace cy { } static JSStaticValue Functor_staticValues[2] = { - {"type", &Functor_getProperty_type, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {"$cyt", &Functor_getProperty_$cyt, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {NULL, NULL, NULL, 0} }; @@ -1993,6 +2039,7 @@ void CYInitializeDynamic() { Array_s = JSStringCreateWithUTF8CString("Array"); cy_s = JSStringCreateWithUTF8CString("$cy"); cyi_s = JSStringCreateWithUTF8CString("$cyi"); + cyt_s = JSStringCreateWithUTF8CString("$cyt"); length_s = JSStringCreateWithUTF8CString("length"); message_s = JSStringCreateWithUTF8CString("message"); name_s = JSStringCreateWithUTF8CString("name"); @@ -2269,6 +2316,8 @@ extern "C" void CYSetupContext(JSGlobalContextRef context) { } #endif + CYSetProperty(context, String_prototype, cyt_s, CYMakeType(context, sig::String()), kJSPropertyAttributeDontEnum); + CYSetProperty(context, cache, CYJSString("dlerror"), CYMakeFunctor(context, "dlerror", "*"), kJSPropertyAttributeDontEnum); CYSetProperty(context, cache, CYJSString("RTLD_DEFAULT"), CYCastJSValue(context, reinterpret_cast(RTLD_DEFAULT)), kJSPropertyAttributeDontEnum); CYSetProperty(context, cache, CYJSString("dlsym"), CYMakeFunctor(context, "dlsym", "^v^v*"), kJSPropertyAttributeDontEnum); diff --git a/Internal.hpp b/Internal.hpp index 0851dea..3c5d5f5 100644 --- a/Internal.hpp +++ b/Internal.hpp @@ -77,7 +77,7 @@ struct Type_privateData : signature.count = 1; ffi_cif cif; - sig::sig_ffi_cif(*pool_, &signature, &cif); + sig::sig_ffi_cif(*pool_, false, signature, &cif); ffi_ = new(*pool_) ffi_type; *ffi_ = *cif.rtype; @@ -145,22 +145,25 @@ struct Functor : { private: void set() { - sig::sig_ffi_cif(*pool_, &signature_, &cif_); + sig::sig_ffi_cif(*pool_, variadic_ ? signature_.count : 0, signature_, &cif_); } public: + bool variadic_; sig::Signature signature_; ffi_cif cif_; - Functor(const sig::Signature &signature, void (*value)()) : - CYValue(reinterpret_cast(value)) + Functor(void (*value)(), bool variadic, const sig::Signature &signature) : + CYValue(reinterpret_cast(value)), + variadic_(variadic) { sig::Copy(*pool_, signature_, signature); set(); } - Functor(const char *encoding, void (*value)()) : - CYValue(reinterpret_cast(value)) + Functor(void (*value)(), const char *encoding) : + CYValue(reinterpret_cast(value)), + variadic_(false) { sig::Parse(*pool_, &signature_, encoding, &Structor_); set(); @@ -182,7 +185,7 @@ struct Closure_privateData : JSValueRef (*adapter_)(JSContextRef, size_t, JSValueRef[], JSObjectRef); Closure_privateData(JSContextRef context, JSObjectRef function, JSValueRef (*adapter)(JSContextRef, size_t, JSValueRef[], JSObjectRef), const sig::Signature &signature) : - cy::Functor(signature, NULL), + cy::Functor(NULL, false, signature), context_(CYGetJSContext(context)), function_(function), adapter_(adapter) diff --git a/JavaScript.hpp b/JavaScript.hpp index 08020fe..a162d9a 100644 --- a/JavaScript.hpp +++ b/JavaScript.hpp @@ -42,6 +42,7 @@ extern JSStringRef Array_s; extern JSStringRef cy_s; extern JSStringRef cyi_s; +extern JSStringRef cyt_s; extern JSStringRef length_s; extern JSStringRef message_s; extern JSStringRef name_s; @@ -111,7 +112,7 @@ _finline Type_ CYCastPointer(JSContextRef context, JSValueRef value, bool *guess } void CYCallFunction(CYPool &pool, JSContextRef context, ffi_cif *cif, void (*function)(), void *value, void **values); -JSValueRef CYCallFunction(CYPool &pool, JSContextRef context, size_t setups, void *setup[], size_t count, const JSValueRef arguments[], bool initialize, sig::Signature *signature, ffi_cif *cif, void (*function)()); +JSValueRef CYCallFunction(CYPool &pool, JSContextRef context, size_t setups, void *setup[], size_t count, const JSValueRef arguments[], bool initialize, bool variadic, const sig::Signature &signature, ffi_cif *cif, void (*function)()); bool CYIsCallable(JSContextRef context, JSValueRef value); JSValueRef CYCallAsFunction(JSContextRef context, JSObjectRef function, JSObjectRef _this, size_t count, const JSValueRef arguments[]); @@ -138,7 +139,6 @@ struct CYRegisterHook { JSObjectRef CYMakePointer(JSContextRef context, void *pointer, const sig::Type &type, ffi_type *ffi, JSObjectRef owner); JSObjectRef CYMakeType(JSContextRef context, const sig::Type &type); -JSObjectRef CYMakeType(JSContextRef context, sig::Signature *signature); void CYFinalize(JSObjectRef object); diff --git a/ObjectiveC/Library.mm b/ObjectiveC/Library.mm index 580660e..b3dcc0a 100644 --- a/ObjectiveC/Library.mm +++ b/ObjectiveC/Library.mm @@ -389,7 +389,7 @@ struct Message_privateData : SEL sel_; Message_privateData(SEL sel, const char *type, IMP value = NULL) : - cy::Functor(type, reinterpret_cast(value)), + cy::Functor(reinterpret_cast(value), type), sel_(sel) { } @@ -848,28 +848,24 @@ NSObject *CYCopyNSObject(CYPool &pool, JSContextRef context, JSValueRef value) { @end static const char *CYBlockEncoding(NSBlock *self); -static sig::Signature *CYBlockSignature(CYPool &pool, NSBlock *self); +static bool CYBlockSignature(CYPool &pool, NSBlock *self, sig::Signature &signature); @implementation NSBlock (Cycript) - (NSString *) cy$toCYON:(bool)objective inSet:(std::set &)objects { CYLocalPool pool; - sig::Signature *signature(CYBlockSignature(pool, self)); - // XXX: I am checking signature->count due to Decode doing it for block_P - if (signature == NULL || signature->count == 0) + sig::Block type; + if (!CYBlockSignature(pool, self, type.signature)) return [super cy$toCYON:objective inSet:objects]; _oassert(objects.insert(self).second); - sig::Block type; - sig::Copy(pool, type.signature, *signature); - CYTypedIdentifier *typed((new(pool) CYTypeExpression(CYDecodeType(pool, &type)))->typed_); - CYTypeFunctionWith *function(typed->Function()); - _assert(function != NULL); - - _assert(function->parameters_ != NULL); - CYObjCBlock *block(new(pool) CYObjCBlock(typed, function->parameters_, NULL)); + CYTypeModifier *&modifier(CYGetLast(typed->modifier_)); + CYTypeBlockWith *with(dynamic_cast(modifier)); + _assert(with != NULL); + CYObjCBlock *block(new(pool) CYObjCBlock(typed, with->parameters_, NULL)); + modifier = NULL; std::ostringstream str; CYOptions options; @@ -1932,14 +1928,21 @@ static const char *CYBlockEncoding(NSBlock *self) { return descriptor3->signature; } -static sig::Signature *CYBlockSignature(CYPool &pool, NSBlock *self) { +static bool CYBlockSignature(CYPool &pool, NSBlock *self, sig::Signature &signature) { const char *encoding(CYBlockEncoding(self)); if (encoding == NULL) - return NULL; - // XXX: this should be stored on a FunctionInstance private value subclass - sig::Signature *signature(new(pool) sig::Signature()); - sig::Parse(pool, signature, encoding, &Structor_); - return signature; + return false; + + sig::Parse(pool, &signature, encoding, &Structor_); + _assert(signature.count >= 2); + + _assert(dynamic_cast(signature.elements[1].type) != NULL); + signature.elements[1] = signature.elements[0]; + + ++signature.elements; + --signature.count; + + return true; } static JSValueRef FunctionInstance_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { @@ -1956,11 +1959,11 @@ static JSValueRef FunctionInstance_callAsFunction(JSContextRef context, JSObject sig::Parse(pool, &signature, encoding, &Structor_); ffi_cif cif; - sig::sig_ffi_cif(pool, &signature, &cif); + sig::sig_ffi_cif(pool, 0, signature, &cif); BlockLiteral *literal(reinterpret_cast(self)); void (*function)() = reinterpret_cast(literal->invoke); - return CYCallFunction(pool, context, 1, setup, count, arguments, false, &signature, &cif, function); + return CYCallFunction(pool, context, 1, setup, count, arguments, false, false, signature, &cif, function); } if (count != 0) @@ -2409,24 +2412,8 @@ JSValueRef CYSendMessage(CYPool &pool, JSContextRef context, id self, Class _cla sig::Signature signature; sig::Parse(pool, &signature, type, &Structor_); - size_t used(count + 3); - if (used > signature.count) { - sig::Element *elements(new (pool) sig::Element[used]); - memcpy(elements, signature.elements, used * sizeof(sig::Element)); - - for (size_t index(signature.count); index != used; ++index) { - sig::Element *element(&elements[index]); - element->name = NULL; - element->offset = _not(size_t); - element->type = new(pool) sig::Object(); - } - - signature.elements = elements; - signature.count = used; - } - ffi_cif cif; - sig::sig_ffi_cif(pool, &signature, &cif); + sig::sig_ffi_cif(pool, 0, signature, &cif); if (imp == NULL) { #ifndef CY_NO_STRET @@ -2438,7 +2425,7 @@ JSValueRef CYSendMessage(CYPool &pool, JSContextRef context, id self, Class _cla } void (*function)() = reinterpret_cast(imp); - return CYCallFunction(pool, context, 2, setup, count, arguments, initialize, &signature, &cif, function); + return CYCallFunction(pool, context, 2, setup, count, arguments, initialize, true, signature, &cif, function); } static JSValueRef $objc_msgSend(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[]) { @@ -2502,7 +2489,7 @@ static JSValueRef Message_callAsFunction(JSContextRef context, JSObjectRef objec setup[0] = &self; setup[1] = &internal->sel_; - return CYCallFunction(pool, context, 2, setup, count, arguments, false, &internal->signature_, &internal->cif_, internal->GetValue()); + return CYCallFunction(pool, context, 2, setup, count, arguments, false, true, internal->signature_, &internal->cif_, internal->GetValue()); } CYCatch(NULL) } static JSObjectRef Super_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { @@ -2553,13 +2540,25 @@ static JSValueRef CYValue_callAsFunction_$cya(JSContextRef context, JSObjectRef return CYMakePointer(context, &internal->value_, *type, ffi, object); } CYCatch(NULL) } -static JSValueRef FunctionInstance_getProperty_type(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { +static JSValueRef Selector_getProperty_$cyt(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { + return CYMakeType(context, sig::Selector()); +} CYCatch(NULL) } + +static JSValueRef Instance_getProperty_$cyt(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { + return CYMakeType(context, sig::Object()); +} CYCatch(NULL) } + +static JSValueRef FunctionInstance_getProperty_$cyt(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { Instance *internal(reinterpret_cast(JSObjectGetPrivate(object))); CYPool pool; - sig::Signature *signature(CYBlockSignature(pool, internal->GetValue())); - if (signature == NULL) + sig::Block type; + if (!CYBlockSignature(pool, internal->GetValue(), type.signature)) return CYJSNull(context); - return CYMakeType(context, signature); + return CYMakeType(context, type); +} CYCatch(NULL) } + +static JSValueRef Class_getProperty_$cyt(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { + return CYMakeType(context, sig::Meta()); } CYCatch(NULL) } static JSValueRef Instance_getProperty_constructor(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { @@ -2700,18 +2699,20 @@ static JSValueRef Selector_callAsFunction_type(JSContextRef context, JSObjectRef objc_method *method(_require(class_getInstanceMethod(_class, sel))); const char *encoding(method_getTypeEncoding(method)); - sig::Signature signature; - sig::Parse(pool, &signature, encoding, &Structor_); - return CYMakeType(context, &signature); + sig::Function type(false); + sig::Parse(pool, &type.signature, encoding, &Structor_); + return CYMakeType(context, type); } CYCatch(NULL) } -static JSStaticValue Selector_staticValues[2] = { +static JSStaticValue Selector_staticValues[3] = { + {"$cyt", &Selector_getProperty_$cyt, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"value", &CYValue_getProperty_value, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete}, {NULL, NULL, NULL, 0} }; -// XXX: this is sadly duplicated in FunctionInstance_staticValues -static JSStaticValue Instance_staticValues[5] = { +static JSStaticValue Instance_staticValues[6] = { + {"$cyt", &Instance_getProperty_$cyt, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + // XXX: this is sadly duplicated in FunctionInstance_staticValues {"constructor", &Instance_getProperty_constructor, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"messages", &Instance_getProperty_messages, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"prototype", &Instance_getProperty_prototype, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, @@ -2720,7 +2721,7 @@ static JSStaticValue Instance_staticValues[5] = { }; static JSStaticValue FunctionInstance_staticValues[6] = { - {"type", &FunctionInstance_getProperty_type, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {"$cyt", &FunctionInstance_getProperty_$cyt, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, // XXX: this is sadly a duplicate of Instance_staticValues {"constructor", &Instance_getProperty_constructor, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"messages", &Instance_getProperty_messages, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, @@ -2744,6 +2745,11 @@ static JSStaticFunction Class_staticFunctions[2] = { {NULL, NULL, 0} }; +static JSStaticValue Class_staticValues[2] = { + {"$cyt", &Class_getProperty_$cyt, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {NULL, NULL, NULL, 0} +}; + static JSStaticFunction Internal_staticFunctions[2] = { {"$cya", &Internal_callAsFunction_$cya, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {NULL, NULL, 0} @@ -2831,6 +2837,7 @@ void CYObjectiveC_Initialize() { /*XXX*/ JSContextRef context(NULL); CYPoolTry { definition = kJSClassDefinitionEmpty; definition.className = "Class"; definition.staticFunctions = Class_staticFunctions; + definition.staticValues = Class_staticValues; Class_ = JSClassCreate(&definition); definition = kJSClassDefinitionEmpty; diff --git a/ObjectiveC/Syntax.hpp b/ObjectiveC/Syntax.hpp index e4b0732..8969357 100644 --- a/ObjectiveC/Syntax.hpp +++ b/ObjectiveC/Syntax.hpp @@ -177,7 +177,8 @@ struct CYMessageParameter : CYWord *name_; CYTypedIdentifier *type_; - CYMessageParameter(CYWord *name, CYTypedIdentifier *type) : + CYMessageParameter(CYWord *name, CYTypedIdentifier *type, CYMessageParameter *next = NULL) : + CYNext(next), name_(name), type_(type) { diff --git a/Output.cpp b/Output.cpp index dc5782a..a617408 100644 --- a/Output.cpp +++ b/Output.cpp @@ -677,7 +677,13 @@ void CYTypeConstant::Output(CYOutput &out, CYIdentifier *identifier) const { void CYTypeFunctionWith::Output(CYOutput &out, CYIdentifier *identifier) const { next_->Output(out, Precedence(), identifier); - out << '(' << parameters_ << ')'; + out << '(' << parameters_; + if (variadic_) { + if (parameters_ != NULL) + out << ',' << ' '; + out << "..."; + } + out << ')'; } void CYTypePointerTo::Output(CYOutput &out, CYIdentifier *identifier) const { diff --git a/Parser.ypp.in b/Parser.ypp.in index acda20a..ec17e71 100644 --- a/Parser.ypp.in +++ b/Parser.ypp.in @@ -85,6 +85,7 @@ %union { CYTypeStructField *structField_; } %union { CYTypeModifier *modifier_; } %union { CYTypeSpecifier *specifier_; } +%union { CYTypedFormal *typedFormal_; } %union { CYTypedIdentifier *typedIdentifier_; } %union { CYTypedParameter *typedParameter_; } @end @@ -434,6 +435,7 @@ type; }) %token _synchronized_ "synchronized" %token _throws_ "throws" %token _transient_ "transient" +%token _typeid_ "typeid" %token _volatile_ "volatile" %token _yield_ "yield" %token _yield__ "!yield" @@ -677,9 +679,10 @@ type; }) %type TypedIdentifierMaybe %type TypedIdentifierNo %type TypedIdentifierYes -%type TypedParameterList_ -%type TypedParameterList -%type TypedParameterListOpt +%type TypedParameterList_ +%type TypedParameterList +%type TypedParameterListOpt +%type TypedParameters @end @begin ObjectiveC @@ -972,6 +975,7 @@ IdentifierTypeNoOf | "target" { $$ = CYNew CYIdentifier("target"); } | "throws" { $$ = CYNew CYIdentifier("throws"); } | "transient" { $$ = CYNew CYIdentifier("transient"); } + | "typeid" { $$ = CYNew CYIdentifier("typeid"); } | "undefined" { $$ = CYNew CYIdentifier("undefined"); } @begin ObjectiveC | "bool" { $$ = CYNew CYIdentifier("bool"); } @@ -2026,12 +2030,12 @@ ParameterModifierOpt ; ParameterTail - : TypedParameterListOpt[parameters] ")" ParameterModifierOpt { $$ = CYNew CYTypeFunctionWith($parameters); } + : TypedParameterListOpt[formal] ")" ParameterModifierOpt { $$ = CYNew CYTypeFunctionWith($formal->variadic_, $formal->parameters_); } ; SuffixedType : SuffixedTypeOpt[typed] "[" RestrictOpt NumericLiteral[size] "]" { $$ = $typed; $$->modifier_ = CYNew CYTypeArrayOf($size, $$->modifier_); } - | "(" "^" TypeQualifierRightOpt[typed] ")" "(" TypedParameterListOpt[parameters] ")" { $$ = $typed; $$->modifier_ = CYNew CYTypeBlockWith($parameters, $$->modifier_); } + | "(" "^" TypeQualifierRightOpt[typed] ")" "(" TypedParameters[parameters] ")" { $$ = $typed; $$->modifier_ = CYNew CYTypeBlockWith($parameters, $$->modifier_); } | TypeSignifier[typed] "(" ParameterTail[modifier] { $$ = $typed; CYSetLast($modifier) = $$->modifier_; $$->modifier_ = $modifier; } | "("[parenthesis] ParameterTail[modifier] { $$ = CYNew CYTypedIdentifier(@parenthesis); CYSetLast($modifier) = $$->modifier_; $$->modifier_ = $modifier; } ; @@ -2163,7 +2167,7 @@ MessageParameterList MessageParameterListOpt : MessageParameterList[pass] { $$ = $pass; } - | { $$ = NULL; } + | TypedParameterList_[formal] { if ($formal->variadic_) CYERR(@$, "unsupported variadic"); /*XXX*/ if ($formal->parameters_ != NULL) CYERR(@$, "temporarily unsupported"); $$ = NULL; } ; MessageParameters @@ -2346,21 +2350,26 @@ MemberAccess /* Cycript (C): Lambda Expressions {{{ */ TypedParameterList_ : "," TypedParameterList[parameters] { $$ = $parameters; } - | { $$ = NULL; } + | { $$ = CYNew CYTypedFormal(false); } ; TypedParameterList - : TypedIdentifierMaybe[typed] TypedParameterList_[next] { $$ = CYNew CYTypedParameter($typed, $next); } + : TypedIdentifierMaybe[typed] TypedParameterList_[formal] { $$ = $formal; $$->parameters_ = CYNew CYTypedParameter($typed, $$->parameters_); } + | "..." { $$ = CYNew CYTypedFormal(true); } ; TypedParameterListOpt : TypedParameterList[pass] { $$ = $pass; } - | "void" { $$ = NULL; } - | { $$ = NULL; } + | "void" { $$ = CYNew CYTypedFormal(false); } + | { $$ = CYNew CYTypedFormal(false); } + ; + +TypedParameters + : TypedParameterListOpt[formal] { if ($formal->variadic_) CYERR(@$, "unsupported variadic"); $$ = $formal->parameters_; } ; PrimaryExpression - : "[" LexOf "&" "]" "(" TypedParameterListOpt[parameters] ")" "->" TypedIdentifierNo[type] "{" FunctionBody[code] "}" { $$ = CYNew CYLambda($type, $parameters, $code); } + : "[" LexOf "&" "]" "(" TypedParameters[parameters] ")" "->" TypedIdentifierNo[type] "{" FunctionBody[code] "}" { $$ = CYNew CYLambda($type, $parameters, $code); } ; /* }}} */ /* Cycript (C): Structure Definitions {{{ */ diff --git a/Replace.cpp b/Replace.cpp index ca05d08..719b3a5 100644 --- a/Replace.cpp +++ b/Replace.cpp @@ -1233,7 +1233,10 @@ CYTarget *CYTypeModifier::Replace(CYContext &context, CYTarget *type) { $T(type) } CYTarget *CYTypeFunctionWith::Replace_(CYContext &context, CYTarget *type) { - return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("functionWith")), parameters_->Argument(context))); + CYList arguments(parameters_->Argument(context)); + if (variadic_) + arguments->*$C_($ CYNull()); + return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("functionWith")), arguments)); } CYTarget *CYTypePointerTo::Replace_(CYContext &context, CYTarget *type) { @@ -1268,15 +1271,15 @@ CYTarget *CYTypedIdentifier::Replace(CYContext &context) { } CYTypeFunctionWith *CYTypedIdentifier::Function() { - CYTypeModifier **modifier(&modifier_); - if (*modifier == NULL) + CYTypeModifier *&modifier(CYGetLast(modifier_)); + if (modifier == NULL) return NULL; - while ((*modifier)->next_ != NULL) - modifier = &(*modifier)->next_; - CYTypeFunctionWith *function((*modifier)->Function()); + + CYTypeFunctionWith *function(modifier->Function()); if (function == NULL) return NULL; - *modifier = NULL; + + modifier = NULL; return function; } diff --git a/Scanner.lpp.in b/Scanner.lpp.in index 7df8388..edadb8f 100644 --- a/Scanner.lpp.in +++ b/Scanner.lpp.in @@ -510,6 +510,7 @@ XMLName {XMLNameStart}{XMLNamePart}* "transient" L /*FII*/ F(tk::_transient_, hi::Meta); "true" L /*LLL*/ F(tk::_true_, hi::Constant); "try" L /*KKK*/ F(tk::_try_, hi::Control); +"typeid" L /*III*/ F(tk::_typeid_, hi::Operator); "typeof" L /*KKK*/ F(tk::_typeof_, hi::Operator); "var" L /*KKK*/ F(tk::_var_, hi::Meta); "void" L /*KKK*/ F(tk::_void_, hi::Operator); diff --git a/Syntax.hpp b/Syntax.hpp index 9786ee7..abf05bc 100644 --- a/Syntax.hpp +++ b/Syntax.hpp @@ -2226,6 +2226,17 @@ struct CYTypedParameter : virtual void Output(CYOutput &out) const; }; +struct CYTypedFormal { + bool variadic_; + CYTypedParameter *parameters_; + + CYTypedFormal(bool variadic) : + variadic_(variadic), + parameters_(NULL) + { + } +}; + struct CYLambda : CYTarget { @@ -2381,10 +2392,12 @@ struct CYTypeBlockWith : struct CYTypeFunctionWith : CYTypeModifier { + bool variadic_; CYTypedParameter *parameters_; - CYTypeFunctionWith(CYTypedParameter *parameters, CYTypeModifier *next = NULL) : + CYTypeFunctionWith(bool variadic, CYTypedParameter *parameters, CYTypeModifier *next = NULL) : CYTypeModifier(next), + variadic_(variadic), parameters_(parameters) { } diff --git a/config.h.in b/config.h.in index 46d3410..2286294 100644 --- a/config.h.in +++ b/config.h.in @@ -12,6 +12,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_FFI_H +/* Define to 1 if you have the `ffi_prep_cif_var' function. */ +#undef HAVE_FFI_PREP_CIF_VAR + /* Define to 1 if you have the `Foundation' framework (-framework Foundation). */ #undef HAVE_FRAMEWORK_FOUNDATION diff --git a/configure b/configure index 0dfc278..3cb5c3c 100755 --- a/configure +++ b/configure @@ -1557,6 +1557,9 @@ Some influential environment variables: WEBKIT_CFLAGS C compiler flags for WEBKIT, overriding pkg-config WEBKIT_LIBS linker flags for WEBKIT, overriding pkg-config + LIBFFI_CFLAGS + C compiler flags for LIBFFI, overriding pkg-config + LIBFFI_LIBS linker flags for LIBFFI, overriding pkg-config GNUSTEP_CONFIG prints information about the current gnustep installation @@ -2154,6 +2157,73 @@ fi } # ac_fn_cxx_check_header_mongrel +# ac_fn_cxx_check_func LINENO FUNC VAR +# ------------------------------------ +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_cxx_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_cxx_check_func + # ac_fn_objcxx_try_link LINENO # ---------------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. @@ -22644,9 +22714,6 @@ done if test "x$ac_cv_header_ffi_h" = xno && test "x$ac_cv_header_ffi_ffi_h" = xno; then : - LIBFFI_CFLAGS - C compiler flags for LIBFFI, overriding pkg-config - LIBFFI_LIBS linker flags for LIBFFI, overriding pkg-config pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBFFI" >&5 @@ -22948,6 +23015,17 @@ fi ;; #( *) : ;; esac + for ac_func in ffi_prep_cif_var +do : + ac_fn_cxx_check_func "$LINENO" "ffi_prep_cif_var" "ac_cv_func_ffi_prep_cif_var" +if test "x$ac_cv_func_ffi_prep_cif_var" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_FFI_PREP_CIF_VAR 1 +_ACEOF + +fi +done + fi LTLIBFFI=$LIBS diff --git a/configure.ac b/configure.ac index a1c34d3..aee07a5 100644 --- a/configure.ac +++ b/configure.ac @@ -211,12 +211,13 @@ AS_CASE([$CY_EXECUTE], [1], [ AC_CHECK_HEADERS([ffi.h ffi/ffi.h], [break]) - CY_LT_LIB([LTLIBFFI], AS_IF([test "x$ac_cv_header_ffi_h" = xno && test "x$ac_cv_header_ffi_ffi_h" = xno], [ + CY_LT_LIB([LTLIBFFI], [AS_IF([test "x$ac_cv_header_ffi_h" = xno && test "x$ac_cv_header_ffi_ffi_h" = xno], [ CY_CHECK_PKG_CONFIG_LIBFFI ], [ AC_SEARCH_LIBS([ffi_call], [ffi]) AS_CASE([$ac_cv_search_ffi_call], [no], [CY_CHECK_PKG_CONFIG_LIBFFI]) - ])) + AC_CHECK_FUNCS([ffi_prep_cif_var]) + ])]) AC_CHECK_FRAMEWORK([JavaVM], [ #include diff --git a/libcycript.cy b/libcycript.cy index 8640a74..4014fd6 100644 --- a/libcycript.cy +++ b/libcycript.cy @@ -25,6 +25,10 @@ var process = { (function() { +this.typeid = function(object) { + return object.$cyt; +}; + let $cy_set = function(object, properties) { for (const name in properties) Object.defineProperty(object, name, { @@ -67,6 +71,8 @@ $cy_set(Error.prototype, { $cy_set(Number.prototype, { toCYON: function() { + if ("$cyt" in this) + return `${this.$cyt.toCYON()}(${this.toString()})`; return `new Number(${this.toString()})`; }, }); diff --git a/modules/com/saurik/substrate/MS.cy b/modules/com/saurik/substrate/MS.cy index 2cd98b8..446b906 100644 --- a/modules/com/saurik/substrate/MS.cy +++ b/modules/com/saurik/substrate/MS.cy @@ -61,7 +61,7 @@ exports.getImageByName = MSGetImageByName; exports.findSymbol = MSFindSymbol; exports.hookFunction = function(func, hook, old) { - var type = func.type; + var type = typeid(func); var pointer; if (old == null || typeof old === "undefined") diff --git a/sig/copy.cpp b/sig/copy.cpp index 8b43fc1..4fb98bd 100644 --- a/sig/copy.cpp +++ b/sig/copy.cpp @@ -91,7 +91,7 @@ Aggregate *Aggregate::Copy(CYPool &pool, const char *name) const { } Function *Function::Copy(CYPool &pool, const char *name) const { - Function *copy(new(pool) Function()); + Function *copy(new(pool) Function(variadic)); sig::Copy(pool, copy->signature, signature); return copy; } diff --git a/sig/ffi_type.cpp b/sig/ffi_type.cpp index 73b3912..e114db8 100644 --- a/sig/ffi_type.cpp +++ b/sig/ffi_type.cpp @@ -29,18 +29,6 @@ namespace sig { -void sig_ffi_types( - CYPool &pool, - const struct Signature *signature, - ffi_type **types, - size_t skip = 0, - size_t offset = 0 -) { - _assert(signature->count >= skip); - for (size_t index = skip; index != signature->count; ++index) - types[index - skip + offset] = signature->elements[index].type->GetFFI(pool); -} - template <> ffi_type *Primitive::GetFFI(CYPool &pool) const { return &ffi_type_uchar; @@ -171,7 +159,8 @@ ffi_type *Aggregate::GetFFI(CYPool &pool) const { ffi->type = FFI_TYPE_STRUCT; ffi->elements = new(pool) ffi_type *[signature.count + 1]; - sig_ffi_types(pool, &signature, ffi->elements); + for (size_t index(0); index != signature.count; ++index) + ffi->elements[index] = signature.elements[index].type->GetFFI(pool); ffi->elements[signature.count] = NULL; return ffi; @@ -185,19 +174,24 @@ ffi_type *Block::GetFFI(CYPool &pool) const { return &ffi_type_pointer; } -void sig_ffi_cif( - CYPool &pool, - struct Signature *signature, - ffi_cif *cif, - size_t skip, - ffi_type **types, - size_t offset -) { - if (types == NULL) - types = new(pool) ffi_type *[signature->count - 1]; - ffi_type *type = signature->elements[0].type->GetFFI(pool); - sig_ffi_types(pool, signature, types, 1 + skip, offset); - ffi_status status = ffi_prep_cif(cif, FFI_DEFAULT_ABI, signature->count - 1 - skip + offset, type, types); +void sig_ffi_cif(CYPool &pool, size_t variadic, const Signature &signature, ffi_cif *cif) { + _assert(signature.count != 0); + size_t count(signature.count - 1); + ffi_type *type(signature.elements[0].type->GetFFI(pool)); + + ffi_type **types(new(pool) ffi_type *[count]); + for (size_t index(0); index != count; ++index) + types[index] = signature.elements[index + 1].type->GetFFI(pool); + + ffi_status status; +#ifdef HAVE_FFI_PREP_CIF_VAR + if (variadic == 0) +#endif + status = ffi_prep_cif(cif, FFI_DEFAULT_ABI, count, type, types); +#ifdef HAVE_FFI_PREP_CIF_VAR + else + status = ffi_prep_cif_var(cif, FFI_DEFAULT_ABI, variadic - 1, count, type, types); +#endif _assert(status == FFI_OK); } diff --git a/sig/ffi_type.hpp b/sig/ffi_type.hpp index b654e0f..2944297 100644 --- a/sig/ffi_type.hpp +++ b/sig/ffi_type.hpp @@ -27,14 +27,7 @@ namespace sig { -void sig_ffi_cif( - CYPool &pool, - struct Signature *signature, - ffi_cif *cif, - size_t skip = 0, - ffi_type **types = NULL, - size_t offset = 0 -); +void sig_ffi_cif(CYPool &pool, size_t variadic, const Signature &signature, ffi_cif *cif); void Copy(CYPool &pool, ffi_type &lhs, ffi_type &rhs); diff --git a/sig/types.hpp b/sig/types.hpp index 3bed8fd..f053046 100644 --- a/sig/types.hpp +++ b/sig/types.hpp @@ -37,6 +37,7 @@ class CYPool; struct CYTypedIdentifier; +struct CYTypedParameter; namespace sig { @@ -270,15 +271,25 @@ struct Callable : Type { Signature signature; + + CYTypedIdentifier *Decode(CYPool &pool) const override; + virtual CYTypedIdentifier *Modify(CYPool &pool, CYTypedIdentifier *result, CYTypedParameter *parameters) const = 0; }; struct Function : Callable { + bool variadic; + + Function(bool variadic) : + variadic(variadic) + { + } + Function *Copy(CYPool &pool, const char *name = NULL) const override; const char *Encode(CYPool &pool) const override; - CYTypedIdentifier *Decode(CYPool &pool) const override; + CYTypedIdentifier *Modify(CYPool &pool, CYTypedIdentifier *result, CYTypedParameter *parameters) const override; ffi_type *GetFFI(CYPool &pool) const override; void PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const override; @@ -292,6 +303,7 @@ struct Block : const char *Encode(CYPool &pool) const override; CYTypedIdentifier *Decode(CYPool &pool) const override; + CYTypedIdentifier *Modify(CYPool &pool, CYTypedIdentifier *result, CYTypedParameter *parameters) const override; ffi_type *GetFFI(CYPool &pool) const override; void PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const override; -- 2.45.2