Skip to content

Commit

Permalink
Expand macro argument non destructive
Browse files Browse the repository at this point in the history
  • Loading branch information
tyfkda committed Oct 15, 2023
1 parent c8d8413 commit 3ee68d9
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 6 deletions.
25 changes: 21 additions & 4 deletions src/cpp/macro.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "../config.h"
#include "macro.h"

#include <alloca.h>
#include <assert.h>
#include <limits.h> // INT_MAX
#include <stdlib.h> // malloc
Expand Down Expand Up @@ -192,6 +193,15 @@ static Vector *subst(Macro *macro, Table *param_table, Vector *args, HideSet *hs
if (body == NULL)
return os;

Vector **expanded_args = NULL;
if (args != NULL && args->len > 0) {
expanded_args = alloca(sizeof(*expanded_args) * args->len);
if (expanded_args == NULL)
error("alloca failed");
for (int i = 0; i < args->len; ++i)
expanded_args[i] = NULL;
}

for (int i = 0; i < body->len; ++i) {
const Token *tok = body->data[i];

Expand Down Expand Up @@ -261,10 +271,17 @@ static Vector *subst(Macro *macro, Table *param_table, Vector *args, HideSet *hs
intptr_t j;
if (table_try_get(param_table, tok->ident, (void*)&j)) {
assert(j < args->len);
Vector *arg = args->data[j];
macro_expand(arg);
for (int k = 0; k < arg->len; ++k) {
const Token *t = arg->data[k];
Vector *expanded = expanded_args[j];
if (expanded == NULL) {
Vector *arg = args->data[j];
expanded = new_vector();
for (int i = 0; i < arg->len; ++i)
vec_push(expanded, arg->data[i]);
macro_expand(expanded);
expanded_args[j] = expanded;
}
for (int k = 0; k < expanded->len; ++k) {
const Token *t = expanded->data[k];
vec_push(os, t);
}
continue;
Expand Down
2 changes: 2 additions & 0 deletions tests/cpptest.sh
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ test_macro() {

try '#if in macro arguments' '{bar}' "#define FOO(x) {x}\nFOO(\n#if 1\nbar\n#else\nqux\n#endif\n)"

try 'expand and stringify' 'a(m_z, "M(z)")' "#define MinM(x) a(x, # x)\n#define M(x) m_ ## x\nMinM(M(z))"

try ', ## empty' 'foo(fmt)' "#define FOO(fmt, ...) foo(fmt, ## __VA_ARGS__)\nFOO(fmt)"
try ', ## some' 'foo(fmt,1, 2, 3)' "#define FOO(fmt, ...) foo(fmt, ## __VA_ARGS__)\nFOO(fmt, 1, 2, 3)"

Expand Down
18 changes: 16 additions & 2 deletions tool/pp.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ class MacroExpander {
}

subst(is, fp, ap, hs) {
const expandedAp = ap.map(_ => null)
const os = []
for (let i = 0; i < is.length; ++i) {
const tt = is[i]
Expand Down Expand Up @@ -175,7 +176,11 @@ class MacroExpander {

const j = fp.indexOf(tt.t)
if (j >= 0) {
os.push(...this.expand(ap[j]))
let expanded = expandedAp[j]
if (expanded == null) {
expanded = expandedAp[j] = this.expand([...ap[j]])
}
os.push(...expanded)
continue
}
}
Expand Down Expand Up @@ -212,7 +217,8 @@ class MacroExpander {
}

stringize(x) {
const s = `"${x}"` // TODO: Escape
const actual = x.map((t) => t.t.toString()).join('')
const s = `"${actual}"` // TODO: Escape
return new Token(TK_OTHER, s)
}

Expand Down Expand Up @@ -415,6 +421,14 @@ function main() {
'STR': new Macro(['x'], '# x'),
})

pptest(
'a(m_z, "M(z)")',
'MinM(M(z))',
{
'MinM': new Macro(['x'], 'a(x, # x)'),
'M': new Macro(['x'], 'm_ ## x'),
})

process.exit(errorCount === 0 ? 0 : 1)
}

Expand Down

0 comments on commit 3ee68d9

Please sign in to comment.