diff options
| -rw-r--r-- | common.c | 12 | ||||
| -rw-r--r-- | io.c | 31 | ||||
| -rw-r--r-- | main.c | 9 | ||||
| -rw-r--r-- | preprocess.c | 72 | ||||
| -rw-r--r-- | tests/073.sh | 20 |
5 files changed, 102 insertions, 42 deletions
@@ -15,18 +15,6 @@ void unimplemented() { fatal_error("unimplemented"); } -char* read_all(FILE* in) { - char* buf = calloc(1024 * 1024, sizeof(char)); - char* cur = buf; - char* tmp = calloc(1024, sizeof(char)); - while (fgets(tmp, 1024, in)) { - size_t len = strlen(tmp); - memcpy(cur, tmp, len); - cur += len; - } - return buf; -} - struct String { char* data; size_t len; @@ -0,0 +1,31 @@ +struct InFile { + const char* filename; + char* buf; +}; +typedef struct InFile InFile; + +InFile* read_all(const char* filename) { + FILE* in; + if (strcmp(filename, "-") == 0) { + in = stdin; + } else { + in = fopen(filename, "rb"); + } + if (!in) { + return NULL; + } + char* buf = calloc(1024 * 1024, sizeof(char)); + char* cur = buf; + char* tmp = calloc(1024, sizeof(char)); + while (fgets(tmp, 1024, in)) { + size_t len = strlen(tmp); + memcpy(cur, tmp, len); + cur += len; + } + fclose(in); + + InFile* in_file = calloc(1, sizeof(InFile)); + in_file->filename = filename; + in_file->buf = buf; + return in_file; +} @@ -2,6 +2,7 @@ // clang-format off #include "std.h" #include "common.c" +#include "io.c" #include "preprocess.c" #include "tokenize.c" #include "ast.c" @@ -13,13 +14,7 @@ int main(int argc, char** argv) { if (argc == 1) { fatal_error("usage: ducc <FILE>"); } - FILE* in; - if (strcmp(argv[1], "-") == 0) { - in = stdin; - } else { - in = fopen(argv[1], "rb"); - } - char* source = read_all(in); + InFile* source = read_all(argv[1]); PpToken* pp_tokens = preprocess(source); Token* tokens = tokenize(pp_tokens); Program* prog = parse(tokens); diff --git a/preprocess.c b/preprocess.c index 4d939fd..4d13b63 100644 --- a/preprocess.c +++ b/preprocess.c @@ -35,9 +35,15 @@ const char* pp_token_kind_stringify(PpTokenKind kind) { unreachable(); } +struct SourceLocation { + const char* filename; +}; +typedef struct SourceLocation SourceLocation; + struct PpToken { PpTokenKind kind; String raw; + SourceLocation loc; }; typedef struct PpToken PpToken; @@ -51,17 +57,19 @@ const char* pp_token_stringify(PpToken* tok) { enum PpMacroKind { PpMacroKind_obj, PpMacroKind_func, + PpMacroKind_builtin_file, }; typedef enum PpMacroKind PpMacroKind; const char* pp_macro_kind_stringify(PpMacroKind kind) { - if (kind == PpMacroKind_obj) { + if (kind == PpMacroKind_obj) return "object-like"; - } else if (kind == PpMacroKind_func) { + else if (kind == PpMacroKind_func) return "function-like"; - } else { + else if (kind == PpMacroKind_builtin_file) + return "__FILE__"; + else unreachable(); - } } struct PpMacro { @@ -79,6 +87,7 @@ struct PpMacros { typedef struct PpMacros PpMacros; struct Preprocessor { + const char* filename; char* src; int pos; PpToken* pp_tokens; @@ -91,7 +100,7 @@ struct Preprocessor { }; typedef struct Preprocessor Preprocessor; -PpToken* do_preprocess(char* src, int depth, PpMacros* pp_macros); +PpToken* do_preprocess(InFile* src, int depth, PpMacros* pp_macros); PpMacros* pp_macros_new() { PpMacros* pp_macros = calloc(1, sizeof(PpMacros)); @@ -118,15 +127,23 @@ void pp_macros_dump(PpMacros* pp_macros) { } void add_predefined_macros(PpMacros* pp_macros) { - PpMacro* pp_macro = pp_macros->data + pp_macros->len; - pp_macro->kind = PpMacroKind_obj; - pp_macro->name.len = strlen("__ducc__"); - pp_macro->name.data = "__ducc__"; - pp_macro->n_replacements = 1; - pp_macro->replacements = calloc(1, sizeof(PpToken)); - pp_macro->replacements[0].kind = PpTokenKind_pp_number; - pp_macro->replacements[0].raw.len = strlen("1"); - pp_macro->replacements[0].raw.data = "1"; + PpMacro* m; + + m = pp_macros->data + pp_macros->len; + m->kind = PpMacroKind_obj; + m->name.len = strlen("__ducc__"); + m->name.data = "__ducc__"; + m->n_replacements = 1; + m->replacements = calloc(1, sizeof(PpToken)); + m->replacements[0].kind = PpTokenKind_pp_number; + m->replacements[0].raw.len = strlen("1"); + m->replacements[0].raw.data = "1"; + pp_macros->len += 1; + + m = pp_macros->data + pp_macros->len; + m->kind = PpMacroKind_builtin_file; + m->name.len = strlen("__FILE__"); + m->name.data = "__FILE__"; pp_macros->len += 1; } @@ -138,13 +155,14 @@ int count_pp_tokens(PpToken* pp_tokens) { return n; } -Preprocessor* preprocessor_new(char* src, int include_depth, PpMacros* pp_macros) { +Preprocessor* preprocessor_new(InFile* src, int include_depth, PpMacros* pp_macros) { if (include_depth >= 32) { fatal_error("include depth limit exceeded"); } Preprocessor* pp = calloc(1, sizeof(Preprocessor)); - pp->src = src; + pp->filename = src->filename; + pp->src = src->buf; pp->pp_tokens = calloc(1024 * 1024, sizeof(PpToken)); pp->pp_macros = pp_macros; pp->include_depth = include_depth; @@ -180,6 +198,7 @@ void pp_tokenize_all(Preprocessor* pp) { int start; while (pp->src[pp->pos]) { PpToken* tok = pp->pp_tokens + pp->n_pp_tokens; + tok->loc.filename = pp->filename; char c = pp->src[pp->pos]; ++pp->pos; if (c == '(') { @@ -576,12 +595,10 @@ PpToken* replace_pp_tokens(Preprocessor* pp, PpToken* dest_start, PpToken* dest_ } PpToken* expand_include_directive(Preprocessor* pp, PpToken* tok, PpToken* tok2, const char* include_name_buf) { - FILE* include_file = fopen(include_name_buf, "rb"); - if (include_file == NULL) { + InFile* include_source = read_all(include_name_buf); + if (!include_source) { fatal_error("cannot open include file: %s", include_name_buf); } - char* include_source = read_all(include_file); - fclose(include_file); PpToken* include_pp_tokens = do_preprocess(include_source, pp->include_depth + 1, pp->pp_macros); return replace_pp_tokens(pp, tok, tok2 + 1, count_pp_tokens(include_pp_tokens), include_pp_tokens); @@ -669,8 +686,17 @@ void expand_macro(Preprocessor* pp, PpToken* tok) { if (pp_macro->kind == PpMacroKind_func) { // also consume '(' and ')' replace_pp_tokens(pp, tok, tok + 3, pp_macro->n_replacements, pp_macro->replacements); - } else { + } else if (pp_macro->kind == PpMacroKind_obj) { replace_pp_tokens(pp, tok, tok + 1, pp_macro->n_replacements, pp_macro->replacements); + } else if (pp_macro->kind == PpMacroKind_builtin_file) { + PpToken* file_tok = calloc(1, sizeof(PpToken)); + file_tok->kind = PpTokenKind_string_literal; + file_tok->raw.len = strlen(tok->loc.filename) + 2; + file_tok->raw.data = calloc(file_tok->raw.len, sizeof(char)); + sprintf(file_tok->raw.data, "\"%s\"", tok->loc.filename); + replace_pp_tokens(pp, tok, tok + 1, 1, file_tok); + } else { + unreachable(); } } @@ -720,7 +746,7 @@ void pp_dump(PpToken* t, int include_whitespace) { } } -PpToken* do_preprocess(char* src, int depth, PpMacros* pp_macros) { +PpToken* do_preprocess(InFile* src, int depth, PpMacros* pp_macros) { Preprocessor* pp = preprocessor_new(src, depth, pp_macros); add_include_path(pp, "/home/ken/src/ducc/include"); add_include_path(pp, "/usr/include"); @@ -729,7 +755,7 @@ PpToken* do_preprocess(char* src, int depth, PpMacros* pp_macros) { return pp->pp_tokens; } -PpToken* preprocess(char* src) { +PpToken* preprocess(InFile* src) { PpMacros* pp_macros = pp_macros_new(); add_predefined_macros(pp_macros); return do_preprocess(src, 0, pp_macros); diff --git a/tests/073.sh b/tests/073.sh new file mode 100644 index 0000000..8dc165e --- /dev/null +++ b/tests/073.sh @@ -0,0 +1,20 @@ +set -e + +cat <<'EOF' > expected +main.c +EOF + +cat <<'EOF' > header.h +#define A __FILE__ +EOF + +bash ../../test_diff.sh <<'EOF' +#define B __FILE__ +#include "header.h" +int printf(); +int main() { + printf("%s\n", __FILE__); + // printf("%s\n", B); + // printf("%s\n", A); +} +EOF |
