]> git.saurik.com Git - cycript.git/commitdiff
Analyze even more headers and added enum typedefs.
authorJay Freeman (saurik) <saurik@saurik.com>
Mon, 4 Jan 2016 02:56:49 +0000 (18:56 -0800)
committerJay Freeman (saurik) <saurik@saurik.com>
Mon, 4 Jan 2016 02:56:49 +0000 (18:56 -0800)
12 files changed:
Analysis.cpp
Analyze.cpp
Decode.cpp
Execute.cpp
Output.cpp
Parser.ypp.in
Replace.cpp
Syntax.hpp
sig/copy.cpp
sig/ffi_type.cpp
sig/parse.cpp
sig/types.hpp

index 4429d22fd09645383488a4862f8ed2648a3686d6..520de5404c3b9d3649ef566eca6ecd72866ad1b5 100644 (file)
 #include <CoreLocation/CoreLocation.h>
 #include <Security/Security.h>
 
+#include <mach/mach.h>
+#include <mach/mach_vm.h>
+#include <mach/vm_map.h>
+
+#include <mach-o/dyld.h>
+#include <mach-o/dyld_images.h>
+
 #if TARGET_OS_IPHONE
 #include <UIKit/UIKit.h>
+extern "C" UIApplication *UIApp;
 #else
 #include <AppKit/AppKit.h>
 #endif
index 49ff5cb5d5c53a04fac2de44e387023544ac80d4..0f46cb43cd1e1ec5309e1c192e0ea996c4f42ba9 100644 (file)
@@ -298,6 +298,18 @@ static CYTypedIdentifier *CYDecodeType(CXType type, const CYCXString &identifier
     return typed;
 }
 
+static void CYParseEnumeration(CXCursor cursor, CYTypedIdentifier *typed) {
+    CYList<CYEnumConstant> 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<CYTypeStructField> 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<CYChildBaton *>(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[]) {
index 819c675b29d07c4febf0fb5cc04d147da7aac4c0..1af478c189a32c2bec57fbf07a59a925d1f515ad 100644 (file)
@@ -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);
 
index 57f3721580e7de2179b3c7118624e019b01ffb5b..527d2cc39786974828502ca34055ff4964327551 100644 (file)
@@ -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<Type_privateData *>(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},
index ae441be9b51f5d9e867f3bc187a9219802fdb145..155230481932471c7f99e0fde65cd84e6d68c516 100644 (file)
@@ -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 {
index 3423e0d4819167a1db7890c6eec19d007a22d15d..19e235fca3fb5b539357c59052b8d6301a7e94b2 100644 (file)
@@ -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 <expression_> YieldExpression
 
 @begin C
+%type <constant_> EnumConstantListOpt_
+%type <constant_> EnumConstantListOpt
+%type <number_> IntegerNumber
 %type <integral_> IntegerType
 %type <integral_> IntegerTypeOpt
 %type <typedIdentifier_> PrefixedType
+%type <specifier_> PrimitiveReference
 %type <specifier_> PrimitiveType
 %type <structField_> StructFieldListOpt
 %type <typedIdentifier_> SuffixedType
@@ -690,6 +695,7 @@ type; })
 %type <typedIdentifier_> TypedIdentifierField
 %type <typedIdentifier_> TypedIdentifierMaybe
 %type <typedIdentifier_> TypedIdentifierNo
+%type <typedIdentifier_> TypedIdentifierTagged
 %type <typedIdentifier_> TypedIdentifierYes
 %type <typedFormal_> TypedParameterList_
 %type <typedFormal_> 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 {{{ */
index 29a78a04c21b5c18c96d932d0bcdb0a07102dcd6..65d8236459baebc6b08340752f01f2c87cba03e2 100644 (file)
@@ -1236,6 +1236,18 @@ CYStatement *CYTypeDefinition::Replace(CYContext &context) {
     return $ CYLexical(false, $B1($B(identifier, $ CYTypeExpression(typed_))));
 }
 
+CYTarget *CYTypeEnum::Replace(CYContext &context) {
+    CYList<CYProperty> 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) {
index f16b877f5e8262edc92eefd50c041a1fe1f71427..5b74e4321f798dad40d6fee1e84d05353867b230 100644 (file)
@@ -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<CYEnumConstant>
+{
+    CYIdentifier *name_;
+    CYNumber *value_;
+
+    CYEnumConstant(CYIdentifier *name, CYNumber *value, CYEnumConstant *next = NULL) :
+        CYNext<CYEnumConstant>(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 {
 
index 63b72fe25ed4e7dfd8bb2d60be881906e73cd7d1..8896ea84ffe471b18ba5a13d8757f42f666b66fd 100644 (file)
@@ -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;
 }
index ab97f7a1b489f82ae8944e9d382ba311fcac91a4..2b6c0d3de61c4d24e701c39fa1dc139716c0096d 100644 (file)
@@ -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);
index 52a974d90d17ce6266e22d63f505cb5fd73f4db1..b2931ef3723d6dcfed3db48e0c2cae76f1696801 100644 (file)
@@ -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);
 }
index ea0a307ade3d2b32b6dc63d624b86e6e50118be3..2f536ac53a910bd6935763d505c9de1ecf1551b5 100644 (file)
@@ -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
 {