scc

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

commit e075a0228c63e8bed0a848713569a3b8fe52012c
parent 82c920e97007a784ca620fdaead55d4ce8bc0ecf
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Wed, 11 Jan 2017 11:17:11 +0100

[cc1] Add support for macro expansion in input buffers

We are going to implement the macro expansion using a push up/pop down of buffers.
It is important to keep a track of the symbol which generates the push up,
because this symbol becomes part of the hide set (see Prosser algorithm)
of the current expansion.

Diffstat:
Mcc1/cc1.h | 4+++-
Mcc1/cpp.c | 31++++++-------------------------
Mcc1/lex.c | 48++++++++++++++++++++++++++++++++++++++++++------
Mcc1/main.c | 2+-
Mcc1/symbol.c | 1+
5 files changed, 53 insertions(+), 33 deletions(-)

diff --git a/cc1/cc1.h b/cc1/cc1.h @@ -307,6 +307,7 @@ struct symbol { Type *type; unsigned short id; unsigned char ctx; + unsigned char hide; char ns; unsigned char token; short flags; @@ -344,6 +345,7 @@ struct yystype { struct input { char *fname; FILE *fp; + Symbol *hide; char *line, *begin, *p; struct input *next; unsigned short nline; @@ -392,7 +394,7 @@ extern unsigned next(void); extern int moreinput(void); extern void expect(unsigned tok); extern void discard(void); -extern int addinput(char *fname); +extern int addinput(char *fname, Symbol *hide); extern void allocinput(char *fname, FILE *fp, char *line); extern void delinput(void); extern void setsafe(int type); diff --git a/cc1/cpp.c b/cc1/cpp.c @@ -238,14 +238,13 @@ expansion_too_long: error("macro expansion of \"%s\" too long", macroname); } -#define BUFSIZE ((INPUTSIZ > FILENAME_MAX+2) ? INPUTSIZ : FILENAME_MAX+2) int expand(char *begin, Symbol *sym) { - size_t total, elen, rlen, llen, ilen; + size_t elen; int n; char *s = sym->u.s; - char *arglist[NR_MACROARG], arguments[INPUTSIZ], buffer[BUFSIZE]; + char *arglist[NR_MACROARG], arguments[INPUTSIZ], buffer[INPUTSIZ]; macroname = sym->name; if (sym == symfile) { @@ -268,30 +267,12 @@ expand(char *begin, Symbol *sym) substitute: DBG("MACRO '%s' expanded to :'%s'", macroname, buffer); - rlen = strlen(input->p); /* rigth length */ - llen = begin - input->line; /* left length */ - ilen = input->p - begin; /* invocation length */ - total = llen + elen + rlen; - - if (total >= LINESIZ) - error("macro expansion of \"%s\" too long", macroname); - - /* cut macro invocation */ - memmove(begin, begin + ilen, rlen); - - /* paste macro expansion */ - memmove(begin + elen, begin, rlen); - memcpy(begin, buffer, elen); - input->line[total] = '\0'; - - input->p = input->begin = begin; - - if (!(sym->flags & SDECLARED)) - killsym(sym); + addinput(NULL, sym); + memcpy(input->line, buffer, elen); + input->line[elen] = '\0'; return 1; } -#undef BUFSIZE static int getpars(Symbol *args[NR_MACROARG]) @@ -449,7 +430,7 @@ includefile(char *dir, char *file, size_t filelen) memcpy(path+dirlen, file, filelen); path[dirlen + filelen] = '\0'; - return addinput(path); + return addinput(path, NULL); } static void diff --git a/cc1/lex.c b/cc1/lex.c @@ -2,6 +2,7 @@ static char sccsid[] = "@(#) ./cc1/lex.c"; #include <ctype.h> #include <errno.h> +#include <limits.h> #include <setjmp.h> #include <stdio.h> #include <stdlib.h> @@ -85,18 +86,32 @@ ilex(void) } int -addinput(char *fname) +addinput(char *fname, Symbol *hide) { FILE *fp; + unsigned nline = 0; - if (fname) { + if (hide) { + /* this is a macro expansion */ + fp = NULL; + fname = xstrdup(input->fname); + nline = input->nline; + if (hide->hide == UCHAR_MAX) + die("Too many macro expansions"); + ++hide->hide; + } else if (fname) { + /* a new file */ if ((fp = fopen(fname, "r")) == NULL) return 0; } else { + /* reading from stdin */ fp = stdin; fname = "<stdin>"; } allocinput(fname, fp, NULL); + input->hide = hide; + input->nline = nline; + return 1; } @@ -104,6 +119,7 @@ void delinput(void) { Input *ip = input; + Symbol *hide = ip->hide; if (ip->fp) { if (fclose(ip->fp)) @@ -112,6 +128,17 @@ delinput(void) if (!ip->next) eof = 1; } + if (hide) { + --hide->hide; + /* + * If the symbol is not declared then it was + * an extension due to a #if directive with + * a non declared symbol (expanded to 0), + * thus we have to kill the symbol + */ + if ((hide->flags & SDECLARED) == 0) + killsym(hide); + } if (eof) return; input = ip->next; @@ -179,14 +206,21 @@ readline(void) char *bp, *lim; char c, peekc = 0; -repeat: +repeat_from_file: input->begin = input->p = input->line; *input->line = '\0'; + +repeat_from_expand: if (eof) return 0; + + if (!input->fp) { + delinput(); + goto repeat_from_expand; + } if (feof(input->fp)) { delinput(); - goto repeat; + goto repeat_from_file; } lim = &input->line[INPUTSIZ-1]; for (bp = input->line; bp < lim; *bp++ = c) { @@ -213,8 +247,10 @@ moreinput(void) static char file[FILENAME_MAX]; static unsigned nline; char *s; + int wasexpand; repeat: + wasexpand = input->hide != NULL; if (!readline()) return 0; while (isspace(*input->p)) @@ -225,7 +261,7 @@ repeat: goto repeat; } - if (onlycpp) { + if (onlycpp && !wasexpand) { putchar('\n'); if (strcmp(file, input->fname)) { strcpy(file, input->fname); @@ -497,7 +533,7 @@ iden(void) input->p = p; tok2str(); if ((sym = lookup(NS_CPP, yytext, NOALLOC)) != NULL) { - if (!disexpand && expand(begin, sym)) + if (!disexpand && !sym->hide && expand(begin, sym)) return next(); } sym = lookup(namespace, yytext, ALLOC); diff --git a/cc1/main.c b/cc1/main.c @@ -102,7 +102,7 @@ main(int argc, char *argv[]) for (i = 0; i < uflags.n; ++i) undefmacro(uflags.s[i]); - if (!addinput(*argv)) { + if (!addinput(*argv, NULL)) { die("error: failed to open input file '%s': %s", *argv, strerror(errno)); } diff --git a/cc1/symbol.c b/cc1/symbol.c @@ -152,6 +152,7 @@ newsym(int ns, char *name) name = xstrdup(name); sym->name = name; sym->id = 0; + sym->hide = 0; sym->ns = ns; sym->ctx = (ns == NS_CPP) ? UCHAR_MAX : curctx; sym->token = IDEN;