You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123 lines
3.4 KiB
C

/* Support library for LJClang, for cases the LuaJIT FFI doesn't handle.
* (Mostly C callbacks with pass-by-value compound arguments/results.) */
#include <stdlib.h>
#include <string.h>
#include <clang-c/Index.h>
/* Our cursor visitor takes the CXCursor objects by pointer. */
typedef enum CXChildVisitResult (*LJCX_CursorVisitor)(
CXCursor *cursor, CXCursor *parent, CXClientData client_data);
/* Compile with cursor kinds bitmap? This was originally intended as
* 'optimization' (because C callback are said to be slow in LuaJIT), but maybe
* it was premature optimization... they're still pretty fast. */
/*#define USE_KINDS_BITAR*/
#define UNUSED(var) (void)(var);
/* NOTE: Make sure that the 'last' CXCursor kind LAST_KIND is the numerically
* greatest. */
#define LAST_KIND CXCursor_LastExtraDecl
#define NUM_KINDS (LAST_KIND+1)
#define KINDS_BITAR_SIZE ((NUM_KINDS+7)>>3)
typedef struct {
LJCX_CursorVisitor visitor;
#ifdef USE_KINDS_BITAR
unsigned char kinds[KINDS_BITAR_SIZE];
#endif
} LJCX_CursorVisitorData;
static LJCX_CursorVisitorData *g_cursorVisitors;
static unsigned g_numVisitors;
/* Registers a LJClang_CursorVisitor callback <visitor> and returns an index by
* which it can be subsequently referenced.
*
* <kinds>: An array containing CXCursorKind values. If <kinds> contains a
* particular cursor kind, <visitor> is invoked on such a cursor.
* NOTE: Only effective if compiled with #define USE_KINDS_BITAR.
*
* <numkinds>: The number of elements in <kinds>. In the special case of being
* 0, all cursor kinds are considered to be visited and <kinds> is not
* accessed.
*
* Returns:
* >=0: the visitor function index on success.
* -1: failed realloc().
* -2: <kinds> contains an invalid CXCursorKind
*/
int ljclang_regCursorVisitor(LJCX_CursorVisitor visitor, enum CXCursorKind *kinds, int numkinds)
{
#ifdef USE_KINDS_BITAR
int i;
#endif
const int szCVD = (int)sizeof(LJCX_CursorVisitorData);
LJCX_CursorVisitorData cvd;
memset(&cvd, 0, szCVD);
cvd.visitor = visitor;
#ifdef USE_KINDS_BITAR
if (numkinds == 0)
memset(cvd.kinds, 255, sizeof(cvd.kinds));
for (i=0; i<numkinds; i++)
{
if ((unsigned)numkinds >= NUM_KINDS)
return -2;
cvd.kinds[i>>3] |= 1<<(i&7);
}
#else
UNUSED(kinds);
UNUSED(numkinds);
#endif
{
/* Finally, reallocate g_cursorVisitors. */
void *newVisitors = realloc(g_cursorVisitors, (g_numVisitors+1)*szCVD);
if (newVisitors == NULL)
return -1;
g_cursorVisitors = (LJCX_CursorVisitorData *)newVisitors;
memcpy(&g_cursorVisitors[g_numVisitors], &cvd, szCVD);
return g_numVisitors++;
}
}
static enum CXChildVisitResult
ourCursorVisitor(CXCursor cursor, CXCursor parent, CXClientData client_data)
{
LJCX_CursorVisitorData *cvd = (LJCX_CursorVisitorData *)client_data;
int k = cursor.kind;
if ((unsigned)k >= NUM_KINDS)
return CXChildVisit_Continue;
#ifdef USE_KINDS_BITAR
if (cvd->kinds[k>>3] & (1<<(k&7)))
#endif
return cvd->visitor(&cursor, &parent, NULL);
return CXChildVisit_Continue;
}
int ljclang_visitChildren(CXCursor parent, int visitoridx)
{
unsigned wasbroken;
if ((unsigned)visitoridx >= g_numVisitors)
return -1;
wasbroken = clang_visitChildren(parent, ourCursorVisitor,
(CXClientData)&g_cursorVisitors[visitoridx]);
return (wasbroken ? 1 : 0);
}