From c5587ed74e6cf565bf30da661579e80d78f96e80 Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Fri, 31 Oct 2014 02:50:48 -0700 Subject: [PATCH] Support extern "C" syntax to FFI via C prototypes. --- Cycript.l.in | 1 + Cycript.yy.in | 11 ++++++++++- Output.cpp | 4 ++++ Parser.hpp | 16 ++++++++++++++++ Replace.cpp | 4 ++++ 5 files changed, 35 insertions(+), 1 deletion(-) diff --git a/Cycript.l.in b/Cycript.l.in index 7ee7d60..ab5d0b3 100644 --- a/Cycript.l.in +++ b/Cycript.l.in @@ -272,6 +272,7 @@ XMLName {XMLNameStart}{XMLNamePart}* "typedef" L C I(identifier, Identifier("typedef"), tk::Typedef, hi::Meta); "unsigned" L C I(identifier, Identifier("unsigned"), tk::Unsigned, hi::Type); "signed" L C I(identifier, Identifier("signed"), tk::Signed, hi::Type); +"extern" L C I(identifier, Identifier("extern"), tk::Extern, hi::Type); @end @begin C diff --git a/Cycript.yy.in b/Cycript.yy.in index 3ad89f8..b2f5629 100644 --- a/Cycript.yy.in +++ b/Cycript.yy.in @@ -245,6 +245,7 @@ int cylex(YYSTYPE *, cy::location *, void *); %token Typedef "typedef" %token Unsigned "unsigned" %token Signed "signed" +%token Extern "extern" @end @begin C @@ -718,6 +719,7 @@ Identifier | "typedef" { $$ = $1; } | "unsigned" { $$ = $1; } | "signed" { $$ = $1; } + | "extern" { $$ = $1; } @end @begin ObjectiveC | "YES" { $$ = $1; } @@ -1434,6 +1436,7 @@ SuffixedType : ArrayedType { $$ = $1; } | "(" LexPushInOff "^" TypeQualifierRight ")" LexPopIn "(" LexPushInOff TypedParameterListOpt ")" LexPopIn { $$ = $4; $$->modifier_ = CYNew CYTypeBlockWith($9, $$->modifier_); } | TypeParenthetical FunctionedType { $$ = $1; CYSetLast($2) = $$->modifier_; $$->modifier_ = $2; } + | IdentifierType FunctionedType { $$ = CYNew CYTypedIdentifier($1); CYSetLast($2) = $$->modifier_; $$->modifier_ = $2; } | FunctionedType { $$ = CYNew CYTypedIdentifier(); CYSetLast($1) = $$->modifier_; $$->modifier_ = $1; } ; @@ -1730,9 +1733,15 @@ PrimaryExpression /* }}} */ /* Cycript (C): Type Definitions {{{ */ Statement__ - : "typedef" TypedIdentifier Terminator { $$ = CYNew CYTypeDefinition($2); } + : "typedef" TypedIdentifier { if ($2->identifier_ == NULL) YYABORT; } Terminator { $$ = CYNew CYTypeDefinition($2); } ; /* }}} */ +/* Cycript (C): extern "C" {{{ */ +Statement__ + : "extern" StringLiteral { if (strcmp($2->Value(), "C") != 0) YYABORT; } TypedIdentifier Terminator { $$ = CYNew CYExternal($2, $4); } + ; +/* }}} */ + @end /* YUI: Documentation Comments {{{ */ diff --git a/Output.cpp b/Output.cpp index 4c4376a..467825c 100644 --- a/Output.cpp +++ b/Output.cpp @@ -329,6 +329,10 @@ void CYExpression::Output(CYOutput &out, int precedence, CYFlags flags) const { Output(out, flags); } +void CYExternal::Output(CYOutput &out, CYFlags flags) const { + out << "extern" << abi_ << typed_ << ';'; +} + void CYFatArrow::Output(CYOutput &out, CYFlags flags) const { out << '(' << parameters_ << ')' << ' ' << "=>" << ' ' << code_; } diff --git a/Parser.hpp b/Parser.hpp index 697fbea..63270a1 100644 --- a/Parser.hpp +++ b/Parser.hpp @@ -1881,6 +1881,22 @@ struct CYImport : virtual void Output(CYOutput &out, CYFlags flags) const; }; +struct CYExternal : + CYStatement +{ + CYString *abi_; + CYTypedIdentifier *typed_; + + CYExternal(CYString *abi, CYTypedIdentifier *typed) : + abi_(abi), + typed_(typed) + { + } + + virtual CYStatement *Replace(CYContext &context); + virtual void Output(CYOutput &out, CYFlags flags) const; +}; + struct CYTypeDefinition : CYStatement { diff --git a/Replace.cpp b/Replace.cpp index b3d1c82..f6d904c 100644 --- a/Replace.cpp +++ b/Replace.cpp @@ -327,6 +327,10 @@ CYAssignment *CYExpression::Assignment(CYContext &context) { return NULL; } +CYStatement *CYExternal::Replace(CYContext &context) { + return $E($ CYAssign($V(typed_->identifier_), $C1(typed_->Replace(context), $C2($V("dlsym"), $V("RTLD_DEFAULT"), $S(typed_->identifier_->Word()))))); +} + CYNumber *CYFalse::Number(CYContext &context) { return $D(0); } -- 2.47.2