]> git.saurik.com Git - cycript.git/commitdiff
Avoid clang_tokenize and just get the source file.
authorJay Freeman (saurik) <saurik@saurik.com>
Wed, 23 Dec 2015 13:27:14 +0000 (05:27 -0800)
committerJay Freeman (saurik) <saurik@saurik.com>
Wed, 23 Dec 2015 13:27:14 +0000 (05:27 -0800)
Analyze.cpp
Execute.cpp
Syntax.cpp
Syntax.hpp

index 332903d2b7f64e80ca26ec8b103d4946d779ff9d..4f7db5d5c44c22baca4028389adf899ed1e8e21f 100644 (file)
@@ -19,6 +19,7 @@
 **/
 /* }}} */
 
+#include <cmath>
 #include <cstring>
 #include <iostream>
 #include <map>
@@ -68,6 +69,11 @@ struct CYCXString {
     {
     }
 
+    CYCXString(CXFile file) :
+        value_(clang_getFileName(file))
+    {
+    }
+
     CYCXString(CXTranslationUnit unit, CXToken token) :
         value_(clang_getTokenSpelling(unit, token))
     {
@@ -86,6 +92,29 @@ struct CYCXString {
     }
 };
 
+template <void (&clang_get_Location)(CXSourceLocation, CXFile *, unsigned *, unsigned *, unsigned *) = clang_getSpellingLocation>
+struct CYCXPosition {
+    CXFile file_;
+    unsigned line_;
+    unsigned column_;
+    unsigned offset_;
+
+    CYCXPosition(CXSourceLocation location) {
+        clang_get_Location(location, &file_, &line_, &column_, &offset_);
+    }
+
+    CXSourceLocation Get(CXTranslationUnit unit) const {
+        return clang_getLocation(unit, file_, line_, column_);
+    }
+};
+
+template <void (&clang_get_Location)(CXSourceLocation, CXFile *, unsigned *, unsigned *, unsigned *)>
+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_;
+}
+
 typedef std::map<std::string, std::string> CYKeyMap;
 
 struct CYChildBaton {
@@ -100,23 +129,27 @@ struct CYChildBaton {
 };
 
 struct CYTokens {
-    CXTranslationUnit unit;
-    CXToken *tokens;
-    unsigned count;
+    CXTranslationUnit unit_;
+    CXToken *tokens_;
+    unsigned count_;
+
+    CYTokens(CXTranslationUnit unit, CXSourceRange range) :
+        unit_(unit)
+    {
+        clang_tokenize(unit_, range, &tokens_, &count_);
+    }
 
     CYTokens(CXTranslationUnit unit, CXCursor cursor) :
-        unit(unit)
+        CYTokens(unit, clang_getCursorExtent(cursor))
     {
-        CXSourceRange range(clang_getCursorExtent(cursor));
-        clang_tokenize(unit, range, &tokens, &count);
     }
 
     ~CYTokens() {
-        clang_disposeTokens(unit, tokens, count);
+        clang_disposeTokens(unit_, tokens_, count_);
     }
 
     operator CXToken *() const {
-        return tokens;
+        return tokens_;
     }
 };
 
@@ -140,10 +173,29 @@ static CYExpression *CYTranslateExpression(CXTranslationUnit unit, CXCursor curs
         } break;
 
         case CXCursor_IntegerLiteral: {
-            CYTokens tokens(unit, cursor);
-            _assert(tokens.count != 0);
-            // XXX: I don't understand why this is often enormous :/
-            return $ CYNumber(CYCastDouble(CYCXString(unit, tokens[0])));
+            // libclang doesn't provide any reasonable way to do this
+            // note: clang_tokenize doesn't work if this is a macro
+            // the token range starts inside the macro but ends after it
+            // the tokenizer freaks out and either fails with 0 tokens
+            // or returns some massive number of tokens ending here :/
+
+            CXSourceRange range(clang_getCursorExtent(cursor));
+            CYCXPosition<> start(clang_getRangeStart(range));
+            CYCXPosition<> end(clang_getRangeEnd(range));
+            CYCXString file(start.file_);
+            _assert(file == CYCXString(end.file_));
+
+            CYPool pool;
+            size_t size;
+            char *data(static_cast<char *>(CYPoolFile(pool, file, &size)));
+            _assert(start.offset_ <= size && end.offset_ <= size && start.offset_ <= end.offset_);
+
+            const char *token($pool.strndup(data + start.offset_, end.offset_ - start.offset_));
+            double value(CYCastDouble(token));
+            if (!std::isnan(value))
+                return $ CYNumber(value);
+
+            return $V(token);
         } break;
 
         case CXCursor_CStyleCastExpr:
@@ -201,17 +253,8 @@ static CXChildVisitResult CYChildVisit(CXCursor cursor, CXCursor parent, CXClien
     std::ostringstream value;
 
     /*CXSourceLocation location(clang_getCursorLocation(cursor));
-
-    CXFile file;
-    unsigned line;
-    unsigned column;
-    unsigned offset;
-    clang_getSpellingLocation(location, &file, &line, &column, &offset);
-
-    if (file != NULL) {
-        CYCXString path(clang_getFileName(file));
-        std::cout << spelling << " " << path << ":" << line << std::endl;
-    }*/
+    CYCXPosition<> position(location);
+    std::cout << spelling << " " << position << std::endl;*/
 
     switch (CXCursorKind kind = clang_getCursorKind(cursor)) {
         case CXCursor_EnumConstantDecl: {
@@ -220,13 +263,13 @@ static CXChildVisitResult CYChildVisit(CXCursor cursor, CXCursor parent, CXClien
 
         case CXCursor_MacroDefinition: {
             CYTokens tokens(unit, cursor);
-            if (tokens.count <= 2)
+            if (tokens.count_ <= 2)
                 goto skip;
 
-            CXCursor cursors[tokens.count];
-            clang_annotateTokens(unit, tokens, tokens.count, cursors);
+            CXCursor cursors[tokens.count_];
+            clang_annotateTokens(unit, tokens, tokens.count_, cursors);
 
-            for (unsigned i(1); i != tokens.count - 1; ++i) {
+            for (unsigned i(1); i != tokens.count_ - 1; ++i) {
                 CYCXString token(unit, tokens[i]);
                 if (i != 1)
                     value << " ";
@@ -292,7 +335,7 @@ static CXChildVisitResult CYChildVisit(CXCursor cursor, CXCursor parent, CXClien
                         break;
 
                     default:
-                        std::cerr << "A:" << CYCXString(child) << std::endl;
+                        //std::cerr << "A:" << CYCXString(child) << std::endl;
                         break;
                 }
             }));
index af61f1a226d3e41db969ba3f73384c216fd0f3cc..e8684c5e7b1683d87adee94604322e5d3edc7bbe 100644 (file)
@@ -1979,53 +1979,6 @@ JSGlobalContextRef CYGetJSContext(JSContextRef context) {
     return reinterpret_cast<Context *>(JSObjectGetPrivate(CYCastJSObject(context, CYGetProperty(context, CYGetGlobalObject(context), cy_s))))->context_;
 }
 
-struct CYFile {
-    void *data_;
-    size_t size_;
-
-    CYFile(void *data, size_t size) :
-        data_(data),
-        size_(size)
-    {
-    }
-};
-
-static void CYFileExit(void *data) {
-    CYFile *file(reinterpret_cast<CYFile *>(data));
-    _syscall(munmap(file->data_, file->size_));
-}
-
-static void *CYPoolFile(CYPool &pool, const char *path, size_t *psize) {
-    int fd(_syscall_(open(path, O_RDONLY), 1, ENOENT));
-    if (fd == -1)
-        return NULL;
-
-    struct stat stat;
-    _syscall(fstat(fd, &stat));
-    size_t size(stat.st_size);
-
-    *psize = size;
-
-    void *base;
-    if (size == 0)
-        base = pool.strndup("", 0);
-    else {
-        _syscall(base = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0));
-
-        CYFile *file(new (pool) CYFile(base, size));
-        pool.atexit(&CYFileExit, file);
-    }
-
-    _syscall(close(fd));
-    return base;
-}
-
-static CYUTF8String CYPoolFileUTF8String(CYPool &pool, const char *path) {
-    CYUTF8String data;
-    data.data = reinterpret_cast<char *>(CYPoolFile(pool, path, &data.size));
-    return data;
-}
-
 static const char *CYPoolLibraryPath(CYPool &pool) {
     Dl_info addr;
     _assert(dladdr(reinterpret_cast<void *>(&CYPoolLibraryPath), &addr) != 0);
index 9fa307440de014ace9fc228efb4380bb8575b459..0b6c742ba07c30d40799a29d324b0b94f8dfbb91 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "Syntax.hpp"
 
+// XXX: this implementation will break if value[size] is a digit
 double CYCastDouble(const char *value, size_t size) {
     char *end;
     double number(strtod(value, &end));
@@ -36,9 +37,71 @@ double CYCastDouble(const char *value) {
     return CYCastDouble(value, strlen(value));
 }
 
+double CYCastDouble(CYUTF8String value) {
+    return CYCastDouble(value.data, value.size);
+}
+
 template <>
 ::pthread_key_t CYLocal<CYPool>::key_ = Key_();
 
 CYRange DigitRange_    (0x3ff000000000000LLU, 0x000000000000000LLU); // 0-9
 CYRange WordStartRange_(0x000001000000000LLU, 0x7fffffe87fffffeLLU); // A-Za-z_$
 CYRange WordEndRange_  (0x3ff001000000000LLU, 0x7fffffe87fffffeLLU); // A-Za-z_$0-9
+
+
+
+// XXX: this really should not be here ... :/
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "String.hpp"
+
+struct CYFile {
+    void *data_;
+    size_t size_;
+
+    CYFile(void *data, size_t size) :
+        data_(data),
+        size_(size)
+    {
+    }
+};
+
+static void CYFileExit(void *data) {
+    CYFile *file(reinterpret_cast<CYFile *>(data));
+    _syscall(munmap(file->data_, file->size_));
+}
+
+void *CYPoolFile(CYPool &pool, const char *path, size_t *psize) {
+    int fd(_syscall_(open(path, O_RDONLY), 1, ENOENT));
+    if (fd == -1)
+        return NULL;
+
+    struct stat stat;
+    _syscall(fstat(fd, &stat));
+    size_t size(stat.st_size);
+
+    *psize = size;
+
+    void *base;
+    if (size == 0)
+        base = pool.strndup("", 0);
+    else {
+        _syscall(base = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0));
+
+        CYFile *file(new (pool) CYFile(base, size));
+        pool.atexit(&CYFileExit, file);
+    }
+
+    _syscall(close(fd));
+    return base;
+}
+
+CYUTF8String CYPoolFileUTF8String(CYPool &pool, const char *path) {
+    CYUTF8String data;
+    data.data = reinterpret_cast<char *>(CYPoolFile(pool, path, &data.size));
+    return data;
+}
index ae0a68b72db3b02961b626c1c87f2c3d626465ae..a82ded1d271a3de5b8ab96a60859be7195e00441 100644 (file)
 
 double CYCastDouble(const char *value, size_t size);
 double CYCastDouble(const char *value);
+double CYCastDouble(CYUTF8String value);
 
 void CYNumerify(std::ostringstream &str, double value);
 void CYStringify(std::ostringstream &str, const char *data, size_t size, bool c = false);
 
+// XXX: this really should not be here ... :/
+void *CYPoolFile(CYPool &pool, const char *path, size_t *psize);
+CYUTF8String CYPoolFileUTF8String(CYPool &pool, const char *path);
+
 struct CYContext;
 
 struct CYThing {