ljclang

FORK: A LuaJIT-based interface to libclang
git clone https://git.neptards.moe/neptards/ljclang.git
Log | Files | Refs

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 }