FILE *dst = fmemopen(dstbuf, ULAS_LINEMAX, "we"); \
assert(ulas_preproc(dst, src) == (expect_ret)); \
fclose(src); \
- fclose(dst); \
+ fclose(dst); printf("%s\n", dstbuf); \
assert(strcmp(dstbuf, (expect_dst)) == 0); \
}
"#macro test\n line $1 1 label$$$$,$$ $$\n line $2 2\n line $3 3 "
"$0\n#endmacro\ntest p1, p2, p3");
assert_preproc("test macro with no args\n", 0,
- "#macro test\ntest macro with no args\n#endmacro\ntest");
+ "#macro mtest\ntest macro with no args\n#endmacro\nmtest");
assert_preproc("", -1, "#macro test\n not terminated\n");
assert_preproc(
- "nested macro t1\nafter\ncontent n1\n", 0,
- "#macro test\nnested macro $1\n#macro "
- "nested\ncontent $1\n#endmacro\nafter\nnested n1\n#endmacro\ntest t1");
+ "content macro t1\nt1\nafter\ncontent n1\n", 0,
+ "#macro test\nmnested macro $1\n$1\n#macro "
+ "mnested\ncontent $1\n#endmacro\nafter\nmnested n1\n#endmacro\ntest t1");
// this macro caused a heap buffer overflow in production code
assert_preproc("ld a, verylongmacroinput & 0xFF\nld [hl+], a\nld a, "
strncat(pp->line.buf, tocat, tocatlen);
}
}
+ // expand macro result again to allow
+ // defines to appear in the macro
+ ulas_strensr(&pp->line2, strlen(pp->line.buf) + 1);
+ sprintf(pp->line2.buf, "%s", pp->line.buf);
+ unsigned long n = strlen(pp->line.buf);
+ pp->exp_depth++;
+ if (pp->exp_depth > ULAS_PREPROC_MAX_MACRO_DEPTH) {
+ ULASERR("Max macro recursion depth reached\n");
+ goto end;
+ }
+ ulas_preprocexpand(pp, pp->line2.buf, &n);
+ pp->exp_depth--;
goto end;
}
}
}
struct ulas_preproc ulas_preprocinit(void) {
- struct ulas_preproc pp = {NULL, 0, ulas_str(1), ulas_str(1)};
+ struct ulas_preproc pp = {NULL, 0, ulas_str(1), ulas_str(1), ulas_str(1)};
for (unsigned long i = 0; i < ULAS_MACROPARAMMAX; i++) {
pp.macroparam[i] = ulas_str(8);
}
// set up initial defs
for (int i = 0; i < ulascfg.defslen; i++) {
- struct ulas_ppdef def = {ULAS_PPDEF, strdup(ulascfg.defs[i]), strdup(""), 0};
+ struct ulas_ppdef def = {ULAS_PPDEF, strdup(ulascfg.defs[i]), strdup(""),
+ 0};
ulas_preprocdef(&pp, def);
}
void ulas_preprocfree(struct ulas_preproc *pp) {
ulas_strfree(&pp->line);
+ ulas_strfree(&pp->line2);
ulas_strfree(&pp->tok);
ulas_preprocclear(pp);