Skip to content

Instantly share code, notes, and snippets.

@patricksuo
Created December 15, 2015 13:54
Show Gist options
  • Save patricksuo/6f44b523390993ef8d43 to your computer and use it in GitHub Desktop.
Save patricksuo/6f44b523390993ef8d43 to your computer and use it in GitHub Desktop.
poorman_tag
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <dirent.h>
#include <clang-c/Index.h>
#define ERR(msg) fprintf(stderr, "[%s] [%s] at %s line %d\n", msg, strerror(errno), __FILE__, __LINE__)
//#define DEBUG(msg) fprintf(stderr, "[DEBUG] file %s line %d : %s", __FILE__, __LINE__, msg)
#define DEBUG(msg) (void) (msg)
#define UNUSED(var) (void) (var)
typedef int (*dir_walker) (const char *d_name, char *f_name, unsigned char f_type, int deep);
int walk_one_file(const char *d_name, char *f_name, unsigned char f_type, int deep);
int walk(const char *d_name, int max_deep, dir_walker fn);
int is_source_file(const char *str);
void parse_source_file(const char *filename);
void process_cursor(CXTranslationUnit tu, CXCursor cu);
enum CXChildVisitResult cursor_visitor(CXCursor cursor, CXCursor parent, CXClientData client_data) ;
static CXIndex g_cx_index;
int main(int argc, char **argv) {
if (argc != 2) {
printf("take one param `DIR`");
return 0;
}
g_cx_index = clang_createIndex(1, 0);
walk(argv[1], 10, walk_one_file);
clang_disposeIndex(g_cx_index);
return 0;
}
int walk(const char *d_name, int max_deep, dir_walker fn) {
if (max_deep == 0) return 0;
struct dirent *entry = NULL;
DIR *dirp = NULL;
dirp = opendir(d_name);
if (!dirp) {
ERR("opendir");
exit(1);
}
while(1) {
entry = readdir(dirp);
if (!entry) {
break;
}
if (!fn(d_name, entry->d_name, entry->d_type, max_deep)) {
break;
}
}
if (closedir(dirp)) {
ERR("closedir");
}
return 0;
}
int walk_one_file(const char *d_name, char *f_name, unsigned char f_type, int deep) {
char path[256];
snprintf(path, 1024, "%s/%s", d_name, f_name);
int next_deep = deep > 0 ? deep-1 : -1;
switch (f_type) {
case DT_DIR:
if (strcmp(".", f_name)==0) {
DEBUG("ingore cwd\n");
break;
}
if (strcmp("..", f_name)==0) {
DEBUG("ingore parent dir\n");
break;
}
//printf("[DEBUG] enter dir %s\n", path);
walk(path, next_deep, walk_one_file);
break;
case DT_REG:
//printf("[DEBUG] reg %s\n", path);
if (is_source_file(path)) {
parse_source_file(path);
}
break;
}
return 1;
}
int is_source_file(const char *str) {
char *dot = strrchr(str, '.');
if (NULL == dot) return 0;
if (strcmp(dot, ".c") == 0) return 1;
if (strcmp(dot, ".cc") == 0) return 1;
if (strcmp(dot, ".h") == 0) return 1;
if (strcmp(dot, ".cpp") == 0) return 1;
return 0;
}
void parse_source_file(const char *filename) {
CXTranslationUnit tu = clang_createTranslationUnitFromSourceFile(g_cx_index, filename,0, NULL, 0, NULL);
if (!tu) {
ERR(filename);
exit(1);
}
CXCursor cu = clang_getTranslationUnitCursor(tu);
process_cursor(tu, cu);
clang_disposeTranslationUnit(tu);
}
void process_cursor(CXTranslationUnit tu, CXCursor cu) {
if (clang_Cursor_isNull(cu)) {
return;
}
enum CXCursorKind kind;
kind = clang_getCursorKind(cu);
switch (kind) {
//case CXCursor_UnexposedDecl:
//case CXCursor_DeclRefExpr:
//case CXCursor_StructDecl:
//case CXCursor_UnionDecl:
//case CXCursor_EnumDecl:
//case CXCursor_VarDecl:
//case CXCursor_TypedefDecl:
case CXCursor_FunctionDecl:
{
CXCursor cu2 = clang_getCursorDefinition(cu);
if (clang_Cursor_isNull(cu2)) {
break;
}
CXString cx_name;
cx_name = clang_getCursorDisplayName(cu2);
printf("%s|", clang_getCString(cx_name));
clang_disposeString(cx_name);
CXSourceLocation location = clang_getNullLocation();
unsigned int line, column;
CXString filename;
CXFile file = NULL;
location = clang_getCursorLocation(cu2);
clang_getSpellingLocation(location, &file, &line, &column, NULL);
filename = clang_getFileName(file);
printf("%s %d %d \n", clang_getCString(filename), line, column);
clang_disposeString(filename);
}
}
clang_visitChildren(cu, cursor_visitor, (CXClientData)(tu));
}
enum CXChildVisitResult cursor_visitor(CXCursor cursor, CXCursor parent, CXClientData client_data) {
process_cursor(((CXTranslationUnit)client_data), cursor);
return 1;
}
@patricksuo
Copy link
Author

尝试做一个穷人版的函数索引,不过 libclang 在解析 linux-4.0.9/drivers/firmware/efi/efi-pstore.c 时会 crash 。暂未深入调试。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment