mirror of https://github.com/rui314/chibicc
Add include guard optimization
This commit is contained in:
parent
f5977e1bff
commit
44776befd8
53
preprocess.c
53
preprocess.c
|
@ -777,6 +777,45 @@ static char *read_include_path(Token **rest, Token *tok) {
|
|||
error_tok(tok, "expected a filename");
|
||||
}
|
||||
|
||||
// Detect the following "include guard" pattern.
|
||||
//
|
||||
// #ifndef FOO_H
|
||||
// #define FOO_H
|
||||
// ...
|
||||
// #endif
|
||||
static char *detect_include_guard(Token *tok) {
|
||||
// Detect the first two lines.
|
||||
if (!is_hash(tok) || !equal(tok->next, "ifndef"))
|
||||
return NULL;
|
||||
tok = tok->next->next;
|
||||
|
||||
if (tok->kind != TK_IDENT)
|
||||
return NULL;
|
||||
|
||||
char *macro = strndup(tok->loc, tok->len);
|
||||
tok = tok->next;
|
||||
|
||||
if (!is_hash(tok) || !equal(tok->next, "define") || !equal(tok->next->next, macro))
|
||||
return NULL;
|
||||
|
||||
// Read until the end of the file.
|
||||
while (tok->kind != TK_EOF) {
|
||||
if (!is_hash(tok)) {
|
||||
tok = tok->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (equal(tok->next, "endif") && tok->next->next->kind == TK_EOF)
|
||||
return macro;
|
||||
|
||||
if (equal(tok, "if") || equal(tok, "ifdef") || equal(tok, "ifndef"))
|
||||
tok = skip_cond_incl(tok->next);
|
||||
else
|
||||
tok = tok->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Read #line arguments
|
||||
static void read_line_marker(Token **rest, Token *tok) {
|
||||
Token *start = tok;
|
||||
|
@ -820,9 +859,23 @@ static Token *preprocess2(Token *tok) {
|
|||
|
||||
if (equal(tok, "include")) {
|
||||
char *path = read_include_path(&tok, tok->next);
|
||||
|
||||
// If we read the same file before, and if the file was guarded
|
||||
// by the usual #ifndef ... #endif pattern, we may be able to
|
||||
// skip the file without opening it.
|
||||
static HashMap include_guards;
|
||||
char *guard_name = hashmap_get(&include_guards, path);
|
||||
if (guard_name && hashmap_get(¯os, guard_name))
|
||||
continue;
|
||||
|
||||
Token *tok2 = tokenize_file(path);
|
||||
if (!tok2)
|
||||
error_tok(start, "%s: cannot open file: %s", path, strerror(errno));
|
||||
|
||||
guard_name = detect_include_guard(tok2);
|
||||
if (guard_name)
|
||||
hashmap_put(&include_guards, path, guard_name);
|
||||
|
||||
tok = append(tok2, tok);
|
||||
continue;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue