diff --git a/ftepp.c b/ftepp.c index e3e91e7..b269757 100644 --- a/ftepp.c +++ b/ftepp.c @@ -408,11 +408,48 @@ static bool ftepp_define_body(ftepp_t *ftepp, ppmacro *macro) { pptoken *ptok; while (ftepp->token != TOKEN_EOL && ftepp->token < TOKEN_EOF) { - if (macro->variadic && !strcmp(ftepp_tokval(ftepp), "__VA_ARGS__")) - ftepp->token = TOKEN_VA_ARGS; - ptok = pptoken_make(ftepp); - vec_push(macro->output, ptok); - ftepp_next(ftepp); + size_t index; + if (macro->variadic && !strcmp(ftepp_tokval(ftepp), "__VA_ARGS__")) { + /* remember the token */ + if (ftepp_next(ftepp) == '#' && + ftepp_next(ftepp) == '#' && + ftepp_next(ftepp) == '[') + { + if (ftepp_next(ftepp) != TOKEN_INTCONST) { + ftepp_error(ftepp, "expected index for __VA_ARGS__ subscript"); + return false; + } + + index = atoi(ftepp_tokval(ftepp)); + + if (ftepp_next(ftepp) != ']') { + ftepp_error(ftepp, "expected `]` in __VA_ARGS__ subscript"); + return false; + } + + /* + * mark it as an array to be handled later as such and not + * as traditional __VA_ARGS__ + */ + ftepp->token = TOKEN_VA_ARGS_ARRAY; + ptok = pptoken_make(ftepp); + ptok->constval.i = index; + vec_push(macro->output, ptok); + ftepp_next(ftepp); + } else { + int old = ftepp->token; + ftepp->token = TOKEN_VA_ARGS; + ptok = pptoken_make(ftepp); + vec_push(macro->output, ptok); + ftepp->token = old; + } + } + else + { + ptok = pptoken_make(ftepp); + vec_push(macro->output, ptok); + ftepp_next(ftepp); + } } /* recursive expansion can cause EOFs here */ if (ftepp->token != TOKEN_EOL && ftepp->token != TOKEN_EOF) { @@ -673,6 +710,7 @@ static bool ftepp_macro_expand(ftepp_t *ftepp, ppmacro *macro, macroparam *param } if (!varargs) break; + pi = 0; ftepp_param_out(ftepp, ¶ms[pi + vararg_start]); for (++pi; pi < varargs; ++pi) { @@ -680,6 +718,17 @@ static bool ftepp_macro_expand(ftepp_t *ftepp, ppmacro *macro, macroparam *param ftepp_param_out(ftepp, ¶ms[pi + vararg_start]); } break; + + case TOKEN_VA_ARGS_ARRAY: + if (out->constval.i >= varargs) { + ftepp_error(ftepp, "subscript of `[%u]` is out of bounds for `__VA_ARGS__`", out->constval.i); + vec_free(old_string); + return false; + } + + ftepp_param_out(ftepp, ¶ms[out->constval.i + vararg_start]); + break; + case TOKEN_IDENT: case TOKEN_TYPENAME: case TOKEN_KEYWORD: diff --git a/lexer.h b/lexer.h index 71ff198..75fb83e 100644 --- a/lexer.h +++ b/lexer.h @@ -75,6 +75,7 @@ enum { TOKEN_ATTRIBUTE_CLOSE, /* ]] */ TOKEN_VA_ARGS, /* for the ftepp only */ + TOKEN_VA_ARGS_ARRAY, /* for the ftepp only */ TOKEN_STRINGCONST, /* not the typename but an actual "string" */ TOKEN_CHARCONST, diff --git a/tests/pp_va_args.qc b/tests/pp_va_args.qc index f73372c..f54533b 100644 --- a/tests/pp_va_args.qc +++ b/tests/pp_va_args.qc @@ -1,9 +1,12 @@ void print(...) = #1; #define NOPARENS(...) __VA_ARGS__ -#define callem(func, args) func(NOPARENS args) +#define callem(func, args) func NOPARENS(args) + +#define callen(func, ...) func __VA_ARGS__##[0] void main() { print(NOPARENS("hello ", "world\n")); callem(print, ("Yay", ", there\n")); + callen(print, ("Woah",", there\n")); } diff --git a/tests/pp_va_args.tmpl b/tests/pp_va_args.tmpl index cf6ed16..c6e0c14 100644 --- a/tests/pp_va_args.tmpl +++ b/tests/pp_va_args.tmpl @@ -4,3 +4,4 @@ T: -execute C: -std=fteqcc M: hello world M: Yay, there +M: Woah, there