ljclang_support.c (3497B)
1 /* Support library for LJClang, for cases the LuaJIT FFI doesn't handle. 2 * (Mostly C callbacks with pass-by-value compound arguments/results.) */ 3 4 #include <stdlib.h> 5 #include <string.h> 6 7 #include <clang-c/Index.h> 8 9 10 /* Our cursor visitor takes the CXCursor objects by pointer. */ 11 typedef enum CXChildVisitResult (*LJCX_CursorVisitor)( 12 CXCursor *cursor, CXCursor *parent, CXClientData client_data); 13 14 /* Compile with cursor kinds bitmap? This was originally intended as 15 * 'optimization' (because C callback are said to be slow in LuaJIT), but maybe 16 * it was premature optimization... they're still pretty fast. */ 17 /*#define USE_KINDS_BITAR*/ 18 19 #define UNUSED(var) (void)(var); 20 21 /* NOTE: Make sure that the 'last' CXCursor kind LAST_KIND is the numerically 22 * greatest. */ 23 #define LAST_KIND CXCursor_LastExtraDecl 24 #define NUM_KINDS (LAST_KIND+1) 25 #define KINDS_BITAR_SIZE ((NUM_KINDS+7)>>3) 26 27 typedef struct { 28 LJCX_CursorVisitor visitor; 29 #ifdef USE_KINDS_BITAR 30 unsigned char kinds[KINDS_BITAR_SIZE]; 31 #endif 32 } LJCX_CursorVisitorData; 33 34 static LJCX_CursorVisitorData *g_cursorVisitors; 35 static unsigned g_numVisitors; 36 37 38 /* Registers a LJClang_CursorVisitor callback <visitor> and returns an index by 39 * which it can be subsequently referenced. 40 * 41 * <kinds>: An array containing CXCursorKind values. If <kinds> contains a 42 * particular cursor kind, <visitor> is invoked on such a cursor. 43 * NOTE: Only effective if compiled with #define USE_KINDS_BITAR. 44 * 45 * <numkinds>: The number of elements in <kinds>. In the special case of being 46 * 0, all cursor kinds are considered to be visited and <kinds> is not 47 * accessed. 48 * 49 * Returns: 50 * >=0: the visitor function index on success. 51 * -1: failed realloc(). 52 * -2: <kinds> contains an invalid CXCursorKind 53 */ 54 int ljclang_regCursorVisitor(LJCX_CursorVisitor visitor, enum CXCursorKind *kinds, int numkinds) 55 { 56 #ifdef USE_KINDS_BITAR 57 int i; 58 #endif 59 const int szCVD = (int)sizeof(LJCX_CursorVisitorData); 60 LJCX_CursorVisitorData cvd; 61 62 memset(&cvd, 0, szCVD); 63 cvd.visitor = visitor; 64 65 #ifdef USE_KINDS_BITAR 66 if (numkinds == 0) 67 memset(cvd.kinds, 255, sizeof(cvd.kinds)); 68 69 for (i=0; i<numkinds; i++) 70 { 71 if ((unsigned)numkinds >= NUM_KINDS) 72 return -2; 73 74 cvd.kinds[i>>3] |= 1<<(i&7); 75 } 76 #else 77 UNUSED(kinds); 78 UNUSED(numkinds); 79 #endif 80 81 { 82 /* Finally, reallocate g_cursorVisitors. */ 83 void *newVisitors = realloc(g_cursorVisitors, (g_numVisitors+1)*szCVD); 84 85 if (newVisitors == NULL) 86 return -1; 87 88 g_cursorVisitors = (LJCX_CursorVisitorData *)newVisitors; 89 memcpy(&g_cursorVisitors[g_numVisitors], &cvd, szCVD); 90 91 return g_numVisitors++; 92 } 93 } 94 95 static enum CXChildVisitResult 96 ourCursorVisitor(CXCursor cursor, CXCursor parent, CXClientData client_data) 97 { 98 LJCX_CursorVisitorData *cvd = (LJCX_CursorVisitorData *)client_data; 99 100 int k = cursor.kind; 101 102 if ((unsigned)k >= NUM_KINDS) 103 return CXChildVisit_Continue; 104 #ifdef USE_KINDS_BITAR 105 if (cvd->kinds[k>>3] & (1<<(k&7))) 106 #endif 107 return cvd->visitor(&cursor, &parent, NULL); 108 109 return CXChildVisit_Continue; 110 } 111 112 int ljclang_visitChildren(CXCursor parent, int visitoridx) 113 { 114 unsigned wasbroken; 115 116 if ((unsigned)visitoridx >= g_numVisitors) 117 return -1; 118 119 wasbroken = clang_visitChildren(parent, ourCursorVisitor, 120 (CXClientData)&g_cursorVisitors[visitoridx]); 121 return (wasbroken ? 1 : 0); 122 }