X-Git-Url: https://git.saurik.com/cycript.git/blobdiff_plain/38c824bf51b0dbdb70b40f9235fe47bd1f39133e..436a877be73ebe14fecd3ef0e9b7dd6b854d2e3b:/Analyze.cpp diff --git a/Analyze.cpp b/Analyze.cpp index 36ec86d..4f84e03 100644 --- a/Analyze.cpp +++ b/Analyze.cpp @@ -1,5 +1,5 @@ -/* Cycript - Optimizing JavaScript Compiler/Runtime - * Copyright (C) 2009-2015 Jay Freeman (saurik) +/* Cycript - The Truly Universal Scripting Language + * Copyright (C) 2009-2016 Jay Freeman (saurik) */ /* GNU Affero General Public License, Version 3 {{{ */ @@ -126,7 +126,14 @@ std::ostream &operator <<(std::ostream &out, const CYCXPosition CYKeyMap; +struct CYKey { + unsigned priority_ = 0; + + std::string code_; + unsigned flags_; +}; + +typedef std::map CYKeyMap; struct CYChildBaton { CXTranslationUnit unit; @@ -288,6 +295,8 @@ static CXChildVisitResult CYChildVisit(CXCursor cursor, CXCursor parent, CXClien CYCXString spelling(cursor); std::string name(spelling); std::ostringstream value; + unsigned priority(2); + unsigned flags(0); /*CXSourceLocation location(clang_getCursorLocation(cursor)); CYCXPosition<> position(location); @@ -306,19 +315,50 @@ static CXChildVisitResult CYChildVisit(CXCursor cursor, CXCursor parent, CXClien CXCursor cursors[tokens.size()]; clang_annotateTokens(unit, tokens, tokens.size(), cursors); - CYCXPosition<> start(clang_getRangeStart(range)); - CYCXString first(unit, tokens[1]); - if (first == "(") { - CYCXPosition<> paren(unit, tokens[1]); - if (start.offset_ + strlen(spelling) == paren.offset_) - _assert(false); // XXX: support parameterized macros + CYLocalPool local; + CYList parameters; + unsigned offset(1); + + if (tokens.size() != 1) { + CYCXPosition<> start(clang_getRangeStart(range)); + CYCXString first(unit, tokens[offset]); + if (first == "(") { + CYCXPosition<> paren(unit, tokens[offset]); + if (start.offset_ + strlen(spelling) == paren.offset_) { + for (;;) { + _assert(++offset != tokens.size()); + CYCXString token(unit, tokens[offset]); + parameters->*$P($B($I(token.Pool($pool)))); + _assert(++offset != tokens.size()); + CYCXString comma(unit, tokens[offset]); + if (comma == ")") + break; + _assert(comma == ","); + } + ++offset; + } + } } - for (unsigned i(1); i != tokens.size(); ++i) { + std::ostringstream body; + for (unsigned i(offset); i != tokens.size(); ++i) { CYCXString token(unit, tokens[i]); - if (i != 1) - value << " "; - value << token; + if (i != offset) + body << " "; + body << token; + } + + if (!parameters) + value << body.str(); + else { + CYOptions options; + CYOutput out(*value.rdbuf(), options); + out << '(' << "function" << '('; + out << parameters; + out << ')' << '{'; + out << "return" << ' '; + value << body.str(); + out << ';' << '}' << ')'; } } catch (const CYException &error) { CYPool pool; @@ -327,10 +367,10 @@ static CXChildVisitResult CYChildVisit(CXCursor cursor, CXCursor parent, CXClien } break; case CXCursor_StructDecl: { - if (!clang_isCursorDefinition(cursor)) - goto skip; if (spelling[0] == '\0') goto skip; + if (!clang_isCursorDefinition(cursor)) + priority = 1; std::ostringstream types; std::ostringstream names; @@ -343,8 +383,8 @@ static CXChildVisitResult CYChildVisit(CXCursor cursor, CXCursor parent, CXClien } })); + value << "new Type([" << types.str() << "],[" << names.str() << "]).withName(\"" << name << "\")"; name += "$cy"; - value << "new Type([" << types.str() << "],[" << names.str() << "])"; } break; case CXCursor_TypedefDecl: { @@ -414,7 +454,14 @@ static CXChildVisitResult CYChildVisit(CXCursor cursor, CXCursor parent, CXClien } break; } - baton.keys[name] = value.str(); + { + CYKey &key(baton.keys[name]); + if (key.priority_ < priority) { + key.priority_ = priority; + key.code_ = value.str(); + key.flags_ = flags; + } + } skip: return CXChildVisit_Continue; @@ -443,11 +490,11 @@ int main(int argc, const char *argv[]) { clang_visitChildren(clang_getTranslationUnitCursor(unit), &CYChildVisit, &baton); for (CYKeyMap::const_iterator key(keys.begin()); key != keys.end(); ++key) { - std::string value(key->second); - for (size_t i(0), e(value.size()); i != e; ++i) - if (value[i] <= 0 || value[i] >= 0x7f || value[i] == '\n') + std::string code(key->second.code_); + for (size_t i(0), e(code.size()); i != e; ++i) + if (code[i] <= 0 || code[i] >= 0x7f || code[i] == '\n') goto skip; - std::cout << key->first << "|\"" << value << "\"" << std::endl; + std::cout << key->first << "|" << key->second.flags_ << "\"" << code << "\"" << std::endl; skip:; } clang_disposeTranslationUnit(unit);