commit e075a0228c63e8bed0a848713569a3b8fe52012c
Author:     Roberto E. Vargas Caballero <[email protected]>
AuthorDate: Wed Jan 11 11:17:11 2017 +0100
Commit:     Roberto E. Vargas Caballero <[email protected]>
CommitDate: Wed Jan 11 12:12:02 2017 +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.

diff --git a/cc1/cc1.h b/cc1/cc1.h
index ac9f9d3..7485a34 100644
--- 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
index c40e436..2d77b16 100644
--- 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
index 98a9713..130c586 100644
--- 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
index 3525cea..83498e9 100644
--- 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
index 633691d..24565d7 100644
--- 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;

Reply via email to