aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2025-07-31 00:26:21 +0900
committernsfisis <nsfisis@gmail.com>2025-08-15 10:04:44 +0900
commit2dcf1082a308bf27f11616c3e1bde4100d22e5c9 (patch)
tree681a0a17fe84fd62f98ebca29c9a094f3d5e56e8
parent2d5b6796c4fcc6a22b77a638e60ec9ea0ac58709 (diff)
downloadducc-2dcf1082a308bf27f11616c3e1bde4100d22e5c9.tar.gz
ducc-2dcf1082a308bf27f11616c3e1bde4100d22e5c9.tar.zst
ducc-2dcf1082a308bf27f11616c3e1bde4100d22e5c9.zip
feat: implement function-like macro without parameters
-rw-r--r--preprocess.c71
-rw-r--r--tests/070.sh15
2 files changed, 69 insertions, 17 deletions
diff --git a/preprocess.c b/preprocess.c
index 7141dec..e909eec 100644
--- a/preprocess.c
+++ b/preprocess.c
@@ -18,7 +18,14 @@ struct PpToken {
};
typedef struct PpToken PpToken;
+enum PpMacroKind {
+ PpMacroKind_obj,
+ PpMacroKind_func,
+};
+typedef enum PpMacroKind PpMacroKind;
+
struct PpMacro {
+ PpMacroKind kind;
String name;
PpToken* tokens;
};
@@ -53,6 +60,7 @@ PpMacros* pp_macros_new() {
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->tokens = calloc(1, sizeof(PpToken));
@@ -500,24 +508,50 @@ PpToken* process_include_directive(Preprocessor* pp, PpToken* tok) {
PpToken* process_define_directive(Preprocessor* pp, PpToken* tok) {
PpToken* tok2 = skip_whitespace(tok + 1);
+ PpToken* macro_replacements;
+ PpMacro* pp_macro;
if (tok2->kind == PpTokenKind_identifier && string_equals_cstr(&tok2->raw, "define")) {
++tok2;
tok2 = skip_whitespace(tok2);
if (tok2->kind == PpTokenKind_identifier) {
PpToken* macro_name = tok2;
++tok2;
- tok2 = skip_whitespace(tok2);
- if (tok2->kind == PpTokenKind_identifier || tok2->kind == PpTokenKind_pp_number) {
- PpToken* macro_replacements = tok2;
-
- PpMacro* pp_macro = pp->pp_macros->data + pp->pp_macros->len;
- pp_macro->name.len = macro_name->raw.len;
- pp_macro->name.data = macro_name->raw.data;
- pp_macro->tokens = calloc(1, sizeof(PpToken));
- pp_macro->tokens[0].kind = macro_replacements->kind;
- pp_macro->tokens[0].raw.len = macro_replacements->raw.len;
- pp_macro->tokens[0].raw.data = macro_replacements->raw.data;
- ++pp->pp_macros->len;
+ if (tok2->kind == PpTokenKind_punctuator && string_equals_cstr(&tok2->raw, "(")) {
+ ++tok2;
+ if (tok2->kind == PpTokenKind_punctuator && string_equals_cstr(&tok2->raw, ")")) {
+ ++tok2;
+ } else {
+ fatal_error("#define: invalid function-like macro syntax");
+ }
+ tok2 = skip_whitespace(tok2);
+ if (tok2->kind == PpTokenKind_identifier || tok2->kind == PpTokenKind_pp_number) {
+ macro_replacements = tok2;
+
+ pp_macro = pp->pp_macros->data + pp->pp_macros->len;
+ pp_macro->kind = PpMacroKind_func;
+ pp_macro->name.len = macro_name->raw.len;
+ pp_macro->name.data = macro_name->raw.data;
+ pp_macro->tokens = calloc(1, sizeof(PpToken));
+ pp_macro->tokens[0].kind = macro_replacements->kind;
+ pp_macro->tokens[0].raw.len = macro_replacements->raw.len;
+ pp_macro->tokens[0].raw.data = macro_replacements->raw.data;
+ ++pp->pp_macros->len;
+ }
+ } else {
+ tok2 = skip_whitespace(tok2);
+ if (tok2->kind == PpTokenKind_identifier || tok2->kind == PpTokenKind_pp_number) {
+ macro_replacements = tok2;
+
+ pp_macro = pp->pp_macros->data + pp->pp_macros->len;
+ pp_macro->kind = PpMacroKind_obj;
+ pp_macro->name.len = macro_name->raw.len;
+ pp_macro->name.data = macro_name->raw.data;
+ pp_macro->tokens = calloc(1, sizeof(PpToken));
+ pp_macro->tokens[0].kind = macro_replacements->kind;
+ pp_macro->tokens[0].raw.len = macro_replacements->raw.len;
+ pp_macro->tokens[0].raw.data = macro_replacements->raw.data;
+ ++pp->pp_macros->len;
+ }
}
}
remove_directive_tokens(tok, tok2 + 1);
@@ -528,12 +562,15 @@ PpToken* process_define_directive(Preprocessor* pp, PpToken* tok) {
void expand_macro(Preprocessor* pp, PpToken* tok) {
int pp_macro_idx = find_pp_macro(pp, &tok->raw);
- if (pp_macro_idx != -1) {
- PpToken* macro_replacements = pp->pp_macros->data[pp_macro_idx].tokens;
- tok->kind = macro_replacements->kind;
- tok->raw.data = macro_replacements->raw.data;
- tok->raw.len = macro_replacements->raw.len;
+ if (pp_macro_idx == -1) {
+ return;
}
+
+ PpMacro* pp_macro = pp->pp_macros->data + pp_macro_idx;
+ PpToken* macro_replacements = pp_macro->tokens;
+ tok->kind = macro_replacements->kind;
+ tok->raw.data = macro_replacements->raw.data;
+ tok->raw.len = macro_replacements->raw.len;
}
void process_pp_directives(Preprocessor* pp) {
diff --git a/tests/070.sh b/tests/070.sh
new file mode 100644
index 0000000..9a15499
--- /dev/null
+++ b/tests/070.sh
@@ -0,0 +1,15 @@
+set -e
+
+cat <<'EOF' > expected
+123
+EOF
+
+bash ../../test_diff.sh <<'EOF'
+#define foo() 123
+
+int printf();
+
+int main() {
+ printf("%d\n", foo());
+}
+EOF