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>
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_);
}
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;
+struct CYKey {
+ unsigned priority_ = 0;
+
+ std::string code_;
+ unsigned flags_;
+};
+
+typedef std::map<std::string, CYKey> CYKeyMap;
struct CYChildBaton {
CXTranslationUnit unit;
};
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) :
operator CXToken *() const {
return tokens_;
}
+
+ size_t size() const {
+ return valid_;
+ }
};
+static CYUTF8String CYCXPoolUTF8Range(CYPool &pool, CXSourceRange range) {
+ CYCXPosition<> start(clang_getRangeStart(range));
+ CYCXPosition<> end(clang_getRangeEnd(range));
+ CYCXString file(start.file_);
+ _assert(file == CYCXString(end.file_));
+
+ CYPool temp;
+ size_t size;
+ char *data(static_cast<char *>(CYPoolFile(temp, file, &size)));
+ _assert(start.offset_ <= size && end.offset_ <= size && start.offset_ <= end.offset_);
+
+ CYUTF8String code;
+ code.size = end.offset_ - start.offset_;
+ code.data = pool.strndup(data + start.offset_, code.size);
+ return code;
+}
+
static CYExpression *CYTranslateExpression(CXTranslationUnit unit, CXCursor cursor) {
switch (CXCursorKind kind = clang_getCursorKind(cursor)) {
case CXCursor_CallExpr: {
// 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_));
+ CYUTF8String token(CYCXPoolUTF8Range($pool, clang_getCursorExtent(cursor)));
double value(CYCastDouble(token));
- if (!std::isnan(value))
- return $ CYNumber(value);
-
- return $V(token);
+ if (std::isnan(value))
+ return $V(token.data);
+ return $ CYNumber(value);
} break;
case CXCursor_CStyleCastExpr:
CYCXString spelling(cursor);
std::string name(spelling);
std::ostringstream value;
+ unsigned priority(2);
+ unsigned flags(0);
/*CXSourceLocation location(clang_getCursorLocation(cursor));
CYCXPosition<> position(location);
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.size()];
+ clang_annotateTokens(unit, tokens, tokens.size(), cursors);
- CXCursor cursors[tokens.count_];
- clang_annotateTokens(unit, tokens, tokens.count_, cursors);
+ CYLocalPool local;
+ CYList<CYFunctionParameter> 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.count_ - 1; ++i) {
+ std::ostringstream body;
+ for (unsigned i(offset); i != tokens.size(); ++i) {
CYCXString token(unit, tokens[i]);
- if (i != 1)
- value << " ";
- else if (strcmp(token, "(") == 0)
- goto skip;
- 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;
+ //std::cerr << error.PoolCString(pool) << std::endl;
+ goto skip;
} 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;
} 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;
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);