aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2025-08-31 00:28:00 +0900
committernsfisis <nsfisis@gmail.com>2025-08-31 12:04:19 +0900
commitda65f1e21a24f0a173ee5ae08f00db91cba5ffda (patch)
tree3ec802f40d7cd0bd9e162ea5b3e50b76f319a884 /src
parenta5ee9d944edf665c814bbfeded2849f2bb980ed8 (diff)
downloadducc-da65f1e21a24f0a173ee5ae08f00db91cba5ffda.tar.gz
ducc-da65f1e21a24f0a173ee5ae08f00db91cba5ffda.tar.zst
ducc-da65f1e21a24f0a173ee5ae08f00db91cba5ffda.zip
feat: support -MMD flag
Diffstat (limited to 'src')
-rw-r--r--src/cli.c8
-rw-r--r--src/cli.h1
-rw-r--r--src/fs.c26
-rw-r--r--src/fs.h7
-rw-r--r--src/io.c7
-rw-r--r--src/main.c21
-rw-r--r--src/preprocess.c33
-rw-r--r--src/preprocess.h3
-rw-r--r--src/std.h1
9 files changed, 90 insertions, 17 deletions
diff --git a/src/cli.c b/src/cli.c
index ccc64b9..d4297aa 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -5,6 +5,7 @@ CliArgs* parse_cli_args(int argc, char** argv) {
const char* output_filename = NULL;
int positional_arguments_start = -1;
BOOL only_compile = FALSE;
+ BOOL generate_deps = FALSE;
for (int i = 1; i < argc; ++i) {
if (argv[i][0] != '-') {
@@ -16,8 +17,8 @@ CliArgs* parse_cli_args(int argc, char** argv) {
// ignore
} else if (c == 'O') {
// ignore
- } else if (c == 'M') {
- // ignore
+ } else if (c == 'M' && argv[i][2] == '\0') {
+ // ignore -M
} else if (c == 'o') {
if (argc <= i + 1) {
fatal_error("-o requires filename");
@@ -26,6 +27,8 @@ CliArgs* parse_cli_args(int argc, char** argv) {
++i;
} else if (c == 'c') {
only_compile = TRUE;
+ } else if (strcmp(argv[i], "-MMD") == 0) {
+ generate_deps = TRUE;
} else {
fatal_error("unknown option: %s", argv[i]);
}
@@ -41,6 +44,7 @@ CliArgs* parse_cli_args(int argc, char** argv) {
a->only_compile = only_compile;
a->totally_deligate_to_gcc = FALSE;
a->gcc_command = NULL;
+ a->generate_deps = generate_deps;
if (!a->only_compile && str_ends_with(a->input_filename, ".o")) {
a->totally_deligate_to_gcc = TRUE;
diff --git a/src/cli.h b/src/cli.h
index 3288c10..398ecaf 100644
--- a/src/cli.h
+++ b/src/cli.h
@@ -8,6 +8,7 @@ struct CliArgs {
const char* output_filename;
BOOL output_assembly;
BOOL only_compile;
+ BOOL generate_deps;
BOOL totally_deligate_to_gcc;
const char* gcc_command;
};
diff --git a/src/fs.c b/src/fs.c
new file mode 100644
index 0000000..a299ef9
--- /dev/null
+++ b/src/fs.c
@@ -0,0 +1,26 @@
+#include "fs.h"
+#include "std.h"
+
+// 'ext' must include '.'.
+char* replace_extension(const char* file_name, const char* ext) {
+ size_t len = strlen(file_name);
+ const char* last_slash = strrchr(file_name, '/');
+ const char* last_dot = strrchr(file_name, '.');
+
+ size_t ext_len = strlen(ext);
+ size_t base_len;
+ // !last_slash: foo.c
+ // last_slash < last_dot: ./bar/foo.c
+ if (last_dot && (!last_slash || last_slash < last_dot)) {
+ base_len = last_dot - file_name;
+ } else {
+ base_len = len;
+ }
+
+ char* result = calloc(base_len + ext_len + 1, sizeof(char));
+ memcpy(result, file_name, base_len);
+ memcpy(result + base_len, ext, ext_len);
+ result[base_len + ext_len] = '\0';
+
+ return result;
+}
diff --git a/src/fs.h b/src/fs.h
new file mode 100644
index 0000000..b71889f
--- /dev/null
+++ b/src/fs.h
@@ -0,0 +1,7 @@
+#ifndef DUCC_FS_H
+#define DUCC_FS_H
+
+// 'ext' must include '.'.
+char* replace_extension(const char* file_name, const char* ext);
+
+#endif
diff --git a/src/io.c b/src/io.c
index 5530ab7..ecbb0c9 100644
--- a/src/io.c
+++ b/src/io.c
@@ -14,12 +14,7 @@ void sourcelocation_build_json(JsonBuilder* builder, SourceLocation* loc) {
}
InFile* infile_open(const char* filename) {
- FILE* in;
- if (strcmp(filename, "-") == 0) {
- in = stdin;
- } else {
- in = fopen(filename, "rb");
- }
+ FILE* in = fopen(filename, "rb");
if (!in) {
return NULL;
}
diff --git a/src/main.c b/src/main.c
index 5704367..b064f39 100644
--- a/src/main.c
+++ b/src/main.c
@@ -2,6 +2,7 @@
#include "cli.h"
#include "codegen.h"
#include "common.h"
+#include "fs.h"
#include "io.h"
#include "parse.h"
#include "preprocess.h"
@@ -16,7 +17,11 @@ int main(int argc, char** argv) {
}
InFile* source = infile_open(cli_args->input_filename);
- TokenArray* pp_tokens = preprocess(source);
+
+ StrArray included_files;
+ strings_init(&included_files);
+
+ TokenArray* pp_tokens = preprocess(source, &included_files);
TokenArray* tokens = tokenize(pp_tokens);
Program* prog = parse(tokens);
@@ -45,4 +50,18 @@ int main(int argc, char** argv) {
fatal_error("gcc failed: %d", result);
}
}
+
+ if (cli_args->generate_deps && cli_args->only_compile && cli_args->output_filename) {
+ const char* dep_filename = replace_extension(cli_args->output_filename, ".d");
+
+ FILE* dep_file = fopen(dep_filename, "w");
+ if (!dep_file) {
+ fatal_error("Cannot open dependency file: %s", dep_filename);
+ }
+ fprintf(dep_file, "%s:", cli_args->output_filename);
+ for (size_t i = 0; i < included_files.len; ++i) {
+ fprintf(dep_file, " \\\n %s", included_files.data[i]);
+ }
+ fprintf(dep_file, "\n");
+ }
}
diff --git a/src/preprocess.c b/src/preprocess.c
index 284a633..03a2121 100644
--- a/src/preprocess.c
+++ b/src/preprocess.c
@@ -559,12 +559,14 @@ struct Preprocessor {
int include_depth;
char** include_paths;
int n_include_paths;
+ StrArray* included_files;
};
typedef struct Preprocessor Preprocessor;
-static TokenArray* do_preprocess(InFile* src, int depth, MacroArray* macros);
+static TokenArray* do_preprocess(InFile* src, int depth, MacroArray* macros, StrArray* included_files);
-static Preprocessor* preprocessor_new(TokenArray* pp_tokens, int include_depth, MacroArray* macros) {
+static Preprocessor* preprocessor_new(TokenArray* pp_tokens, int include_depth, MacroArray* macros,
+ StrArray* included_files) {
if (include_depth >= 32) {
fatal_error("include depth limit exceeded");
}
@@ -574,6 +576,7 @@ static Preprocessor* preprocessor_new(TokenArray* pp_tokens, int include_depth,
pp->macros = macros;
pp->include_depth = include_depth;
pp->include_paths = calloc(16, sizeof(char*));
+ pp->included_files = included_files;
return pp;
}
@@ -745,7 +748,8 @@ static void expand_include_directive(Preprocessor* pp, const char* include_name,
original_include_name_tok->loc.line, token_stringify(original_include_name_tok));
}
- TokenArray* include_pp_tokens = do_preprocess(include_source, pp->include_depth + 1, pp->macros);
+ TokenArray* include_pp_tokens =
+ do_preprocess(include_source, pp->include_depth + 1, pp->macros, pp->included_files);
tokens_pop(include_pp_tokens); // pop EOF token
pp->pos = insert_pp_tokens(pp, pp->pos, include_pp_tokens);
}
@@ -1119,6 +1123,20 @@ static void preprocess_include_directive(Preprocessor* pp) {
fatal_error("%s:%d: cannot resolve include file name: %s", include_name->loc.filename, include_name->loc.line,
token_stringify(include_name));
}
+
+ if (include_name->value.string[0] == '"') {
+ BOOL already_included = FALSE;
+ for (size_t i = 0; i < pp->included_files->len; ++i) {
+ if (strcmp(pp->included_files->data[i], include_name_resolved) == 0) {
+ already_included = TRUE;
+ break;
+ }
+ }
+ if (!already_included) {
+ strings_push(pp->included_files, include_name_resolved);
+ }
+ }
+
skip_whitespaces(pp);
expect_pp_token(pp, TokenKind_newline);
expand_include_directive(pp, include_name_resolved, include_name);
@@ -1379,9 +1397,9 @@ static char* get_ducc_include_path() {
return buf;
}
-static TokenArray* do_preprocess(InFile* src, int depth, MacroArray* macros) {
+static TokenArray* do_preprocess(InFile* src, int depth, MacroArray* macros, StrArray* included_files) {
TokenArray* pp_tokens = pp_tokenize(src);
- Preprocessor* pp = preprocessor_new(pp_tokens, depth, macros);
+ Preprocessor* pp = preprocessor_new(pp_tokens, depth, macros, included_files);
add_include_path(pp, get_ducc_include_path());
add_include_path(pp, "/usr/include/x86_64-linux-gnu");
add_include_path(pp, "/usr/include");
@@ -1390,8 +1408,9 @@ static TokenArray* do_preprocess(InFile* src, int depth, MacroArray* macros) {
return pp->pp_tokens;
}
-TokenArray* preprocess(InFile* src) {
+TokenArray* preprocess(InFile* src, StrArray* included_files) {
MacroArray* macros = macros_new();
add_predefined_macros(macros);
- return do_preprocess(src, 0, macros);
+ strings_push(included_files, src->loc.filename);
+ return do_preprocess(src, 0, macros, included_files);
}
diff --git a/src/preprocess.h b/src/preprocess.h
index b43ec4c..81007c3 100644
--- a/src/preprocess.h
+++ b/src/preprocess.h
@@ -1,9 +1,10 @@
#ifndef DUCC_PREPROCESS_H
#define DUCC_PREPROCESS_H
+#include "common.h"
#include "io.h"
#include "token.h"
-TokenArray* preprocess(InFile* src);
+TokenArray* preprocess(InFile* src, StrArray* included_files);
#endif
diff --git a/src/std.h b/src/std.h
index 2353026..2b1ad4a 100644
--- a/src/std.h
+++ b/src/std.h
@@ -34,6 +34,7 @@ int strncmp(const char*, const char*, size_t);
char* strdup(const char*);
char* strndup(const char*, size_t);
char* strstr(const char*, const char*);
+char* strrchr(const char*, int);
long strtol(const char*, char**, int);
int system(const char*);