[PATCH 15/21] pre-process.c: split try_arg()
Al Viro <[email protected]> Mon, 16 Mar 2026 07:04:09 +0000
| Newsgroups | org.kernel.vger.linux-sparse |
|---|---|
| Message-ID | <[email protected]> |
more __VA_OPT__ preparations - we want to split the "parse the possible variable" from the parts that are sensitive to the kind of variable access (in particular, to subsequent ## being or not being there). With __VA_OPT__ we'll have a possibility of relevant ## being a lot further ahead than the next token and we won't find it until we'd parsed the entire __VA_OPT__(.....). We could check for __VA_OPT__ _before_ checking for arguments, but that ends up screwing code generation a lot, slowing down the normal case where we've not a single __VA_OPT__ in the input. Replace try_arg() with two new primitives: * check_arg() - returns 0 if the next token is not an argument; if the token is an argument, it gets converted to TOKEN_MACRO_ARGUMENT and slot number + 1 is returned. That function gets only token and arg_state array - 'kind' is not known yet. At the moment 'args' is not needed, but it will be needed for __VA_OPT__ handling, so that argument stays. Note that unlike try_arg() we don't need a special return value to tell vararg from non-vararg argument - the slot number is sufficient now. It's a vararg if and only if it occupies slot 0, i.e. if check_arg() has returned 1. * seen_arg() - gets called only for TOKEN_MACRO_ARGUMENT token, does the rest of what try_arg() used to do. Returns void. Calls of try_arg() are replaced with combinations of these two, the first try_arg() in handle_hashhash() lifted into the only caller of handle_hashhash() and its check_arg() folded with the one we do for non-## case there. Signed-off-by: Al Viro <[email protected]> --- pre-process.c | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/pre-process.c b/pre-process.c index fed3dc2a..51ad916c 100644 --- a/pre-process.c +++ b/pre-process.c @@ -1166,7 +1166,7 @@ struct arg_state { struct token *needs_str; }; -static int try_arg(struct token *token, enum arg_kind kind, struct arg_state args[]) +static int check_arg(struct token *token, struct arg_state args[]) { struct ident *ident = token->ident; int nr; @@ -1181,8 +1181,14 @@ static int try_arg(struct token *token, enum arg_kind kind, struct arg_state arg return 0; nr = nr == macro_vararg ? 0 : nr + 1; - token->argnum = (nr << ARGNUM_BITS_STOLEN) | kind; + token->argnum = nr << ARGNUM_BITS_STOLEN; token_type(token) = TOKEN_MACRO_ARGUMENT; + return nr + 1; +} + +static void seen_arg(struct token *token, enum arg_kind kind, struct arg_state args[], int nr) +{ + token->argnum |= kind; switch (kind) { case ARG_QUOTED: args[nr].needs_raw = token; @@ -1197,7 +1203,6 @@ static int try_arg(struct token *token, enum arg_kind kind, struct arg_state arg args[nr].needs_raw = token; args[nr].needs_str = token; } - return nr == 0 ? 2 : 1; } static struct token *handle_hash(struct token **p, struct arg_state args[]) @@ -1205,8 +1210,12 @@ static struct token *handle_hash(struct token **p, struct arg_state args[]) struct token *token = *p; if (macro_funclike) { struct token *next = token->next; - if (!try_arg(next, ARG_STR, args)) + int nr = check_arg(next, args); + + if (!nr) goto Equote; + + seen_arg(next, ARG_STR, args, nr - 1); next->pos.whitespace = token->pos.whitespace; __free_token(token); token = *p = next; @@ -1226,12 +1235,10 @@ static struct token *handle_hashhash(struct token *token, struct arg_state args[ struct token *last = token; struct token *concat; int state = match_op(token, ','); - - try_arg(token, ARG_QUOTED, args); + int nr; while (1) { struct token *t; - int is_arg; /* eat duplicate ## */ concat = token->next; @@ -1251,10 +1258,13 @@ static struct token *handle_hashhash(struct token *token, struct arg_state args[ return NULL; } - is_arg = try_arg(t, ARG_QUOTED, args); + nr = check_arg(t, args); + if (nr > 0) + seen_arg(t, ARG_QUOTED, args, nr - 1); - if (state == 1 && is_arg) { - state = is_arg; + if (state == 1 && nr > 0) { + if (nr == 1) + state = 2; } else { last = t; state = match_op(t, ','); @@ -1280,6 +1290,7 @@ static struct token *parse_expansion(struct token *expansion, struct ident *name struct arg_state args[slots] = {}; struct token *token = expansion; struct token **p; + int nr; if (match_op(token, SPECIAL_HASHHASH)) goto Econcat; @@ -1290,12 +1301,16 @@ static struct token *parse_expansion(struct token *expansion, struct ident *name if (!token) return NULL; } + nr = check_arg(token, args); if (match_op(token->next, SPECIAL_HASHHASH)) { + if (nr > 0) + seen_arg(token, ARG_QUOTED, args, nr - 1); token = handle_hashhash(token, args); if (!token) return NULL; } else { - try_arg(token, ARG_NORMAL, args); + if (nr > 0) + seen_arg(token, ARG_NORMAL, args, nr - 1); } } for (int i = 0; i < slots; i++) { -- 2.47.3