diff options
| author | nsfisis <nsfisis@gmail.com> | 2025-08-04 08:58:47 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2025-08-15 10:06:21 +0900 |
| commit | df4cce06a3c84c1441f113b0c2973eec8c2f7d49 (patch) | |
| tree | 83aa16326c5140799988dd788f1f3846f859f398 | |
| parent | 44ad877f2e9a688b5befcdffe204d7b550200302 (diff) | |
| download | ducc-df4cce06a3c84c1441f113b0c2973eec8c2f7d49.tar.gz ducc-df4cce06a3c84c1441f113b0c2973eec8c2f7d49.tar.zst ducc-df4cce06a3c84c1441f113b0c2973eec8c2f7d49.zip | |
refactor: refactor preprocessor
| -rw-r--r-- | preprocess.c | 237 | ||||
| -rw-r--r-- | tests/083.sh | 10 |
2 files changed, 115 insertions, 132 deletions
diff --git a/preprocess.c b/preprocess.c index 72e8ca3..32be2b4 100644 --- a/preprocess.c +++ b/preprocess.c @@ -668,58 +668,42 @@ void remove_directive_tokens(Token* start, Token* end) { } } -Token* process_endif_directive(Preprocessor* pp, Token* tok) { - Token* tok2 = skip_whitespace(tok + 1); - if (tok2->kind == TokenKind_ident && string_equals_cstr(&tok2->raw, "endif")) { - ++tok2; - pp->skip_pp_tokens = FALSE; - remove_directive_tokens(tok, tok2); - return tok2; - } - return NULL; +Token* process_endif_directive(Preprocessor* pp, Token* tok, Token* tok2) { + ++tok2; + pp->skip_pp_tokens = FALSE; + remove_directive_tokens(tok, tok2); + return tok2; } -Token* process_else_directive(Preprocessor* pp, Token* tok) { - Token* tok2 = skip_whitespace(tok + 1); - if (tok2->kind == TokenKind_keyword_else) { - ++tok2; - pp->skip_pp_tokens = !pp->skip_pp_tokens; - remove_directive_tokens(tok, tok2); - return tok2; - } - return NULL; +Token* process_else_directive(Preprocessor* pp, Token* tok, Token* tok2) { + ++tok2; + pp->skip_pp_tokens = !pp->skip_pp_tokens; + remove_directive_tokens(tok, tok2); + return tok2; } -Token* process_ifdef_directive(Preprocessor* pp, Token* tok) { - Token* tok2 = skip_whitespace(tok + 1); - if (tok2->kind == TokenKind_ident && string_equals_cstr(&tok2->raw, "ifdef")) { +Token* process_ifdef_directive(Preprocessor* pp, Token* tok, Token* tok2) { + ++tok2; + tok2 = skip_whitespace(tok2); + if (tok2->kind == TokenKind_ident) { + Token* name = tok2; ++tok2; - tok2 = skip_whitespace(tok2); - if (tok2->kind == TokenKind_ident) { - Token* name = tok2; - ++tok2; - pp->skip_pp_tokens = find_pp_macro(pp, &name->raw) == -1; - } - remove_directive_tokens(tok, tok2); - return tok2; + pp->skip_pp_tokens = find_pp_macro(pp, &name->raw) == -1; } - return NULL; + remove_directive_tokens(tok, tok2); + return tok2; } -Token* process_ifndef_directive(Preprocessor* pp, Token* tok) { - Token* tok2 = skip_whitespace(tok + 1); - if (tok2->kind == TokenKind_ident && string_equals_cstr(&tok2->raw, "ifndef")) { +Token* process_ifndef_directive(Preprocessor* pp, Token* tok, Token* tok2) { + ++tok2; + tok2 = skip_whitespace(tok2); + if (tok2->kind == TokenKind_ident) { + Token* name = tok2; ++tok2; - tok2 = skip_whitespace(tok2); - if (tok2->kind == TokenKind_ident) { - Token* name = tok2; - ++tok2; - pp->skip_pp_tokens = find_pp_macro(pp, &name->raw) != -1; - } - remove_directive_tokens(tok, tok2); - return tok2; + pp->skip_pp_tokens = find_pp_macro(pp, &name->raw) != -1; } - return NULL; + remove_directive_tokens(tok, tok2); + return tok2; } Token* read_include_header_name(Token* tok2, String* include_name) { @@ -801,93 +785,82 @@ Token* expand_include_directive(Preprocessor* pp, Token* tok, Token* tok2, const return replace_pp_tokens(pp, tok, tok2 + 1, count_pp_tokens(include_pp_tokens), include_pp_tokens); } -Token* process_include_directive(Preprocessor* pp, Token* tok) { - Token* tok2 = skip_whitespace(tok + 1); - - if (tok2->kind == TokenKind_ident && string_equals_cstr(&tok2->raw, "include")) { - ++tok2; - tok2 = skip_whitespace(tok2); - String* include_name = calloc(1, sizeof(String)); - tok2 = read_include_header_name(tok2, include_name); - const char* include_name_buf = resolve_include_name(pp, include_name); - if (include_name_buf == NULL) { - fatal_error("cannot resolve include file name: %.*s", include_name->len, include_name->data); - } - return expand_include_directive(pp, tok, tok2, include_name_buf); +Token* process_include_directive(Preprocessor* pp, Token* tok, Token* tok2) { + ++tok2; + tok2 = skip_whitespace(tok2); + String* include_name = calloc(1, sizeof(String)); + tok2 = read_include_header_name(tok2, include_name); + const char* include_name_buf = resolve_include_name(pp, include_name); + if (include_name_buf == NULL) { + fatal_error("cannot resolve include file name: %.*s", include_name->len, include_name->data); } - return NULL; + return expand_include_directive(pp, tok, tok2, include_name_buf); } -Token* process_define_directive(Preprocessor* pp, Token* tok) { - Token* tok2 = skip_whitespace(tok + 1); +Token* process_define_directive(Preprocessor* pp, Token* tok, Token* tok2) { Token* tok3 = NULL; PpMacro* pp_macro; int i; - if (tok2->kind == TokenKind_ident && string_equals_cstr(&tok2->raw, "define")) { + ++tok2; + tok2 = skip_whitespace(tok2); + if (tok2->kind != TokenKind_ident) { + fatal_error("%s:%s: invalid #define syntax", tok2->loc.filename, tok2->loc.line); + } + + Token* macro_name = tok2; + ++tok2; + if (tok2->kind == TokenKind_paren_l) { ++tok2; - tok2 = skip_whitespace(tok2); - if (tok2->kind == TokenKind_ident) { - Token* macro_name = tok2; + if (tok2->kind == TokenKind_paren_r) { ++tok2; - if (tok2->kind == TokenKind_paren_l) { - ++tok2; - if (tok2->kind == TokenKind_paren_r) { - ++tok2; - } else { - fatal_error("%s:%d: invalid function-like macro syntax (#define %.*s)", macro_name->loc.filename, - macro_name->loc.line, macro_name->raw.len, macro_name->raw.data); - } - tok3 = find_next_newline(tok2); - if (tok3) { - pp_macro = pp->pp_macros->data + pp->pp_macros->len; - pp_macro->kind = PpMacroKind_func; - pp_macro->name = macro_name->raw; - pp_macro->n_replacements = tok3 - tok2; - pp_macro->replacements = calloc(pp_macro->n_replacements, sizeof(Token)); - for (i = 0; i < pp_macro->n_replacements; ++i) { - pp_macro->replacements[i] = tok2[i]; - } - ++pp->pp_macros->len; - } - } else { - tok3 = find_next_newline(tok2); - if (tok3) { - pp_macro = pp->pp_macros->data + pp->pp_macros->len; - pp_macro->kind = PpMacroKind_obj; - pp_macro->name = macro_name->raw; - pp_macro->n_replacements = tok3 - tok2; - pp_macro->replacements = calloc(pp_macro->n_replacements, sizeof(Token)); - for (i = 0; i < pp_macro->n_replacements; ++i) { - pp_macro->replacements[i] = tok2[i]; - } - ++pp->pp_macros->len; - } - } + } else { + fatal_error("%s:%d: invalid function-like macro syntax (#define %.*s)", macro_name->loc.filename, + macro_name->loc.line, macro_name->raw.len, macro_name->raw.data); + } + tok3 = find_next_newline(tok2); + if (!tok3) { + fatal_error("%s:%s: invalid #define syntax", tok3->loc.filename, tok3->loc.line); + } + pp_macro = pp->pp_macros->data + pp->pp_macros->len; + pp_macro->kind = PpMacroKind_func; + pp_macro->name = macro_name->raw; + pp_macro->n_replacements = tok3 - tok2; + pp_macro->replacements = calloc(pp_macro->n_replacements, sizeof(Token)); + for (i = 0; i < pp_macro->n_replacements; ++i) { + pp_macro->replacements[i] = tok2[i]; + } + ++pp->pp_macros->len; + } else { + tok3 = find_next_newline(tok2); + if (!tok3) { + fatal_error("%s:%s: invalid #define syntax", tok3->loc.filename, tok3->loc.line); } - if (tok3) { - remove_directive_tokens(tok, tok3); - return tok3; + pp_macro = pp->pp_macros->data + pp->pp_macros->len; + pp_macro->kind = PpMacroKind_obj; + pp_macro->name = macro_name->raw; + pp_macro->n_replacements = tok3 - tok2; + pp_macro->replacements = calloc(pp_macro->n_replacements, sizeof(Token)); + for (i = 0; i < pp_macro->n_replacements; ++i) { + pp_macro->replacements[i] = tok2[i]; } + ++pp->pp_macros->len; } - return NULL; + remove_directive_tokens(tok, tok3); + return tok3; } -Token* process_undef_directive(Preprocessor* pp, Token* tok) { - Token* tok2 = skip_whitespace(tok + 1); - if (tok2->kind == TokenKind_ident && string_equals_cstr(&tok2->raw, "undef")) { - tok2 = skip_whitespace(tok2 + 1); - if (tok2->kind == TokenKind_ident) { - Token* macro_name = tok2; - ++tok2; - int pp_macro_idx = find_pp_macro(pp, ¯o_name->raw); - if (pp_macro_idx != -1) { - undef_pp_macro(pp, pp_macro_idx); - } +Token* process_undef_directive(Preprocessor* pp, Token* tok, Token* tok2) { + tok2 = skip_whitespace(tok2 + 1); + if (tok2->kind == TokenKind_ident) { + Token* macro_name = tok2; + ++tok2; + int pp_macro_idx = find_pp_macro(pp, ¯o_name->raw); + if (pp_macro_idx != -1) { + undef_pp_macro(pp, pp_macro_idx); } - remove_directive_tokens(tok, tok2); - return tok2; } - return NULL; + remove_directive_tokens(tok, tok2); + return tok2; } BOOL expand_macro(Preprocessor* pp, Token* tok) { @@ -942,38 +915,38 @@ void process_pp_directives(Preprocessor* pp) { while (tok->kind != TokenKind_eof) { if (is_pp_hash(tok)) { - Token* next_tok; - - if ((next_tok = process_endif_directive(pp, tok)) != NULL) { - tok = next_tok; + // TODO: don't skip newline after '#'. + Token* tok2 = skip_whitespace(tok + 1); + if (tok2->kind == TokenKind_ident && string_equals_cstr(&tok2->raw, "endif")) { + tok = process_endif_directive(pp, tok, tok2); continue; } - if ((next_tok = process_else_directive(pp, tok)) != NULL) { - tok = next_tok; + if (tok2->kind == TokenKind_keyword_else) { + tok = process_else_directive(pp, tok, tok2); continue; } - if ((next_tok = process_ifdef_directive(pp, tok)) != NULL) { - tok = next_tok; + if (tok2->kind == TokenKind_ident && string_equals_cstr(&tok2->raw, "ifdef")) { + tok = process_ifdef_directive(pp, tok, tok2); continue; } - if ((next_tok = process_ifndef_directive(pp, tok)) != NULL) { - tok = next_tok; + if (tok2->kind == TokenKind_ident && string_equals_cstr(&tok2->raw, "ifndef")) { + tok = process_ifndef_directive(pp, tok, tok2); continue; } if (skip_pp_tokens(pp)) { make_token_whitespace(tok); - } else if ((next_tok = process_include_directive(pp, tok)) != NULL) { - tok = next_tok; + } else if (tok2->kind == TokenKind_ident && string_equals_cstr(&tok2->raw, "include")) { + tok = process_include_directive(pp, tok, tok2); continue; - } else if ((next_tok = process_define_directive(pp, tok)) != NULL) { - tok = next_tok; + } else if (tok2->kind == TokenKind_ident && string_equals_cstr(&tok2->raw, "define")) { + tok = process_define_directive(pp, tok, tok2); continue; - } else if ((next_tok = process_undef_directive(pp, tok)) != NULL) { - tok = next_tok; + } else if (tok2->kind == TokenKind_ident && string_equals_cstr(&tok2->raw, "undef")) { + tok = process_undef_directive(pp, tok, tok2); continue; } else { - fatal_error("%s:%d: unknown preprocessor directive (%s)", tok->loc.filename, tok->loc.line, - token_stringify(tok + 1)); + fatal_error("%s:%d: unknown preprocessor directive (%s)", tok2->loc.filename, tok2->loc.line, + token_stringify(tok2)); } } else if (skip_pp_tokens(pp)) { make_token_whitespace(tok); diff --git a/tests/083.sh b/tests/083.sh index 8047f1f..1d95dae 100644 --- a/tests/083.sh +++ b/tests/083.sh @@ -9,3 +9,13 @@ bash ../../test_compile_error.sh <<'EOF' int main() {} EOF + +cat <<'EOF' > expected +main.c:1: unknown preprocessor directive (bar (<identifier>)) +EOF + +bash ../../test_compile_error.sh <<'EOF' +# bar 1 2 3 + +int main() {} +EOF |
