commit 49f35dc9bb53bafb4fced17fc3d62754620a7792
parent ac253bd1bb4aa75dc5291e9c27dc2db74670b49a
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Mon, 30 Jan 2017 15:52:29 +0100
[cc1] Use LOC variables for input
It is a bad idea to use the values stored directly in input structures,
because input structures disappear before the errors are printed, so it
means that we can try to access through a NULL pointer.
Small fix in newline() and addinput() clarification by quinq.
Diffstat:
4 files changed, 70 insertions(+), 46 deletions(-)
diff --git a/cc1/cc1.h b/cc1/cc1.h
@@ -352,8 +352,8 @@ struct yystype {
struct input {
char flags;
- unsigned short nline;
- char *fname;
+ unsigned lineno;
+ char *filenam;
FILE *fp;
Symbol *hide;
char *line, *begin, *p;
@@ -406,6 +406,7 @@ extern int addinput(char *fname, Symbol *hide, char *buffer);
extern void delinput(void);
extern void setsafe(int type);
extern void ilex(void);
+extern int setloc(char *fname, unsigned line);
#define accept(t) ((yytoken == (t)) ? next() : 0)
/* code.c */
@@ -458,6 +459,8 @@ extern int onlycpp, onlyheader;
extern unsigned curctx;
extern Symbol *curfun, *zero, *one;
extern char *infile, *outfile;
+unsigned lineno;
+char filenam[FILENAME_MAX];
extern Type *voidtype, *pvoidtype, *booltype,
*uchartype, *chartype, *schartype,
diff --git a/cc1/cpp.c b/cc1/cpp.c
@@ -34,8 +34,8 @@ defdefine(char *macro, char *val, char *source)
def = xmalloc(strlen(fmt) + strlen(macro) + strlen(val));
sprintf(def, fmt, macro, val);
+ lineno = ++ncmdlines;
addinput(source, &dummy, def);
- input->nline = ++ncmdlines;
cpp();
delinput();
}
@@ -254,11 +254,11 @@ expand(char *begin, Symbol *sym)
macroname = sym->name;
if (sym == symfile) {
- elen = sprintf(buffer, "\"%s\" ", input->fname);
+ elen = sprintf(buffer, "\"%s\" ", filenam);
goto substitute;
}
if (sym == symline) {
- elen = sprintf(buffer, "%d ", input->nline);
+ elen = sprintf(buffer, "%d ", lineno);
goto substitute;
}
if (!s)
@@ -275,7 +275,7 @@ expand(char *begin, Symbol *sym)
substitute:
DBG("MACRO '%s' expanded to :'%s'", macroname, buffer);
buffer[elen] = '\0';
- addinput(input->fname, sym, xstrdup(buffer));
+ addinput(filenam, sym, xstrdup(buffer));
return 1;
}
@@ -448,7 +448,7 @@ includefile(char *dir, char *file, size_t filelen)
static char *
cwd(char *buf)
{
- char *p, *s = input->fname;
+ char *p, *s = filenam;
size_t len;
if ((p = strrchr(s, '/')) == NULL)
@@ -538,7 +538,7 @@ static void
line(void)
{
long n;
- char *endp;
+ char *endp, *fname;
if (cppoff)
return;
@@ -552,20 +552,18 @@ line(void)
}
next();
- if (yytoken == EOFTOK)
- goto set_line;
-
- if (*yytext != '\"' || yylen == 1) {
- cpperror("second parameter of #line is not a valid filename");
- return;
+ if (yytoken == '\n') {
+ fname = NULL;
+ } else {
+ if (*yytext != '\"' || yylen == 1) {
+ cpperror("second parameter of #line is not a valid filename");
+ return;
+ }
+ fname = yylval.sym->u.s;
}
-
- free(input->fname);
- input->fname = xstrdup(yylval.sym->u.s);
- next();
-
-set_line:
- input->nline = n - 1;
+ setloc(fname, n - 1);
+ if (yytoken != '\n')
+ next();
}
static void
diff --git a/cc1/error.c b/cc1/error.c
@@ -18,7 +18,7 @@ warn_error(int flag, char *fmt, va_list va)
if (flag == 0)
return;
fprintf(stderr, "%s:%u: %s: ",
- input->fname, input->nline,
+ filenam, lineno,
(flag < 0) ? "error" : "warning");
vfprintf(stderr, fmt, va);
putc('\n', stderr);
diff --git a/cc1/lex.c b/cc1/lex.c
@@ -18,6 +18,8 @@ struct yystype yylval;
char yytext[STRINGSIZ+3];
unsigned short yylen;
int lexmode = CCMODE;
+unsigned lineno;
+char filenam[FILENAME_MAX];
int namespace = NS_IDEN;
static int safe;
@@ -69,17 +71,31 @@ ilex(void)
}
int
+setloc(char *fname, unsigned line)
+{
+ size_t len;
+
+ if ((len = strlen(fname)) >= FILENAME_MAX)
+ die("file name too long: '%s'", fname);
+ memcpy(filenam, fname, len);
+ filenam[len] = '\0';
+
+ free(input->filenam);
+ input->filenam = xstrdup(fname);
+ lineno = input->lineno = line;
+ return 1;
+}
+
+int
addinput(char *fname, Symbol *hide, char *buffer)
{
FILE *fp;
- unsigned flags, nline = 0;
- Input *ip;
+ unsigned flags;
+ Input *newip, *curip = input;
if (hide) {
/* this is a macro expansion */
fp = NULL;
- if (input)
- nline = input->nline;
if (hide->hide == UCHAR_MAX)
die("Too many macro expansions");
++hide->hide;
@@ -87,9 +103,9 @@ addinput(char *fname, Symbol *hide, char *buffer)
} else if (fname) {
/* a new file */
if ((fp = fopen(fname, "r")) == NULL)
- return 0;
+ die("Error opening '%s': %s", fname, strerror(errno));
flags = IFILE;
- if (input && onlyheader)
+ if (curip && onlyheader)
printf("%s: %s\n", infile, fname);
} else {
/* reading from stdin */
@@ -98,23 +114,26 @@ addinput(char *fname, Symbol *hide, char *buffer)
flags = ISTDIN;
}
- ip = xmalloc(sizeof(*ip));
+ newip = xmalloc(sizeof(*newip));
if (!buffer) {
buffer = xmalloc(INPUTSIZ);
buffer[0] = '\0';
}
- ip->p = ip->begin = ip->line = buffer;
- ip->fname = xstrdup(fname);
- ip->next = input;
- ip->fp = fp;
- ip->hide = hide;
- ip->nline = nline;
- ip->flags = flags;
- input = ip;
+ if (curip)
+ curip->lineno = lineno;
- return 1;
+ newip->p = newip->begin = newip->line = buffer;
+ newip->filenam = NULL;
+ newip->lineno = 0;
+ newip->next = curip;
+ newip->fp = fp;
+ newip->hide = hide;
+ newip->flags = flags;
+ input = newip;
+
+ return setloc(fname, (curip) ? curip->lineno : newip->lineno);
}
void
@@ -127,7 +146,7 @@ delinput(void)
case IFILE:
if (fclose(ip->fp))
die("error: failed to read from input file '%s'",
- ip->fname);
+ ip->filenam);
break;
case IMACRO:
assert(hide->hide == 1);
@@ -135,15 +154,19 @@ delinput(void)
break;
}
input = ip->next;
- free(ip->fname);
+ free(ip->filenam);
free(ip->line);
+ if (input) {
+ lineno = input->lineno;
+ strcpy(filenam, input->filenam);
+ }
}
static void
newline(void)
{
- if (++input->nline == 0)
- die("error: input file '%s' too long", input->fname);
+ if (++lineno == 0)
+ die("error: input file '%s' too long", filenam);
}
/*
@@ -280,15 +303,15 @@ repeat:
char *s;
putchar('\n');
- if (strcmp(file, input->fname)) {
- strcpy(file, input->fname);
+ if (strcmp(file, filenam)) {
+ strcpy(file, filenam);
s = "#line %u %s\n";
- } else if (nline+1 != input->nline) {
+ } else if (nline+1 != lineno) {
s = "#line %u\n";
} else {
s = "";
}
- nline = input->nline;
+ nline = lineno;
printf(s, nline, file);
}
return 1;