]>
Commit | Line | Data |
---|---|---|
8d20f0f1 JF |
1 | #include <cstring> |
2 | #include <iostream> | |
3 | #include <map> | |
4 | #include <sstream> | |
5 | #include <string> | |
6 | ||
7 | #include <clang-c/Index.h> | |
8 | ||
9 | struct CYCXString { | |
10 | CXString value_; | |
11 | ||
12 | CYCXString(CXString value) : | |
13 | value_(value) | |
14 | { | |
15 | } | |
16 | ||
17 | ~CYCXString() { | |
18 | clang_disposeString(value_); | |
19 | } | |
20 | ||
21 | operator const char *() const { | |
22 | return clang_getCString(value_); | |
23 | } | |
24 | }; | |
25 | ||
26 | struct CYFieldBaton { | |
27 | std::ostringstream types; | |
28 | std::ostringstream names; | |
29 | }; | |
30 | ||
31 | static CXChildVisitResult CYFieldVisit(CXCursor cursor, CXCursor parent, CXClientData arg) { | |
32 | CYFieldBaton &baton(*static_cast<CYFieldBaton *>(arg)); | |
33 | ||
34 | if (clang_getCursorKind(cursor) == CXCursor_FieldDecl) { | |
35 | CXType type(clang_getCursorType(cursor)); | |
36 | baton.types << "(typedef " << CYCXString(clang_getTypeSpelling(type)) << "),"; | |
37 | baton.names << "'" << CYCXString(clang_getCursorSpelling(cursor)) << "',"; | |
38 | } | |
39 | ||
40 | return CXChildVisit_Continue; | |
41 | } | |
42 | ||
43 | typedef std::map<std::string, std::string> CYKeyMap; | |
44 | ||
45 | struct CYChildBaton { | |
46 | CXTranslationUnit unit; | |
47 | CYKeyMap &keys; | |
48 | ||
49 | CYChildBaton(CXTranslationUnit unit, CYKeyMap &keys) : | |
50 | unit(unit), | |
51 | keys(keys) | |
52 | { | |
53 | } | |
54 | }; | |
55 | ||
56 | struct CYTokens { | |
57 | CXTranslationUnit unit; | |
58 | CXToken *tokens; | |
59 | unsigned count; | |
60 | ||
61 | CYTokens(CXTranslationUnit unit, CXCursor cursor) : | |
62 | unit(unit) | |
63 | { | |
64 | CXSourceRange range(clang_getCursorExtent(cursor)); | |
65 | clang_tokenize(unit, range, &tokens, &count); | |
66 | } | |
67 | ||
68 | ~CYTokens() { | |
69 | clang_disposeTokens(unit, tokens, count); | |
70 | } | |
71 | ||
72 | operator CXToken *() const { | |
73 | return tokens; | |
74 | } | |
75 | }; | |
76 | ||
77 | static CXChildVisitResult CYChildVisit(CXCursor cursor, CXCursor parent, CXClientData arg) { | |
78 | CYChildBaton &baton(*static_cast<CYChildBaton *>(arg)); | |
79 | CXTranslationUnit &unit(baton.unit); | |
80 | ||
81 | CYCXString spelling(clang_getCursorSpelling(cursor)); | |
82 | std::string name(spelling); | |
83 | std::ostringstream value; | |
84 | ||
85 | /*CXSourceLocation location(clang_getCursorLocation(cursor)); | |
86 | ||
87 | CXFile file; | |
88 | unsigned line; | |
89 | unsigned column; | |
90 | unsigned offset; | |
91 | clang_getSpellingLocation(location, &file, &line, &column, &offset); | |
92 | ||
93 | if (file != NULL) { | |
94 | CYCXString path(clang_getFileName(file)); | |
95 | std::cout << spelling << " " << path << ":" << line << std::endl; | |
96 | }*/ | |
97 | ||
98 | switch (clang_getCursorKind(cursor)) { | |
99 | case CXCursor_EnumConstantDecl: { | |
100 | value << clang_getEnumConstantDeclValue(cursor); | |
101 | } break; | |
102 | ||
103 | case CXCursor_MacroDefinition: { | |
104 | CYTokens tokens(unit, cursor); | |
105 | if (tokens.count <= 2) | |
106 | goto skip; | |
107 | ||
108 | CXCursor cursors[tokens.count]; | |
109 | clang_annotateTokens(unit, tokens, tokens.count, cursors); | |
110 | ||
111 | for (unsigned i(1); i != tokens.count - 1; ++i) { | |
112 | CYCXString token(clang_getTokenSpelling(unit, tokens[i])); | |
113 | if (i != 1) | |
114 | value << " "; | |
115 | else if (strcmp(token, "(") == 0) | |
116 | goto skip; | |
117 | value << token; | |
118 | } | |
119 | } break; | |
120 | ||
121 | case CXCursor_StructDecl: { | |
122 | if (!clang_isCursorDefinition(cursor)) | |
123 | goto skip; | |
124 | if (spelling[0] == '\0') | |
125 | goto skip; | |
126 | ||
127 | CYFieldBaton baton; | |
128 | ||
129 | baton.types << "["; | |
130 | baton.names << "["; | |
131 | clang_visitChildren(cursor, &CYFieldVisit, &baton); | |
132 | baton.types << "]"; | |
133 | baton.names << "]"; | |
134 | ||
135 | name += "$cy"; | |
136 | value << "new Type(" << baton.types.str() << "," << baton.names.str() << ")"; | |
137 | } break; | |
138 | ||
139 | case CXCursor_TypedefDecl: { | |
140 | CXType type(clang_getTypedefDeclUnderlyingType(cursor)); | |
141 | value << "(typedef " << CYCXString(clang_getTypeSpelling(type)) << ")"; | |
142 | } break; | |
143 | ||
144 | case CXCursor_FunctionDecl: | |
145 | case CXCursor_VarDecl: { | |
146 | CXType type(clang_getCursorType(cursor)); | |
147 | value << "*(typedef " << CYCXString(clang_getTypeSpelling(type)) << ").pointerTo()(dlsym(RTLD_DEFAULT,'" << spelling << "'))"; | |
148 | } break; | |
149 | ||
150 | default: { | |
151 | return CXChildVisit_Recurse; | |
152 | } break; | |
153 | } | |
154 | ||
155 | baton.keys[name] = value.str(); | |
156 | ||
157 | skip: | |
158 | return CXChildVisit_Continue; | |
159 | } | |
160 | ||
161 | int main(int argc, const char *argv[]) { | |
162 | CXIndex index(clang_createIndex(0, 0)); | |
163 | ||
164 | const char *file(argv[1]); | |
165 | ||
166 | unsigned offset(3); | |
167 | #if CY_OBJECTIVEC | |
168 | argv[--offset] = "-ObjC++"; | |
169 | #endif | |
170 | ||
171 | CXTranslationUnit unit(clang_parseTranslationUnit(index, file, argv + offset, argc - offset, NULL, 0, CXTranslationUnit_DetailedPreprocessingRecord | CXTranslationUnit_SkipFunctionBodies)); | |
172 | ||
173 | for (unsigned i(0), e(clang_getNumDiagnostics(unit)); i != e; ++i) { | |
174 | CXDiagnostic diagnostic(clang_getDiagnostic(unit, i)); | |
175 | CYCXString spelling(clang_getDiagnosticSpelling(diagnostic)); | |
176 | std::cerr << spelling << std::endl; | |
177 | } | |
178 | ||
179 | CYKeyMap keys; | |
180 | CYChildBaton baton(unit, keys); | |
181 | clang_visitChildren(clang_getTranslationUnitCursor(unit), &CYChildVisit, &baton); | |
182 | ||
183 | for (CYKeyMap::const_iterator key(keys.begin()); key != keys.end(); ++key) { | |
184 | std::string value(key->second); | |
185 | for (size_t i(0), e(value.size()); i != e; ++i) | |
186 | if (value[i] <= 0 || value[i] >= 0x7f || value[i] == '\n') | |
187 | goto skip; | |
188 | std::cout << key->first << "|\"" << value << "\"" << std::endl; | |
189 | skip:; } | |
190 | ||
191 | clang_disposeTranslationUnit(unit); | |
192 | clang_disposeIndex(index); | |
193 | ||
194 | return 0; | |
195 | } |