Skip to content

Commit

Permalink
Rework CondIncl objects
Browse files Browse the repository at this point in the history
  • Loading branch information
fuhsnn committed Dec 20, 2024
1 parent 9756a16 commit 4fe5acd
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 22 deletions.
58 changes: 37 additions & 21 deletions preprocess.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,21 +44,24 @@ 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
// the lastest one for unlocking.
static Macro *locked_macros;

static HashMap macros;
static CondIncl *cond_incl;
static HashMap pragma_once;
static HashMap include_guards;

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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)
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion slimcc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down

0 comments on commit 4fe5acd

Please sign in to comment.