From e725ab2b44889b31b0f664434d15ff1bd4f8a2f5 Mon Sep 17 00:00:00 2001 From: Alexey Frunze Date: Wed, 14 May 2014 02:49:38 -0700 Subject: [PATCH] Update cpp to pcc 1.0.0's cpp Update the preprocessor to fix some of its bugs. --- src/cmd/cpp/Makefile | 10 +- src/cmd/cpp/compat.c | 91 +++ src/cmd/cpp/compat.h | 14 + src/cmd/cpp/config.h | 11 + src/cmd/cpp/cpp.c | 1654 +++++++++++++++++++++----------------- src/cmd/cpp/cpp.h | 137 ++-- src/cmd/cpp/cpy.y | 3 + src/cmd/cpp/scanner.l | 939 ++++++++++++++++++++++ src/cmd/cpp/tests/res11 | 22 + src/cmd/cpp/tests/res12 | 21 + src/cmd/cpp/tests/res13 | 13 + src/cmd/cpp/tests/res2 | 3 +- src/cmd/cpp/tests/test11 | 20 + src/cmd/cpp/tests/test12 | 19 + src/cmd/cpp/tests/test13 | 11 + src/cmd/cpp/token.c | 363 +++++---- 16 files changed, 2384 insertions(+), 947 deletions(-) create mode 100644 src/cmd/cpp/compat.c create mode 100644 src/cmd/cpp/compat.h create mode 100644 src/cmd/cpp/config.h create mode 100644 src/cmd/cpp/scanner.l create mode 100644 src/cmd/cpp/tests/res11 create mode 100644 src/cmd/cpp/tests/res12 create mode 100644 src/cmd/cpp/tests/res13 create mode 100644 src/cmd/cpp/tests/test11 create mode 100644 src/cmd/cpp/tests/test12 create mode 100644 src/cmd/cpp/tests/test13 diff --git a/src/cmd/cpp/Makefile b/src/cmd/cpp/Makefile index 80a3036..6091894 100644 --- a/src/cmd/cpp/Makefile +++ b/src/cmd/cpp/Makefile @@ -3,7 +3,7 @@ include $(TOPSRC)/target.mk #include $(TOPSRC)/cross.mk #CFLAGS = -DCROSS -OBJS = cpp.o cpy.o token.o doprnt.o +OBJS = cpp.o cpy.o token.o compat.o doprnt.o MAN = cpp.0 MANSRC = cpp.1 @@ -31,7 +31,7 @@ install: all install cpp $(DESTDIR)/bin/ cp cpp.0 $(DESTDIR)/share/man/cat1/ -cpp.o: cpp.c y.tab.h +cpp.o: cpp.c cpp.h y.tab.h config.h .l.o: $(LEX) $(LFLAGS) $< @@ -62,3 +62,9 @@ test: cmp tests/run9 tests/res9 ./cpp < tests/test10 > tests/run10 cmp tests/run10 tests/res10 + ./cpp < tests/test11 > tests/run11 + cmp tests/run11 tests/res11 + ./cpp < tests/test12 > tests/run12 + cmp tests/run12 tests/res12 + ./cpp < tests/test13 > tests/run13 + cmp tests/run13 tests/res13 diff --git a/src/cmd/cpp/compat.c b/src/cmd/cpp/compat.c new file mode 100644 index 0000000..e01786d --- /dev/null +++ b/src/cmd/cpp/compat.c @@ -0,0 +1,91 @@ +/* $OpenBSD: strlcat.c,v 1.8 2001/05/13 15:40:15 deraadt Exp $ */ +/* $OpenBSD: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $ */ +/* + * Copyright (c) 1998, 2003-2005, 2010-2011, 2013 + * Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "config.h" +#include + +#ifndef HAVE_STRLCAT +/* + * Appends src to string dst of size siz (unlike strncat, siz is the + * full size of dst, not space left). At most siz-1 characters + * will be copied. Always NUL terminates (unless siz <= strlen(dst)). + * Returns strlen(src) + MIN(siz, strlen(initial dst)). + * If retval >= siz, truncation occurred. + */ +size_t +strlcat(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + size_t dlen; + + /* Find the end of dst and adjust bytes left but don't go past end */ + while (n-- != 0 && *d != '\0') + d++; + dlen = d - dst; + n = siz - dlen; + + if (n == 0) + return dlen + strlen(s); + while (*s != '\0') { + if (n != 1) { + *d++ = *s; + n--; + } + s++; + } + *d = '\0'; + + return dlen + (s - src); /* count does not include NUL */ +} +#endif /* HAVE_STRLCAT */ + +#ifndef HAVE_STRLCPY +/* + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +size_t +strlcpy(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0 && --n != 0) { + do { + if ((*d++ = *s++) == 0) + break; + } while (--n != 0); + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + + return s - src - 1; /* count does not include NUL */ +} +#endif /* HAVE_STRLCPY */ diff --git a/src/cmd/cpp/compat.h b/src/cmd/cpp/compat.h new file mode 100644 index 0000000..6d9e654 --- /dev/null +++ b/src/cmd/cpp/compat.h @@ -0,0 +1,14 @@ +#ifndef COMPAT_H__ +#define COMPAT_H__ + +#include + +#ifndef HAVE_STRLCPY +size_t strlcpy(char* dst, const char* src, size_t size); +#endif + +#ifndef HAVE_STRLCAT +size_t strlcat(char* dst, const char* src, size_t size); +#endif + +#endif // COMPAT_H__ diff --git a/src/cmd/cpp/config.h b/src/cmd/cpp/config.h new file mode 100644 index 0000000..b5d0468 --- /dev/null +++ b/src/cmd/cpp/config.h @@ -0,0 +1,11 @@ +#ifndef CONFIG_H__ +#define CONFIG_H__ + +#define VERSSTR "cpp for RetroBSD" + +#define HAVE_UNISTD_H 1 +#define HAVE_SYS_WAIT_H 1 +//#define HAVE_STRLCPY 1 +//#define HAVE_STRLCAT 1 + +#endif // CONFIG_H__ diff --git a/src/cmd/cpp/cpp.c b/src/cmd/cpp/cpp.c index 59b4141..7a14424 100644 --- a/src/cmd/cpp/cpp.c +++ b/src/cmd/cpp/cpp.c @@ -1,8 +1,6 @@ +/* $Id: cpp.c,v 1.124.2.2 2011/03/27 13:17:19 ragge Exp $ */ + /* - * The C preprocessor. - * This code originates from the V6 preprocessor with some additions - * from V7 cpp, and at last ansi/c99 support. - * * Copyright (c) 2004,2010 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. * @@ -26,32 +24,46 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifdef CROSS -# include -# include -# include -#else -# include -# include -# include + +/* + * The C preprocessor. + * This code originates from the V6 preprocessor with some additions + * from V7 cpp, and at last ansi/c99 support. + */ + +#include "config.h" + +#ifdef HAVE_SYS_WAIT_H +#include #endif +#include #include +#ifdef HAVE_UNISTD_H #include +#endif +#include #include +#include +#include +#include +#include +#include "compat.h" #include "cpp.h" #include "y.tab.h" -#define MAXARG 20 /* # of args to a macro, limited by char value */ -#define SBSIZE (12*1024) +struct includ *ifiles; +int slow; /* scan slowly for new tokens */ -static uchar sbf[SBSIZE]; +#define SBSIZE (12*1024)//1000000 + +static usch sbf[SBSIZE]; /* C command */ int tflag; /* traditional cpp syntax */ -#ifdef CPP_DEBUG int dflag; /* debug printouts */ +#ifdef CPP_DEBUG #define DPRINT(x) if (dflag) printf x #define DDPRINT(x) if (dflag > 1) printf x #else @@ -59,26 +71,18 @@ int dflag; /* debug printouts */ #define DDPRINT(x) #endif -#define GCC_VARI - int ofd; -uchar outbuf[CPPBUF]; +usch outbuf[CPPBUF]; int obufp, istty; int Cflag, Mflag, dMflag, Pflag; -uchar *Mfile; +usch *Mfile; struct initar *initar; -int readmac; - -/* avoid recursion */ -struct recur { - struct recur *next; - struct symtab *sp; -}; +int readmac, lastoch; /* include dirs */ struct incs { struct incs *next; - uchar *dir; + usch *dir; dev_t dev; ino_t ino; } *incdir[2]; @@ -87,11 +91,12 @@ struct incs { static struct symtab *filloc; static struct symtab *linloc; +static struct symtab *pragloc; int trulvl; int flslvl; int elflvl; int elslvl; -uchar *stringbuf = sbf; +usch *stringbuf = sbf; /* * Macro replacement list syntax: @@ -100,7 +105,7 @@ uchar *stringbuf = sbf; * character WARN followed by the argument number. * - The value element points to the end of the string, to simplify * pushback onto the input queue. - * + * * The first character (from the end) in the replacement list is * the number of arguments: * VARG - ends with ellipsis, next char is argcount without ellips. @@ -111,74 +116,31 @@ uchar *stringbuf = sbf; * WARN is used: * - in stored replacement lists to tell that an argument comes * - When expanding replacement lists to tell that the list ended. + * + * To ensure that an already expanded identifier won't get expanded + * again a EBLOCK char + its number is stored directly before any + * expanded identifier. */ -#define GCCARG 0xfd /* has gcc varargs that may be replaced with 0 */ -#define VARG 0xfe /* has varargs */ -#define OBJCT 0xff -#define WARN 1 /* SOH, not legal char */ -#define CONC 2 /* STX, not legal char */ -#define SNUFF 3 /* ETX, not legal char */ -#define NOEXP 4 /* EOT, not legal char */ -#define EXPAND 5 /* ENQ, not legal char */ - /* args for lookup() */ #define FIND 0 #define ENTER 1 -static void expdef(const uchar *proto, struct recur *, int gotwarn); +static int readargs(struct symtab *sp, const usch **args); +void prline(const usch *s); +static void prrep(const usch *s); +static void exparg(int); +static void subarg(struct symtab *sp, const usch **args, int); void define(void); -static int canexpand(struct recur *, struct symtab *np); void include(void); void include_next(void); void line(void); void flbuf(void); void usage(void); +usch *xstrdup(const usch *str); static void addidir(char *idir, struct incs **ww); - -/* - * Copy src to string dst of size siz. At most siz-1 characters - * will be copied. Always NUL terminates (unless siz == 0). - * Returns strlen(src); if retval >= siz, truncation occurred. - */ -static size_t -my_strlcpy(char *dst, const char *src, size_t siz) -{ - char *d = dst; - const char *s = src; - size_t n = siz; - - /* Copy as many bytes as will fit */ - if (n != 0 && --n != 0) { - do { - if ((*d++ = *s++) == 0) - break; - } while (--n != 0); - } - - /* Not enough room in dst, add NUL and traverse rest of src */ - if (n == 0) { - if (siz != 0) - *d = '\0'; /* NUL-terminate dst */ - while (*s++) - ; - } - - return(s - src - 1); /* count does not include NUL */ -} - -static uchar * -xstrdup(const char *str) -{ - size_t len = strlen(str)+1; - uchar *rv; - - rv = malloc(len); - if (! rv) - error("xstrdup: out of mem"); - my_strlcpy((char *)rv, str, len); - return rv; -} +void imp(const char *); +#define IMP(x) if (dflag>1) imp(x) int main(int argc, char **argv) @@ -186,7 +148,7 @@ main(int argc, char **argv) struct initar *it; struct symtab *nl; register int ch; - const uchar *fn1, *fn2; + const usch *fn1, *fn2; #ifdef TIMING struct timeval t1, t2; @@ -204,8 +166,7 @@ main(int argc, char **argv) case 'U': /* undef */ case 'D': /* define something */ /* XXX should not need malloc() here */ - it = malloc(sizeof(struct initar)); - if (it == NULL) + if ((it = malloc(sizeof(struct initar))) == NULL) error("couldn't apply -%c %s", ch, optarg); it->type = ch; it->str = optarg; @@ -254,48 +215,59 @@ main(int argc, char **argv) argc -= optind; argv += optind; - filloc = lookup((const uchar *)"__FILE__", ENTER); - linloc = lookup((const uchar *)"__LINE__", ENTER); - filloc->value = linloc->value = (const uchar *)""; /* Just something */ + filloc = lookup((const usch *)"__FILE__", ENTER); + linloc = lookup((const usch *)"__LINE__", ENTER); + filloc->value = linloc->value = stringbuf; + savch(OBJCT); + + /* create a complete macro for pragma */ + pragloc = lookup((const usch *)"_Pragma", ENTER); + savch(0); + savstr((const usch *)"_Pragma("); + savch(0); + savch(WARN); + savch(')'); + pragloc->value = stringbuf; + savch(1); if (tflag == 0) { time_t t = time(NULL); - uchar *n = (uchar *)ctime(&t); + usch *n = (usch *)ctime(&t); /* * Manually move in the predefined macros. */ - nl = lookup((const uchar *)"__TIME__", ENTER); + nl = lookup((const usch *)"__TIME__", ENTER); savch(0); savch('"'); n[19] = 0; savstr(&n[11]); savch('"'); savch(OBJCT); nl->value = stringbuf-1; - nl = lookup((const uchar *)"__DATE__", ENTER); + nl = lookup((const usch *)"__DATE__", ENTER); savch(0); savch('"'); n[24] = n[11] = 0; savstr(&n[4]); savstr(&n[20]); savch('"'); savch(OBJCT); nl->value = stringbuf-1; - nl = lookup((const uchar *)"__STDC__", ENTER); + nl = lookup((const usch *)"__STDC__", ENTER); savch(0); savch('1'); savch(OBJCT); nl->value = stringbuf-1; - nl = lookup((const uchar *)"__STDC_VERSION__", ENTER); - savch(0); savstr((const uchar *)"199901L"); savch(OBJCT); + nl = lookup((const usch *)"__STDC_VERSION__", ENTER); + savch(0); savstr((const usch *)"199901L"); savch(OBJCT); nl->value = stringbuf-1; } if (Mflag && !dMflag) { - uchar *c; + usch *c; if (argc < 1) error("-M and no infile"); - if ((c = (uchar *)strrchr(argv[0], '/')) == NULL) - c = (uchar *)argv[0]; + if ((c = (usch *)strrchr(argv[0], '/')) == NULL) + c = (usch *)argv[0]; else c++; Mfile = stringbuf; savstr(c); savch(0); - if ((c = (uchar *)strrchr((char *)Mfile, '.')) == NULL) + if ((c = (usch *)strrchr((char *)Mfile, '.')) == NULL) error("-M and no extension: "); c[1] = 'o'; c[2] = 0; @@ -309,10 +281,10 @@ main(int argc, char **argv) istty = isatty(ofd); if (argc && strcmp(argv[0], "-")) { - fn1 = fn2 = (uchar *)argv[0]; + fn1 = fn2 = (usch *)argv[0]; } else { fn1 = NULL; - fn2 = (const uchar *)""; + fn2 = (const usch *)""; } if (pushfile(fn1, fn2, 0, NULL)) error("cannot open %s", argv[0]); @@ -350,126 +322,20 @@ addidir(char *idir, struct incs **ww) return; ww = &w->next; } - w = calloc(sizeof(struct incs), 1); - if (w == NULL) + if ((w = calloc(sizeof(struct incs), 1)) == NULL) error("couldn't add path %s", idir); - w->dir = (uchar *)idir; + w->dir = (usch *)idir; w->dev = st.st_dev; w->ino = st.st_ino; *ww = w; } -uchar * -gotident(struct symtab *nl) -{ - struct symtab *thisnl; - uchar *osp, *ss2, *base; - int c; - - thisnl = NULL; - readmac++; - base = osp = stringbuf; - goto found; - - while ((c = sloscan()) != 0) { - switch (c) { - case IDENT: - if (flslvl) - break; - osp = stringbuf; - - DPRINT(("IDENT0: %s\n", yytext)); - nl = lookup((uchar *)yytext, FIND); - if (nl == 0 || thisnl == 0) - goto found; - if (thisnl == nl) { - nl = 0; - goto found; - } - ss2 = stringbuf; - if ((c = sloscan()) == WSPACE) { - savstr((uchar *)yytext); - c = sloscan(); - } - if (c != EXPAND) { - unpstr((const uchar *)yytext); - if (ss2 != stringbuf) - unpstr(ss2); - unpstr(nl->namep); - (void)sloscan(); /* get yytext correct */ - nl = 0; /* ignore */ - } else { - thisnl = NULL; - if (nl->value[0] == OBJCT) { - unpstr(nl->namep); - (void)sloscan(); /* get yytext correct */ - nl = 0; - } - } - stringbuf = ss2; - -found: if (nl == 0 || subst(nl, NULL) == 0) { - if (nl) - savstr(nl->namep); - else - savstr((uchar *)yytext); - } else if (osp != stringbuf) { - DPRINT(("IDENT1: unput osp %p stringbuf %p\n", - osp, stringbuf)); - ss2 = stringbuf; - cunput(EXPAND); - while (ss2 > osp) - cunput(*--ss2); - thisnl = nl; - stringbuf = osp; /* clean up heap */ - } - break; - - case EXPAND: - DPRINT(("EXPAND!\n")); - thisnl = NULL; - break; - - case CMNT: - getcmnt(); - break; - - case '\n': - /* sloscan() will not eat */ - (void)cinput(); - savch(c); - break; - - case STRING: - case NUMBER: - case WSPACE: - savstr((uchar *)yytext); - break; - - default: - if (c < 256) - savch(c); - else - savstr((uchar *)yytext); - break; - } - if (thisnl == NULL) { - readmac--; - savch(0); - return base; - } - } - error("premature EOF"); - /* NOTREACHED */ - return NULL; /* XXX gcc */ -} - void line() { - static uchar *lbuf; + static usch *lbuf; static int llen; - uchar *p; + usch *p; int c; if ((c = yylex()) != NUMBER) @@ -482,7 +348,7 @@ line() if (c != STRING) goto bad; - p = (uchar *)yytext; + p = (usch *)yytext; if (*p == 'L') p++; c = strlen((char *)p); @@ -493,7 +359,7 @@ line() llen = c; } p[strlen((char *)p)-1] = 0; - if (my_strlcpy((char *)lbuf, (char *)&p[1], SBSIZE) >= SBSIZE) + if (strlcpy((char *)lbuf, (char *)&p[1], SBSIZE) >= SBSIZE) error("line exceeded buffer size"); ifiles->fname = lbuf; @@ -508,17 +374,19 @@ bad: error("bad line directive"); * Return 1 on success. */ static int -fsrch(const uchar *fn, int idx, struct incs *w) +fsrch(const usch *fn, int idx, struct incs *w) { - for (; idx <= SYSINC; idx++) { - if (idx == SYSINC) - w = incdir[SYSINC]; + int i; + + for (i = idx; i < 2; i++) { + if (i > idx) + w = incdir[i]; for (; w; w = w->next) { - uchar *nm = stringbuf; + usch *nm = stringbuf; savstr(w->dir); savch('/'); savstr(fn); savch(0); - if (pushfile(nm, fn, idx, w->next) == 0) + if (pushfile(nm, fn, i, w->next) == 0) return 1; stringbuf = nm; } @@ -535,9 +403,9 @@ void include() { struct symtab *nl; - uchar *osp; - uchar *fn, *safefn; - int c; + usch *osp; + usch *fn, *safefn; + int c/*, it*/; if (flslvl) return; @@ -547,9 +415,12 @@ include() ; if (c == IDENT) { /* sloscan() will not expand idents */ - if ((nl = lookup((uchar *)yytext, FIND)) == NULL) + if ((nl = lookup((usch *)yytext, FIND)) == NULL) goto bad; - unpstr(gotident(nl)); + if (kfind(nl)) + unpstr(stringbuf); + else + unpstr(nl->namep); stringbuf = osp; c = yylex(); } @@ -561,25 +432,26 @@ include() while ((c = sloscan()) != '>' && c != '\n') { if (c == '\n') /* XXX check - cannot reach */ goto bad; - savstr((uchar *)yytext); + savstr((usch *)yytext); } savch('\0'); while ((c = sloscan()) == WSPACE) ; if (c != '\n') goto bad; + //it = SYSINC; safefn = fn; } else { - uchar *nm = stringbuf; + usch *nm = stringbuf; - yytext[strlen(yytext)-1] = 0; - fn = (uchar *)&yytext[1]; + yytext[strlen((char *)yytext)-1] = 0; + fn = (usch *)&yytext[1]; /* first try to open file relative to previous file */ /* but only if it is not an absolute path */ if (*fn != '/') { savstr(ifiles->orgfn); - stringbuf = (uchar *)strrchr((char *)nm, '/'); - if (stringbuf == NULL) + if ((stringbuf = + (usch *)strrchr((char *)nm, '/')) == NULL) stringbuf = nm; else stringbuf++; @@ -594,7 +466,7 @@ include() /* XXX may loose stringbuf space */ } - if (fsrch(safefn, INCINC, incdir[INCINC])) + if (fsrch(safefn, 0, incdir[0])) goto okret; error("cannot find '%s'", safefn); @@ -610,8 +482,8 @@ void include_next() { struct symtab *nl; - uchar *osp; - uchar *fn; + usch *osp; + usch *fn; int c; if (flslvl) @@ -621,9 +493,12 @@ include_next() ; if (c == IDENT) { /* sloscan() will not expand idents */ - if ((nl = lookup((uchar *)yytext, FIND)) == NULL) + if ((nl = lookup((usch *)yytext, FIND)) == NULL) goto bad; - unpstr(gotident(nl)); + if (kfind(nl)) + unpstr(stringbuf); + else + unpstr(nl->namep); stringbuf = osp; c = yylex(); } @@ -632,13 +507,13 @@ include_next() fn = stringbuf; if (c == STRING) { - savstr((uchar *)&yytext[1]); + savstr((usch *)&yytext[1]); stringbuf[-1] = 0; } else { /* < > */ while ((c = sloscan()) != '>') { if (c == '\n') goto bad; - savstr((uchar *)yytext); + savstr((usch *)yytext); } savch('\0'); } @@ -672,14 +547,14 @@ getcmnt(void) { int c; - savstr((uchar *)yytext); + savstr((usch *)yytext); savch(cinput()); /* Lost * */ for (;;) { c = cinput(); if (c == '*') { c = cinput(); if (c == '/') { - savstr((const uchar *)"*/"); + savstr((const usch *)"*/"); return; } cunput(c); @@ -693,7 +568,7 @@ getcmnt(void) * Compare two replacement lists, taking in account comments etc. */ static int -cmprepl(const uchar *o, const uchar *n) +cmprepl(const usch *o, const usch *n) { for (; *o; o--, n--) { /* comment skip */ @@ -738,12 +613,12 @@ void define() { struct symtab *np; - uchar *args[MAXARG], *ubuf, *sbeg; + usch *args[MAXARGS+1], *ubuf, *sbeg; int c, i, redef; int mkstr = 0, narg = -1; int ellips = 0; -#ifdef GCC_VARI - uchar *gccvari = NULL; +#ifdef GCC_COMPAT + usch *gccvari = NULL; int wascon; #endif @@ -755,7 +630,7 @@ define() if (isdigit((int)yytext[0])) goto bad; - np = lookup((uchar *)yytext, ENTER); + np = lookup((usch *)yytext, ENTER); redef = np->value != NULL; readmac = 1; @@ -776,16 +651,18 @@ define() if (c == IDENT) { /* make sure there is no arg of same name */ for (i = 0; i < narg; i++) - if (!strcmp((char *) args[i], yytext)) + if (!strcmp((char *) args[i], (char *)yytext)) error("Duplicate macro " "parameter \"%s\"", yytext); + if (narg == MAXARGS) + error("Too many macro args"); args[narg++] = xstrdup(yytext); if ((c = definp()) == ',') { if ((c = definp()) == ')') goto bad; continue; } -#ifdef GCC_VARI +#ifdef GCC_COMPAT if (c == '.' && isell()) { if (definp() != ')') goto bad; @@ -813,7 +690,7 @@ define() if ((c = sloscan()) == '#') goto bad; savch('\0'); -#ifdef GCC_VARI +#ifdef GCC_COMPAT wascon = 0; #endif goto in2; @@ -822,7 +699,7 @@ define() /* parse replacement-list, substituting arguments */ savch('\0'); while (c != '\n') { -#ifdef GCC_VARI +#ifdef GCC_COMPAT wascon = 0; loop: #endif @@ -830,7 +707,7 @@ loop: case WSPACE: /* remove spaces if it surrounds a ## directive */ ubuf = stringbuf; - savstr((uchar *)yytext); + savstr((usch *)yytext); c = sloscan(); if (c == '#') { if ((c = sloscan()) != '#') @@ -839,7 +716,7 @@ loop: savch(CONC); if ((c = sloscan()) == WSPACE) c = sloscan(); -#ifdef GCC_VARI +#ifdef GCC_COMPAT if (c == '\n') break; wascon = 1; @@ -855,7 +732,7 @@ loop: savch(CONC); if ((c = sloscan()) == WSPACE) c = sloscan(); -#ifdef GCC_VARI +#ifdef GCC_COMPAT if (c == '\n') break; wascon = 1; @@ -863,7 +740,7 @@ loop: #else continue; #endif - } + } in2: if (narg < 0) { /* no meaning in object-type macro */ savch('#'); @@ -874,15 +751,20 @@ in2: if (narg < 0) { if (c == WSPACE) c = sloscan(); /* whitespace, ignore */ mkstr = 1; - if (c == IDENT && strcmp(yytext, "__VA_ARGS__") == 0) + if (c == IDENT && strcmp((char *)yytext, "__VA_ARGS__") == 0) continue; /* FALLTHROUGH */ case IDENT: - if (strcmp(yytext, "__VA_ARGS__") == 0) { + if (strcmp((char *)yytext, "__VA_ARGS__") == 0) { if (ellips == 0) error("unwanted %s", yytext); +#ifdef GCC_COMPAT + savch(wascon ? GCCARG : VARG); +#else savch(VARG); +#endif + savch(WARN); if (mkstr) savch(SNUFF), mkstr = 0; @@ -892,12 +774,12 @@ in2: if (narg < 0) { goto id; /* just add it if object */ /* check if its an argument */ for (i = 0; i < narg; i++) - if (strcmp(yytext, (char *)args[i]) == 0) + if (strcmp((char *)yytext, (char *)args[i]) == 0) break; if (i == narg) { -#ifdef GCC_VARI +#ifdef GCC_COMPAT if (gccvari && - strcmp(yytext, (char *)gccvari) == 0) { + strcmp((char *)yytext, (char *)gccvari) == 0) { savch(wascon ? GCCARG : VARG); savch(WARN); if (mkstr) @@ -920,7 +802,7 @@ in2: if (narg < 0) { break; default: -id: savstr((uchar *)yytext); +id: savstr((usch *)yytext); break; } c = sloscan(); @@ -936,7 +818,7 @@ id: savstr((uchar *)yytext); else break; } -#ifdef GCC_VARI +#ifdef GCC_COMPAT if (gccvari) { savch(narg); savch(VARG); @@ -947,17 +829,20 @@ id: savstr((uchar *)yytext); savch(VARG); } else savch(narg < 0 ? OBJCT : narg); - if (redef) { - if (cmprepl(np->value, stringbuf-1)) - error("%s redefined\nprevious define: %s:%d", + if (redef && ifiles->idx != SYSINC) { + if (cmprepl(np->value, stringbuf-1)) { + sbeg = stringbuf; + np->value = stringbuf-1; + warning("%s redefined\nprevious define: %s:%d", np->namep, np->file, np->line); + } stringbuf = sbeg; /* forget this space */ } else np->value = stringbuf-1; #ifdef CPP_DEBUG if (dflag) { - const uchar *w = np->value; + const usch *w = np->value; printf("!define: "); if (*w == OBJCT) @@ -983,44 +868,107 @@ bad: error("bad define"); } void -xwarning(uchar *s) +xwarning(usch *s) { - uchar *t; - uchar *sb = stringbuf; + usch *t; + usch *sb = stringbuf; + //int dummy; flbuf(); savch(0); if (ifiles != NULL) { t = sheap("%s:%d: warning: ", ifiles->fname, ifiles->lineno); - if (write (2, t, strlen((char *)t)) < 0) - /* ignore */; + write (2, t, strlen((char *)t)); } - if (write (2, s, strlen((char *)s)) < 0) - /* ignore */; - if (write (2, "\n", 1) < 0) - /* ignore */; + /*dummy =*/ write (2, s, strlen((char *)s)); + /*dummy =*/ write (2, "\n", 1); stringbuf = sb; } void -xerror(uchar *s) +xerror(usch *s) { - uchar *t; + usch *t; + //int dummy; flbuf(); savch(0); if (ifiles != NULL) { t = sheap("%s:%d: error: ", ifiles->fname, ifiles->lineno); - if (write (2, t, strlen((char *)t)) < 0) - /* ignore */; + /*dummy =*/ write (2, t, strlen((char *)t)); } - if (write (2, s, strlen((char *)s)) < 0) - /* ignore */; - if (write (2, "\n", 1) < 0) - /* ignore */; + /*dummy =*/ write (2, s, strlen((char *)s)); + /*dummy =*/ write (2, "\n", 1); exit(1); } +static void +sss(void) +{ + savch(EBLOCK); + savch(cinput()); + savch(cinput()); +} + +static int +addmac(struct symtab *sp) +{ + int c, i; + + /* Check if it exists; then save some space */ + /* May be more difficult to debug cpp */ + for (i = 1; i < norepptr; i++) + if (norep[i] == sp) + return i; + if (norepptr >= RECMAX) + error("too many macros"); + /* check norepptr */ + if ((norepptr & 255) == 0) + norepptr++; + if (((norepptr >> 8) & 255) == 0) + norepptr += 256; + c = norepptr; + norep[norepptr++] = sp; + return c; +} + +static void +doblk(void) +{ + int c; + + do { + donex(); + } while ((c = sloscan()) == EBLOCK); + if (c != IDENT) + error("EBLOCK sync error"); +} + +/* Block next nr in lex buffer to expand */ +int +donex(void) +{ + int n, i; + + if (bidx == RECMAX) + error("too deep macro recursion"); + n = cinput(); + n = MKB(n, cinput()); + for (i = 0; i < bidx; i++) + if (bptr[i] == n) + return n; /* already blocked */ + bptr[bidx++] = n; + /* XXX - check for sp buffer overflow */ + if (dflag>1) { + printf("donex %d (%d) blocking:\n", bidx, n); + printf("donex %s(%d) blocking:", norep[n]->namep, n); + for (i = bidx-1; i >= 0; i--) + printf(" '%s'", norep[bptr[i]]->namep); + printf("\n"); + } + return n; +} + /* * store a character into the "define" buffer. */ @@ -1028,240 +976,639 @@ void savch(int c) { if (stringbuf-sbf < SBSIZE) { - *stringbuf++ = (uchar)c; + *stringbuf++ = (usch)c; } else { stringbuf = sbf; /* need space to write error message */ error("Too much defining"); - } + } } /* - * substitute namep for sp->value. + * convert _Pragma to #pragma for output. + * Syntax is already correct. */ -int -subst(struct symtab *sp, struct recur *rp) +static void +pragoper(void) { - struct recur rp2; - register const uchar *vp, *cp; - register uchar *obp; - int c, nl; + usch *s; + int t; - DPRINT(("subst: %s\n", sp->namep)); - /* - * First check for special macros. - */ - if (sp == filloc) { - (void)sheap("\"%s\"", ifiles->fname); - return 1; - } else if (sp == linloc) { - (void)sheap("%d", ifiles->lineno); - return 1; + while ((t = sloscan()) != '(') + ; + + while ((t = sloscan()) == WSPACE) + ; + if (t != STRING) + error("pragma must have string argument"); + savstr((const usch *)"\n#pragma "); + s = (usch *)yytext; + if (*s == 'L') + s++; + for (; *s; s++) { + if (*s == '\"') + continue; + if (*s == '\\' && (s[1] == '\"' || s[1] == '\\')) + s++; + savch(*s); } - vp = sp->value; + sheap("\n# %d \"%s\"\n", ifiles->lineno, ifiles->fname); + while ((t = sloscan()) == WSPACE) + ; + if (t != ')') + error("pragma syntax error"); +} - rp2.next = rp; - rp2.sp = sp; +/* + * Return true if it is OK to expand this symbol. + */ +static int +okexp(struct symtab *sp) +{ + int i; - if (*vp-- != OBJCT) { - int gotwarn = 0; - - /* should we be here at all? */ - /* check if identifier is followed by parentheses */ - - obp = stringbuf; - nl = 0; - do { - c = cinput(); - *stringbuf++ = (uchar)c; - if (c == WARN) { - gotwarn++; - if (rp == NULL) - break; - } - if (c == '\n') - nl++; - } while (c == ' ' || c == '\t' || c == '\n' || - c == '\r' || c == WARN); - - DPRINT(("c %d\n", c)); - if (c == '(' ) { - cunput(c); - stringbuf = obp; - ifiles->lineno += nl; - expdef(vp, &rp2, gotwarn); - return 1; - } else { - *stringbuf = 0; - unpstr(obp); - unpstr(sp->namep); - if ((c = sloscan()) != IDENT) - error("internal sync error"); - stringbuf = obp; + if (sp == NULL) + return 0; + for (i = 0; i < bidx; i++) + if (norep[bptr[i]] == sp) return 0; - } - } else { - cunput(WARN); - cp = vp; - while (*cp) { - if (*cp != CONC) - cunput(*cp); - cp--; - } - expmac(&rp2); - } return 1; } +/* + * Insert block(s) before each expanded name. + * Input is in lex buffer, output on lex buffer. + */ +static void +insblock(int bnr) +{ + usch *bp = stringbuf; + int c, i; + + IMP("IB"); + while ((c = sloscan()) != WARN) { + if (c == EBLOCK) { + sss(); + continue; + } + if (c == IDENT) { + savch(EBLOCK), savch(bnr & 255), savch(bnr >> 8); + for (i = 0; i < bidx; i++) + savch(EBLOCK), savch(bptr[i] & 255), + savch(bptr[i] >> 8); + } + savstr((const usch *)yytext); + if (c == '\n') + (void)cinput(); + } + savch(0); + cunput(WARN); + unpstr(bp); + stringbuf = bp; + IMP("IBRET"); +} + +/* Delete next WARN on the input stream */ +static void +delwarn(void) +{ + usch *bp = stringbuf; + int c; + + IMP("DELWARN"); + while ((c = sloscan()) != WARN) { + if (c == EBLOCK) { + sss(); + } else + savstr(yytext); + } + savch(0); + unpstr(bp); + stringbuf = bp; + IMP("DELWRET"); +} + +/* + * Handle defined macro keywords found on input stream. + * When finished print out the full expanded line. + * Everything on lex buffer except for the symtab. + */ +int +kfind(struct symtab *sp) +{ + struct symtab *nl; + const usch *argary[MAXARGS+1], *cbp; + usch *sbp; + int c, o, chkf; + + DPRINT(("%d:enter kfind(%s)\n",0,sp->namep)); + IMP("KFIND"); + if (*sp->value == OBJCT) { + if (sp == filloc) { + unpstr(sheap("\"%s\"", ifiles->fname)); + return 1; + } else if (sp == linloc) { + unpstr(sheap("%d", ifiles->lineno)); + return 1; + } + IMP("END1"); + cunput(WARN); + for (cbp = sp->value-1; *cbp; cbp--) + cunput(*cbp); + insblock(addmac(sp)); + IMP("ENDX"); + exparg(1); + +upp: sbp = stringbuf; + chkf = 1; + if (obufp != 0) + lastoch = outbuf[obufp-1]; + if (iswsnl(lastoch)) + chkf = 0; + while ((c = sloscan()) != WARN) { + switch (c) { + case STRING: + /* Remove embedded directives */ + for (cbp = (usch *)yytext; *cbp; cbp++) { + if (*cbp == EBLOCK) + cbp+=2; + else if (*cbp != CONC) + savch(*cbp); + } + break; + + case EBLOCK: + doblk(); + /* FALLTHROUGH */ + case IDENT: + /* + * Tricky: if this is the last identifier + * in the expanded list, and it is defined + * as a function-like macro, then push it + * back on the input stream and let fastscan + * handle it as a new macro. + * BUT: if this macro is blocked then this + * should not be done. + */ + nl = lookup((usch *)yytext, FIND); + o = okexp(nl); + bidx = 0; + /* Deal with pragmas here */ + if (nl == pragloc) { + pragoper(); + break; + } + if (nl == NULL || !o || *nl->value == OBJCT) { + /* Not fun-like macro */ + savstr(yytext); + break; + } + c = cinput(); + if (c == WARN) { + /* succeeded, push back */ + unpstr(yytext); + } else { + savstr(yytext); + } + cunput(c); + break; + + default: + if (chkf && c < 127) + putch(' '); + savstr(yytext); + break; + } + chkf = 0; + } + IMP("END2"); + norepptr = 1; + savch(0); + stringbuf = sbp; + return 1; + } + /* Is a function-like macro */ + + /* Search for '(' */ + sbp = stringbuf; + while (iswsnl(c = cinput())) + savch(c); + savch(0); + stringbuf = sbp; + if (c != '(') { + cunput(c); + unpstr(sbp); + return 0; /* Failed */ + } + + /* Found one, output \n to be in sync */ + for (; *sbp; sbp++) { + if (*sbp == '\n') + putch('\n'), ifiles->lineno++; + } + + /* fetch arguments */ + if (readargs(sp, argary)) + error("readargs"); + + c = addmac(sp); + sbp = stringbuf; + cunput(WARN); + + IMP("KEXP"); + subarg(sp, argary, 1); + IMP("KNEX"); + insblock(c); + IMP("KBLK"); + + stringbuf = sbp; + + exparg(1); + + IMP("END"); + + goto upp; + +} + +/* + * Replace and push-back on input stream the eventual replaced macro. + * The check for whether it can expand or not should already have been done. + * Blocks for this identifier will be added via insblock() after expansion. + */ +int +submac(struct symtab *sp, int lvl) +{ + const usch *argary[MAXARGS+1]; + const usch *cp; + usch *bp; + int ch; + + DPRINT(("%d:submac1: trying '%s'\n", lvl, sp->namep)); + if (*sp->value == OBJCT) { + if (sp == filloc) { + unpstr(sheap("\"%s\"", ifiles->fname)); + return 1; + } else if (sp == linloc) { + unpstr(sheap("%d", ifiles->lineno)); + return 1; + } + + DPRINT(("submac: exp object macro '%s'\n",sp->namep)); + /* expand object-type macros */ + ch = addmac(sp); + cunput(WARN); + + for (cp = sp->value-1; *cp; cp--) + cunput(*cp); + insblock(ch); + delwarn(); + return 1; + } + + /* + * Function-like macro; see if it is followed by a ( + * Be careful about the expand/noexpand balance. + * Store read data on heap meanwhile. + * For directive #define foo() kaka + * If input is foo() then + * output should be kaka. + */ + bp = stringbuf; + while (iswsnl(ch = cinput())) + savch(ch); + savch(0); + stringbuf = bp; + if (ch != '(') { + cunput(ch); + unpstr(bp); + return 0; /* Failed */ + } + + /* no \n should be here */ + + /* + * A function-like macro has been found. Read in the arguments, + * expand them and push-back everything for another scan. + */ + DPRINT(("%d:submac: continue macro '%s'\n", lvl, sp->namep)); + savch(0); + if (readargs(sp, argary)) { + /* Bailed out in the middle of arg list */ + unpstr(bp); + if (dflag>1)printf("%d:noreadargs\n", lvl); + stringbuf = bp; + return 0; + } + + /* when all args are read from input stream */ + ch = addmac(sp); + + DDPRINT(("%d:submac pre\n", lvl)); + cunput(WARN); + + subarg(sp, argary, lvl+1); + + DDPRINT(("%d:submac post\n", lvl)); + insblock(ch); + delwarn(); + + stringbuf = bp; /* Reset heap */ + DPRINT(("%d:Return submac\n", lvl)); + IMP("SM1"); + return 1; +} + +/* + * Read arguments and put in argument array. + * If WARN is encountered return 1, otherwise 0. + */ +int +readargs(struct symtab *sp, const usch **args) +{ + const usch *vp = sp->value; + int c, i, plev, narg, ellips = 0; + int warn; + + DPRINT(("readargs\n")); + + narg = *vp--; + if (narg == VARG) { + narg = *vp--; + ellips = 1; + } + + IMP("RDA1"); + /* + * read arguments and store them on heap. + */ + warn = 0; + c = '('; + for (i = 0; i < narg && c != ')'; i++) { + args[i] = stringbuf; + plev = 0; + while ((c = sloscan()) == WSPACE || c == '\n') + if (c == '\n') + putch(cinput()); + for (;;) { + while (c == EBLOCK) { + sss(); + c = sloscan(); + } + if (c == WARN) { + warn++; + goto oho; + } + if (plev == 0 && (c == ')' || c == ',')) + break; + if (c == '(') + plev++; + if (c == ')') + plev--; + savstr((usch *)yytext); +oho: while ((c = sloscan()) == '\n') { + putch(cinput()); + savch(' '); + } + while (c == CMNT) { + getcmnt(); + c = sloscan(); + } + if (c == 0) + error("eof in macro"); + } + while (args[i] < stringbuf && + iswsnl(stringbuf[-1]) && stringbuf[-3] != EBLOCK) + stringbuf--; + savch('\0'); + if (dflag) { + printf("readargs: save arg %d '", i); + prline(args[i]); + printf("'\n"); + } + } + + IMP("RDA2"); + /* Handle varargs readin */ + if (ellips) + args[i] = (const usch *)""; + if (ellips && c != ')') { + args[i] = stringbuf; + plev = 0; + while ((c = sloscan()) == WSPACE) + ; + for (;;) { + if (plev == 0 && c == ')') + break; + if (c == '(') + plev++; + if (c == ')') + plev--; + if (c == EBLOCK) { + sss(); + } else + savstr((usch *)yytext); + while ((c = sloscan()) == '\n') { + cinput(); + savch(' '); + } + } + while (args[i] < stringbuf && iswsnl(stringbuf[-1])) + stringbuf--; + savch('\0'); + + } + if (narg == 0 && ellips == 0) + while ((c = sloscan()) == WSPACE || c == '\n') + if (c == '\n') + cinput(); + + if (c != ')' || (i != narg && ellips == 0) || (i < narg && ellips == 1)) + error("wrong arg count"); + while (warn) + cunput(WARN), warn--; + return 0; +} + +#if 0 /* * Maybe an indentifier (for macro expansion). */ static int -mayid(uchar *s) +mayid(usch *s) { for (; *s; s++) if (!isdigit(*s) && !isalpha(*s) && *s != '_') return 0; return 1; } +#endif /* - * do macro-expansion until WARN character read. - * read from lex buffer and store result on heap. - * will recurse into lookup() for recursive expansion. - * when returning all expansions on the token list is done. + * expand a function-like macro. + * vp points to end of replacement-list + * reads function arguments from sloscan() + * result is pushed-back for more scanning. */ void -expmac(struct recur *rp) +subarg(struct symtab *nl, const usch **args, int lvl) +{ + int narg, instr, snuff; + const usch *sp, *bp, *ap, *vp; + + DPRINT(("%d:subarg '%s'\n", lvl, nl->namep)); + vp = nl->value; + narg = *vp--; + if (narg == VARG) + narg = *vp--; + + sp = vp; + instr = snuff = 0; + if (dflag>1) { + printf("%d:subarg ARGlist for %s: '", lvl, nl->namep); + prrep(vp); + printf("'\n"); + } + + /* + * push-back replacement-list onto lex buffer while replacing + * arguments. Arguments are macro-expanded if required. + */ + while (*sp != 0) { + if (*sp == SNUFF) + cunput('\"'), snuff ^= 1; + else if (*sp == CONC) + ; + else if (*sp == WARN) { + + if (sp[-1] == VARG) { + bp = ap = args[narg]; + sp--; +#ifdef GCC_COMPAT + } else if (sp[-1] == GCCARG) { + ap = args[narg]; + if (ap[0] == 0) + ap = (const usch *)"0"; + bp = ap; + sp--; +#endif + } else + bp = ap = args[(int)*--sp]; + if (dflag>1){ + printf("%d:subarg GOTwarn; arglist '", lvl); + prline(bp); + printf("'\n"); + } + if (sp[2] != CONC && !snuff && sp[-1] != CONC) { + /* + * Expand an argument; 6.10.3.1: + * "A parameter in the replacement list, + * is replaced by the corresponding argument + * after all macros contained therein have + * been expanded.". + */ + cunput(WARN); + unpstr(bp); + exparg(lvl+1); + delwarn(); + } else { + while (*bp) + bp++; + while (bp > ap) { + bp--; + if (snuff && !instr && iswsnl(*bp)) { + while (iswsnl(*bp)) + bp--; + cunput(' '); + } + + cunput(*bp); + if ((*bp == '\'' || *bp == '"') + && bp[-1] != '\\' && snuff) { + instr ^= 1; + if (instr == 0 && *bp == '"') + cunput('\\'); + } + if (instr && (*bp == '\\' || *bp == '"')) + cunput('\\'); + } + } + } else + cunput(*sp); + sp--; + } + DPRINT(("%d:Return subarg\n", lvl)); + IMP("SUBARG"); +} + +/* + * Do a (correct) expansion of a WARN-terminated buffer of tokens. + * Data is read from the lex buffer, result on lex buffer, WARN-terminated. + * Expansion blocking is not altered here unless when tokens are + * concatenated, in which case they are removed. + */ +void +exparg(int lvl) { struct symtab *nl; - int c, noexp = 0, orgexp; - uchar *och, *stksv; + int c, i; + usch *och; + usch *osb = stringbuf; + int anychange; + + DPRINT(("%d:exparg\n", lvl)); + IMP("EXPARG"); -#ifdef CPP_DEBUG - if (dflag) { - struct recur *rp2 = rp; - printf("\nexpmac\n"); - while (rp2) { - printf("do not expand %s\n", rp2->sp->namep); - rp2 = rp2->next; - } - } -#endif readmac++; +rescan: + anychange = 0; while ((c = sloscan()) != WARN) { + DDPRINT(("%d:exparg swdata %d\n", lvl, c)); + IMP("EA0"); switch (c) { - case NOEXP: noexp++; break; - case EXPAND: noexp--; break; - case NUMBER: /* handled as ident if no .+- in it */ - if (!mayid((uchar *)yytext)) - goto def; + case EBLOCK: + doblk(); /* FALLTHROUGH */ case IDENT: /* * Handle argument concatenation here. - * If an identifier is found and directly - * after EXPAND or NOEXP then push the - * identifier back on the input stream and - * call sloscan() again. - * Be careful to keep the noexp balance. + * In case of concatenation, scratch all blockings. */ + DDPRINT(("%d:exparg ident %d\n", lvl, c)); och = stringbuf; - savstr((uchar *)yytext); - DDPRINT(("id: str %s\n", och)); - orgexp = 0; - while ((c = sloscan()) == EXPAND || c == NOEXP) - if (c == EXPAND) - orgexp--; - else - orgexp++; +sav: savstr(yytext); - DDPRINT(("id1: typ %d noexp %d orgexp %d\n", - c, noexp, orgexp)); - if (c == IDENT || - (c == NUMBER && mayid((uchar *)yytext))) { - DDPRINT(("id2: str %s\n", yytext)); - /* OK to always expand here? */ - savstr((uchar *)yytext); - switch (orgexp) { - case 0: /* been EXP+NOEXP */ - if (noexp == 0) - break; - if (noexp != 1) - error("case 0"); - cunput(NOEXP); - noexp = 0; - break; - case -1: /* been EXP */ - if (noexp != 1) - error("case -1"); - noexp = 0; - break; - case 1: - if (noexp != 0) - error("case 1"); - cunput(NOEXP); - break; - default: - error("orgexp = %d", orgexp); + if ((c = cinput()) == EBLOCK) { + /* yep, are concatenating; forget blocks */ + do { + (void)cinput(); + (void)cinput(); + } while ((c = sloscan()) == EBLOCK); + bidx = 0; + goto sav; + } + cunput(c); + + DPRINT(("%d:exparg: str '%s'\n", lvl, och)); + IMP("EA1"); + /* see if ident is expandable */ + if ((nl = lookup(och, FIND)) && okexp(nl)) { + if (submac(nl, lvl+1)) { + /* Could expand, result on lexbuffer */ + stringbuf = och; /* clear saved name */ + anychange = 1; } - unpstr(och); + } else if (bidx) { + /* must restore blocks */ stringbuf = och; - continue; /* New longer identifier */ + for (i = 0; i < bidx; i++) + savch(EBLOCK), savch(bptr[i] & 255), + savch(bptr[i] >> 8); + savstr(yytext); } - unpstr((const uchar *)yytext); - if (orgexp == -1) - cunput(EXPAND); - else if (orgexp == -2) - cunput(EXPAND), cunput(EXPAND); - else if (orgexp == 1) - cunput(NOEXP); - unpstr(och); - stringbuf = och; - - - sloscan(); /* XXX reget last identifier */ - - if ((nl = lookup((uchar *)yytext, FIND)) == NULL) - goto def; - - if (canexpand(rp, nl) == 0) - goto def; - /* - * If noexp == 0 then expansion of any macro is - * allowed. If noexp == 1 then expansion of a - * fun-like macro is allowed iff there is an - * EXPAND between the identifier and the '('. - */ - if (noexp == 0) { - if ((c = subst(nl, rp)) == 0) - goto def; - break; - } - if (noexp != 1) - error("bad noexp %d", noexp); - stksv = NULL; - if ((c = sloscan()) == WSPACE) { - stksv = xstrdup(yytext); - c = sloscan(); - } - /* only valid for expansion if fun macro */ - if (c == EXPAND && *nl->value != OBJCT) { - noexp--; - if (subst(nl, rp)) - break; - savstr(nl->namep); - if (stksv) - savstr(stksv); - } else { - unpstr((const uchar *)yytext); - if (stksv) - unpstr(stksv); - savstr(nl->namep); - } - if (stksv) - free(stksv); + bidx = 0; + IMP("EA2"); break; case CMNT: @@ -1273,237 +1620,65 @@ expmac(struct recur *rp) savch(' '); break; - case STRING: - /* remove EXPAND/NOEXP from strings */ - if (yytext[1] == NOEXP) { - savch('"'); - och = (uchar *)&yytext[2]; - while (*och != EXPAND) - savch(*och++); - savch('"'); - break; - } - /* FALLTHROUGH */ - -def: default: - savstr((uchar *)yytext); + default: + savstr((usch *)yytext); break; } } - if (noexp) - error("expmac noexp=%d", noexp); - readmac--; - DPRINT(("return from expmac\n")); -} - -/* - * expand a function-like macro. - * vp points to end of replacement-list - * reads function arguments from sloscan() - * result is written on top of heap - */ -void -expdef(const uchar *vp, struct recur *rp, int gotwarn) -{ - const uchar **args, *ap, *bp, *sp; - uchar *sptr; - int narg, c, i, plev, snuff, instr; - int ellips = 0, shot = gotwarn; - size_t allocsz; - - DPRINT(("expdef rp %s\n", (rp ? (const char *)rp->sp->namep : ""))); - c = sloscan(); - if (c != '(') - error("got %c, expected (", c); - - if (vp[1] == VARG) { - narg = *vp--; - ellips = 1; - } else - narg = vp[1]; - - // The code depends on malloc(0) returning a non-NULL pointer, which is not guaranteed. - // Workaround it. - allocsz = sizeof(uchar *) * ((narg+ellips) ? (narg+ellips) : 1); - args = malloc(allocsz); - if (args == NULL) - error("expdef: out of mem"); - - /* - * read arguments and store them on heap. - * will be removed just before return from this function. - */ - sptr = stringbuf; - instr = 0; - for (i = 0; i < narg && c != ')'; i++) { - args[i] = stringbuf; - plev = 0; - while ((c = sloscan()) == WSPACE || c == '\n') - if (c == '\n') - putch(cinput()); - DDPRINT((":AAA (%d)", c)); - if (instr == -1) - savch(NOEXP), instr = 1; - if (c == NOEXP) - instr = 1; - for (;;) { - if (plev == 0 && (c == ')' || c == ',')) - break; - if (c == '(') - plev++; - if (c == ')') - plev--; - savstr((uchar *)yytext); - while ((c = sloscan()) == '\n') { - putch(cinput()); - savch('\n'); - } - while (c == CMNT) { - getcmnt(); - c = sloscan(); - } - if (c == EXPAND) - instr = 0; - if (c == 0) - error("eof in macro"); - } - while (args[i] < stringbuf && - (stringbuf[-1] == ' ' || stringbuf[-1] == '\t')) - stringbuf--; - if (instr == 1) - savch(EXPAND), instr = -1; - savch('\0'); - } - if (ellips) - args[i] = (const uchar *)""; - if (ellips && c != ')') { - args[i] = stringbuf; - plev = 0; - instr = 0; - while ((c = sloscan()) == WSPACE) - ; - if (c == NOEXP) - instr++; - DDPRINT((":AAY (%d)", c)); - for (;;) { - if (plev == 0 && c == ')') - break; - if (c == '(') - plev++; - if (c == ')') - plev--; - if (plev == 0 && c == ',' && instr) { - savch(EXPAND); - savch(','); - savch(NOEXP); - } else - savstr((uchar *)yytext); - while ((c = sloscan()) == '\n') { - cinput(); - savch('\n'); - } - if (c == EXPAND) - instr--; - } - while (args[i] < stringbuf && - (stringbuf[-1] == ' ' || stringbuf[-1] == '\t')) - stringbuf--; - savch('\0'); - - } - if (narg == 0 && ellips == 0) - while ((c = sloscan()) == WSPACE || c == '\n') - if (c == '\n') - cinput(); - - if (c != ')' || (i != narg && ellips == 0) || (i < narg && ellips == 1)) - error("wrong arg count"); - - while (gotwarn--) - cunput(WARN); - - sp = vp; - instr = snuff = 0; - - /* - * push-back replacement-list onto lex buffer while replacing - * arguments. - */ + *stringbuf = 0; cunput(WARN); - while (*sp != 0) { - if (*sp == SNUFF) - cunput('\"'), snuff ^= 1; - else if (*sp == CONC) - ; - else if (*sp == WARN) { - - if (sp[-1] == VARG) { - bp = ap = args[narg]; - sp--; -#ifdef GCC_VARI - } else if (sp[-1] == GCCARG) { - ap = args[narg]; - if (ap[0] == 0) - ap = (const uchar *)"0"; - bp = ap; - sp--; -#endif - } else - bp = ap = args[(int)*--sp]; - if (sp[2] != CONC && !snuff && sp[-1] != CONC) { - struct recur *r2 = rp->next; - cunput(WARN); - while (*bp) - bp++; - while (bp > ap) - cunput(*--bp); - DPRINT(("expand arg %d string %s\n", *sp, ap)); - bp = ap = stringbuf; - savch(NOEXP); - while (shot && r2) - r2 = r2->next, shot--; - expmac(r2); - savch(EXPAND); - savch('\0'); - } - while (*bp) - bp++; - while (bp > ap) { - bp--; - if (snuff && !instr && - (*bp == ' ' || *bp == '\t' || *bp == '\n')){ - while (*bp == ' ' || *bp == '\t' || - *bp == '\n') { - bp--; - } - cunput(' '); - } - if (!snuff || (*bp != EXPAND && *bp != NOEXP)) - cunput(*bp); - if ((*bp == '\'' || *bp == '"') - && bp[-1] != '\\' && snuff) { - instr ^= 1; - if (instr == 0 && *bp == '"') - cunput('\\'); - } - if (instr && (*bp == '\\' || *bp == '"')) - cunput('\\'); - } - } else - cunput(*sp); - sp--; - } - stringbuf = sptr; - - /* scan the input buffer (until WARN) and save result on heap */ - expmac(rp); - free(args); + unpstr(osb); + DPRINT(("%d:exparg return: change %d\n", lvl, anychange)); + IMP("EXPRET"); + stringbuf = osb; + if (anychange) + goto rescan; + readmac--; } -uchar * -savstr(const uchar *str) +void +imp(const char *str) { - uchar *rv = stringbuf; + printf("%s (%d) '", str, bidx); + prline(ifiles->curptr); + printf("'\n"); +} + +void +prrep(const usch *s) +{ + while (*s) { + switch (*s) { + case WARN: printf("", *--s); break; + case CONC: printf(""); break; + case SNUFF: printf(""); break; + case EBLOCK: printf("",s[-1] + s[-2] * 256); s-=2; break; + default: printf("%c", *s); break; + } + s--; + } +} + +void +prline(const usch *s) +{ + while (*s) { + switch (*s) { + case WARN: printf(""); break; + case CONC: printf(""); break; + case SNUFF: printf(""); break; + case EBLOCK: printf("",s[1] + s[2] * 256); s+=2; break; + case '\n': printf(""); break; + default: printf("%c", *s); break; + } + s++; + } +} + +usch * +savstr(const usch *str) +{ + usch *rv = stringbuf; do { if (stringbuf >= &sbf[SBSIZE]) { @@ -1515,25 +1690,23 @@ savstr(const uchar *str) return rv; } -int -canexpand(struct recur *rp, struct symtab *np) -{ - struct recur *w; - - for (w = rp; w && w->sp != np; w = w->next) - ; - if (w != NULL) - return 0; - return 1; -} - void -unpstr(const uchar *c) +unpstr(const usch *c) { - const uchar *d = c; + const usch *d = c; - while (*d) +#if 0 + if (dflag>1) { + printf("Xunpstr: '"); + prline(c); + printf("'\n"); + } +#endif + while (*d) { + if (*d == EBLOCK) + d += 2; d++; + } while (d > c) { cunput(*--d); } @@ -1546,19 +1719,20 @@ flbuf() return; if (Mflag == 0 && write(ofd, outbuf, obufp) < 0) error("obuf write error"); + lastoch = outbuf[obufp-1]; obufp = 0; } void putch(int ch) { - outbuf[obufp++] = (uchar)ch; + outbuf[obufp++] = (usch)ch; if (obufp == CPPBUF || (istty && ch == '\n')) flbuf(); } void -putstr(const uchar *s) +putstr(const usch *s) { for (; *s; s++) { outbuf[obufp++] = *s; @@ -1573,14 +1747,14 @@ putstr(const uchar *s) static void num2str(int num) { - static uchar buf[12]; - uchar *b = buf; + static usch buf[12]; + usch *b = buf; int m = 0; - + if (num < 0) num = -num, m = 1; do { - *b++ = (uchar)(num % 10 + '0'); + *b++ = (usch)(num % 10 + '0'); num /= 10; } while (num); if (m) @@ -1590,14 +1764,14 @@ num2str(int num) } /* - * similar to sprintf, but only handles %s and %d. + * similar to sprintf, but only handles %s and %d. * saves result on heap. */ -uchar * +usch * sheap(const char *fmt, ...) { va_list ap; - uchar *op = stringbuf; + usch *op = stringbuf; va_start(ap, fmt); for (; *fmt; fmt++) { @@ -1605,7 +1779,7 @@ sheap(const char *fmt, ...) fmt++; switch (*fmt) { case 's': - savstr(va_arg(ap, uchar *)); + savstr(va_arg(ap, usch *)); break; case 'd': num2str(va_arg(ap, int)); @@ -1630,13 +1804,26 @@ usage() error("Usage: cpp [-Cdt] [-Dvar=val] [-Uvar] [-Ipath] [-Spath]"); } +#ifdef notyet /* * Symbol table stuff. - * The data structure used is a patricia tree implementation. + * The data structure used is a patricia tree implementation using only + * bytes to store offsets. + * The information stored is (lower address to higher): + * + * unsigned char bitno[2]; bit number in the string + * unsigned char left[3]; offset from base to left element + * unsigned char right[3]; offset from base to right element + */ +#endif + +/* + * This patricia implementation is more-or-less the same as + * used in ccom for string matching. */ struct tree { - int bitno; /* bit number in the string */ - struct tree *lr[2]; /* left/right element */ + int bitno; + struct tree *lr[2]; }; #define BITNO(x) ((x) & ~(LEFT_IS_LEAF|RIGHT_IS_LEAF)) @@ -1654,7 +1841,7 @@ static int numsyms; * Allocate a symtab struct and store the string. */ static struct symtab * -getsymtab(const uchar *str) +getsymtab(const usch *str) { struct symtab *sp = malloc(sizeof(struct symtab)); @@ -1663,7 +1850,7 @@ getsymtab(const uchar *str) sp->namep = savstr(str); savch('\0'); sp->value = NULL; - sp->file = ifiles ? ifiles->orgfn : (const uchar *)""; + sp->file = ifiles ? ifiles->orgfn : (const usch *)""; sp->line = ifiles ? ifiles->lineno : 0; return sp; } @@ -1673,12 +1860,12 @@ getsymtab(const uchar *str) * Only do full string matching, no pointer optimisations. */ struct symtab * -lookup(const uchar *key, int enterf) +lookup(const usch *key, int enterf) { struct symtab *sp; struct tree *w, *new, *last; int len, cix, bit, fbit, svbit, ix, bitno; - const uchar *k, *m; + const usch *k, *m/*, *sm*/; /* Count full string length */ for (k = key, len = 0; *k; k++, len++) @@ -1694,6 +1881,7 @@ lookup(const uchar *key, int enterf) case 1: w = sympole; + svbit = 0; /* XXX gcc */ break; default: @@ -1712,7 +1900,7 @@ lookup(const uchar *key, int enterf) sp = (struct symtab *)w; - m = sp->namep; + /*sm =*/ m = sp->namep; k = key; /* Check for correct string and return */ @@ -1732,8 +1920,7 @@ lookup(const uchar *key, int enterf) ix >>= 1, cix++; /* Create new node */ - new = malloc(sizeof *new); - if (! new) + if ((new = malloc(sizeof *new)) == NULL) error("getree: couldn't allocate tree"); bit = P_BIT(key, cix); new->bitno = cix | (bit ? RIGHT_IS_LEAF : LEFT_IS_LEAF); @@ -1748,7 +1935,6 @@ lookup(const uchar *key, int enterf) w = sympole; last = NULL; - svbit = 0; /* XXX gcc */ for (;;) { fbit = w->bitno; bitno = BITNO(w->bitno); @@ -1774,3 +1960,15 @@ lookup(const uchar *key, int enterf) new->bitno |= (bit ? LEFT_IS_LEAF : RIGHT_IS_LEAF); return (struct symtab *)new->lr[bit]; } + +usch * +xstrdup(const usch *str) +{ + size_t len = strlen((const char *)str)+1; + usch *rv; + + if ((rv = malloc(len)) == NULL) + error("xstrdup: out of mem"); + strlcpy((char *)rv, (const char *)str, len); + return rv; +} diff --git a/src/cmd/cpp/cpp.h b/src/cmd/cpp/cpp.h index 1356dd8..bebc226 100644 --- a/src/cmd/cpp/cpp.h +++ b/src/cmd/cpp/cpp.h @@ -1,5 +1,7 @@ +/* $Id: cpp.h,v 1.47.2.1 2011/02/26 06:36:40 ragge Exp $ */ + /* - * Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se). + * Copyright (c) 2004,2010 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -10,8 +12,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES @@ -24,25 +24,15 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifdef CROSS -# include -# include -#else -# include /* for obuf */ -# include -#endif + +#include /* for obuf */ #include -/* Version string */ -#define VERSSTR "cpp for RetroBSD" +#include "config.h" -typedef unsigned char uchar; -#ifdef YYTEXT_POINTER -extern char *yytext; -#else -extern char yytext[]; -#endif -extern uchar *stringbuf; +typedef unsigned char usch; +extern usch yytext[]; +extern usch *stringbuf; extern int trulvl; extern int flslvl; @@ -50,7 +40,7 @@ extern int elflvl; extern int elslvl; extern int tflag, Cflag, Pflag; extern int Mflag, dMflag; -extern uchar *Mfile; +extern usch *Mfile; extern int ofd; /* args for lookup() */ @@ -58,32 +48,77 @@ extern int ofd; #define ENTER 1 /* buffer used internally */ -#define CPPBUF 512 +#define CPPBUF 512 +#ifndef CPPBUF +#if defined(__pdp11__) +#define CPPBUF BUFSIZ +#define BUF_STACK +#elif defined(WIN32) +/* winxp seems to fail > 26608 bytes */ +#define CPPBUF 16384 +#else +#define CPPBUF (65536*2) +#endif +#endif + +#define MAXARGS 20//128 /* Max # of args to a macro. Should be enouth */ #define NAMEMAX CPPBUF /* currently pushbackbuffer */ +#define BBUFSZ (NAMEMAX+CPPBUF+1) + +#define GCCARG 0xfd /* has gcc varargs that may be replaced with 0 */ +#define VARG 0xfe /* has varargs */ +#define OBJCT 0xff +#define WARN 1 /* SOH, not legal char */ +#define CONC 2 /* STX, not legal char */ +#define SNUFF 3 /* ETX, not legal char */ +#define EBLOCK 4 /* EOT, not legal char */ + +/* Used in macro expansion */ +#define RECMAX 400//10000 /* max # of recursive macros */ +extern struct symtab *norep[RECMAX]; +extern int norepptr; +extern unsigned short bptr[RECMAX]; +extern int bidx; +#define MKB(l,h) (l+((h)<<8)) + +/* quick checks for some characters */ +#define C_SPEC 001 +#define C_EP 002 +#define C_ID 004 +#define C_I (C_SPEC|C_ID) +#define C_2 010 /* for yylex() tokenizing */ +#define C_WSNL 020 /* ' ','\t','\r','\n' */ +#define iswsnl(x) (spechr[x] & C_WSNL) +extern char spechr[]; /* definition for include file info */ struct includ { struct includ *next; - const uchar *fname; /* current fn, changed if #line found */ - const uchar *orgfn; /* current fn, not changed */ + const usch *fname; /* current fn, changed if #line found */ + const usch *orgfn; /* current fn, not changed */ int lineno; int infil; - uchar *curptr; - uchar *maxread; - uchar *ostr; - uchar *buffer; + usch *curptr; + usch *maxread; + usch *ostr; + usch *buffer; int idx; void *incs; - const uchar *fn; - uchar bbuf[NAMEMAX+CPPBUF+1]; -} *ifiles; + const usch *fn; +#ifdef BUF_STACK + usch bbuf[BBUFSZ]; +#else + usch *bbuf; +#endif +}; +extern struct includ *ifiles; /* Symbol table entry */ struct symtab { - const uchar *namep; - const uchar *value; - const uchar *file; + const usch *namep; + const usch *value; + const usch *file; int line; }; @@ -110,13 +145,15 @@ struct nd { #define nd_val n.val #define nd_uval n.uval -struct recur; /* not used outside cpp.c */ -int subst(struct symtab *, struct recur *); -struct symtab *lookup(const uchar *namep, int enterf); -uchar *gotident(struct symtab *nl); -int slow; /* scan slowly for new tokens */ +struct symtab *lookup(const usch *namep, int enterf); +usch *gotident(struct symtab *nl); +extern int slow; /* scan slowly for new tokens */ +int submac(struct symtab *nl, int); +int kfind(struct symtab *nl); +int doexp(void); +int donex(void); -int pushfile(const uchar *fname, const uchar *fn, int idx, void *incs); +int pushfile(const usch *fname, const usch *fn, int idx, void *incs); void popfile(void); void prtline(void); int yylex(void); @@ -128,18 +165,22 @@ void setline(int); void setfile(char *); int yyparse(void); void yyerror(const char *); -void unpstr(const uchar *); -uchar *savstr(const uchar *str); +void unpstr(const usch *); +usch *savstr(const usch *str); void savch(int c); void mainscan(void); void putch(int); -void putstr(const uchar *s); +void putstr(const usch *s); void line(void); -uchar *sheap(const char *fmt, ...); -void xwarning(uchar *); -void xerror(uchar *); -#define warning(args...) xwarning(sheap(args)) -#define error(args...) xerror(sheap(args)) -void expmac(struct recur *); +usch *sheap(const char *fmt, ...); +void xwarning(usch *); +void xerror(usch *); +#ifdef HAVE_CPP_VARARG_MACRO_GCC +#define warning(...) xwarning(sheap(__VA_ARGS__)) +#define error(...) xerror(sheap(__VA_ARGS__)) +#else +#define warning printf +#define error printf +#endif int cinput(void); void getcmnt(void); diff --git a/src/cmd/cpp/cpy.y b/src/cmd/cpp/cpy.y index 4e4c1a5..78bc3ca 100644 --- a/src/cmd/cpp/cpy.y +++ b/src/cmd/cpp/cpy.y @@ -1,3 +1,5 @@ +/* $Id: cpy.y,v 1.18 2010/02/25 15:49:00 ragge Exp $ */ + /* * Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -58,6 +60,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ + %{ #include "cpp.h" diff --git a/src/cmd/cpp/scanner.l b/src/cmd/cpp/scanner.l new file mode 100644 index 0000000..f1e4bf9 --- /dev/null +++ b/src/cmd/cpp/scanner.l @@ -0,0 +1,939 @@ +%{ +/* $Id: scanner.l,v 1.49 2009/02/14 09:23:55 ragge Exp $ */ + +/* + * Copyright (c) 2004 Anders Magnusson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include + +#include "compat.h" +#include "cpp.h" +#include "y.tab.h" +%} + +%{ +static void cvtdig(int rad); +static int charcon(usch *); +static void elsestmt(void); +static void ifdefstmt(void); +static void ifndefstmt(void); +static void endifstmt(void); +static void ifstmt(void); +static void cpperror(void); +static void pragmastmt(void); +static void undefstmt(void); +static void cpperror(void); +static void elifstmt(void); +static void storepb(void); +static void badop(const char *); +void include(void); +void define(void); + +extern int yyget_lineno (void); +extern void yyset_lineno (int); + +static int inch(void); + +static int scale, gotdef, contr; +int inif; + +#ifdef FLEX_SCANNER /* should be set by autoconf instead */ +static int +yyinput(char *b, int m) +{ + int c, i; + + for (i = 0; i < m; i++) { + if ((c = inch()) < 0) + break; + *b++ = c; + if (c == '\n') { + i++; + break; + } + } + return i; +} +#undef YY_INPUT +#undef YY_BUF_SIZE +#define YY_BUF_SIZE (8*65536) +#define YY_INPUT(b,r,m) (r = yyinput(b, m)) +#ifdef HAVE_CPP_VARARG_MACRO_GCC +#define fprintf(x, ...) error(__VA_ARGS__) +#endif +#define ECHO putstr((usch *)yytext) +#undef fileno +#define fileno(x) 0 + +#if YY_FLEX_SUBMINOR_VERSION >= 31 +/* Hack to avoid unnecessary warnings */ +FILE *yyget_in (void); +FILE *yyget_out (void); +int yyget_leng (void); +char *yyget_text (void); +void yyset_in (FILE * in_str ); +void yyset_out (FILE * out_str ); +int yyget_debug (void); +void yyset_debug (int bdebug ); +int yylex_destroy (void); +#endif +#else /* Assume lex here */ +#undef input +#undef unput +#define input() inch() +#define unput(ch) unch(ch) +#endif +#define PRTOUT(x) if (YYSTATE || slow) return x; if (!flslvl) putstr((usch *)yytext); +/* protection against recursion in #include */ +#define MAX_INCLEVEL 100 +static int inclevel; +%} + +D [0-9] +L [a-zA-Z_] +H [a-fA-F0-9] +E [Ee][+-]?{D}+ +FS (f|F|l|L) +IS (u|U|l|L)* +WS [\t ] + +%s IFR CONTR DEF COMMENT + +%% + +"\n" { int os = YYSTATE; + if (os != IFR) + BEGIN 0; + ifiles->lineno++; + if (flslvl == 0) { + if (ifiles->lineno == 1) + prtline(); + else + putch('\n'); + } + if ((os != 0 || slow) && !contr) + return '\n'; + contr = 0; + } + +"\r" { ; /* Ignore CR's */ } + +"++" { badop("++"); } +"--" { badop("--"); } +"==" { return EQ; } +"!=" { return NE; } +"<=" { return LE; } +"<<" { return LS; } +">>" { return RS; } +">=" { return GE; } +"||" { return OROR; } +"&&" { return ANDAND; } +"defined" { int p, c; + gotdef = 1; + if ((p = c = yylex()) == '(') + c = yylex(); + if (c != IDENT || (p != IDENT && p != '(')) + error("syntax error"); + if (p == '(' && yylex() != ')') + error("syntax error"); + return NUMBER; + } + +{WS}+ { ; } +{L}({L}|{D})* { + yylval.node.op = NUMBER; + if (gotdef) { + yylval.node.nd_val + = lookup((usch *)yytext, FIND) != 0; + gotdef = 0; + return IDENT; + } + yylval.node.nd_val = 0; + return NUMBER; + } + +[0-9][0-9]* { + if (slow && !YYSTATE) + return IDENT; + scale = yytext[0] == '0' ? 8 : 10; + goto num; + } + +0[xX]{H}+{IS}? { scale = 16; + num: if (YYSTATE == IFR) + cvtdig(scale); + PRTOUT(NUMBER); + } +0{D}+{IS}? { scale = 8; goto num; } +{D}+{IS}? { scale = 10; goto num; } +'(\\.|[^\\'])+' { + if (YYSTATE || slow) { + yylval.node.op = NUMBER; + yylval.node.nd_val = charcon((usch *)yytext); + return (NUMBER); + } + if (tflag) + yyless(1); + if (!flslvl) + putstr((usch *)yytext); + } + +. { return yytext[0]; } + +{D}+{E}{FS}? { PRTOUT(FPOINT); } +{D}*"."{D}+({E})?{FS}? { PRTOUT(FPOINT); } +{D}+"."{D}*({E})?{FS}? { PRTOUT(FPOINT); } + +^{WS}*#{WS}* { extern int inmac; + + if (inmac) + error("preprocessor directive found " + "while expanding macro"); + contr = 1; + BEGIN CONTR; + } +{WS}+ { PRTOUT(WSPACE); } + +"ifndef" { contr = 0; ifndefstmt(); } +"ifdef" { contr = 0; ifdefstmt(); } +"if" { contr = 0; storepb(); BEGIN IFR; ifstmt(); BEGIN 0; } +"include" { contr = 0; BEGIN 0; include(); prtline(); } +"else" { contr = 0; elsestmt(); } +"endif" { contr = 0; endifstmt(); } +"error" { contr = 0; if (slow) return IDENT; cpperror(); BEGIN 0; } +"define" { contr = 0; BEGIN DEF; define(); BEGIN 0; } +"undef" { contr = 0; if (slow) return IDENT; undefstmt(); } +"line" { contr = 0; storepb(); BEGIN 0; line(); } +"pragma" { contr = 0; pragmastmt(); BEGIN 0; } +"elif" { contr = 0; storepb(); BEGIN IFR; elifstmt(); BEGIN 0; } + + + +"//".*$ { /* if (tflag) yyless(..) */ + if (Cflag && !flslvl && !slow) + putstr((usch *)yytext); + else if (!flslvl) + putch(' '); + } +"/*" { int c, wrn; + int prtcm = Cflag && !flslvl && !slow; + extern int readmac; + + if (Cflag && !flslvl && readmac) + return CMNT; + + if (prtcm) + putstr((usch *)yytext); + wrn = 0; + more: while ((c = input()) && c != '*') { + if (c == '\n') + putch(c), ifiles->lineno++; + else if (c == 1) /* WARN */ + wrn = 1; + else if (prtcm) + putch(c); + } + if (c == 0) + return 0; + if (prtcm) + putch(c); + if ((c = input()) && c != '/') { + unput(c); + goto more; + } + if (prtcm) + putch(c); + if (c == 0) + return 0; + if (!tflag && !Cflag && !flslvl) + unput(' '); + if (wrn) + unput(1); + } + +"##" { return CONCAT; } +"#" { return MKSTR; } +"..." { return ELLIPS; } +"__VA_ARGS__" { return VA_ARGS; } + +L?\"(\\.|[^\\"])*\" { PRTOUT(STRING); } +[a-zA-Z_0-9]+ { /* {L}({L}|{D})* */ + struct symtab *nl; + if (slow) + return IDENT; + if (YYSTATE == CONTR) { + if (flslvl == 0) { + /*error("undefined control");*/ + while (input() != '\n') + ; + unput('\n'); + BEGIN 0; + goto xx; + } else { + BEGIN 0; /* do nothing */ + } + } + if (flslvl) { + ; /* do nothing */ + } else if (isdigit((int)yytext[0]) == 0 && + (nl = lookup((usch *)yytext, FIND)) != 0) { + usch *op = stringbuf; + putstr(gotident(nl)); + stringbuf = op; + } else + putstr((usch *)yytext); + xx: ; + } + +. { + if (contr) { + while (input() != '\n') + ; + unput('\n'); + BEGIN 0; + contr = 0; + goto yy; + } + if (YYSTATE || slow) + return yytext[0]; + if (yytext[0] == 6) { /* PRAGS */ + usch *obp = stringbuf; + extern usch *prtprag(usch *); + *stringbuf++ = yytext[0]; + do { + *stringbuf = input(); + } while (*stringbuf++ != 14); + prtprag(obp); + stringbuf = obp; + } else { + PRTOUT(yytext[0]); + } + yy:; + } + +%% + +usch *yyp, yybuf[CPPBUF]; + +int yylex(void); +int yywrap(void); + +static int +inpch(void) +{ + int len; + + if (ifiles->curptr < ifiles->maxread) + return *ifiles->curptr++; + + if ((len = read(ifiles->infil, ifiles->buffer, CPPBUF)) < 0) + error("read error on file %s", ifiles->orgfn); + if (len == 0) + return -1; + ifiles->curptr = ifiles->buffer; + ifiles->maxread = ifiles->buffer + len; + return inpch(); +} + +#define unch(c) *--ifiles->curptr = c + +static int +inch(void) +{ + int c; + +again: switch (c = inpch()) { + case '\\': /* continued lines */ +msdos: if ((c = inpch()) == '\n') { + ifiles->lineno++; + putch('\n'); + goto again; + } else if (c == '\r') + goto msdos; + unch(c); + return '\\'; + case '?': /* trigraphs */ + if ((c = inpch()) != '?') { + unch(c); + return '?'; + } + switch (c = inpch()) { + case '=': c = '#'; break; + case '(': c = '['; break; + case ')': c = ']'; break; + case '<': c = '{'; break; + case '>': c = '}'; break; + case '/': c = '\\'; break; + case '\'': c = '^'; break; + case '!': c = '|'; break; + case '-': c = '~'; break; + default: + unch(c); + unch('?'); + return '?'; + } + unch(c); + goto again; + default: + return c; + } +} + +/* + * Let the command-line args be faked defines at beginning of file. + */ +static void +prinit(struct initar *it, struct includ *ic) +{ + char *a, *pre, *post; + + if (it->next) + prinit(it->next, ic); + pre = post = NULL; /* XXX gcc */ + switch (it->type) { + case 'D': + pre = "#define "; + if ((a = strchr(it->str, '=')) != NULL) { + *a = ' '; + post = "\n"; + } else + post = " 1\n"; + break; + case 'U': + pre = "#undef "; + post = "\n"; + break; + case 'i': + pre = "#include \""; + post = "\"\n"; + break; + default: + error("prinit"); + } + strlcat((char *)ic->buffer, pre, CPPBUF+1); + strlcat((char *)ic->buffer, it->str, CPPBUF+1); + if (strlcat((char *)ic->buffer, post, CPPBUF+1) >= CPPBUF+1) + error("line exceeds buffer size"); + + ic->lineno--; + while (*ic->maxread) + ic->maxread++; +} + +/* + * A new file included. + * If ifiles == NULL, this is the first file and already opened (stdin). + * Return 0 on success, -1 if file to be included is not found. + */ +int +pushfile(usch *file) +{ + extern struct initar *initar; + struct includ ibuf; + struct includ *ic; + int c, otrulvl; + + ic = &ibuf; + ic->next = ifiles; + + slow = 0; + if (file != NULL) { + if ((ic->infil = open((char *)file, O_RDONLY)) < 0) + return -1; + ic->orgfn = ic->fname = file; + if (++inclevel > MAX_INCLEVEL) + error("Limit for nested includes exceeded"); + } else { + ic->infil = 0; + ic->orgfn = ic->fname = (usch *)""; + } + ic->buffer = ic->bbuf+NAMEMAX; + ic->curptr = ic->buffer; + ifiles = ic; + ic->lineno = 1; + ic->maxread = ic->curptr; + prtline(); + if (initar) { + *ic->maxread = 0; + prinit(initar, ic); + if (dMflag) + write(ofd, ic->buffer, strlen((char *)ic->buffer)); + initar = NULL; + } + + otrulvl = trulvl; + + if ((c = yylex()) != 0) + error("yylex returned %d", c); + + if (otrulvl != trulvl || flslvl) + error("unterminated conditional"); + + ifiles = ic->next; + close(ic->infil); + inclevel--; + return 0; +} + +/* + * Print current position to output file. + */ +void +prtline() +{ + usch *s, *os = stringbuf; + + if (Mflag) { + if (dMflag) + return; /* no output */ + if (ifiles->lineno == 1) { + s = sheap("%s: %s\n", Mfile, ifiles->fname); + write(ofd, s, strlen((char *)s)); + } + } else if (!Pflag) + putstr(sheap("# %d \"%s\"\n", ifiles->lineno, ifiles->fname)); + stringbuf = os; +} + +void +cunput(int c) +{ +#ifdef CPP_DEBUG + extern int dflag; + if (dflag)printf(": '%c'(%d)", c > 31 ? c : ' ', c); +#endif + unput(c); +} + +int yywrap(void) { return 1; } + +static int +dig2num(int c) +{ + if (c >= 'a') + c = c - 'a' + 10; + else if (c >= 'A') + c = c - 'A' + 10; + else + c = c - '0'; + return c; +} + +/* + * Convert string numbers to unsigned long long and check overflow. + */ +static void +cvtdig(int rad) +{ + unsigned long long rv = 0; + unsigned long long rv2 = 0; + char *y = yytext; + int c; + + c = *y++; + if (rad == 16) + y++; + while (isxdigit(c)) { + rv = rv * rad + dig2num(c); + /* check overflow */ + if (rv / rad < rv2) + error("Constant \"%s\" is out of range", yytext); + rv2 = rv; + c = *y++; + } + y--; + while (*y == 'l' || *y == 'L') + y++; + yylval.node.op = *y == 'u' || *y == 'U' ? UNUMBER : NUMBER; + yylval.node.nd_uval = rv; + if ((rad == 8 || rad == 16) && yylval.node.nd_val < 0) + yylval.node.op = UNUMBER; + if (yylval.node.op == NUMBER && yylval.node.nd_val < 0) + /* too large for signed */ + error("Constant \"%s\" is out of range", yytext); +} + +static int +charcon(usch *p) +{ + int val, c; + + p++; /* skip first ' */ + val = 0; + if (*p++ == '\\') { + switch (*p++) { + case 'a': val = '\a'; break; + case 'b': val = '\b'; break; + case 'f': val = '\f'; break; + case 'n': val = '\n'; break; + case 'r': val = '\r'; break; + case 't': val = '\t'; break; + case 'v': val = '\v'; break; + case '\"': val = '\"'; break; + case '\'': val = '\''; break; + case '\\': val = '\\'; break; + case 'x': + while (isxdigit(c = *p)) { + val = val * 16 + dig2num(c); + p++; + } + break; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': + p--; + while (isdigit(c = *p)) { + val = val * 8 + (c - '0'); + p++; + } + break; + default: val = p[-1]; + } + + } else + val = p[-1]; + return val; +} + +static void +chknl(int ignore) +{ + int t; + + slow = 1; + while ((t = yylex()) == WSPACE) + ; + if (t != '\n') { + if (ignore) { + warning("newline expected, got \"%s\"", yytext); + /* ignore rest of line */ + while ((t = yylex()) && t != '\n') + ; + } + else + error("newline expected, got \"%s\"", yytext); + } + slow = 0; +} + +static void +elsestmt(void) +{ + if (flslvl) { + if (elflvl > trulvl) + ; + else if (--flslvl!=0) { + flslvl++; + } else { + trulvl++; + prtline(); + } + } else if (trulvl) { + flslvl++; + trulvl--; + } else + error("If-less else"); + if (elslvl==trulvl+flslvl) + error("Too many else"); + elslvl=trulvl+flslvl; + chknl(1); +} + +static void +ifdefstmt(void) +{ + int t; + + if (flslvl) { + /* just ignore the rest of the line */ + while (input() != '\n') + ; + unput('\n'); + yylex(); + flslvl++; + return; + } + slow = 1; + do + t = yylex(); + while (t == WSPACE); + if (t != IDENT) + error("bad ifdef"); + slow = 0; + if (flslvl == 0 && lookup((usch *)yytext, FIND) != 0) + trulvl++; + else + flslvl++; + chknl(0); +} + +static void +ifndefstmt(void) +{ + int t; + + slow = 1; + do + t = yylex(); + while (t == WSPACE); + if (t != IDENT) + error("bad ifndef"); + slow = 0; + if (flslvl == 0 && lookup((usch *)yytext, FIND) == 0) + trulvl++; + else + flslvl++; + chknl(0); +} + +static void +endifstmt(void) +{ + if (flslvl) { + flslvl--; + if (flslvl == 0) + prtline(); + } else if (trulvl) + trulvl--; + else + error("If-less endif"); + if (flslvl == 0) + elflvl = 0; + elslvl = 0; + chknl(1); +} + +/* + * Note! Ugly! + * Walk over the string s and search for defined, and replace it with + * spaces and a 1 or 0. + */ +static void +fixdefined(usch *s) +{ + usch *bc, oc; + + for (; *s; s++) { + if (*s != 'd') + continue; + if (memcmp(s, "defined", 7)) + continue; + /* Ok, got defined, can scratch it now */ + memset(s, ' ', 7); + s += 7; +#define WSARG(x) (x == ' ' || x == '\t') + if (*s != '(' && !WSARG(*s)) + continue; + while (WSARG(*s)) + s++; + if (*s == '(') + s++; + while (WSARG(*s)) + s++; +#define IDARG(x) ((x>= 'A' && x <= 'Z') || (x >= 'a' && x <= 'z') || (x == '_')) +#define NUMARG(x) (x >= '0' && x <= '9') + if (!IDARG(*s)) + error("bad defined arg"); + bc = s; + while (IDARG(*s) || NUMARG(*s)) + s++; + oc = *s; + *s = 0; + *bc = (lookup(bc, FIND) != 0) + '0'; + memset(bc+1, ' ', s-bc-1); + *s = oc; + } +} + +/* + * get the full line of identifiers after an #if, pushback a WARN and + * the line and prepare for expmac() to expand. + * This is done before switching state. When expmac is finished, + * pushback the expanded line, change state and call yyparse. + */ +static void +storepb(void) +{ + usch *opb = stringbuf; + int c; + + while ((c = input()) != '\n') { + if (c == '/') { + if ((c = input()) == '*') { + /* ignore comments here whatsoever */ + usch *g = stringbuf; + getcmnt(); + stringbuf = g; + continue; + } else if (c == '/') { + while ((c = input()) && c != '\n') + ; + break; + } + unput(c); + c = '/'; + } + savch(c); + } + cunput('\n'); + savch(0); + fixdefined(opb); /* XXX can fail if #line? */ + cunput(1); /* WARN XXX */ + unpstr(opb); + stringbuf = opb; + slow = 1; + expmac(NULL); + slow = 0; + /* line now expanded */ + while (stringbuf > opb) + cunput(*--stringbuf); +} + +static void +ifstmt(void) +{ + if (flslvl == 0) { + slow = 1; + if (yyparse()) + ++trulvl; + else + ++flslvl; + slow = 0; + } else + ++flslvl; +} + +static void +elifstmt(void) +{ + if (flslvl == 0) + elflvl = trulvl; + if (flslvl) { + if (elflvl > trulvl) + ; + else if (--flslvl!=0) + ++flslvl; + else { + slow = 1; + if (yyparse()) { + ++trulvl; + prtline(); + } else + ++flslvl; + slow = 0; + } + } else if (trulvl) { + ++flslvl; + --trulvl; + } else + error("If-less elif"); +} + +static usch * +svinp(void) +{ + int c; + usch *cp = stringbuf; + + while ((c = input()) && c != '\n') + savch(c); + savch('\n'); + savch(0); + BEGIN 0; + return cp; +} + +static void +cpperror(void) +{ + usch *cp; + int c; + + if (flslvl) + return; + c = yylex(); + if (c != WSPACE && c != '\n') + error("bad error"); + cp = svinp(); + if (flslvl) + stringbuf = cp; + else + error("%s", cp); +} + +static void +undefstmt(void) +{ + struct symtab *np; + + slow = 1; + if (yylex() != WSPACE || yylex() != IDENT) + error("bad undef"); + if (flslvl == 0 && (np = lookup((usch *)yytext, FIND))) + np->value = 0; + slow = 0; + chknl(0); +} + +static void +pragmastmt(void) +{ + int c; + + slow = 1; + if (yylex() != WSPACE) + error("bad pragma"); + if (!flslvl) + putstr((usch *)"#pragma "); + do { + c = input(); + if (!flslvl) + putch(c); /* Do arg expansion instead? */ + } while (c && c != '\n'); + ifiles->lineno++; + prtline(); + slow = 0; +} + +static void +badop(const char *op) +{ + error("invalid operator in preprocessor expression: %s", op); +} + +int +cinput() +{ + return input(); +} diff --git a/src/cmd/cpp/tests/res11 b/src/cmd/cpp/tests/res11 new file mode 100644 index 0000000..4c49d18 --- /dev/null +++ b/src/cmd/cpp/tests/res11 @@ -0,0 +1,22 @@ + +# 1 "" + + + + + +a +a b +a b c +a b c d + + + + + + +__attribute__((__noreturn__)) + + +1 2 + diff --git a/src/cmd/cpp/tests/res12 b/src/cmd/cpp/tests/res12 new file mode 100644 index 0000000..1420d39 --- /dev/null +++ b/src/cmd/cpp/tests/res12 @@ -0,0 +1,21 @@ + +# 1 "" + + + + + +2 2 2 2 2; + + + + + + + + + + + + +(0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, diff --git a/src/cmd/cpp/tests/res13 b/src/cmd/cpp/tests/res13 new file mode 100644 index 0000000..5ec9b41 --- /dev/null +++ b/src/cmd/cpp/tests/res13 @@ -0,0 +1,13 @@ + +# 1 "" + + + + +long + + + + + + diff --git a/src/cmd/cpp/tests/res2 b/src/cmd/cpp/tests/res2 index 945449b..e9fb624 100644 --- a/src/cmd/cpp/tests/res2 +++ b/src/cmd/cpp/tests/res2 @@ -15,7 +15,8 @@ f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1); -f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1); +f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & +f(2 * (0,1))^m(0,1); int i[] = { 1, 23, 4, 5, }; char c[2][6] = { "hello", "" }; diff --git a/src/cmd/cpp/tests/test11 b/src/cmd/cpp/tests/test11 new file mode 100644 index 0000000..5bf4249 --- /dev/null +++ b/src/cmd/cpp/tests/test11 @@ -0,0 +1,20 @@ +#define D1(s, ...) s +#define D2(s, ...) s D1(__VA_ARGS__) +#define D3(s, ...) s D2(__VA_ARGS__) +#define D4(s, ...) s D3(__VA_ARGS__) + +D1(a) +D2(a, b) +D3(a, b, c) +D4(a, b, c, d) + + +#define __sun_attr___noreturn__ __attribute__((__noreturn__)) +#define ___sun_attr_inner(__a) __sun_attr_##__a +#define __sun_attr__(__a) ___sun_attr_inner __a +#define __NORETURN __sun_attr__((__noreturn__)) +__NORETURN +#define X(...) +#define Y(...) 1 __VA_ARGS__ 2 +Y(X X() ()) + diff --git a/src/cmd/cpp/tests/test12 b/src/cmd/cpp/tests/test12 new file mode 100644 index 0000000..a0a36f1 --- /dev/null +++ b/src/cmd/cpp/tests/test12 @@ -0,0 +1,19 @@ +#define y 2 +#define fe(p) sfe(p) p +#define sfe(p) p +#define Y fe(y) y fe(y) + +Y; + +# define S2B_QMIN 0 +# define S2B_CMIN (S2B_QMIN + 8) +#define S2B_1(i) i, +#define S2B_2(i) S2B_1(i) S2B_1(i) +#define S2B_4(i) S2B_2(i) S2B_2(i) +#define S2B_8(i) S2B_4(i) S2B_4(i) +#define S2B_16(i) S2B_8(i) S2B_8(i) +#define S2B_32(i) S2B_16(i) S2B_16(i) +#define S2B_64(i) S2B_32(i) S2B_32(i) +#define S2B_128(i) S2B_64(i) S2B_64(i) +#define S2B_256(i) S2B_128(i) S2B_128(i) +S2B_256(S2B_CMIN + 0) diff --git a/src/cmd/cpp/tests/test13 b/src/cmd/cpp/tests/test13 new file mode 100644 index 0000000..51e2385 --- /dev/null +++ b/src/cmd/cpp/tests/test13 @@ -0,0 +1,11 @@ + +#define UL long, foo +#define D(I,F) I +#define E(I) D(I) +E(UL) + +#define FOO 1 + +#if (FOO == 1) + +#endif /* FOO */ diff --git a/src/cmd/cpp/token.c b/src/cmd/cpp/token.c index aeac691..e6e6d96 100644 --- a/src/cmd/cpp/token.c +++ b/src/cmd/cpp/token.c @@ -1,3 +1,5 @@ +/* $Id: token.c,v 1.48.2.2 2011/03/12 17:08:26 ragge Exp $ */ + /* * Copyright (c) 2004,2009 Anders Magnusson. All rights reserved. * @@ -37,21 +39,24 @@ * - inch() is like inpch but \\n and trigraphs are expanded. * - unch() pushes back a character to the input stream. */ -#ifdef CROSS -# include -#else -# include -#endif + +#include "config.h" + #include +#include +#include +#ifdef HAVE_UNISTD_H #include +#endif #include #include +#include "compat.h" #include "cpp.h" #include "y.tab.h" static void cvtdig(int rad); -static int charcon(uchar *); +static int charcon(usch *); static void elsestmt(void); static void ifdefstmt(void); static void ifndefstmt(void); @@ -75,9 +80,8 @@ extern void yyset_lineno (int); static int inch(void); -size_t strlcat(char *dst, const char *src, size_t siz); - int inif; +extern int dflag; #define PUTCH(ch) if (!flslvl) putch(ch) /* protection against recursion in #include */ @@ -87,25 +91,16 @@ static int inclevel; /* get next character unaltered */ #define NXTCH() (ifiles->curptr < ifiles->maxread ? *ifiles->curptr++ : inpch()) -#ifdef YYTEXT_POINTER -static char buf[CPPBUF]; -char *yytext = buf; -#else -char yytext[CPPBUF]; -#endif +usch yytext[CPPBUF]; -#define C_SPEC 1 -#define C_EP 2 -#define C_ID 4 -#define C_I (C_SPEC|C_ID) -#define C_2 8 /* for yylex() tokenizing */ -static const char spechr[256] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, C_SPEC, 0, 0, 0, 0, 0, +char spechr[256] = { + 0, 0, 0, 0, C_SPEC, C_SPEC, 0, 0, + 0, C_WSNL, C_SPEC|C_WSNL, 0, + 0, C_WSNL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, C_2, C_SPEC, 0, 0, 0, C_2, C_SPEC, + C_WSNL, C_2, C_SPEC, 0, 0, 0, C_2, C_SPEC, 0, 0, 0, C_2, 0, C_2, 0, C_SPEC|C_2, C_I, C_I, C_I, C_I, C_I, C_I, C_I, C_I, C_I, C_I, 0, 0, C_2, C_2, C_2, C_SPEC, @@ -122,14 +117,55 @@ static const char spechr[256] = { }; +/* + * No-replacement array. If a macro is found and exists in this array + * then no replacement shall occur. This is a stack. + */ +struct symtab *norep[RECMAX]; /* Symbol table index table */ +int norepptr = 1; /* Top of index table */ +unsigned short bptr[RECMAX]; /* currently active noexpand macro stack */ +int bidx; /* Top of bptr stack */ + static void unch(int c) { - + --ifiles->curptr; if (ifiles->curptr < ifiles->bbuf) error("pushback buffer full"); - *ifiles->curptr = (uchar)c; + *ifiles->curptr = (usch)c; +} + +static int +eatcmnt(void) +{ + int ch; + + if (Cflag) { PUTCH('/'); PUTCH('*'); } + for (;;) { + ch = inch(); + if (ch == '\n') { + ifiles->lineno++; + PUTCH('\n'); + } + if (ch == -1) + return -1; + if (ch == '*') { + ch = inch(); + if (ch == '/') { + if (Cflag) { + PUTCH('*'); + PUTCH('/'); + } else + PUTCH(' '); + break; + } + unch(ch); + ch = '*'; + } + if (Cflag) PUTCH(ch); + } + return 0; } /* @@ -146,51 +182,38 @@ static void fastscan(void) { struct symtab *nl; - int ch, i; + int ch, i, ccnt/*, onemore*/; + usch *cp; goto run; for (;;) { ch = NXTCH(); xloop: if (ch == -1) return; + if (dflag>1) + printf("fastscan ch %d (%c)\n", ch, ch > 31 ? ch : '@'); if ((spechr[ch] & C_SPEC) == 0) { PUTCH(ch); continue; } switch (ch) { + case EBLOCK: + case WARN: + case CONC: + error("bad char passed"); + break; + case '/': /* Comments */ if ((ch = inch()) == '/') { - if (Cflag) { PUTCH(ch); } else { PUTCH(' '); } +cppcmt: if (Cflag) { PUTCH(ch); } else { PUTCH(' '); } do { if (Cflag) PUTCH(ch); ch = inch(); } while (ch != -1 && ch != '\n'); goto xloop; } else if (ch == '*') { - if (Cflag) { PUTCH('/'); PUTCH('*'); } - for (;;) { - ch = inch(); - if (ch == '\n') { - ifiles->lineno++; - PUTCH('\n'); - } - if (ch == -1) - return; - if (ch == '*') { - ch = inch(); - if (ch == '/') { - if (Cflag) { - PUTCH('*'); - PUTCH('/'); - } else - PUTCH(' '); - break; - } - unch(ch); - ch = '*'; - } - if (Cflag) PUTCH(ch); - } + if (eatcmnt()) + return; } else { PUTCH('/'); goto xloop; @@ -213,11 +236,30 @@ xloop: if (ch == -1) goto xloop; case '\n': /* newlines, for pp directives */ - ifiles->lineno++; +run2: ifiles->lineno++; do { PUTCH(ch); run: ch = NXTCH(); + if (ch == '/') { + ch = NXTCH(); + if (ch == '/') + goto cppcmt; + if (ch == '*') { + if (eatcmnt()) + return; + goto run; + } + unch(ch); + ch = '/'; + } } while (ch == ' ' || ch == '\t'); + if (ch == '\\') { + ch = NXTCH(); + if (ch == '\n') + goto run2; + unch(ch); + ch = '\\'; + } if (ch == '#') { ppdir(); continue; @@ -236,7 +278,7 @@ run: ch = NXTCH(); case '\"': /* strings */ str: PUTCH(ch); while ((ch = inch()) != '\"') { - PUTCH(ch); + PUTCH(ch); if (ch == '\\') { ch = inch(); PUTCH(ch); @@ -257,7 +299,16 @@ str: PUTCH(ch); case '5': case '6': case '7': case '8': case '9': do { PUTCH(ch); - ch = NXTCH(); +nxt: ch = NXTCH(); + if (ch == '\\') { + ch = NXTCH(); + if (ch == '\n') { + goto nxt; + } else { + unch(ch); + ch = '\\'; + } + } if (spechr[ch] & C_EP) { PUTCH(ch); ch = NXTCH(); @@ -305,9 +356,9 @@ con: PUTCH(ch); ch = NXTCH(); goto xloop; } - i = 0; + /*onemore =*/ i = ccnt = 0; do { - yytext[i++] = (uchar)ch; + yytext[i++] = (usch)ch; ch = NXTCH(); if (ch == '\\') { ch = NXTCH(); @@ -322,14 +373,17 @@ con: PUTCH(ch); if (ch < 0) return; } while (spechr[ch] & C_ID); + yytext[i] = 0; unch(ch); - if ((nl = lookup((uchar *)yytext, FIND)) != 0) { - uchar *op = stringbuf; - putstr(gotident(nl)); - stringbuf = op; + + cp = stringbuf; + if ((nl = lookup((usch *)yytext, FIND)) && kfind(nl)) { + putstr(stringbuf); } else - putstr((uchar *)yytext); + putstr((usch *)yytext); + stringbuf = cp; + break; } } @@ -344,7 +398,7 @@ sloscan() zagain: yyp = 0; ch = inch(); - yytext[yyp++] = (uchar)ch; + yytext[yyp++] = (usch)ch; switch (ch) { case -1: return 0; @@ -357,24 +411,24 @@ zagain: yyp = 0; break; - case '0': case '1': case '2': case '3': case '4': case '5': + case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* readin a "pp-number" */ ppnum: for (;;) { ch = inch(); if (spechr[ch] & C_EP) { - yytext[yyp++] = (uchar)ch; + yytext[yyp++] = (usch)ch; ch = inch(); if (ch == '-' || ch == '+') { - yytext[yyp++] = (uchar)ch; + yytext[yyp++] = (usch)ch; } else unch(ch); continue; } if ((spechr[ch] & C_ID) || ch == '.') { - yytext[yyp++] = (uchar)ch; + yytext[yyp++] = (usch)ch; continue; - } + } break; } unch(ch); @@ -383,11 +437,11 @@ ppnum: for (;;) { return NUMBER; case '\'': -chlit: +chlit: for (;;) { if ((ch = inch()) == '\\') { - yytext[yyp++] = (uchar)ch; - yytext[yyp++] = (uchar)inch(); + yytext[yyp++] = (usch)ch; + yytext[yyp++] = (usch)inch(); continue; } else if (ch == '\n') { /* not a constant */ @@ -396,7 +450,7 @@ chlit: ch = '\''; goto any; } else - yytext[yyp++] = (uchar)ch; + yytext[yyp++] = (usch)ch; if (ch == '\'') break; } @@ -407,7 +461,7 @@ chlit: case ' ': case '\t': while ((ch = inch()) == ' ' || ch == '\t') - yytext[yyp++] = (uchar)ch; + yytext[yyp++] = (usch)ch; unch(ch); yytext[yyp] = 0; return(WSPACE); @@ -415,7 +469,7 @@ chlit: case '/': if ((ch = inch()) == '/') { do { - yytext[yyp++] = (uchar)ch; + yytext[yyp++] = (usch)ch; ch = inch(); } while (ch && ch != '\n'); yytext[yyp] = 0; @@ -435,7 +489,10 @@ chlit: more: while ((c = inch()) && c != '*') { if (c == '\n') putch(c), ifiles->lineno++; - else if (c == 1) /* WARN */ + else if (c == EBLOCK) { + (void)inch(); + (void)inch(); + } else if (c == 1) /* WARN */ wrn = 1; } if (c == 0) @@ -459,7 +516,7 @@ chlit: case '.': ch = inch(); if (isdigit(ch)) { - yytext[yyp++] = (uchar)ch; + yytext[yyp++] = (usch)ch; goto ppnum; } else { unch(ch); @@ -468,14 +525,16 @@ chlit: goto any; case '\"': + if (tflag) + goto any; strng: for (;;) { if ((ch = inch()) == '\\') { - yytext[yyp++] = (uchar)ch; - yytext[yyp++] = (uchar)inch(); + yytext[yyp++] = (usch)ch; + yytext[yyp++] = (usch)inch(); continue; - } else - yytext[yyp++] = (uchar)ch; + } else + yytext[yyp++] = (usch)ch; if (ch == '\"') break; } @@ -483,26 +542,26 @@ chlit: return(STRING); case 'L': - if ((ch = inch()) == '\"') { - yytext[yyp++] = (uchar)ch; + if ((ch = inch()) == '\"' && !tflag) { + yytext[yyp++] = (usch)ch; goto strng; - } else if (ch == '\'') { - yytext[yyp++] = (uchar)ch; + } else if (ch == '\'' && !tflag) { + yytext[yyp++] = (usch)ch; goto chlit; } unch(ch); /* FALLTHROUGH */ /* Yetch, all identifiers */ - case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': - case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': - case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': - case 's': case 't': case 'u': case 'v': case 'w': case 'x': + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': + case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': + case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': - case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': - case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': - case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': + case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': + case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': case '_': /* {L}({L}|{D})* */ @@ -510,7 +569,7 @@ chlit: for (;;) { /* get chars */ ch = inch(); if (isalpha(ch) || isdigit(ch) || ch == '_') { - yytext[yyp++] = (uchar)ch; + yytext[yyp++] = (usch)ch; } else { unch(ch); break; @@ -584,27 +643,31 @@ yylex() case NUMBER: if (yytext[0] == '\'') { yylval.node.op = NUMBER; - yylval.node.nd_val = charcon((uchar *)yytext); + yylval.node.nd_val = charcon((usch *)yytext); } else cvtdig(yytext[0] != '0' ? 10 : yytext[1] == 'x' || yytext[1] == 'X' ? 16 : 8); return NUMBER; case IDENT: - if (strcmp(yytext, "defined") == 0) { + if (strcmp((char *)yytext, "defined") == 0) { ifdef = 1; return DEFINED; } - nl = lookup((uchar *)yytext, FIND); + nl = lookup((usch *)yytext, FIND); if (ifdef) { yylval.node.nd_val = nl != NULL; ifdef = 0; } else if (nl && noex == 0) { - uchar *c, *och = stringbuf; + usch *och = stringbuf; + int i; - c = gotident(nl); - unch(1); - unpstr(c); + i = kfind(nl); + unch(WARN); + if (i) + unpstr(stringbuf); + else + unpstr(nl->namep); stringbuf = och; noex = 1; return yylex(); @@ -613,7 +676,7 @@ yylex() } yylval.node.op = NUMBER; return NUMBER; - case 1: /* WARN */ + case WARN: noex = 0; return yylex(); default: @@ -623,7 +686,7 @@ yylex() return ch; } -uchar *yyp, yybuf[CPPBUF]; +usch *yyp, yybuf[CPPBUF]; int yywrap(void); @@ -671,41 +734,6 @@ msdos: if ((c = inpch()) == '\n') { } } -/* - * Appends src to string dst of size siz (unlike strncat, siz is the - * full size of dst, not space left). At most siz-1 characters - * will be copied. Always NUL terminates (unless siz <= strlen(dst)). - * Returns strlen(initial dst) + strlen(src); if retval >= siz, - * truncation occurred. - */ -size_t -strlcat(char *dst, const char *src, size_t siz) -{ - char *d = dst; - const char *s = src; - size_t n = siz; - size_t dlen; - - /* Find the end of dst and adjust bytes left but don't go past end */ - while (n-- != 0 && *d != '\0') - d++; - dlen = d - dst; - n = siz - dlen; - - if (n == 0) - return(dlen + strlen(s)); - while (*s != '\0') { - if (n != 1) { - *d++ = *s; - n--; - } - s++; - } - *d = '\0'; - - return(dlen + (s - src)); /* count does not include NUL */ -} - /* * Let the command-line args be faked defines at beginning of file. */ @@ -754,30 +782,29 @@ prinit(struct initar *it, struct includ *ic) * Return 0 on success, -1 if file to be included is not found. */ int -pushfile(const uchar *file, const uchar *fn, int idx, void *incs) +pushfile(const usch *file, const usch *fn, int idx, void *incs) { extern struct initar *initar; + struct includ ibuf; struct includ *ic; int otrulvl; - ic = malloc(sizeof(struct includ)); - if (ic == NULL) - error("out of memory for %s", file); + ic = &ibuf; ic->next = ifiles; if (file != NULL) { - ic->infil = open((const char *)file, O_RDONLY); - if (ic->infil < 0) { - free(ic); + if ((ic->infil = open((const char *)file, O_RDONLY)) < 0) return -1; - } ic->orgfn = ic->fname = file; if (++inclevel > MAX_INCLEVEL) error("Limit for nested includes exceeded"); } else { ic->infil = 0; - ic->orgfn = ic->fname = (const uchar *)""; + ic->orgfn = ic->fname = (const usch *)""; } +#ifndef BUF_STACK + ic->bbuf = malloc(BBUFSZ); +#endif ic->buffer = ic->bbuf+NAMEMAX; ic->curptr = ic->buffer; ifiles = ic; @@ -794,8 +821,7 @@ pushfile(const uchar *file, const uchar *fn, int idx, void *incs) prinit(initar, ic); initar = NULL; if (dMflag) - if (write(ofd, ic->buffer, strlen((char *)ic->buffer)) < 0) - /* ignore */; + write(ofd, ic->buffer, strlen((char *)ic->buffer)); fastscan(); prtline(); ic->infil = oin; @@ -808,9 +834,11 @@ pushfile(const uchar *file, const uchar *fn, int idx, void *incs) if (otrulvl != trulvl || flslvl) error("unterminated conditional"); +#ifndef BUF_STACK + free(ic->bbuf); +#endif ifiles = ic->next; close(ic->infil); - free(ic); inclevel--; return 0; } @@ -821,15 +849,14 @@ pushfile(const uchar *file, const uchar *fn, int idx, void *incs) void prtline() { - uchar *s, *os = stringbuf; + usch *s, *os = stringbuf; if (Mflag) { if (dMflag) return; /* no output */ if (ifiles->lineno == 1) { s = sheap("%s: %s\n", Mfile, ifiles->fname); - if (write(ofd, s, strlen((char *)s)) < 0) - /* ignore */; + write(ofd, s, strlen((char *)s)); } } else if (!Pflag) putstr(sheap("\n# %d \"%s\"\n", ifiles->lineno, ifiles->fname)); @@ -840,8 +867,8 @@ void cunput(int c) { #ifdef CPP_DEBUG - extern int dflag; - if (dflag)printf(": '%c'(%d)", c > 31 ? c : ' ', c); +// extern int dflag; +// if (dflag)printf(": '%c'(%d)\n", c > 31 ? c : ' ', c); #endif #if 0 if (c == 10) { @@ -873,7 +900,7 @@ cvtdig(int rad) { unsigned long long rv = 0; unsigned long long rv2 = 0; - char *y = yytext; + usch *y = yytext; int c; c = *y++; @@ -900,7 +927,7 @@ cvtdig(int rad) } static int -charcon(uchar *p) +charcon(usch *p) { int val, c; @@ -993,8 +1020,8 @@ skpln(void) } static void -ifdefstmt(void) -{ +ifdefstmt(void) +{ int t; if (flslvl) { @@ -1006,7 +1033,7 @@ ifdefstmt(void) while (t == WSPACE); if (t != IDENT) error("bad ifdef"); - if (lookup((uchar *)yytext, FIND) == 0) { + if (lookup((usch *)yytext, FIND) == 0) { putch('\n'); flslvl++; } else @@ -1015,8 +1042,8 @@ ifdefstmt(void) } static void -ifndefstmt(void) -{ +ifndefstmt(void) +{ int t; if (flslvl) { @@ -1028,7 +1055,7 @@ ifndefstmt(void) while (t == WSPACE); if (t != IDENT) error("bad ifndef"); - if (lookup((uchar *)yytext, FIND) != 0) { + if (lookup((usch *)yytext, FIND) != 0) { putch('\n'); flslvl++; } else @@ -1037,7 +1064,7 @@ ifndefstmt(void) } static void -endifstmt(void) +endifstmt(void) { if (flslvl) { flslvl--; @@ -1094,11 +1121,11 @@ elifstmt(void) error("If-less elif"); } -static uchar * +static usch * svinp(void) { int c; - uchar *cp = stringbuf; + usch *cp = stringbuf; while ((c = inch()) && c != '\n') savch(c); @@ -1110,7 +1137,7 @@ svinp(void) static void cpperror(void) { - uchar *cp; + usch *cp; int c; if (flslvl) @@ -1128,7 +1155,7 @@ cpperror(void) static void cppwarning(void) { - uchar *cp; + usch *cp; int c; if (flslvl) @@ -1158,7 +1185,7 @@ undefstmt(void) if (sloscan() != WSPACE || sloscan() != IDENT) error("bad undef"); - if (flslvl == 0 && (np = lookup((uchar *)yytext, FIND))) + if (flslvl == 0 && (np = lookup((usch *)yytext, FIND))) np->value = 0; chknl(0); } @@ -1171,7 +1198,7 @@ pragmastmt(void) if (sloscan() != WSPACE) error("bad pragma"); if (!flslvl) - putstr((const uchar *)"#pragma "); + putstr((const usch *)"\n#pragma "); do { c = inch(); if (!flslvl) @@ -1265,7 +1292,7 @@ ppdir(void) goto out; /* something else, ignore */ i = 0; do { - bp[i++] = (uchar)ch; + bp[i++] = (usch)ch; if (i == sizeof(bp)-1) goto out; /* too long */ ch = inch();