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:
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;
}