From 5e1a570b75d5f5edf41be6c1409c283ca768e7e6 Mon Sep 17 00:00:00 2001 From: Michael Forney Date: Thu, 2 Sep 2021 12:03:25 -0700 Subject: pp: Implement #line directives and gcc line markers Fixes #66. --- cc.h | 1 + configure | 2 +- pp.c | 23 ++++++++++++++++++++--- scan.c | 6 ++++++ 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/cc.h b/cc.h index a996541..3b33e8c 100644 --- a/cc.h +++ b/cc.h @@ -383,6 +383,7 @@ _Noreturn void error(const struct location *, const char *, ...); void scanfrom(const char *, FILE *); void scanopen(void); +void scansetloc(struct location loc); void scan(struct token *); /* preprocessor */ diff --git a/configure b/configure index 1d8a0f2..7b8555d 100755 --- a/configure +++ b/configure @@ -139,7 +139,7 @@ static const char target[] = "$target"; static const char *const startfiles[] = {$startfiles}; static const char *const endfiles[] = {$endfiles}; static const char *const preprocesscmd[] = { - "$DEFAULT_PREPROCESSOR", "-P", + "$DEFAULT_PREPROCESSOR", "-E", /* clear preprocessor GNU C version */ "-U", "__GNUC__", diff --git a/pp.c b/pp.c index 9f0c74d..96f76fc 100644 --- a/pp.c +++ b/pp.c @@ -302,15 +302,18 @@ undef(void) static void directive(void) { + struct location newloc; enum ppflags oldflags; - char *name; + char *name = NULL; scan(&tok); if (tok.kind == TNEWLINE) return; /* empty directive */ oldflags = ppflags; ppflags |= PPNEWLINE; - name = tokencheck(&tok, TIDENT, "or newline after '#'"); + if (tok.kind == TNUMBER) + goto line; /* gcc line markers */ + name = tokencheck(&tok, TIDENT, "newline, or number after '#'"); if (strcmp(name, "if") == 0) { error(&tok.loc, "#if directive is not implemented"); } else if (strcmp(name, "ifdef") == 0) { @@ -330,7 +333,21 @@ directive(void) scan(&tok); undef(); } else if (strcmp(name, "line") == 0) { - error(&tok.loc, "#line directive is not implemented"); + scan(&tok); + tokencheck(&tok, TNUMBER, "after #line"); +line: + newloc.line = strtoull(tok.lit, NULL, 0); + scan(&tok); + newloc.file = tok.loc.file; + if (tok.kind == TSTRINGLIT) { + /* XXX: handle escape sequences (reuse string decoding from expr.c) */ + newloc.file = strchr(tok.lit, '"') + 1; + *strchr(newloc.file, '"') = '\0'; + scan(&tok); + } + while (tok.kind == TNUMBER) + scan(&tok); + scansetloc(newloc); } else if (strcmp(name, "error") == 0) { error(&tok.loc, "#error directive is not implemented"); } else if (strcmp(name, "pragma") == 0) { diff --git a/scan.c b/scan.c index 34e003e..a8327bf 100644 --- a/scan.c +++ b/scan.c @@ -444,6 +444,12 @@ scanopen(void) } } +void +scansetloc(struct location loc) +{ + scanner->loc = loc; +} + static void scanclose(void) { -- cgit v1.2.3