mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-25 13:11:00 +00:00
[qfcc] Get function-type macro arguments working
Or at least mostly so: token##pasting is still broken, but #stringize and nested macros seem to work.
This commit is contained in:
parent
6bfb1f37f0
commit
b952c11dce
1 changed files with 125 additions and 48 deletions
|
@ -1109,6 +1109,17 @@ token_expr (int token, const rua_tok_t *tok)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static rua_tok_t
|
||||||
|
expr_token (const rua_expr_t *e)
|
||||||
|
{
|
||||||
|
return (rua_tok_t) {
|
||||||
|
.location = e->location,
|
||||||
|
.textlen = e->textlen,
|
||||||
|
.text = e->text, // macro token strings use save_string
|
||||||
|
.token = e->token,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
join_tokens (rua_expr_t *out, const rua_expr_t *p1, const rua_expr_t *p2,
|
join_tokens (rua_expr_t *out, const rua_expr_t *p1, const rua_expr_t *p2,
|
||||||
rua_extra_t *extra)
|
rua_extra_t *extra)
|
||||||
|
@ -1272,12 +1283,8 @@ qc_token (rua_extra_t *extra, int token, rua_tok_t *tok, yyscan_t *scanner)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rua_start_args (void *scanner)
|
rua_reset_args (rua_macro_t *macro)
|
||||||
{
|
{
|
||||||
auto extra = qc_yyget_extra (scanner);
|
|
||||||
extra->recording = true;
|
|
||||||
|
|
||||||
auto macro = extra->pending_macro;
|
|
||||||
macro->num_args = 0;
|
macro->num_args = 0;
|
||||||
|
|
||||||
int num_params = macro->num_params;
|
int num_params = macro->num_params;
|
||||||
|
@ -1296,6 +1303,15 @@ rua_start_args (void *scanner)
|
||||||
.tail = &arg->tokens,
|
.tail = &arg->tokens,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rua_start_args (void *scanner)
|
||||||
|
{
|
||||||
|
auto extra = qc_yyget_extra (scanner);
|
||||||
|
extra->recording = true;
|
||||||
|
|
||||||
|
rua_reset_args (extra->pending_macro);
|
||||||
yy_push_state (ARGS, scanner);
|
yy_push_state (ARGS, scanner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1307,6 +1323,18 @@ rua_end_args (void *scanner)
|
||||||
yy_pop_state (scanner);
|
yy_pop_state (scanner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void __attribute__((used))
|
||||||
|
dump_macro (rua_macro_t *macro)
|
||||||
|
{
|
||||||
|
printf ("\n%s: ", macro->name);
|
||||||
|
for (auto t = macro->tokens; t; t = t->next) {
|
||||||
|
printf ("%s", t->text);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < macro->num_args; i++) {
|
||||||
|
dump_macro (macro->args[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
qc_process (rua_extra_t *extra, int token, rua_tok_t *tok, yyscan_t scanner)
|
qc_process (rua_extra_t *extra, int token, rua_tok_t *tok, yyscan_t scanner)
|
||||||
{
|
{
|
||||||
|
@ -1433,6 +1461,96 @@ next_macro_token (rua_extra_t *extra)
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
next_token (rua_tok_t *tok, yyscan_t scanner)
|
||||||
|
{
|
||||||
|
auto extra = qc_yyget_extra (scanner);
|
||||||
|
int token;
|
||||||
|
rescan:
|
||||||
|
while (extra->macro && !extra->macro->cursor) {
|
||||||
|
auto macro = extra->macro;
|
||||||
|
extra->macro = macro->next;
|
||||||
|
macro->next = 0;
|
||||||
|
}
|
||||||
|
if (extra->macro && extra->macro->cursor) {
|
||||||
|
symbol_t *sym;
|
||||||
|
auto macro = extra->macro;
|
||||||
|
auto e = next_macro_token (extra);
|
||||||
|
token = e.token;
|
||||||
|
if (token == '#') {
|
||||||
|
sym = symtab_lookup (macro->params, e.next->text);
|
||||||
|
auto arg = macro->args[sym->s.offset];
|
||||||
|
stringize_arg (&e, arg, extra);
|
||||||
|
next_macro_token (extra); // consume arg
|
||||||
|
} else if (token == -rua_id && macro->params
|
||||||
|
&& (sym = symtab_lookup (macro->params, e.text))
|
||||||
|
&& !macro->args[sym->s.offset]->next) {
|
||||||
|
auto arg = macro->args[sym->s.offset];
|
||||||
|
arg->cursor = arg->tokens;
|
||||||
|
arg->next = extra->macro;
|
||||||
|
extra->macro = arg;
|
||||||
|
goto rescan;
|
||||||
|
} else if (token == -rua_id && !macro->name /* in arg */
|
||||||
|
&& (sym = symtab_lookup (extra->macro_tab, e.text))
|
||||||
|
&& !sym->s.macro->next) {
|
||||||
|
auto m = sym->s.macro;
|
||||||
|
if (m->update) {
|
||||||
|
m->update (m, scanner);
|
||||||
|
}
|
||||||
|
m->cursor = m->tokens;
|
||||||
|
if (!m->params) {
|
||||||
|
m->next = extra->macro;
|
||||||
|
extra->macro = m;
|
||||||
|
goto rescan;
|
||||||
|
}
|
||||||
|
|
||||||
|
m->next = extra->pending_macro;
|
||||||
|
extra->pending_macro = m;
|
||||||
|
auto t = macro->cursor;
|
||||||
|
for (; t && t->token == -rua_space; t = t->next) continue;
|
||||||
|
// to be in an arg, a function-like macro must either have
|
||||||
|
// both open and close parans, or none
|
||||||
|
if (t && t->token == '(') {
|
||||||
|
rua_reset_args (m);
|
||||||
|
int paren = 1;
|
||||||
|
auto tk = expr_token (t);
|
||||||
|
auto a = rua_macro_arg (&tk, scanner);
|
||||||
|
for (t = t->next; t; t = t->next) {
|
||||||
|
if (t->token == '(') {
|
||||||
|
paren++;
|
||||||
|
} else if (t->token == ')') {
|
||||||
|
if (!(--paren)) {
|
||||||
|
t = t->next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tk = expr_token (t);
|
||||||
|
if (t->token == ',' && paren == 1) {
|
||||||
|
a = rua_macro_arg (&tk, scanner);
|
||||||
|
} else {
|
||||||
|
rua_macro_append (a, &tk, scanner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
macro->cursor = t;
|
||||||
|
extra->pending_macro = m->next;
|
||||||
|
m->next = extra->macro;
|
||||||
|
extra->macro = m;
|
||||||
|
goto rescan;
|
||||||
|
} else if (e.next && e.next->token == PRE_CONCAT) {
|
||||||
|
next_macro_token (extra); // consume ##
|
||||||
|
rua_expr_t t = next_macro_token (extra);
|
||||||
|
if (!join_tokens (&e, &e, &t, extra)) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*tok = expr_token (&e);
|
||||||
|
token = tok->token;
|
||||||
|
} else {
|
||||||
|
token = yylex (tok, &tok->location, scanner);
|
||||||
|
}
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
qc_yyparse (FILE *in)
|
qc_yyparse (FILE *in)
|
||||||
{
|
{
|
||||||
|
@ -1454,43 +1572,7 @@ qc_yyparse (FILE *in)
|
||||||
int status;
|
int status;
|
||||||
rua_tok_t tok = { .location = { 1, 1, 1, 1, pr.source_file }, };
|
rua_tok_t tok = { .location = { 1, 1, 1, 1, pr.source_file }, };
|
||||||
do {
|
do {
|
||||||
int token;
|
int token = next_token (&tok, scanner);
|
||||||
if (extra.macro) {
|
|
||||||
symbol_t *sym;
|
|
||||||
rescan:
|
|
||||||
auto macro = extra.macro;
|
|
||||||
auto e = next_macro_token (&extra);
|
|
||||||
token = e.token;
|
|
||||||
if (token == '#') {
|
|
||||||
sym = symtab_lookup (macro->params, e.next->text);
|
|
||||||
auto arg = macro->args[sym->s.offset];
|
|
||||||
stringize_arg (&e, arg, &extra);
|
|
||||||
next_macro_token (&extra); // consume arg
|
|
||||||
} else if (token == -rua_id && macro->params
|
|
||||||
&& (sym = symtab_lookup (macro->params, e.text))) {
|
|
||||||
auto arg = macro->args[sym->s.offset];
|
|
||||||
//printf ("%3d '%s'\n", token, quote_string (e.text));
|
|
||||||
if (!arg->next && arg->tokens) {
|
|
||||||
arg->cursor = arg->tokens;
|
|
||||||
arg->next = extra.macro;
|
|
||||||
extra.macro = arg;
|
|
||||||
goto rescan;
|
|
||||||
}
|
|
||||||
} else if (e.next && e.next->token == PRE_CONCAT) {
|
|
||||||
next_macro_token (&extra); // consume ##
|
|
||||||
rua_expr_t t = next_macro_token (&extra);
|
|
||||||
if (!join_tokens (&e, &e, &t, &extra)) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tok = (rua_tok_t) {
|
|
||||||
.location = e.location,
|
|
||||||
.textlen = e.textlen,
|
|
||||||
.text = e.text, // macro token strings use save_string
|
|
||||||
.token = token,
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
token = yylex (&tok, &tok.location, scanner);
|
|
||||||
}
|
|
||||||
if (!token && extra.cond_stack.size) {
|
if (!token && extra.cond_stack.size) {
|
||||||
int ind = extra.cond_stack.size - 1;
|
int ind = extra.cond_stack.size - 1;
|
||||||
auto cond = extra.cond_stack.a[ind];
|
auto cond = extra.cond_stack.a[ind];
|
||||||
|
@ -2006,12 +2088,7 @@ rua_parse_define (const char *def)
|
||||||
extra.macro = extra.macro->next;
|
extra.macro = extra.macro->next;
|
||||||
}
|
}
|
||||||
token = expr.token;
|
token = expr.token;
|
||||||
tok = (rua_tok_t) {
|
tok = expr_token (&expr);
|
||||||
.location = expr.location,
|
|
||||||
.textlen = expr.textlen,
|
|
||||||
.text = expr.text, // macro token strings use save_string
|
|
||||||
.token = token,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
} while (status == YYPUSH_MORE);
|
} while (status == YYPUSH_MORE);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue