From aaa29c28ae45afad21be2891d38744d68d3c907e Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Sun, 3 Jan 2016 18:56:49 -0800 Subject: [PATCH] Analyze even more headers and added enum typedefs. --- Analysis.cpp | 8 ++++++ Analyze.cpp | 64 ++++++++++++++++++++++++++++++++++++++---------- Decode.cpp | 10 ++++++++ Execute.cpp | 62 ++++++++++++++++++++++++++++++++++++++++++---- Output.cpp | 39 +++++++++++++++++++++++++++-- Parser.ypp.in | 41 +++++++++++++++++++++++++++---- Replace.cpp | 21 +++++++++++++++- Syntax.hpp | 41 ++++++++++++++++++++++++++++++- sig/copy.cpp | 18 ++++++++++++++ sig/ffi_type.cpp | 4 +++ sig/parse.cpp | 4 +++ sig/types.hpp | 33 +++++++++++++++++++++++++ 12 files changed, 318 insertions(+), 27 deletions(-) diff --git a/Analysis.cpp b/Analysis.cpp index 4429d22..520de54 100644 --- a/Analysis.cpp +++ b/Analysis.cpp @@ -66,8 +66,16 @@ #include #include +#include +#include +#include + +#include +#include + #if TARGET_OS_IPHONE #include +extern "C" UIApplication *UIApp; #else #include #endif diff --git a/Analyze.cpp b/Analyze.cpp index 49ff5cb..0f46cb4 100644 --- a/Analyze.cpp +++ b/Analyze.cpp @@ -298,6 +298,18 @@ static CYTypedIdentifier *CYDecodeType(CXType type, const CYCXString &identifier return typed; } +static void CYParseEnumeration(CXCursor cursor, CYTypedIdentifier *typed) { + CYList constants; + + CYForChild(cursor, fun([&](CXCursor child) { + if (clang_getCursorKind(child) == CXCursor_EnumConstantDecl) + constants->*$ CYEnumConstant($I($pool.strdup(CYCXString(child))), $D(clang_getEnumConstantDeclValue(child))); + })); + + CYTypedIdentifier *integer(CYDecodeType(clang_getEnumDeclIntegerType(cursor))); + typed->specifier_ = $ CYTypeEnum(NULL, integer->specifier_, constants); +} + static void CYParseStructure(CXCursor cursor, CYTypedIdentifier *typed) { CYList fields; CYForChild(cursor, fun([&](CXCursor child) { @@ -316,16 +328,14 @@ static void CYParseCursor(CXType type, CXCursor cursor, CYTypedIdentifier *typed switch (CXCursorKind kind = clang_getCursorKind(cursor)) { case CXCursor_EnumDecl: if (spelling[0] != '\0') - // XXX: should we have a special enum keyword? - typed->specifier_ = $ CYTypeVariable($I(spelling.Pool($pool))); + typed->specifier_ = $ CYTypeReference(CYTypeReferenceEnum, $I(spelling.Pool($pool))); else - // XXX: maybe replace with "enum : int" instead of "int" - CYParseType(clang_getEnumDeclIntegerType(cursor), typed); + CYParseEnumeration(cursor, typed); break; case CXCursor_StructDecl: { if (spelling[0] != '\0') - typed->specifier_ = $ CYTypeReference($I(spelling.Pool($pool))); + typed->specifier_ = $ CYTypeReference(CYTypeReferenceStruct, $I(spelling.Pool($pool))); else CYParseStructure(cursor, typed); } break; @@ -408,8 +418,9 @@ static void CYParseType(CXType type, CYTypedIdentifier *typed) { break; case CXType_IncompleteArray: - // XXX: I should support these :/ - _assert(false); + // XXX: I probably should not decay to Pointer + CYParseType(clang_getArrayElementType(type), typed); + typed = typed->Modify($ CYTypePointerTo()); break; case CXType_ObjCClass: @@ -444,7 +455,7 @@ static void CYParseType(CXType type, CYTypedIdentifier *typed) { break; case CXType_Record: - typed->specifier_ = $ CYTypeReference($I($pool.strdup(CYCXString(clang_getTypeSpelling(type))))); + typed->specifier_ = $ CYTypeReference(CYTypeReferenceStruct, $I($pool.strdup(CYCXString(clang_getTypeSpelling(type))))); break; case CXType_Typedef: @@ -480,6 +491,7 @@ static CXChildVisitResult CYChildVisit(CXCursor cursor, CXCursor parent, CXClien CYChildBaton &baton(*static_cast(arg)); CXTranslationUnit &unit(baton.unit); + CXChildVisitResult result(CXChildVisit_Continue); CYCXString spelling(cursor); std::string name(spelling); std::ostringstream value; @@ -495,6 +507,31 @@ static CXChildVisitResult CYChildVisit(CXCursor cursor, CXCursor parent, CXClien value << clang_getEnumConstantDeclValue(cursor); } break; + case CXCursor_EnumDecl: { + if (spelling[0] == '\0') + goto skip; + // XXX: this was blindly copied from StructDecl + if (!clang_isCursorDefinition(cursor)) + priority = 1; + + CYLocalPool pool; + + CYTypedIdentifier typed(NULL); + CYParseEnumeration(cursor, &typed); + + CYOptions options; + CYOutput out(*value.rdbuf(), options); + CYTypeExpression(&typed).Output(out, CYNoBFC); + + value << ".withName(\"" << name << "\")"; + name += "$cye"; + flags = CYBridgeType; + + // the enum constants are implemented separately *also* + // XXX: maybe move output logic to function we can call + result = CXChildVisit_Recurse; + } break; + case CXCursor_MacroDefinition: { CXSourceRange range(clang_getCursorExtent(cursor)); CYTokens tokens(unit, range); @@ -566,7 +603,7 @@ static CXChildVisitResult CYChildVisit(CXCursor cursor, CXCursor parent, CXClien CYTypeExpression(&typed).Output(out, CYNoBFC); value << ".withName(\"" << name << "\")"; - name += "$cy"; + name += "$cys"; flags = CYBridgeType; } break; @@ -636,9 +673,10 @@ static CXChildVisitResult CYChildVisit(CXCursor cursor, CXCursor parent, CXClien } } break; - default: { - return CXChildVisit_Recurse; - } break; + default: + result = CXChildVisit_Recurse; + goto skip; + break; } { CYKey &key(baton.keys[name]); if (key.priority_ <= priority) { @@ -652,7 +690,7 @@ static CXChildVisitResult CYChildVisit(CXCursor cursor, CXCursor parent, CXClien } skip: - return CXChildVisit_Continue; + return result; } int main(int argc, const char *argv[]) { diff --git a/Decode.cpp b/Decode.cpp index 819c675..1af478c 100644 --- a/Decode.cpp +++ b/Decode.cpp @@ -153,6 +153,16 @@ CYTypedIdentifier *Object::Decode(CYPool &pool) const { } #endif +CYTypedIdentifier *Enum::Decode(CYPool &pool) const { + CYEnumConstant *values(NULL); + for (size_t i(count); i != 0; --i) + values = $ CYEnumConstant($I(pool.strdup(constants[i - 1].name)), $D(constants[i - 1].value), values); + CYIdentifier *identifier(name == NULL ? NULL : $I(name)); + CYTypedIdentifier *typed(type.Decode(pool)); + _assert(typed->modifier_ == NULL); + return $ CYTypedIdentifier($ CYTypeEnum(identifier, typed->specifier_, values)); +} + CYTypedIdentifier *Aggregate::Decode(CYPool &pool) const { _assert(!overlap); diff --git a/Execute.cpp b/Execute.cpp index 57f3721..527d2cc 100644 --- a/Execute.cpp +++ b/Execute.cpp @@ -771,6 +771,10 @@ void Array::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *dat CYArrayCopy(pool, context, base, size, type, ffi->elements[0], value, object); } +void Enum::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const { + return type.PoolFFI(pool, context, ffi, data, value); +} + void Aggregate::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const { _assert(!overlap); @@ -860,6 +864,10 @@ JSValueRef Array::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool return CArray::Make(context, data, size, type, ffi->elements[0], context, owner); } +JSValueRef Enum::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const { + return type.FromFFI(context, ffi, data, initialize, owner); +} + JSValueRef Aggregate::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const { return Struct_privateData::Make(context, data, *this, ffi, context, owner); } @@ -1446,10 +1454,22 @@ static JSObjectRef Type_new(JSContextRef context, JSObjectRef object, size_t cou if (false) { } else if (count == 1) { - const char *encoding(CYPoolCString(pool, context, arguments[0])); - sig::Signature signature; - sig::Parse(pool, &signature, encoding, &Structor_); - return CYMakeType(context, *signature.elements[0].type); + switch (JSValueGetType(context, arguments[0])) { + case kJSTypeString: { + const char *encoding(CYPoolCString(pool, context, arguments[0])); + sig::Signature signature; + sig::Parse(pool, &signature, encoding, &Structor_); + return CYMakeType(context, *signature.elements[0].type); + } break; + + case kJSTypeObject: { + // XXX: accept a set of enum constants and /guess/ at their size + _assert(false); + } break; + + default: + throw CYJSError(context, "incorrect kind of argument to new Type"); + } } else if (count == 2) { JSObjectRef types(CYCastJSObject(context, arguments[0])); size_t count(CYArrayLength(context, types)); @@ -1543,6 +1563,37 @@ static JSValueRef Type_callAsFunction_constant(JSContextRef context, JSObjectRef return CYMakeType(context, *type); } CYCatch(NULL) } +static JSValueRef Type_callAsFunction_enumFor(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.enumFor"); + Type_privateData *internal(reinterpret_cast(JSObjectGetPrivate(_this))); + + CYPool pool; + + JSObjectRef constants(CYCastJSObject(context, arguments[0])); + + // XXX: this is, sadly, going to leak + JSPropertyNameArrayRef names(JSObjectCopyPropertyNames(context, constants)); + + size_t count(JSPropertyNameArrayGetCount(names)); + + sig::Enum type(*internal->type_, count); + type.constants = new(pool) sig::Constant[count]; + + for (size_t index(0); index != count; ++index) { + JSStringRef name(JSPropertyNameArrayGetNameAtIndex(names, index)); + JSValueRef value(CYGetProperty(context, constants, name)); + _assert(JSValueGetType(context, value) == kJSTypeNumber); + CYUTF8String string(CYPoolUTF8String(pool, context, name)); + type.constants[index].name = string.data; + type.constants[index].value = CYCastDouble(context, value); + } + + JSPropertyNameArrayRelease(names); + + return CYMakeType(context, type); +} CYCatch(NULL) } + static JSValueRef Type_callAsFunction_functionWith(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { bool variadic(count != 0 && JSValueIsNull(context, arguments[count - 1])); sig::Function type(variadic); @@ -1889,10 +1940,11 @@ static JSStaticValue Type_staticValues[4] = { {NULL, NULL, NULL, 0} }; -static JSStaticFunction Type_staticFunctions[9] = { +static JSStaticFunction Type_staticFunctions[10] = { {"arrayOf", &Type_callAsFunction_arrayOf, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"blockWith", &Type_callAsFunction_blockWith, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"constant", &Type_callAsFunction_constant, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {"enumFor", &Type_callAsFunction_enumFor, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"functionWith", &Type_callAsFunction_functionWith, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"pointerTo", &Type_callAsFunction_pointerTo, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"withName", &Type_callAsFunction_withName, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, diff --git a/Output.cpp b/Output.cpp index ae441be..1552304 100644 --- a/Output.cpp +++ b/Output.cpp @@ -728,7 +728,7 @@ void CYTypeModifier::Output(CYOutput &out, int precedence, CYIdentifier *identif } void CYTypedIdentifier::Output(CYOutput &out) const { - specifier_->Output(out); + out << *specifier_; modifier_->Output(out, 0, identifier_, true); } @@ -1067,6 +1067,35 @@ void CYTypeCharacter::Output(CYOutput &out) const { out << "char"; } +void CYTypeEnum::Output(CYOutput &out) const { + out << "enum" << ' '; + if (name_ != NULL) + out << *name_; + else { + if (specifier_ != NULL) + out << ':' << ' ' << *specifier_ << ' '; + + out << '{' << '\n'; + ++out.indent_; + bool comma(false); + + CYForEach (constant, constants_) { + if (comma) + out << ',' << '\n'; + else + comma = true; + out << '\t' << constant->name_; + out << ' ' << '=' << ' ' << constant->value_; + } + + if (out.pretty_) + out << ','; + out << '\n'; + --out.indent_; + out << '\t' << '}'; + } +} + void CYTypeError::Output(CYOutput &out) const { out << "@error"; } @@ -1102,7 +1131,13 @@ void CYTypeStruct::Output(CYOutput &out) const { } void CYTypeReference::Output(CYOutput &out) const { - out << "struct" << ' ' << *name_; + switch (kind_) { + case CYTypeReferenceStruct: out << "struct"; break; + case CYTypeReferenceEnum: out << "enum"; break; + default: _assert(false); + } + + out << ' ' << *name_; } void CYTypeVariable::Output(CYOutput &out) const { diff --git a/Parser.ypp.in b/Parser.ypp.in index 3423e0d..19e235f 100644 --- a/Parser.ypp.in +++ b/Parser.ypp.in @@ -55,6 +55,7 @@ %union { CYClassTail *classTail_; } %union { CYComprehension *comprehension_; } %union { CYElement *element_; } +%union { CYEnumConstant *constant_; } %union { CYExpression *expression_; } %union { CYFalse *false_; } %union { CYVariable *variable_; } @@ -669,9 +670,13 @@ type; }) %type YieldExpression @begin C +%type EnumConstantListOpt_ +%type EnumConstantListOpt +%type IntegerNumber %type IntegerType %type IntegerTypeOpt %type PrefixedType +%type PrimitiveReference %type PrimitiveType %type StructFieldListOpt %type SuffixedType @@ -690,6 +695,7 @@ type; }) %type TypedIdentifierField %type TypedIdentifierMaybe %type TypedIdentifierNo +%type TypedIdentifierTagged %type TypedIdentifierYes %type TypedParameterList_ %type TypedParameterList @@ -2109,6 +2115,21 @@ StructFieldListOpt | { $$ = NULL; } ; +IntegerNumber + : NumericLiteral[pass] { $$ = $pass; } + | "-" NumericLiteral[positive] { $$ = $positive; $$->value_ = -$$->value_; } + ; + +EnumConstantListOpt_ + : "," EnumConstantListOpt[pass] { $$ = $pass; } + | { $$ = NULL; } + ; + +EnumConstantListOpt + : IdentifierType[name] "=" IntegerNumber[value] EnumConstantListOpt_[next] { $$ = CYNew CYEnumConstant($name, $value, $next); } + | { $$ = NULL; } + ; + TypeSigning : { $$ = CYTypeNeutral; } | "signed" { $$ = CYTypeSigned; } @@ -2120,13 +2141,18 @@ PrimitiveType | IntegerType[pass] { $$ = $pass; } | TypeSigning[signing] "char" { $$ = CYNew CYTypeCharacter($signing); } | TypeSigning[signing] "__int128" { $$ = CYNew CYTypeInt128($signing); } - | "struct" IdentifierType[name] { $$ = CYNew CYTypeReference($name); } + ; + +PrimitiveReference + : PrimitiveType[pass] { $$ = $pass; } + | "struct" IdentifierType[name] { $$ = CYNew CYTypeReference(CYTypeReferenceStruct, $name); } + | "enum" IdentifierType[name] { $$ = CYNew CYTypeReference(CYTypeReferenceEnum, $name); } ; TypedIdentifierMaybe : TypeQualifierLeft[modifier] "void" TypeQualifierRight[typed] { $$ = $typed; $$->specifier_ = CYNew CYTypeVoid(); CYSetLast($modifier) = $$->modifier_; $$->modifier_ = $modifier; } | "void" TypeQualifierRight[typed] { $$ = $typed; $$->specifier_ = CYNew CYTypeVoid(); } - | TypeQualifierLeftOpt[modifier] PrimitiveType[specifier] TypeQualifierRightOpt[typed] { $$ = $typed; $$->specifier_ = $specifier; CYSetLast($modifier) = $$->modifier_; $$->modifier_ = $modifier; } + | TypeQualifierLeftOpt[modifier] PrimitiveReference[specifier] TypeQualifierRightOpt[typed] { $$ = $typed; $$->specifier_ = $specifier; CYSetLast($modifier) = $$->modifier_; $$->modifier_ = $modifier; } ; TypedIdentifierYes @@ -2137,14 +2163,19 @@ TypedIdentifierNo : TypedIdentifierMaybe[typed] { if ($typed->identifier_ != NULL) CYERR($typed->location_, "unexpected identifier"); $$ = $typed; } ; +TypedIdentifierTagged + : TypeQualifierLeftOpt[modifier] "struct" "{" StructFieldListOpt[fields] "}" TypeQualifierRightOpt[typed] { $$ = $typed; $$->specifier_ = CYNew CYTypeStruct(NULL, CYNew CYStructTail($fields)); CYSetLast($modifier) = $$->modifier_; $$->modifier_ = $modifier; } + | TypeQualifierLeftOpt[modifier] "enum" ":" PrimitiveType[specifier] "{" EnumConstantListOpt[constants] "}" TypeQualifierRightOpt[typed] { $$ = $typed; $$->specifier_ = CYNew CYTypeEnum(NULL, $specifier, $constants); CYSetLast($modifier) = $$->modifier_; $$->modifier_ = $modifier; } + ; + TypedIdentifierField : TypedIdentifierYes[pass] { $$ = $pass; } - | TypeQualifierLeftOpt[modifier] "struct" "{" StructFieldListOpt[fields] "}" TypeQualifierRightOpt[typed] { if ($typed->identifier_ == NULL) CYERR($typed->location_, "expected identifier"); $$ = $typed; $$->specifier_ = CYNew CYTypeStruct(NULL, CYNew CYStructTail($fields)); CYSetLast($modifier) = $$->modifier_; $$->modifier_ = $modifier; } + | TypedIdentifierTagged[typed] { if ($typed->identifier_ == NULL) CYERR($typed->location_, "expected identifier"); $$ = $typed; } ; TypedIdentifierEncoding : TypedIdentifierNo[pass] { $$ = $pass; } - | TypeQualifierLeftOpt[modifier] "struct" "{" StructFieldListOpt[fields] "}" TypeQualifierRightOpt[typed] { if ($typed->identifier_ != NULL) CYERR($typed->location_, "unexpected identifier"); $$ = $typed; $$->specifier_ = CYNew CYTypeStruct(NULL, CYNew CYStructTail($fields)); CYSetLast($modifier) = $$->modifier_; $$->modifier_ = $modifier; } + | TypedIdentifierTagged[typed] { if ($typed->identifier_ != NULL) CYERR($typed->location_, "unexpected identifier"); $$ = $typed; } | "void" TypeSignifierNone[typed] { $$ = $typed; $$->specifier_ = CYNew CYTypeVoid(); } ; @@ -2408,7 +2439,7 @@ Statement__ ; PrimaryExpression - : "(" LexOf "struct" NewLineOpt IdentifierType[name] TypeQualifierRightOpt[typed] ")" { $typed->specifier_ = CYNew CYTypeReference($name); $$ = CYNew CYTypeExpression($typed); } + : "(" LexOf "struct" NewLineOpt IdentifierType[name] TypeQualifierRightOpt[typed] ")" { $typed->specifier_ = CYNew CYTypeReference(CYTypeReferenceStruct, $name); $$ = CYNew CYTypeExpression($typed); } ; /* }}} */ /* Cycript (C): Type Definitions {{{ */ diff --git a/Replace.cpp b/Replace.cpp index 29a78a0..65d8236 100644 --- a/Replace.cpp +++ b/Replace.cpp @@ -1236,6 +1236,18 @@ CYStatement *CYTypeDefinition::Replace(CYContext &context) { return $ CYLexical(false, $B1($B(identifier, $ CYTypeExpression(typed_)))); } +CYTarget *CYTypeEnum::Replace(CYContext &context) { + CYList properties; + CYForEach (constant, constants_) + properties->*$ CYPropertyValue($S(constant->name_->Word()), constant->value_); + CYObject *constants($ CYObject(properties)); + + if (specifier_ == NULL) + return $N1($V("Type"), constants); + else + return $C1($M(specifier_->Replace(context), $S("enumFor")), constants); +} + CYTarget *CYTypeError::Replace(CYContext &context) { _assert(false); return NULL; @@ -1276,7 +1288,14 @@ CYTarget *CYTypePointerTo::Replace_(CYContext &context, CYTarget *type) { } CYTarget *CYTypeReference::Replace(CYContext &context) { - return $V($pool.strcat(name_->Word(), "$cy", NULL)); + const char *suffix; + switch (kind_) { + case CYTypeReferenceStruct: suffix = "$cys"; break; + case CYTypeReferenceEnum: suffix = "$cye"; break; + default: _assert(false); + } + + return $V($pool.strcat(name_->Word(), suffix, NULL)); } CYTarget *CYTypeStruct::Replace(CYContext &context) { diff --git a/Syntax.hpp b/Syntax.hpp index f16b877..5b74e43 100644 --- a/Syntax.hpp +++ b/Syntax.hpp @@ -2140,12 +2140,19 @@ struct CYTypeVoid : virtual void Output(CYOutput &out) const; }; +enum CYTypeReferenceKind { + CYTypeReferenceStruct, + CYTypeReferenceEnum, +}; + struct CYTypeReference : CYTypeSpecifier { + CYTypeReferenceKind kind_; CYIdentifier *name_; - CYTypeReference(CYIdentifier *name) : + CYTypeReference(CYTypeReferenceKind kind, CYIdentifier *name) : + kind_(kind), name_(name) { } @@ -2585,6 +2592,38 @@ struct CYStructDefinition : virtual void Output(CYOutput &out, CYFlags flags) const; }; +struct CYEnumConstant : + CYNext +{ + CYIdentifier *name_; + CYNumber *value_; + + CYEnumConstant(CYIdentifier *name, CYNumber *value, CYEnumConstant *next = NULL) : + CYNext(next), + name_(name), + value_(value) + { + } +}; + +struct CYTypeEnum : + CYTypeSpecifier +{ + CYIdentifier *name_; + CYTypeSpecifier *specifier_; + CYEnumConstant *constants_; + + CYTypeEnum(CYIdentifier *name, CYTypeSpecifier *specifier, CYEnumConstant *constants) : + name_(name), + specifier_(specifier), + constants_(constants) + { + } + + virtual CYTarget *Replace(CYContext &context); + virtual void Output(CYOutput &out) const; +}; + namespace cy { namespace Syntax { diff --git a/sig/copy.cpp b/sig/copy.cpp index 63b72fe..8896ea8 100644 --- a/sig/copy.cpp +++ b/sig/copy.cpp @@ -85,6 +85,20 @@ Object *Object::Copy(CYPool &pool, const char *rename) const { } #endif +Enum *Enum::Copy(CYPool &pool, const char *rename) const { + if (rename == NULL) + rename = pool.strdup(name); + else if (rename[0] == '\0') + rename = NULL; + Enum *copy(new(pool) Enum(*type.Copy(pool), count, rename)); + copy->constants = new(pool) Constant[count]; + for (size_t i(0); i != count; ++i) { + copy->constants[i].name = pool.strdup(constants[i].name); + copy->constants[i].value = constants[i].value; + } + return copy; +} + Aggregate *Aggregate::Copy(CYPool &pool, const char *rename) const { if (rename == NULL) rename = pool.strdup(name); @@ -136,6 +150,10 @@ const char *Type::GetName() const { return NULL; } +const char *Enum::GetName() const { + return name; +} + const char *Aggregate::GetName() const { return name; } diff --git a/sig/ffi_type.cpp b/sig/ffi_type.cpp index ab97f7a..2b6c0d3 100644 --- a/sig/ffi_type.cpp +++ b/sig/ffi_type.cpp @@ -171,6 +171,10 @@ ffi_type *Object::GetFFI(CYPool &pool) const { } #endif +ffi_type *Enum::GetFFI(CYPool &pool) const { + return type.GetFFI(pool); +} + ffi_type *Aggregate::GetFFI(CYPool &pool) const { // XXX: we can totally make overlap work _assert(!overlap); diff --git a/sig/parse.cpp b/sig/parse.cpp index 52a974d..b2931ef 100644 --- a/sig/parse.cpp +++ b/sig/parse.cpp @@ -381,6 +381,10 @@ const char *Object::Encode(CYPool &pool) const { } #endif +const char *Enum::Encode(CYPool &pool) const { + return type.Encode(pool); +} + const char *Aggregate::Encode(CYPool &pool) const { return pool.strcat(overlap ? "(" : "{", name == NULL ? "?" : name, "=", Unparse(pool, &signature), overlap ? ")" : "}", NULL); } diff --git a/sig/types.hpp b/sig/types.hpp index ea0a307..2f536ac 100644 --- a/sig/types.hpp +++ b/sig/types.hpp @@ -246,6 +246,39 @@ struct Object : }; #endif +struct Constant { + const char *name; + double value; +}; + +struct Enum : + Type +{ + Type &type; + unsigned count; + const char *name; + + Constant *constants; + + Enum(Type &type, unsigned count, const char *name = NULL) : + type(type), + count(count), + name(name), + constants(NULL) + { + } + + Enum *Copy(CYPool &pool, const char *rename = NULL) const override; + const char *GetName() const override; + + const char *Encode(CYPool &pool) const override; + CYTypedIdentifier *Decode(CYPool &pool) const override; + + ffi_type *GetFFI(CYPool &pool) const override; + void PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const override; + JSValueRef FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const override; +}; + struct Aggregate : Type { -- 2.45.2