src/FFI/libclang/wrapper.c
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "wrapper.h"
#include <clang-c/Index.h>
#include <stdio.h>
#include <stdlib.h>
// utility.
#define aloc(T) ((T *)malloc(sizeof(T)))
CXCursor *ptrToCXCursor(CXCursor t)
{
CXCursor *c = aloc(CXCursor);
*c = t;
return c;
}
CXString *ptrToCXString(CXString t)
{
CXString *c = aloc(CXString);
*c = t;
return c;
}
CXType *ptrToCXType(CXType t)
{
CXType *c = aloc(CXType);
*c = t;
return c;
}
CXSourceLocation *ptrToCXSourceLocation(CXSourceLocation t)
{
CXSourceLocation *c = aloc(CXSourceLocation);
*c = t;
return c;
}
CXSourceRange *ptrToCXSourceRange(CXSourceRange t)
{
CXSourceRange *c = aloc(CXSourceRange);
*c = t;
return c;
}
// START ===== Functions for testing libclang behavior in C.
enum CXChildVisitResult visitor_for_test_in_c(CXCursor cursor, CXCursor parent, CXClientData clientData)
{
printf("Cursor- kind: %s, name: %s\n", clang_getCString(clang_getCursorKindSpelling(clang_getCursorKind(cursor))), clang_getCString(clang_getCursorSpelling(cursor)));
return CXChildVisit_Continue;
}
int test_in_c()
{
printf("==========================run==========================\n");
CXIndex Index = clang_createIndex(0, 0);
CXTranslationUnit TU = clang_parseTranslationUnit(Index,
"./test.h", 0, 0, NULL, 0, CXTranslationUnit_None);
if (TU == NULL)
{
printf("Error creating TU\n");
return 0;
}
CXCursor root = clang_getTranslationUnitCursor(TU);
unsigned a = clang_visitChildren(root, visitor_for_test_in_c, NULL);
clang_disposeTranslationUnit(TU);
clang_disposeIndex(Index);
printf("\n==========================end==========================\n");
return 0;
}
// END ===== Functions for testing libclang behavior in C ============================
// START ===== WRAPPER FUNCTIONS =====================
const char *clang_getCString_wrap(CXString *string)
{
const char *a = clang_getCString(*string);
return a;
}
void clang_disposeString_wrap(CXString *string)
{
clang_disposeString(*string);
free(string);
}
enum CXCursorKind clang_getCursorKind_wrap(CXCursor *cursor)
{
return clang_getCursorKind(*cursor);
}
CXString *clang_getCursorKindSpelling_wrap(enum CXCursorKind kind)
{
return ptrToCXString(clang_getCursorKindSpelling(kind));
}
CXType *clang_getCursorType_wrap(CXCursor *cursor)
{
return ptrToCXType(clang_getCursorType(*cursor));
}
CXString *clang_getTypeSpelling_wrap(CXType *type)
{
return ptrToCXString(clang_getTypeSpelling(*type));
}
CXString *clang_getTypeKindSpelling_wrap(enum CXTypeKind typeKind)
{
return ptrToCXString(clang_getTypeKindSpelling(typeKind));
}
CXType *clang_getResultType_wrap(CXType *functionType)
{
return ptrToCXType(clang_getResultType(*functionType));
}
CXType *clang_getPointeeType_wrap(CXType *pointerType)
{
return ptrToCXType(clang_getPointeeType(*pointerType));
}
CXType *clang_getCanonicalType_wrap(CXType *typerefType)
{
return ptrToCXType(clang_getCanonicalType(*typerefType));
}
CXType *clang_Type_getNamedType_wrap(CXType *elaboratedType)
{
return ptrToCXType(clang_Type_getNamedType(*elaboratedType));
}
CXCursor *clang_getTypeDeclaration_wrap(CXType *cxtype)
{
return ptrToCXCursor(clang_getTypeDeclaration(*cxtype));
}
CXType *clang_getTypedefDeclUnderlyingType_wrap(CXCursor *cxcursor)
{
return ptrToCXType(clang_getTypedefDeclUnderlyingType(*cxcursor));
}
/** The name of parameter, struct, typedef. */
CXString *clang_getCursorSpelling_wrap(CXCursor *cursor)
{
return ptrToCXString(clang_getCursorSpelling(*cursor));
}
CXCursor *clang_getTranslationUnitCursor_wrap(CXTranslationUnit tu)
{
return ptrToCXCursor(clang_getTranslationUnitCursor(tu));
}
CXString *clang_formatDiagnostic_wrap(CXDiagnostic diag, int opts)
{
return ptrToCXString(clang_formatDiagnostic(diag, opts));
}
// Alternative typedef for [CXCursorVisitor] using pointer for passing cursor and parent
// instead of passing by value
typedef enum CXChildVisitResult (*ModifiedCXCursorVisitor)(CXCursor *cursor,
CXCursor *parent,
CXClientData client_data);
struct _stackForVisitChildren
{
ModifiedCXCursorVisitor modifiedVisitor;
struct _stackForVisitChildren *link;
} * _visitorTemp;
// Holds list of Isolate-Processor pairs, each having their own stack
// to hold the visitorFunctions.
struct _listForIsolateProcessPair
{
long long uid;
struct _listForIsolateProcessPair *next;
struct _stackForVisitChildren *_visitorTop;
} ipHead, *ipTemp;
// `ipHead` is used only as head marker and will not contain any information.
// Finds/Creates an Isolate-Processor pair from/in the linkedlist.
struct _listForIsolateProcessPair *_findIP(long long uid)
{
struct _listForIsolateProcessPair *temp = ipHead.next;
while (temp != NULL)
{
if (temp->uid == uid)
{
return temp;
}
temp = temp->next;
}
// If we reach here this means no IP pair was found and we should create one
// and add it to the head of our list.
temp = aloc(struct _listForIsolateProcessPair);
temp->next = ipHead.next;
temp->uid = uid;
temp->_visitorTop = NULL;
ipHead.next = temp;
return temp;
}
void _push(ModifiedCXCursorVisitor modifiedVisitor, long long uid)
{
struct _listForIsolateProcessPair *current = _findIP(uid);
if (current->_visitorTop == NULL)
{
current->_visitorTop = aloc(struct _stackForVisitChildren);
current->_visitorTop->link = NULL;
current->_visitorTop->modifiedVisitor = modifiedVisitor;
}
else
{
_visitorTemp = aloc(struct _stackForVisitChildren);
_visitorTemp->link = current->_visitorTop;
_visitorTemp->modifiedVisitor = modifiedVisitor;
current->_visitorTop = _visitorTemp;
}
}
void _pop(long long uid)
{
struct _listForIsolateProcessPair *current = _findIP(uid);
_visitorTemp = current->_visitorTop;
if (_visitorTemp == NULL)
{
printf("\n Error, Wrapper.C : Trying to pop from empty stack");
return;
}
else
_visitorTemp = current->_visitorTop->link;
free(current->_visitorTop);
current->_visitorTop = _visitorTemp;
}
ModifiedCXCursorVisitor _top(long long uid)
{
return _findIP(uid)->_visitorTop->modifiedVisitor;
}
// Do not write binding for this function.
// used by [clang_visitChildren_wrap].
enum CXChildVisitResult
_visitorwrap(CXCursor cursor, CXCursor parent, CXClientData clientData)
{
// Use clientData (which is a unique ID) to get reference to the stack which
// this particular process-isolate pair uses.
long long uid = *((long long *)clientData);
enum CXChildVisitResult e = (_top(uid)(ptrToCXCursor(cursor), ptrToCXCursor(parent), clientData));
return e;
}
/** Visitor is a function pointer with parameters having pointers to cxcursor
* instead of cxcursor by default. */
unsigned clang_visitChildren_wrap(CXCursor *parent, ModifiedCXCursorVisitor _modifiedVisitor, long long uid)
{
long long *clientData = aloc(long long);
*clientData = uid;
_push(_modifiedVisitor, uid);
unsigned a = clang_visitChildren(*parent, _visitorwrap, clientData);
_pop(uid);
return a;
}
int clang_Cursor_getNumArguments_wrap(CXCursor *cursor)
{
return clang_Cursor_getNumArguments(*cursor);
}
CXCursor *clang_Cursor_getArgument_wrap(CXCursor *cursor, unsigned index)
{
return ptrToCXCursor(clang_Cursor_getArgument(*cursor, index));
}
int clang_getNumArgTypes_wrap(CXType *cxtype)
{
return clang_getNumArgTypes(*cxtype);
}
CXType *clang_getArgType_wrap(CXType *cxtype, unsigned index)
{
return ptrToCXType(clang_getArgType(*cxtype, index));
}
long long clang_getEnumConstantDeclValue_wrap(CXCursor *cursor)
{
return clang_getEnumConstantDeclValue(*cursor);
}
/** Returns non-zero if the ranges are the same, zero if they differ. */
unsigned clang_equalRanges_wrap(CXSourceRange *c1, CXSourceRange *c2)
{
return clang_equalRanges(*c1, *c2);
}
/** Returns the comment range. */
CXSourceRange *clang_Cursor_getCommentRange_wrap(CXCursor *cursor)
{
return ptrToCXSourceRange(clang_Cursor_getCommentRange(*cursor));
}
/** Returns the raw comment. */
CXString *clang_Cursor_getRawCommentText_wrap(CXCursor *cursor)
{
return ptrToCXString(clang_Cursor_getRawCommentText(*cursor));
}
/** Returns the first paragraph of doxygen doc comment. */
CXString *clang_Cursor_getBriefCommentText_wrap(CXCursor *cursor)
{
return ptrToCXString(clang_Cursor_getBriefCommentText(*cursor));
}
CXSourceLocation *clang_getCursorLocation_wrap(CXCursor *cursor)
{
return ptrToCXSourceLocation(clang_getCursorLocation(*cursor));
}
void clang_getFileLocation_wrap(CXSourceLocation *location, CXFile *file, unsigned *line, unsigned *column, unsigned *offset)
{
return clang_getFileLocation(*location, file, line, column, offset);
}
CXString *clang_getFileName_wrap(CXFile SFile)
{
return ptrToCXString(clang_getFileName(SFile));
}
unsigned long long clang_getNumElements_wrap(CXType *cxtype)
{
return clang_getNumElements(*cxtype);
}
CXType *clang_getArrayElementType_wrap(CXType *cxtype)
{
return ptrToCXType(clang_getArrayElementType(*cxtype));
}
unsigned int clang_Cursor_isMacroFunctionLike_wrap(CXCursor *cursor)
{
return clang_Cursor_isMacroFunctionLike(*cursor);
}
unsigned clang_Cursor_isMacroBuiltin_wrap(CXCursor *cursor)
{
return clang_Cursor_isMacroBuiltin(*cursor);
}
CXEvalResult clang_Cursor_Evaluate_wrap(CXCursor *cursor)
{
return clang_Cursor_Evaluate(*cursor);
}
unsigned clang_Cursor_isAnonymous_wrap(CXCursor *cursor)
{
return clang_Cursor_isAnonymous(*cursor);
}
unsigned clang_Cursor_isAnonymousRecordDecl_wrap(CXCursor *cursor)
{
return clang_Cursor_isAnonymousRecordDecl(*cursor);
}
CXString *clang_getCursorUSR_wrap(CXCursor *cursor)
{
return ptrToCXString(clang_getCursorUSR(*cursor));
}
int clang_getFieldDeclBitWidth_wrap(CXCursor *cursor){
return clang_getFieldDeclBitWidth(*cursor);
}
CXString *clang_getCursorPrettyPrinted_wrap(CXCursor *cursor, CXPrintingPolicy policy)
{
return ptrToCXString(clang_getCursorPrettyPrinted(*cursor, policy));
}
CXCursor *clang_getCursorReferenced_wrap(CXCursor *cursor)
{
return ptrToCXCursor(clang_getCursorReferenced(*cursor));
}
unsigned clang_isFunctionTypeVariadic_wrap(CXType *type)
{
return clang_isFunctionTypeVariadic(*type);
}
unsigned clang_isConstQualifiedType_wrap(CXType *type)
{
return clang_isConstQualifiedType(*type);
}
unsigned clang_getNumOverloadedDecls_wrap(CXCursor *cursor)
{
return clang_getNumOverloadedDecls(*cursor);
}
CXCursor *clang_getOverloadedDecl_wrap(CXCursor *cursor, unsigned index)
{
return ptrToCXCursor(clang_getOverloadedDecl(*cursor, index));
}
CXPrintingPolicy clang_getCursorPrintingPolicy_wrap(CXCursor *cursor)
{
return clang_getCursorPrintingPolicy(*cursor);
}
// END ===== WRAPPER FUNCTIONS =====================