From: Jay Freeman (saurik) Date: Wed, 23 Dec 2015 13:27:14 +0000 (-0800) Subject: Avoid clang_tokenize and just get the source file. X-Git-Tag: v0.9.590~150 X-Git-Url: https://git.saurik.com/cycript.git/commitdiff_plain/3935b9e5dc2b437a11a4b61a9fb5793af2d4beef?ds=inline Avoid clang_tokenize and just get the source file. --- diff --git a/Analyze.cpp b/Analyze.cpp index 332903d..4f7db5d 100644 --- a/Analyze.cpp +++ b/Analyze.cpp @@ -19,6 +19,7 @@ **/ /* }}} */ +#include #include #include #include @@ -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 +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 +std::ostream &operator <<(std::ostream &out, const CYCXPosition &position) { + if (position.file_ != NULL) + out << "[" << CYCXString(position.file_) << "]:"; + out << position.line_ << ":" << position.column_; +} + typedef std::map 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(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; } })); diff --git a/Execute.cpp b/Execute.cpp index af61f1a..e8684c5 100644 --- a/Execute.cpp +++ b/Execute.cpp @@ -1979,53 +1979,6 @@ JSGlobalContextRef CYGetJSContext(JSContextRef context) { return reinterpret_cast(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(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(CYPoolFile(pool, path, &data.size)); - return data; -} - static const char *CYPoolLibraryPath(CYPool &pool) { Dl_info addr; _assert(dladdr(reinterpret_cast(&CYPoolLibraryPath), &addr) != 0); diff --git a/Syntax.cpp b/Syntax.cpp index 9fa3074..0b6c742 100644 --- a/Syntax.cpp +++ b/Syntax.cpp @@ -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::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 +#include +#include +#include + +#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(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(CYPoolFile(pool, path, &data.size)); + return data; +} diff --git a/Syntax.hpp b/Syntax.hpp index ae0a68b..a82ded1 100644 --- a/Syntax.hpp +++ b/Syntax.hpp @@ -37,10 +37,15 @@ 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 {