mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2024-11-27 22:22:17 +00:00
Implement subscripting for __VA_ARGS__, and added test-case. This only works on INTCONST for now.
This commit is contained in:
parent
3e1c10628c
commit
b4fbba5708
4 changed files with 60 additions and 6 deletions
59
ftepp.c
59
ftepp.c
|
@ -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, ¶ms[pi + vararg_start]);
|
ftepp_param_out(ftepp, ¶ms[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, ¶ms[pi + vararg_start]);
|
ftepp_param_out(ftepp, ¶ms[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, ¶ms[out->constval.i + vararg_start]);
|
||||||
|
break;
|
||||||
|
|
||||||
case TOKEN_IDENT:
|
case TOKEN_IDENT:
|
||||||
case TOKEN_TYPENAME:
|
case TOKEN_TYPENAME:
|
||||||
case TOKEN_KEYWORD:
|
case TOKEN_KEYWORD:
|
||||||
|
|
1
lexer.h
1
lexer.h
|
@ -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,
|
||||||
|
|
|
@ -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"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue