aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--common.c12
-rw-r--r--io.c31
-rw-r--r--main.c9
-rw-r--r--preprocess.c72
-rw-r--r--tests/073.sh20
5 files changed, 102 insertions, 42 deletions
diff --git a/common.c b/common.c
index 63a3feb..965c020 100644
--- a/common.c
+++ b/common.c
@@ -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;
diff --git a/io.c b/io.c
new file mode 100644
index 0000000..6c92b20
--- /dev/null
+++ b/io.c
@@ -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;
+}
diff --git a/main.c b/main.c
index 0aedc6d..3d06c02 100644
--- a/main.c
+++ b/main.c
@@ -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