From: Jay Freeman (saurik) Date: Wed, 23 Dec 2015 15:54:37 +0000 (-0800) Subject: Work around libclang to find parameterized macros. X-Git-Tag: v0.9.590~146 X-Git-Url: https://git.saurik.com/cycript.git/commitdiff_plain/7752205a17e5ea74ed609e029169a633c25d7621?ds=sidebyside Work around libclang to find parameterized macros. --- diff --git a/Analyze.cpp b/Analyze.cpp index 4f7db5d..dd0c26a 100644 --- a/Analyze.cpp +++ b/Analyze.cpp @@ -90,6 +90,11 @@ struct CYCXString { const char *Pool(CYPool &pool) const { return pool.strdup(*this); } + + bool operator ==(const char *rhs) const { + const char *lhs(*this); + return lhs == rhs || strcmp(lhs, rhs) == 0; + } }; template @@ -103,6 +108,11 @@ struct CYCXPosition { clang_get_Location(location, &file_, &line_, &column_, &offset_); } + CYCXPosition(CXTranslationUnit unit, CXToken token) : + CYCXPosition(clang_getTokenLocation(unit, token)) + { + } + CXSourceLocation Get(CXTranslationUnit unit) const { return clang_getLocation(unit, file_, line_, column_); } @@ -112,7 +122,8 @@ template &position) { if (position.file_ != NULL) out << "[" << CYCXString(position.file_) << "]:"; - out << position.line_ << ":" << position.column_; + out << position.line_ << ":" << position.column_ << "@" << position.offset_; + return out; } typedef std::map CYKeyMap; @@ -129,14 +140,31 @@ struct CYChildBaton { }; struct CYTokens { + private: CXTranslationUnit unit_; CXToken *tokens_; unsigned count_; + unsigned valid_; + public: CYTokens(CXTranslationUnit unit, CXSourceRange range) : unit_(unit) { clang_tokenize(unit_, range, &tokens_, &count_); + + + // libclang's tokenizer is horribly broken and returns "extra" tokens. + // this code goes back through the tokens and filters for good ones :/ + + CYCXPosition<> end(clang_getRangeEnd(range)); + CYCXString file(end.file_); + + for (valid_ = 0; valid_ != count_; ++valid_) { + CYCXPosition<> position(unit, tokens_[valid_]); + _assert(CYCXString(position.file_) == file); + if (position.offset_ >= end.offset_) + break; + } } CYTokens(CXTranslationUnit unit, CXCursor cursor) : @@ -151,6 +179,10 @@ struct CYTokens { operator CXToken *() const { return tokens_; } + + size_t size() const { + return valid_; + } }; static CYExpression *CYTranslateExpression(CXTranslationUnit unit, CXCursor cursor) { @@ -261,22 +293,32 @@ static CXChildVisitResult CYChildVisit(CXCursor cursor, CXCursor parent, CXClien value << clang_getEnumConstantDeclValue(cursor); } break; - case CXCursor_MacroDefinition: { - CYTokens tokens(unit, cursor); - if (tokens.count_ <= 2) - goto skip; + case CXCursor_MacroDefinition: try { + CXSourceRange range(clang_getCursorExtent(cursor)); + CYTokens tokens(unit, range); + _assert(tokens.size() != 0); - CXCursor cursors[tokens.count_]; - clang_annotateTokens(unit, tokens, tokens.count_, cursors); + 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 + } - for (unsigned i(1); i != tokens.count_ - 1; ++i) { + for (unsigned i(1); i != tokens.size(); ++i) { CYCXString token(unit, tokens[i]); if (i != 1) value << " "; - else if (strcmp(token, "(") == 0) - goto skip; value << token; } + } catch (const CYException &error) { + CYPool pool; + //std::cerr << error.PoolCString(pool) << std::endl; + goto skip; } break; case CXCursor_StructDecl: { diff --git a/libcycript.cy b/libcycript.cy index 3f699c8..20a1017 100644 --- a/libcycript.cy +++ b/libcycript.cy @@ -35,10 +35,6 @@ let $cy_set = function(object, properties) { }); }; -const X_OK = (1<<0); -const W_OK = (1<<1); -const R_OK = (1<<2); - $cy_set(Date.prototype, { toCYON: function() { return `new ${this.constructor.name}(${this.toUTCString().toCYON()})`; diff --git a/libcycript.sh b/libcycript.sh index 1ff3ace..d5aa9c8 100755 --- a/libcycript.sh +++ b/libcycript.sh @@ -29,5 +29,5 @@ echo "create table cache (name text not null, system int not null, value text no def=$3 if [[ -n "${def}" ]]; then - { echo "begin;"; cat "$def"; echo "commit;"; } | sed -e 's/^\([^|]*\)|\"\(.*\)\"$/insert into cache (name, system, value) values (<<\1>>, '"$sys"', <<\2>>);/;s/'"'"'/'"'"''"'"'/g;s/\(<<\|>>\)/'"'"'/g' | sqlite3 "${sql}" + { echo "begin;"; cat "$def"; echo "commit;"; } | sed -e 's/^\([^|]*\)|\"\(.*\)\"$/insert into cache (name, system, value) values (<@<\1>@>, '"$sys"', <@<\2>@>);/;s/'"'"'/'"'"''"'"'/g;s/\(<@<\|>@>\)/'"'"'/g' | sqlite3 "${sql}" fi