Implement subscripting for __VA_ARGS__, and added test-case. This only works on INTCONST for now.

This commit is contained in:
Dale Weiler 2013-01-27 12:55:56 +00:00
parent 3e1c10628c
commit b4fbba5708
4 changed files with 60 additions and 6 deletions

59
ftepp.c
View file

@ -408,11 +408,48 @@ static bool ftepp_define_body(ftepp_t *ftepp, ppmacro *macro)
{ {
pptoken *ptok; pptoken *ptok;
while (ftepp->token != TOKEN_EOL && ftepp->token < TOKEN_EOF) { while (ftepp->token != TOKEN_EOL && ftepp->token < TOKEN_EOF) {
if (macro->variadic && !strcmp(ftepp_tokval(ftepp), "__VA_ARGS__")) size_t index;
ftepp->token = TOKEN_VA_ARGS; if (macro->variadic && !strcmp(ftepp_tokval(ftepp), "__VA_ARGS__")) {
ptok = pptoken_make(ftepp); /* remember the token */
vec_push(macro->output, ptok); if (ftepp_next(ftepp) == '#' &&
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 */ /* recursive expansion can cause EOFs here */
if (ftepp->token != TOKEN_EOL && ftepp->token != TOKEN_EOF) { 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) if (!varargs)
break; break;
pi = 0; pi = 0;
ftepp_param_out(ftepp, &params[pi + vararg_start]); ftepp_param_out(ftepp, &params[pi + vararg_start]);
for (++pi; pi < varargs; ++pi) { 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, &params[pi + vararg_start]); ftepp_param_out(ftepp, &params[pi + vararg_start]);
} }
break; 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, &params[out->constval.i + vararg_start]);
break;
case TOKEN_IDENT: case TOKEN_IDENT:
case TOKEN_TYPENAME: case TOKEN_TYPENAME:
case TOKEN_KEYWORD: case TOKEN_KEYWORD:

View file

@ -75,6 +75,7 @@ enum {
TOKEN_ATTRIBUTE_CLOSE, /* ]] */ TOKEN_ATTRIBUTE_CLOSE, /* ]] */
TOKEN_VA_ARGS, /* for the ftepp only */ 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_STRINGCONST, /* not the typename but an actual "string" */
TOKEN_CHARCONST, TOKEN_CHARCONST,

View file

@ -1,9 +1,12 @@
void print(...) = #1; void print(...) = #1;
#define NOPARENS(...) __VA_ARGS__ #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() { void main() {
print(NOPARENS("hello ", "world\n")); print(NOPARENS("hello ", "world\n"));
callem(print, ("Yay", ", there\n")); callem(print, ("Yay", ", there\n"));
callen(print, ("Woah",", there\n"));
} }

View file

@ -4,3 +4,4 @@ T: -execute
C: -std=fteqcc C: -std=fteqcc
M: hello world M: hello world
M: Yay, there M: Yay, there
M: Woah, there