aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2025-07-31 06:52:46 +0900
committernsfisis <nsfisis@gmail.com>2025-08-15 10:06:21 +0900
commitf53b6ff29c79b288792da24feb55b7ed9db2ba40 (patch)
treea4ebc4e6ad07c79efe5bf99f8eed1b1359f54d2d
parent788cfd8bcc932e545db73da282c48a9bad8ca271 (diff)
downloadducc-f53b6ff29c79b288792da24feb55b7ed9db2ba40.tar.gz
ducc-f53b6ff29c79b288792da24feb55b7ed9db2ba40.tar.zst
ducc-f53b6ff29c79b288792da24feb55b7ed9db2ba40.zip
feat: implement __LINE__ macro
-rw-r--r--preprocess.c23
-rw-r--r--tests/074.sh20
2 files changed, 43 insertions, 0 deletions
diff --git a/preprocess.c b/preprocess.c
index 4d13b63..148b89a 100644
--- a/preprocess.c
+++ b/preprocess.c
@@ -37,6 +37,7 @@ const char* pp_token_kind_stringify(PpTokenKind kind) {
struct SourceLocation {
const char* filename;
+ int line;
};
typedef struct SourceLocation SourceLocation;
@@ -58,6 +59,7 @@ enum PpMacroKind {
PpMacroKind_obj,
PpMacroKind_func,
PpMacroKind_builtin_file,
+ PpMacroKind_builtin_line,
};
typedef enum PpMacroKind PpMacroKind;
@@ -68,6 +70,8 @@ const char* pp_macro_kind_stringify(PpMacroKind kind) {
return "function-like";
else if (kind == PpMacroKind_builtin_file)
return "__FILE__";
+ else if (kind == PpMacroKind_builtin_line)
+ return "__LINE__";
else
unreachable();
}
@@ -88,6 +92,7 @@ typedef struct PpMacros PpMacros;
struct Preprocessor {
const char* filename;
+ int line;
char* src;
int pos;
PpToken* pp_tokens;
@@ -145,6 +150,12 @@ void add_predefined_macros(PpMacros* pp_macros) {
m->name.len = strlen("__FILE__");
m->name.data = "__FILE__";
pp_macros->len += 1;
+
+ m = pp_macros->data + pp_macros->len;
+ m->kind = PpMacroKind_builtin_line;
+ m->name.len = strlen("__LINE__");
+ m->name.data = "__LINE__";
+ pp_macros->len += 1;
}
int count_pp_tokens(PpToken* pp_tokens) {
@@ -162,6 +173,7 @@ Preprocessor* preprocessor_new(InFile* src, int include_depth, PpMacros* pp_macr
Preprocessor* pp = calloc(1, sizeof(Preprocessor));
pp->filename = src->filename;
+ pp->line = 1;
pp->src = src->buf;
pp->pp_tokens = calloc(1024 * 1024, sizeof(PpToken));
pp->pp_macros = pp_macros;
@@ -199,6 +211,7 @@ void pp_tokenize_all(Preprocessor* pp) {
while (pp->src[pp->pos]) {
PpToken* tok = pp->pp_tokens + pp->n_pp_tokens;
tok->loc.filename = pp->filename;
+ tok->loc.line = pp->line;
char c = pp->src[pp->pos];
++pp->pos;
if (c == '(') {
@@ -434,6 +447,9 @@ void pp_tokenize_all(Preprocessor* pp) {
tok->raw.len = pp->pos - start;
tok->kind = PpTokenKind_identifier;
} else if (isspace(c)) {
+ if (c == '\n' || c == '\r') {
+ ++pp->line;
+ }
tok->kind = PpTokenKind_whitespace;
tok->raw.len = 1;
tok->raw.data = pp->src + pp->pos - tok->raw.len;
@@ -695,6 +711,13 @@ void expand_macro(Preprocessor* pp, PpToken* tok) {
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 if (pp_macro->kind == PpMacroKind_builtin_line) {
+ PpToken* line_tok = calloc(1, sizeof(PpToken));
+ line_tok->kind = PpTokenKind_pp_number;
+ line_tok->raw.data = calloc(10, sizeof(char));
+ sprintf(line_tok->raw.data, "%d", tok->loc.line);
+ line_tok->raw.len = strlen(line_tok->raw.data);
+ replace_pp_tokens(pp, tok, tok + 1, 1, line_tok);
} else {
unreachable();
}
diff --git a/tests/074.sh b/tests/074.sh
new file mode 100644
index 0000000..90b86c6
--- /dev/null
+++ b/tests/074.sh
@@ -0,0 +1,20 @@
+set -e
+
+cat <<'EOF' > expected
+5
+EOF
+
+cat <<'EOF' > header.h
+#define A __LINE__
+EOF
+
+bash ../../test_diff.sh <<'EOF'
+#define B __LINE__
+#include "header.h"
+int printf();
+int main() {
+ printf("%d\n", __LINE__);
+ // printf("%d\n", B);
+ // printf("%d\n", A);
+}
+EOF