scc

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

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:
Mcc1/cc1.h | 7+++++--
Mcc1/cpp.c | 36+++++++++++++++++-------------------
Mcc1/error.c | 2+-
Mcc1/lex.c | 71+++++++++++++++++++++++++++++++++++++++++++++++------------------------
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;