From 4fe5acd08a1fe7778169d97da72586300ce5da0a Mon Sep 17 00:00:00 2001 From: fuhsnn <66062782+fuhsnn@users.noreply.github.com> Date: Sat, 21 Dec 2024 00:47:22 +0800 Subject: [PATCH] Rework CondIncl objects --- preprocess.c | 58 +++++++++++++++++++++++++++++++++------------------- slimcc.h | 2 +- 2 files changed, 38 insertions(+), 22 deletions(-) diff --git a/preprocess.c b/preprocess.c index d0b19ec..68e171b 100644 --- a/preprocess.c +++ b/preprocess.c @@ -44,13 +44,17 @@ typedef struct { } MacroContext; // `#if` can be nested, so we use a stack to manage nested `#if`s. -typedef struct CondIncl CondIncl; -struct CondIncl { - CondIncl *next; - enum { IN_THEN, IN_ELIF, IN_ELSE } ctx; +typedef struct { Token *tok; + enum { IN_THEN, IN_ELIF, IN_ELSE } ctx; bool included; -}; +} CondIncl; + +static struct { + CondIncl *data; + int capacity; + int cnt; +} cond_incl_stk; // A linked list of locked macros. Since macro nesting happens in // LIFO fashion (inner expansions end first), we only need to check @@ -58,7 +62,6 @@ struct CondIncl { static Macro *locked_macros; static HashMap macros; -static CondIncl *cond_incl; static HashMap pragma_once; static HashMap include_guards; @@ -355,14 +358,21 @@ static int64_t eval_const_expr(Token *tok) { return val; } -static CondIncl *push_cond_incl(Token *tok, bool included) { - CondIncl *ci = calloc(1, sizeof(CondIncl)); - ci->next = cond_incl; - ci->ctx = IN_THEN; - ci->tok = tok; - ci->included = included; - cond_incl = ci; - return ci; +static void push_cond_incl(Token *tok, bool included) { + int idx = cond_incl_stk.cnt++; + if (idx >= cond_incl_stk.capacity) { + cond_incl_stk.capacity = idx + 8; + cond_incl_stk.data = realloc(cond_incl_stk.data, sizeof(CondIncl) * cond_incl_stk.capacity); + } + cond_incl_stk.data[idx].ctx = IN_THEN; + cond_incl_stk.data[idx].tok = tok; + cond_incl_stk.data[idx].included = included; +} + +static CondIncl *get_cond_incl(void) { + if (cond_incl_stk.cnt > 0) + return &cond_incl_stk.data[cond_incl_stk.cnt - 1]; + return NULL; } static Macro *find_macro(Token *tok) { @@ -951,8 +961,8 @@ static Token *include_file(Token *tok, char *path, Token *filename_tok, int *inc return tok; if (is_hash(start) && equal(start->next, "ifndef") && - start->next->next->kind == TK_IDENT && equal(end, "endif")) - start->next->guard_file = end->guard_file = path; + start->next->next->kind == TK_IDENT && equal(end, "endif")) + start->next->is_incl_guard = end->is_incl_guard = true; end->next = tok; return start; @@ -1168,9 +1178,11 @@ static Token *directives(Token **cur, Token *start) { } if (equal(tok, "elif")) { + CondIncl *cond_incl = get_cond_incl(); if (!cond_incl || cond_incl->ctx == IN_ELSE) error_tok(start, "stray #elif"); cond_incl->ctx = IN_ELIF; + cond_incl->tok->is_incl_guard = false; if (!cond_incl->included && eval_const_expr(split_line(&tok, tok->next))) cond_incl->included = true; @@ -1180,9 +1192,11 @@ static Token *directives(Token **cur, Token *start) { } if (equal(tok, "else")) { + CondIncl *cond_incl = get_cond_incl(); if (!cond_incl || cond_incl->ctx == IN_ELSE) error_tok(start, "stray #else"); cond_incl->ctx = IN_ELSE; + cond_incl->tok->is_incl_guard = false; tok = skip_line(tok->next); if (cond_incl->included) @@ -1191,16 +1205,18 @@ static Token *directives(Token **cur, Token *start) { } if (equal(tok, "endif")) { + CondIncl *cond_incl = get_cond_incl(); if (!cond_incl) error_tok(start, "stray #endif"); - if (tok->guard_file && tok->guard_file == cond_incl->tok->guard_file) { + if (tok->is_incl_guard && cond_incl->tok->is_incl_guard && + tok->file == cond_incl->tok->file) { Token *name_tok = cond_incl->tok->next; char *guard_name = strndup(name_tok->loc, name_tok->len); - hashmap_put(&include_guards, tok->guard_file, guard_name); + hashmap_put(&include_guards, tok->file->name, guard_name); } - cond_incl = cond_incl->next; + cond_incl_stk.cnt--; tok = skip_line(tok->next); return tok; } @@ -1700,8 +1716,8 @@ static Token *preprocess3(Token *tok) { // Entry point function of the preprocessor. Token *preprocess(Token *tok) { tok = preprocess2(tok); - if (cond_incl) - error_tok(cond_incl->tok, "unterminated conditional directive"); + if (cond_incl_stk.cnt) + error_tok(get_cond_incl()->tok, "unterminated conditional directive"); if (opt_E) return tok; diff --git a/slimcc.h b/slimcc.h index bc307e0..1f7c576 100644 --- a/slimcc.h +++ b/slimcc.h @@ -146,8 +146,8 @@ struct Token { bool at_bol; // True if this token is at beginning of line bool has_space; // True if this token follows a space character bool dont_expand; // True if a macro token is encountered during the macro's expansion + bool is_incl_guard; Token *origin; // If this is expanded from a macro, the original token - char *guard_file; // The path of a potentially include-guarded file Token *attr_next; } PACKED;