scc

simple C compiler
git clone git://git.2f30.org/scc
Log | Files | Refs | README | LICENSE

commit 84ae6c8c605f208229ccf38cfcc6b42ae735b1db
parent 4b68176e2bfbb30df5a9820800a53d87ca7d0620
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Sun, 10 May 2015 10:39:32 +0200

Add #line directive

Diffstat:
Mcc1/cc1.h | 6++++--
Mcc1/cpp.c | 39+++++++++++++++++++++++++++++++++++++--
Mcc1/error.c | 2+-
Mcc1/lex.c | 19++++++++++++++++---
4 files changed, 58 insertions(+), 8 deletions(-)

diff --git a/cc1/cc1.h b/cc1/cc1.h @@ -263,8 +263,10 @@ extern uint8_t ahead(void); extern uint8_t next(void); extern void expect(uint8_t tok); extern void discard(void); -extern char *filename(void); -extern unsigned short fileline(void); +extern char *getfname(void); +extern unsigned short getfline(void); +extern void setfname(char *name); +extern void setfline(unsigned short line); extern bool addinput(char *fname); extern void delinput(void); #define accept(t) ((yytoken == (t)) ? next() : 0) diff --git a/cc1/cpp.c b/cc1/cpp.c @@ -9,7 +9,7 @@ #include "cc1.h" /* TODO: preprocessor error must not rise recover */ -char * +static char * include(char *s) { char fname[FILENAME_MAX], delim, c, *p; @@ -50,6 +50,39 @@ bad_include: } static char * +line(char *s) +{ + char *p, *q; + + for (p = s; isdigit(*p); ++p) + /* nothing */; + switch (*p) { + case ' ': + case '\t': + while (isspace(*p)) + ++p; + if (*p != '"') + goto bad_line; + for (q = p+1; *q && *q != '"'; ++q) + /* nothing */; + if (*q == '\0') + goto bad_line; + *q = '\0'; + setfname(p); + p = q+1; + /* passthrough */ + case '\0': + setfline(atoi(s)-1); + return p; + default: + goto bad_line; + } + +bad_line: + error("incorrect #line directive"); +} + +static char * pragma(char *s) { while (*s) @@ -60,7 +93,7 @@ pragma(char *s) static char * usererr(char *s) { - fprintf(stderr, "%s:%u:error: #error %s\n", filename(), fileline(), s); + fprintf(stderr, "%s:%u:error: #error %s\n", getfname(), getfline(), s); exit(-1); } @@ -71,12 +104,14 @@ preprocessor(char *p) unsigned short n; static char **bp, *cmds[] = { "include", + "line", "pragma", "error", NULL }; static char *(*funs[])(char *) = { include, + line, pragma, usererr }; diff --git a/cc1/error.c b/cc1/error.c @@ -18,7 +18,7 @@ warn_helper(int8_t flag, char *fmt, va_list va) if (!flag) return; fprintf(stderr, "%s:%s:%u: ", - (flag < 0) ? "error" : "warning", filename(), fileline()); + (flag < 0) ? "error" : "warning", getfname(), getfline()); vfprintf(stderr, fmt, va); putc('\n', stderr); if (flag < 0 && nerrors++ == MAXERRNUM) { diff --git a/cc1/lex.c b/cc1/lex.c @@ -45,7 +45,7 @@ addinput(char *fname) fname = xstrdup(fname); } else if (!input) { fp = stdin; - fname = "(stdin)"; + fname = xstrdup("<stdin>"); } else { fname = input->fname; nline = input->nline; @@ -79,14 +79,27 @@ delinput(void) free(ip); } +void +setfname(char *name) +{ + free(input->fname); + input->fname = xstrdup(name); +} + char * -filename(void) +getfname(void) { return input->fname; } +void +setfline(unsigned short line) +{ + input->nline = line; +} + unsigned short -fileline(void) +getfline(void) { return input->nline; }