Skip to content

Commit

Permalink
'Fix' API macro parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
dkorpel committed Jul 23, 2023
1 parent a517e4b commit 7767f69
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 5 deletions.
7 changes: 6 additions & 1 deletion source/ctod/cdeclaration.d
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,13 @@ bool ctodTryDeclaration(ref CtodCtx ctx, ref Node node) {
InlineType[] inlinetypes;

bool translateDecl(string suffix, bool cInit) {
Decl[] decls = parseDecls(ctx, node, inlinetypes);
string apiMacro;
Decl[] decls = parseDecls(ctx, node, inlinetypes, &apiMacro);

string result = "";
if (apiMacro.length > 0) {
result ~= apiMacro ~ " ";
}
foreach(s; inlinetypes) {
result ~= s.toString();
}
Expand Down
8 changes: 7 additions & 1 deletion source/ctod/ctype.d
Original file line number Diff line number Diff line change
Expand Up @@ -294,14 +294,20 @@ bool tryParseTypeQual(ref CtodCtx ctx, ref Node node, ref CQuals quals) {
/// Parse declarations
/// Often a node represents a single declaration, but in case of e.g. `int x, *y;` they are split up into two
/// declarations since in D you can't declare differently typed variables in one declaration
Decl[] parseDecls(ref CtodCtx ctx, ref Node node, ref InlineType[] inlineTypes) {
Decl[] parseDecls(ref CtodCtx ctx, ref Node node, ref InlineType[] inlineTypes, scope string* apiMacro = null) {
auto typeNode = node.childField(Field.type);
if (!typeNode) {
return null;
}
const oldLen = inlineTypes.length;
auto primitiveType = parseTypeNode(ctx, *typeNode, inlineTypes, false);

// This happens with API macros, which get parsed as a return type.
if (apiMacro && node.children.length > 1 && node.children[1].typeEnum == Sym.error) {
*apiMacro = primitiveType;
primitiveType = node.children[1].source;
}

// there may be multiple type_qualifier fields
// if (auto qualNode = node.childField(Field.type_qualifier))
CQuals quals;
Expand Down
9 changes: 8 additions & 1 deletion source/ctod/test.d
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,13 @@ union U {
);

test("inline static void foo(int x);", "pragma(inline, true) private void foo(int x);");

// Test API macro before function definition
test("WINAPI int** Whoa(void);", "WINAPI int** Whoa();");
// Unfortunately, tree-sitter sees this as 2 declarations with a missing ';',
// so there's no translation unsigned int => uint, but it should be clear what happened
test("MYAPI unsigned int f(void);", "MYAPI unsigned; int f();");

test("
int main(void) {
static int xx;
Expand Down Expand Up @@ -389,7 +396,7 @@ alias B = X.B;

test("int so9 = sizeof(int) * 5;", "int so9 = int.sizeof * 5;");
test("int soA = sizeof(unsigned char) * 5;", "int soA = ubyte.sizeof * 5;");
test("int soB = = sizeof(int*) * 5;", "int soB = (int*).sizeof * 5;");
test("int soB = sizeof(int*) * 5;", "int soB = (int*).sizeof * 5;");
test("int soC = sizeof(struct mg_dns_header);", "int soC = mg_dns_header.sizeof;");

test("int of = offsetof(S, f);", "int of = S.f.offsetof;");
Expand Down
3 changes: 1 addition & 2 deletions source/ctod/translate.d
Original file line number Diff line number Diff line change
Expand Up @@ -172,9 +172,8 @@ nothrow:
currentTypeScope().fieldIndex++;
}

int uniqueIdCounter = 0;
string uniqueIdentifier(string suggestion) {
static toUpper(char c) {return cast(char) (c - (c >= 'a' && c <= 'z') * ('a' - 'A'));}
static char toUpper(char c) {return cast(char) (c - (c >= 'a' && c <= 'z') * ('a' - 'A'));}
if (suggestion.length > 0) {
return "_" ~ toUpper(suggestion[0]) ~ suggestion[1..$];
} else {
Expand Down
1 change: 1 addition & 0 deletions source/ctod/tree_sitter.d
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ enum Field : ubyte {

/// Identifies a C tree-sitter node
enum Sym : ushort {
error = 0xFFFF,
identifier = 1,
aux_preproc_include_token1 = 2,
anon_LF = 3,
Expand Down

0 comments on commit 7767f69

Please sign in to comment.