]> git.saurik.com Git - cycript.git/commitdiff
Work around libclang to find parameterized macros.
authorJay Freeman (saurik) <saurik@saurik.com>
Wed, 23 Dec 2015 15:54:37 +0000 (07:54 -0800)
committerJay Freeman (saurik) <saurik@saurik.com>
Wed, 23 Dec 2015 15:54:37 +0000 (07:54 -0800)
Analyze.cpp
libcycript.cy
libcycript.sh

index 4f7db5d5c44c22baca4028389adf899ed1e8e21f..dd0c26ae0cb919fbbdd479c3af0171c95c2a527f 100644 (file)
@@ -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 <void (&clang_get_Location)(CXSourceLocation, CXFile *, unsigned *, unsigned *, unsigned *) = clang_getSpellingLocation>
@@ -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 <void (&clang_get_Location)(CXSourceLocation, CXFile *, unsigned *, uns
 std::ostream &operator <<(std::ostream &out, const CYCXPosition<clang_get_Location> &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<std::string, std::string> 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: {
index 3f699c8a7226d15e24197dd616731096afb3cb72..20a101710b7cfff1b12eb1a4a66085396f386205 100644 (file)
@@ -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()})`;
index 1ff3ace531add21dbe2bfceeee4ba8000da2c5c1..d5aa9c8601b3acd5271b9f98d41c5f0471a4cb13 100755 (executable)
@@ -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