Quick Search:

Mode

Context

Displaying 3 lines of context. None | Less | More | Full

Other Diffs

Ignore

Blank Lines Whitespace: Expand:

Diff

1.111
 
1.112
 
MAIN:ragge:20110109152539
 
cpp.c
_>5353 #include "cpp.h"
 5454 #include "y.tab.h"
 5555 
<>56 -#define MAXARG  250     /* # of args to a macro, limited by char value */
5756 #define SBSIZE  600000
 5857 
 5958 static usch     sbf[SBSIZE];
     
 !
7978 struct initar *initar;
 8079 int readmac;
 8180 
<>82 -/* avoid recursion */
 83 -struct recur {
 84 -        struct recur *next;
 85 -        struct symtab *sp;
 86 -};
 87 -
8881 /* include dirs */
 8982 struct incs {
 9083         struct incs *next;
     
 !
124117  *      - When expanding replacement lists to tell that the list ended.
 125118  */
 126119 
<>127 -#define GCCARG  0xfd    /* has gcc varargs that may be replaced with 0 */
 128 -#define VARG    0xfe    /* has varargs */
 129 -#define OBJCT   0xff
 130 -#define WARN    1       /* SOH, not legal char */
 131 -#define CONC    2       /* STX, not legal char */
 132 -#define SNUFF   3       /* ETX, not legal char */
 133 -#define NOEXP   4       /* EOT, not legal char */
 134 -#define EXPAND  5       /* ENQ, not legal char */
 135 -#define PRAGS   6       /* start of converted pragma */
 136 -#define PRAGE   14      /* end of converted pragma */
 137 -
138120 /* args for lookup() */
 139121 #define FIND    0
 140122 #define ENTER   1
 141123 
<>142 -static void expdef(const usch *proto, struct recur *, int gotwarn);
  124+static int readargs(struct symtab *sp, const usch **args);
  125+void prline(const usch *s);
  126+static void prrep(const usch *s);
  127+static void exparg(const usch *bp, int);
  128+static void subarg(struct symtab *sp, const usch **args, int);
143129 void define(void);
<>144 -static int canexpand(struct recur *, struct symtab *np);
145130 void include(void);
 146131 void include_next(void);
 147132 void line(void);
     
 !
150135 usch *xstrdup(const char *str);
 151136 const usch *prtprag(const usch *opb);
 152137 static void addidir(char *idir, struct incs **ww);
<> 138+void imp(char *);
  139+#define IMP(x) if (dflag>1) imp(x)
153140 
 154141 int
 155142 main(int argc, char **argv)
     
 !
227214         filloc = lookup((const usch *)"__FILE__", ENTER);
 228215         linloc = lookup((const usch *)"__LINE__", ENTER);
 229216         pragloc = lookup((const usch *)"_Pragma", ENTER);
<>230 -        filloc->value = linloc->value = (const usch *)""; /* Just something */
 231 -        pragloc->value = (const usch *)"";
  217+        pragloc->value = filloc->value = linloc->value = stringbuf;
  218+        savch(OBJCT);
232219 
 233220         if (tflag == 0) {
 234221                 time_t t = time(NULL);
     
 !
330317         *ww = w;
 331318 }
 332319 
<>333 -usch *
 334 -gotident(struct symtab *nl)
 335 -{
 336 -        struct symtab *thisnl;
 337 -        usch *osp, *ss2, *base;
 338 -        int c;
 339 -
 340 -        thisnl = NULL;
 341 -        readmac++;
 342 -        base = osp = stringbuf;
 343 -        goto found;
 344 -
 345 -        while ((c = sloscan()) != 0) {
 346 -                switch (c) {
 347 -                case IDENT:
 348 -                        if (flslvl)
 349 -                                break;
 350 -                        osp = stringbuf;
 351 -
 352 -                        DPRINT(("IDENT0: %s\n", yytext));
 353 -                        nl = lookup((usch *)yytext, FIND);
 354 -                        if (nl == 0 || thisnl == 0)
 355 -                                goto found;
 356 -                        if (thisnl == nl) {
 357 -                                nl = 0;
 358 -                                goto found;
 359 -                        }
 360 -                        ss2 = stringbuf;
 361 -                        if ((c = sloscan()) == WSPACE) {
 362 -                                savstr((usch *)yytext);
 363 -                                c = sloscan();
 364 -                        }
 365 -                        if (c != EXPAND) {
 366 -                                unpstr((const usch *)yytext);
 367 -                                if (ss2 != stringbuf)
 368 -                                        unpstr(ss2);
 369 -                                unpstr(nl->namep);
 370 -                                (void)sloscan(); /* get yytext correct */
 371 -                                nl = 0; /* ignore */
 372 -                        } else {
 373 -                                thisnl = NULL;
 374 -                                if (nl->value[0] == OBJCT) {
 375 -                                        unpstr(nl->namep);
 376 -                                        (void)sloscan(); /* get yytext correct */
 377 -                                        nl = 0;
 378 -                                }
 379 -                        }
 380 -                        stringbuf = ss2;
 381 -
 382 -found:                  if (nl == 0 || subst(nl, NULL) == 0) {
 383 -                                if (nl)
 384 -                                        savstr(nl->namep);
 385 -                                else
 386 -                                        savstr((usch *)yytext);
 387 -                        } else if (osp != stringbuf) {
 388 -                                DPRINT(("IDENT1: unput osp %p stringbuf %p\n",
 389 -                                    osp, stringbuf));
 390 -                                ss2 = stringbuf;
 391 -                                cunput(EXPAND);
 392 -                                while (ss2 > osp)
 393 -                                        cunput(*--ss2);
 394 -                                thisnl = nl;
 395 -                                stringbuf = osp; /* clean up heap */
 396 -                        }
 397 -                        break;
 398 -
 399 -                case EXPAND:
 400 -                        DPRINT(("EXPAND!\n"));
 401 -                        thisnl = NULL;
 402 -                        break;
 403 -
 404 -                case CMNT:
 405 -                        getcmnt();
 406 -                        break;
 407 -
 408 -                case '\n':
 409 -                        /* sloscan() will not eat */
 410 -                        (void)cinput();
 411 -                        savch(c);
 412 -                        break;
 413 -
 414 -                case STRING:
 415 -                case NUMBER:
 416 -                case WSPACE:
 417 -                        savstr((usch *)yytext);
 418 -                        break;
 419 -
 420 -                default:
 421 -                        if (c < 256)
 422 -                                savch(c);
 423 -                        else
 424 -                                savstr((usch *)yytext);
 425 -                        break;
 426 -                }
 427 -                if (thisnl == NULL) {
 428 -                        readmac--;
 429 -                        savch(0);
 430 -                        return base;
 431 -                }
 432 -        }
 433 -        error("premature EOF");
 434 -        /* NOTREACHED */
 435 -        return NULL; /* XXX gcc */
 436 -}
 437 -
438320 void
 439321 line()
 440322 {
     
 !
522404                 /* sloscan() will not expand idents */
 523405                 if ((nl = lookup((usch *)yytext, FIND)) == NULL)
 524406                         goto bad;
<>525 -                unpstr(gotident(nl));
  407+                if (kfind(nl))
  408+                        unpstr(stringbuf);
  409+                else
  410+                        unpstr(nl->namep);
526411                 stringbuf = osp;
 527412                 c = yylex();
 528413         }
     
 !
597482                 /* sloscan() will not expand idents */
 598483                 if ((nl = lookup((usch *)yytext, FIND)) == NULL)
 599484                         goto bad;
<>600 -                unpstr(gotident(nl));
  485+                if (kfind(nl))
  486+                        unpstr(stringbuf);
  487+                else
  488+                        unpstr(nl->namep);
601489                 stringbuf = osp;
 602490                 c = yylex();
 603491         }
     
 !
712600 define()
 713601 {
 714602         struct symtab *np;
<>715 -        usch *args[MAXARG], *ubuf, *sbeg;
  603+        usch *args[MAXARGS+1], *ubuf, *sbeg;
716604         int c, i, redef;
 717605         int mkstr = 0, narg = -1;
 718606         int ellips = 0;
     
 !
753641                                         if (!strcmp((char *) args[i], yytext))
 754642                                                 error("Duplicate macro "
 755643                                                   "parameter \"%s\"", yytext);
<> 644+                                if (narg == MAXARGS)
  645+                                        error("Too many macro args");
756646                                 args[narg++] = xstrdup(yytext);
 757647                                 if ((c = definp()) == ',') {
 758648                                         if ((c = definp()) == ')')
     
 !
991881         exit(1);
 992882 }
 993883 
<> 884+static int
  885+addmac(struct symtab *sp)
  886+{
  887+        int c, i;
  888+
  889+        /* Check if it exists; then save some space */
  890+        /* May be more difficult to debug cpp */
  891+        for (i = 1; i < norepptr; i++)
  892+                if (norep[i] == sp)
  893+                        return i;
  894+        if ((c = norepptr) == RECMAX)
  895+                error("too many macros");
  896+        norep[norepptr++] = sp;
  897+        return c;
  898+}
  899+
  900+/* Allow next nr in lex buffer to expand */
  901+int
  902+doexp(void)
  903+{
  904+        int i, n = cinput();
  905+        DDPRINT(("doexp %s(%d) blocking:", norep[n]->namep, n));
  906+        if (n != bptr[--bidx])
  907+                error("expansion sync error");
  908+        if (dflag>1) {
  909+                for (i = bidx-1; i >= 0; i--)
  910+                        printf(" '%s'", norep[bptr[i]]->namep);
  911+                printf("\n");
  912+        }
  913+        return n;
  914+}
  915+
  916+/* Block next nr in lex buffer to expand */
  917+int
  918+donex(void)
  919+{
  920+        int n, i;
  921+
  922+        if (bidx == RECMAX)
  923+                error("too deep macro recursion");
  924+        bptr[bidx++] = n = cinput();
  925+        /* XXX - check for sp buffer overflow */
  926+        if (dflag>1) {
  927+                printf("donex %d (%d) blocking:\n", bidx, n);
  928+                printf("donex %s(%d) blocking:", norep[n]->namep, n);
  929+                for (i = bidx-1; i >= 0; i--)
  930+                        printf(" '%s'", norep[bptr[i]]->namep);
  931+                printf("\n");
  932+        }
  933+        return n;
  934+}
  935+
994936 /*
 995937  * store a character into the "define" buffer.
 996938  */
     
 !
1035977         cunput(WARN);
 1036978         unpstr(opb);
 1037979         stringbuf = opb;
<> 980+        error("pragoper expmac");
  981+#if 0
1038982         expmac(NULL);
<> 983+#endif
1039984         cunput('\n');
 1040985         while (stringbuf > opb)
 1041986                 cunput(*--stringbuf);
     
 !
10561001 }
 10571002 
 10581003 /*
<>1059 - * substitute namep for sp->value.
  1004+ * Return true if it is OK to expand this symbol.
10601005  */
<> 1006+static int
  1007+okexp(struct symtab *sp)
  1008+{
  1009+        int i;
  1010+
  1011+        if (sp == NULL)
  1012+                return 0;
  1013+        for (i = 0; i < bidx; i++)
  1014+                if (norep[bptr[i]] == sp)
  1015+                        return 0;
  1016+        return 1;
  1017+}
  1018+
  1019+/*
  1020+ * Handle defined macro keywords found on input stream.
  1021+ * When finished print out the full expanded line.
  1022+ */
10611023 int
<>1062 -subst(struct symtab *sp, struct recur *rp)
  1024+kfind(struct symtab *sp)
10631025 {
<>1064 -        struct recur rp2;
 1065 -        register const usch *vp, *cp;
 1066 -        register usch *obp;
 1067 -        int c, nl;
  1026+        struct symtab *nl;
  1027+        const usch *argary[MAXARGS+1];
  1028+        usch *bp, *sbp;
  1029+        int c;
10681030 
<>1069 -        DPRINT(("subst: %s\n", sp->namep));
 1070 -        /*
 1071 -         * First check for special macros.
 1072 -         */
 1073 -        if (sp == filloc) {
 1074 -                (void)sheap("\"%s\"", ifiles->fname);
  1031+        DPRINT(("%d:enter kfind(%s)\n",0,sp->namep));
  1032+        IMP("KFIND");
  1033+        if (*sp->value == OBJCT) {
  1034+                cunput(WARN);
  1035+                exparg(sp->namep, 1);
  1036+upp:            sbp = bp = stringbuf;
  1037+                unpstr(bp);
  1038+                IMP("ENDX");
  1039+                while ((c = sloscan()) != WARN) {
  1040+                        switch (c) {
  1041+                        case NEX:
  1042+                                donex();
  1043+                                break;
  1044+                        case EXP:
  1045+                                doexp();
  1046+                                break;
  1047+                        case STRING:
  1048+                                /* Remove embedded directives */
  1049+                                for (bp = (usch *)yytext; *bp; bp++) {
  1050+                                        if (*bp == EXP || *bp == NEX)
  1051+                                                bp++;
  1052+                                        else if (*bp != CONC)
  1053+                                                savch(*bp);
  1054+                                }
  1055+                                break;
  1056+
  1057+                        case IDENT:
  1058+                                /*
  1059+                                 * Tricky: if this is the last identifier
  1060+                                 * in the expanded list, and it is defined
  1061+                                 * as a function-like macro, then push it
  1062+                                 * back on the input stream and let fastscan
  1063+                                 * handle it as a new macro.
  1064+                                 * BUT: if this macro is blocked then this
  1065+                                 * should not me done.
  1066+                                 */
  1067+                                nl = lookup((usch *)yytext, FIND);
  1068+                                if (nl == NULL || !okexp(nl) ||
  1069+                                    *nl->value == OBJCT) {
  1070+                                        /* Not fun-like macro */
  1071+                                        savstr((usch *)yytext);
  1072+                                        break;
  1073+                                }
  1074+                                while ((c = cinput()) == NEX || c == EXP)
  1075+                                        c == EXP ? doexp() : donex();
  1076+                                if (c == WARN) {
  1077+                                        /* succeeded, push back */
  1078+                                        unpstr((usch *)yytext);
  1079+                                } else {
  1080+                                        savstr((usch *)yytext);
  1081+                                }
  1082+                                cunput(c);
  1083+                                break;
  1084+
  1085+                        default:
  1086+                                savstr((usch *)yytext);
  1087+                                break;
  1088+                        }
  1089+                }
  1090+                IMP("END2");
  1091+                if (bidx != 0)
  1092+                        error("exp/noexp sync error");
  1093+                norepptr = 1;
  1094+                savch(0);
  1095+                stringbuf = sbp;
10751096                 return 1;
<>1076 -        } else if (sp == linloc) {
 1077 -                (void)sheap("%d", ifiles->lineno);
 1078 -                return 1;
 1079 -        } else if (sp == pragloc) {
 1080 -                pragoper();
 1081 -                return 1;
10821097         }
<>1083 -        vp = sp->value;
  1098+        /* Is a function-like macro */
10841099 
<>1085 -        rp2.next = rp;
 1086 -        rp2.sp = sp;
  1100+        /* Search for '(' */
  1101+        bp = stringbuf;
  1102+        while (iswsnl(c = cinput()))
  1103+                savch(c);
  1104+        savch(0);
  1105+        stringbuf = bp;
  1106+        if (c != '(') {
  1107+                cunput(c);
  1108+                unpstr(bp);
  1109+                return 0; /* Failed */
  1110+        }
10871111 
<>1088 -        if (*vp-- != OBJCT) {
 1089 -                int gotwarn = 0;
  1112+        /* Found one, output \n to be in sync */
  1113+        for (; *bp; bp++) {
  1114+                if (*bp == '\n')
  1115+                        putch('\n'), ifiles->lineno++;
  1116+        }
10901117 
<>1091 -                /* should we be here at all? */
 1092 -                /* check if identifier is followed by parentheses */
  1118+        /* fetch arguments */
  1119+        if (readargs(sp, argary))
  1120+                error("readargs");
10931121 
<>1094 -                obp = stringbuf;
 1095 -                nl = 0;
 1096 -                do {
 1097 -                        c = cinput();
 1098 -                        *stringbuf++ = (usch)c;
 1099 -                        if (c == WARN) {
 1100 -                                gotwarn++;
 1101 -                                if (rp == NULL)
 1102 -                                        break;
 1103 -                        }
 1104 -                        if (c == '\n')
 1105 -                                nl++;
 1106 -                } while (c == ' ' || c == '\t' || c == '\n' ||
 1107 -                            c == '\r' || c == WARN);
  1122+        c = addmac(sp);
  1123+        bp = stringbuf;
  1124+        cunput(WARN);
  1125+        cunput(WARN);
  1126+        cunput(c);
  1127+        cunput(EXP);
  1128+        IMP("KEXP");
11081129 
<>1109 -                DPRINT(("c %d\n", c));
 1110 -                if (c == '(' ) {
 1111 -                        cunput(c);
 1112 -                        stringbuf = obp;
 1113 -                        ifiles->lineno += nl;
 1114 -                        expdef(vp, &rp2, gotwarn);
 1115 -                        return 1;
 1116 -                } else {
 1117 -                        *stringbuf = 0;
 1118 -                        unpstr(obp);
 1119 -                        unpstr(sp->namep);
 1120 -                        if ((c = sloscan()) != IDENT)
 1121 -                                error("internal sync error");
 1122 -                        stringbuf = obp;
 1123 -                        return 0;
 1124 -                }
 1125 -        } else {
 1126 -                cunput(WARN);
 1127 -                cp = vp;
 1128 -                while (*cp) {
 1129 -                        if (*cp != CONC)
 1130 -                                cunput(*cp);
 1131 -                        cp--;
 1132 -                }
 1133 -                expmac(&rp2);
  1130+        subarg(sp, argary, 1);
  1131+
  1132+        cunput(c);
  1133+        cunput(NEX);
  1134+        IMP("KNEX");
  1135+
  1136+        stringbuf = bp;
  1137+
  1138+        IMP("MID1");
  1139+
  1140+        while ((c = cinput()) != WARN) {
  1141+                savch(c);
  1142+                if (c == EXP || c == NEX)
  1143+                        savch(cinput());
11341144         }
<>1135 -        return 1;
 1136 -}
  1145+        savch(0);
11371146 
<>1138 -/*
 1139 - * Maybe an indentifier (for macro expansion).
 1140 - */
 1141 -static int
 1142 -mayid(usch *s)
 1143 -{
 1144 -        for (; *s; s++)
 1145 -                if (!isdigit(*s) && !isalpha(*s) && *s != '_')
 1146 -                        return 0;
 1147 -        return 1;
  1147+        exparg(bp, 0);
  1148+
  1149+        IMP("END");
  1150+
  1151+        goto upp;
  1152+
11481153 }
 11491154 
 11501155 /*
<>1151 - * do macro-expansion until WARN character read.
 1152 - * read from lex buffer and store result on heap.
 1153 - * will recurse into lookup() for recursive expansion.
 1154 - * when returning all expansions on the token list is done.
  1156+ * Replace and push-back on input stream the eventual replaced macro.
11551157  */
<>1156 -void
 1157 -expmac(struct recur *rp)
  1158+int
  1159+submac(struct symtab *sp, int lvl)
11581160 {
<>1159 -        struct symtab *nl;
 1160 -        int c, noexp = 0, orgexp;
 1161 -        usch *och, *stksv;
  1161+        const usch *argary[MAXARGS+1];
  1162+        usch savc[100], savn[100];
  1163+        const usch *cp;
  1164+        usch *obp;
  1165+        int ch, nl, i, ccnt, bsv, gotnex;
11621166 
<>1163 -#ifdef CPP_DEBUG
 1164 -        if (dflag) {
 1165 -                struct recur *rp2 = rp;
 1166 -                printf("\nexpmac\n");
 1167 -                while (rp2) {
 1168 -                        printf("do not expand %s\n", rp2->sp->namep);
 1169 -                        rp2 = rp2->next;
  1167+        DPRINT(("%d:submac1: trying '%s'\n", lvl, sp->namep));
  1168+        if (*sp->value == OBJCT) {
  1169+                if (!okexp(sp))
  1170+                        return 0; /* cannot expand */
  1171+
  1172+                if (sp == filloc) {
  1173+                        unpstr(sheap("\"%s\"", ifiles->fname));
  1174+                        return 1;
  1175+                } else if (sp == linloc) {
  1176+                        unpstr(sheap("%d", ifiles->lineno));
  1177+                        return 1;
  1178+                } else if (sp == pragloc) {
  1179+                        pragoper();
  1180+                        return 1;
11701181                 }
<>1171 -        }
 1172 -#endif
 1173 -        readmac++;
 1174 -        while ((c = sloscan()) != WARN) {
 1175 -                switch (c) {
 1176 -                case NOEXP: noexp++; break;
 1177 -                case EXPAND: noexp--; break;
  1182+                /* XXX insert special check here */
11781183 
<>1179 -                case NUMBER: /* handled as ident if no .+- in it */
 1180 -                        if (!mayid((usch *)yytext))
 1181 -                                goto def;
 1182 -                        /* FALLTHROUGH */
 1183 -                case IDENT:
 1184 -                        /*
 1185 -                         * Handle argument concatenation here.
 1186 -                         * If an identifier is found and directly
 1187 -                         * after EXPAND or NOEXP then push the
 1188 -                         * identifier back on the input stream and
 1189 -                         * call sloscan() again.
 1190 -                         * Be careful to keep the noexp balance.
 1191 -                         */
 1192 -                        och = stringbuf;
 1193 -                        savstr((usch *)yytext);
 1194 -                        DDPRINT(("id: str %s\n", och));
  1184+                DPRINT(("submac: exp object macro '%s'\n",sp->namep));
  1185+                /* expand object-type macros */
  1186+                ch = addmac(sp);
11951187 
<>1196 -                        orgexp = 0;
 1197 -                        while ((c = sloscan()) == EXPAND || c == NOEXP)
 1198 -                                if (c == EXPAND)
 1199 -                                        orgexp--;
 1200 -                                else
 1201 -                                        orgexp++;
  1188+                cunput(ch);
  1189+                cunput(EXP);
  1190+                for (cp = sp->value-1; *cp; cp--)
  1191+                        cunput(*cp);
  1192+                cunput(ch);
  1193+                cunput(NEX);
  1194+                return 1;
  1195+        }
12021196 
<>1203 -                        DDPRINT(("id1: typ %d noexp %d orgexp %d\n",
 1204 -                            c, noexp, orgexp));
 1205 -                        if (c == IDENT ||
 1206 -                            (c == NUMBER && mayid((usch *)yytext))) {
 1207 -                                DDPRINT(("id2: str %s\n", yytext));
 1208 -                                /* OK to always expand here? */
 1209 -                                savstr((usch *)yytext);
 1210 -                                switch (orgexp) {
 1211 -                                case 0: /* been EXP+NOEXP */
 1212 -                                        if (noexp == 0)
 1213 -                                                break;
 1214 -                                        if (noexp != 1)
 1215 -                                                error("case 0");
 1216 -                                        cunput(NOEXP);
 1217 -                                        noexp = 0;
 1218 -                                        break;
 1219 -                                case -1: /* been EXP */
 1220 -                                        if (noexp != 1)
 1221 -                                                error("case -1");
 1222 -                                        noexp = 0;
 1223 -                                        break;
 1224 -                                case 1:
 1225 -                                        if (noexp != 0)
 1226 -                                                error("case 1");
 1227 -                                        cunput(NOEXP);
 1228 -                                        break;
 1229 -                                default:
 1230 -                                        error("orgexp = %d", orgexp);
 1231 -                                }
 1232 -                                unpstr(och);
 1233 -                                stringbuf = och;
 1234 -                                continue; /* New longer identifier */
  1197+        /*
  1198+         * Function-like macro; see if it is followed by a (
  1199+         * Be careful about the expand/noexpand balance.
  1200+         * Store read data on heap meanwhile.
  1201+         * For directive        #define foo() kaka
  1202+         * If input is          <NEX><NEX>foo<EXP>()<EXP> then
  1203+         * output should be     <NEX><NEX><EXP>kaka<EXP>.
  1204+         */
  1205+        obp = stringbuf;
  1206+        gotnex = nl = ccnt = 0;
  1207+        i = bidx;
  1208+        do {
  1209+                switch (ch = cinput()) {
  1210+                case NEX: /* disallow expansion */
  1211+                        savc[ccnt] = ch;
  1212+                        savn[ccnt] = cinput();
  1213+                        gotnex = 1;
  1214+                        ccnt++;
  1215+                        break;
  1216+                case EXP: /* allow expansion */
  1217+                        savc[ccnt] = ch;
  1218+                        if (gotnex == 0) {
  1219+                                savn[ccnt] = doexp();
  1220+                        } else {
  1221+                                savn[ccnt] = cinput();
12351222                         }
<>1236 -                        unpstr((const usch *)yytext);
 1237 -                        if (orgexp == -1)
 1238 -                                cunput(EXPAND);
 1239 -                        else if (orgexp == -2)
 1240 -                                cunput(EXPAND), cunput(EXPAND);
 1241 -                        else if (orgexp == 1)
 1242 -                                cunput(NOEXP);
 1243 -                        unpstr(och);
 1244 -                        stringbuf = och;
  1223+                        ccnt++;
  1224+                        break;
12451225 
<> 1226+                case '\n':
  1227+                        nl++;
  1228+                        /* FALLTHROUGH */
  1229+                default:
  1230+                        savch(ch);
  1231+                }
  1232+        } while (iswsnl(ch) || ch == EXP || ch == NEX);
12461233 
<>1247 -                        sloscan(); /* XXX reget last identifier */
  1234+        /*
  1235+         * Is there any macro to expand?
  1236+         * The okexp() call must be done here because an EXP may
  1237+         * have been found.
  1238+         */
  1239+        bsv = okexp(sp);
  1240+        bidx = i;
  1241+        
  1242+        if (ch != '(' || !bsv) {
  1243+                DPRINT(("submac: failed '%s' %s\n",sp->namep,
  1244+                    ch != '(' ? "no (" : "already expanded"));
  1245+                cunput(ch);
  1246+                *--stringbuf = 0; /* remove saved ch */
  1247+                /* push back exp/noexp first */
  1248+                for (i = ccnt-1; i >= 0; i--)
  1249+                        cunput(savn[i]), cunput(savc[i]);
  1250+                /* push back rest */
  1251+                unpstr(obp);
  1252+                stringbuf = obp;
  1253+                return 0;
  1254+        }
12481255 
<>1249 -                        if ((nl = lookup((usch *)yytext, FIND)) == NULL)
 1250 -                                goto def;
  1256+        /*
  1257+         * A function-like macro has been found.  Read in the arguments,
  1258+         * expand them and push-back everything for another scan.
  1259+         */
  1260+        DPRINT(("%d:submac: continue macro '%s'\n", lvl, sp->namep));
  1261+        savch(0);
  1262+        if (readargs(sp, argary)) {
  1263+                /* Bailed out in the middle of arg list */
  1264+                /* XXX EXP balance */
  1265+                unpstr(obp);
  1266+                if (dflag>1)printf("%d:noreadargs\n", lvl);
  1267+                stringbuf = obp;
  1268+                return 0;
  1269+        }
  1270+        ifiles->lineno += nl;
12511271 
<>1252 -                        if (canexpand(rp, nl) == 0)
 1253 -                                goto def;
 1254 -                        /*
 1255 -                         * If noexp == 0 then expansion of any macro is
 1256 -                         * allowed.  If noexp == 1 then expansion of a
 1257 -                         * fun-like macro is allowed iff there is an
 1258 -                         * EXPAND between the identifier and the '('.
 1259 -                         */
 1260 -                        if (noexp == 0) {
 1261 -                                if ((c = subst(nl, rp)) == 0)
 1262 -                                        goto def;
 1263 -                                break;
 1264 -                        }
 1265 -                        if (noexp != 1)
 1266 -                                error("bad noexp %d", noexp);
 1267 -                        stksv = NULL;
 1268 -                        if ((c = sloscan()) == WSPACE) {
 1269 -                                stksv = xstrdup(yytext);
 1270 -                                c = sloscan();
 1271 -                        }
 1272 -                        /* only valid for expansion if fun macro */
 1273 -                        if (c == EXPAND && *nl->value != OBJCT) {
 1274 -                                noexp--;
 1275 -                                if (subst(nl, rp))
 1276 -                                        break;
 1277 -                                savstr(nl->namep);
 1278 -                                if (stksv)
 1279 -                                        savstr(stksv);
 1280 -                        } else {
 1281 -                                unpstr((const usch *)yytext);
 1282 -                                if (stksv)
 1283 -                                        unpstr(stksv);
 1284 -                                savstr(nl->namep);
 1285 -                        }
 1286 -                        if (stksv)
 1287 -                                free(stksv);
 1288 -                        break;
  1272+        /* when all args are read from input stream */
  1273+        ch = addmac(sp);
12891274 
<>1290 -                case CMNT:
 1291 -                        getcmnt();
 1292 -                        break;
  1275+        cunput(ch);
  1276+        cunput(EXP);
  1277+        DDPRINT(("%d:cunput(EXP)\n", lvl));
12931278 
<>1294 -                case '\n':
 1295 -                        cinput();
 1296 -                        savch(' ');
 1297 -                        break;
  1279+        subarg(sp, argary, lvl+1);
12981280 
<>1299 -                case STRING:
 1300 -                        /* remove EXPAND/NOEXP from strings */
 1301 -                        if (yytext[1] == NOEXP) {
 1302 -                                savch('"');
 1303 -                                och = (usch *)&yytext[2];
 1304 -                                while (*och != EXPAND)
 1305 -                                        savch(*och++);
 1306 -                                savch('"');
 1307 -                                break;
 1308 -                        }
 1309 -                        /* FALLTHROUGH */
  1281+        cunput(ch);
  1282+        cunput(NEX);
  1283+        DDPRINT(("%d:cunput(NEX)\n", lvl));
13101284 
<>1311 -def:            default:
 1312 -                        savstr((usch *)yytext);
 1313 -                        break;
 1314 -                }
 1315 -        }
 1316 -        if (noexp)
 1317 -                error("expmac noexp=%d", noexp);
 1318 -        readmac--;
 1319 -        DPRINT(("return from expmac\n"));
  1285+        for (i = ccnt-1; i >= 0; i--)
  1286+                cunput(savn[i]), cunput(savc[i]);
  1287+
  1288+        stringbuf = obp; /* Reset heap */
  1289+        DPRINT(("%d:Return submac\n", lvl));
  1290+        IMP("SM1");
  1291+        return 1;
13201292 }
 13211293 
 13221294 /*
<>1323 - * expand a function-like macro.
 1324 - * vp points to end of replacement-list
 1325 - * reads function arguments from sloscan()
 1326 - * result is written on top of heap
  1295+ * Read arguments and put in argument array.
  1296+ * If WARN is encountered return 1, otherwise 0.
13271297  */
<>1328 -void
 1329 -expdef(const usch *vp, struct recur *rp, int gotwarn)
  1298+int
  1299+readargs(struct symtab *sp, const usch **args)
13301300 {
<>1331 -        const usch **args, *ap, *bp, *sp;
 1332 -        usch *sptr;
 1333 -        int narg, c, i, plev, snuff, instr;
 1334 -        int ellips = 0, shot = gotwarn;
  1301+        const usch *vp = sp->value;
  1302+        usch savn[100];
  1303+        int c, i, plev, narg, ellips = 0;
  1304+        int gotnex, ccnt, warn;
13351305 
<>1336 -        DPRINT(("expdef rp %s\n", (rp ? (const char *)rp->sp->namep : "")));
 1337 -        if ((c = sloscan()) != '(')
 1338 -                error("got %c, expected (", c);
 1339 -        if (vp[1] == VARG) {
  1306+        DPRINT(("readargs\n"));
  1307+
  1308+        narg = *vp--;
  1309+        if (narg == VARG) {
13401310                 narg = *vp--;
 13411311                 ellips = 1;
<>1342 -        } else
 1343 -                narg = vp[1];
 1344 -        if ((args = malloc(sizeof(usch *) * (narg+ellips))) == NULL)
 1345 -                error("expdef: out of mem");
  1312+        }
13461313 
<> 1314+        IMP("RDA1");
13471315         /*
 13481316          * read arguments and store them on heap.
<>1349 -         * will be removed just before return from this function.
13501317          */
<>1351 -        sptr = stringbuf;
 1352 -        instr = 0;
  1318+        gotnex = ccnt = warn = 0;
  1319+        c = '(';
13531320         for (i = 0; i < narg && c != ')'; i++) {
 13541321                 args[i] = stringbuf;
 13551322                 plev = 0;
 13561323                 while ((c = sloscan()) == WSPACE || c == '\n')
 13571324                         if (c == '\n')
 13581325                                 putch(cinput());
<>1359 -                DDPRINT((":AAA (%d)", c));
 1360 -                if (instr == -1)
 1361 -                        savch(NOEXP), instr = 1;
 1362 -                if (c == NOEXP)
 1363 -                        instr = 1;
13641326                 for (;;) {
<> 1327+                        if (c == NEX) {
  1328+                                gotnex = 1;
  1329+                                savch(NEX);
  1330+                                savch(cinput());
  1331+                                goto oho;
  1332+                        }
  1333+                        if (c == EXP) {
  1334+                                if (gotnex == 0) {
  1335+                                        savn[ccnt++] = cinput();
  1336+                                } else {
  1337+                                        savch(EXP);
  1338+                                        savch(cinput());
  1339+                                }
  1340+                                goto oho;
  1341+                        }
  1342+                        if (c == WARN) {
  1343+                                warn++;
  1344+                                goto oho;
  1345+                        }
13651346                         if (plev == 0 && (c == ')' || c == ','))
 13661347                                 break;
 13671348                         if (c == '(')
 13681349                                 plev++;
 13691350                         if (c == ')')
 13701351                                 plev--;
 13711352                         savstr((usch *)yytext);
<>1372 -                        while ((c = sloscan()) == '\n') {
  1353+oho:                    while ((c = sloscan()) == '\n') {
13731354                                 putch(cinput());
 13741355                                 savch('\n');
 13751356                         }
 13761357                         while (c == CMNT) {
 13771358                                 getcmnt();
 13781359                                 c = sloscan();
 13791360                         }
<>1380 -                        if (c == EXPAND)
 1381 -                                instr = 0;
13821361                         if (c == 0)
 13831362                                 error("eof in macro");
 13841363                 }
 13851364                 while (args[i] < stringbuf &&
<>1386 -                    (stringbuf[-1] == ' ' || stringbuf[-1] == '\t' ||
 1387 -                     stringbuf[-1] == '\n'))
  1365+                    (iswsnl(stringbuf[-1]) &&
  1366+                    !(stringbuf[-2] == EXP || stringbuf[-2] == NEX)))
13881367                         stringbuf--;
<>1389 -                if (instr == 1)
 1390 -                        savch(EXPAND), instr = -1;
13911368                 savch('\0');
<> 1369+                if (dflag) {
  1370+                        printf("readargs: save arg %d '", i);
  1371+                        prline(args[i]);
  1372+                        printf("'\n");
  1373+                }
13921374         }
<> 1375+
  1376+        IMP("RDA2");
  1377+        /* Handle varargs readin */
13931378         if (ellips)
 13941379                 args[i] = (const usch *)"";
 13951380         if (ellips && c != ')') {
 13961381                 args[i] = stringbuf;
 13971382                 plev = 0;
<>1398 -                instr = 0;
13991383                 while ((c = sloscan()) == WSPACE)
 14001384                         ;
<>1401 -                if (c == NOEXP)
 1402 -                        instr++;
 1403 -                DDPRINT((":AAY (%d)", c));
14041385                 for (;;) {
 14051386                         if (plev == 0 && c == ')')
 14061387                                 break;
 14071388                         if (c == '(')
 14081389                                 plev++;
 14091390                         if (c == ')')
 14101391                                 plev--;
<>1411 -                        if (plev == 0 && c == ',' && instr) {
 1412 -                                savch(EXPAND);
 1413 -                                savch(',');
 1414 -                                savch(NOEXP);
 1415 -                        } else
 1416 -                                savstr((usch *)yytext);
  1392+                        savstr((usch *)yytext);
14171393                         while ((c = sloscan()) == '\n') {
 14181394                                 cinput();
 14191395                                 savch('\n');
 14201396                         }
<>1421 -                        if (c == EXPAND)
 1422 -                                instr--;
14231397                 }
<>1424 -                while (args[i] < stringbuf &&
 1425 -                    (stringbuf[-1] == ' ' || stringbuf[-1] == '\t'))
  1398+                while (args[i] < stringbuf && iswsnl(stringbuf[-1]))
14261399                         stringbuf--;
 14271400                 savch('\0');
 14281401                 
     
 !
14341407 
 14351408         if (c != ')' || (i != narg && ellips == 0) || (i < narg && ellips == 1))
 14361409                 error("wrong arg count");
<> 1410+        while (warn)
  1411+                cunput(WARN), warn--;
  1412+        while (ccnt)
  1413+                cunput(savn[--ccnt]), cunput(EXP);
  1414+        return 0;
  1415+}
14371416 
<>1438 -        while (gotwarn--)
 1439 -                cunput(WARN);
  1417+/*
  1418+ * Maybe an indentifier (for macro expansion).
  1419+ */
  1420+static int
  1421+mayid(usch *s)
  1422+{
  1423+        for (; *s; s++)
  1424+                if (!isdigit(*s) && !isalpha(*s) && *s != '_')
  1425+                        return 0;
  1426+        return 1;
  1427+}
14401428 
<> 1429+/*
  1430+ * expand a function-like macro.
  1431+ * vp points to end of replacement-list
  1432+ * reads function arguments from sloscan()
  1433+ * result is pushed-back for more scanning.
  1434+ */
  1435+void
  1436+subarg(struct symtab *nl, const usch **args, int lvl)
  1437+{
  1438+        int narg, instr, snuff;
  1439+        const usch *sp, *bp, *ap, *vp;
  1440+
  1441+        DPRINT(("%d:subarg(%s)\n", lvl,nl->namep));
  1442+        vp = nl->value;
  1443+        narg = *vp--;
  1444+        if (narg == VARG)
  1445+                narg = *vp--;
  1446+
14411447         sp = vp;
 14421448         instr = snuff = 0;
<> 1449+        if (dflag>1) {
  1450+                printf("%d:subarg ARGlist for %s: '", lvl, nl->namep);
  1451+                prrep(vp);
  1452+                printf("'\n");
  1453+        }
14431454 
 14441455         /*
 14451456          * push-back replacement-list onto lex buffer while replacing
<>1446 -         * arguments.
  1457+         * arguments.  Arguments are macro-expanded if required.
14471458          */
<>1448 -        cunput(WARN);
14491459         while (*sp != 0) {
 14501460                 if (*sp == SNUFF)
 14511461                         cunput('\"'), snuff ^= 1;
     
 !
14661476 #endif
 14671477                         } else
 14681478                                 bp = ap = args[(int)*--sp];
<>1469 -                        if (sp[2] != CONC && !snuff && sp[-1] != CONC) {
 1470 -                                struct recur *r2 = rp->next;
 1471 -                                cunput(WARN);
 1472 -                                while (*bp)
 1473 -                                        bp++;
 1474 -                                while (bp > ap)
 1475 -                                        cunput(*--bp);
 1476 -                                DPRINT(("expand arg %d string %s\n", *sp, ap));
 1477 -                                bp = ap = stringbuf;
 1478 -                                savch(NOEXP);
 1479 -                                while (shot && r2)
 1480 -                                        r2 = r2->next, shot--;
 1481 -                                expmac(r2);
 1482 -                                savch(EXPAND);
 1483 -                                savch('\0');
  1479+                        if (dflag>1){
  1480+                                printf("%d:subarg GOTwarn; arglist '", lvl);
  1481+                                prline(bp);
  1482+                                printf("'\n");
14841483                         }
<> 1484+                        if (sp[2] != CONC && !snuff && sp[-1] != CONC) {
  1485+                                /*
  1486+                                 * Expand an argument; 6.10.3.1:
  1487+                                 * "A parameter in the replacement list,
  1488+                                 *  is replaced by the corresponding argument
  1489+                                 *  after all macros contained therein have
  1490+                                 *  been expanded.".
  1491+                                 */
  1492+                                exparg(bp, lvl+1);
  1493+                                unpstr(stringbuf);
  1494+                        } else {
14851495                         while (*bp)
 14861496                                 bp++;
 14871497                         while (bp > ap) {
 14881498                                 bp--;
<>1489 -                                if (snuff && !instr &&
 1490 -                                    (*bp == ' ' || *bp == '\t' || *bp == '\n')){
 1491 -                                        while (*bp == ' ' || *bp == '\t' ||
 1492 -                                            *bp == '\n') {
  1499+                                if (snuff && !instr && iswsnl(*bp)) {
  1500+                                        while (iswsnl(*bp))
14931501                                                 bp--;
<>1494 -                                        }
14951502                                         cunput(' ');
 14961503                                 }
<>1497 -                                if (!snuff || (*bp != EXPAND && *bp != NOEXP))
 1498 -                                        cunput(*bp);
  1504+
  1505+                                cunput(*bp);
14991506                                 if ((*bp == '\'' || *bp == '"')
 15001507                                      && bp[-1] != '\\' && snuff) {
 15011508                                         instr ^= 1;
     
 !
15051512                                 if (instr && (*bp == '\\' || *bp == '"'))
 15061513                                         cunput('\\');
 15071514                         }
<> 1515+                        }
15081516                 } else
 15091517                         cunput(*sp);
 15101518                 sp--;
 15111519         }
<>1512 -        stringbuf = sptr;
  1520+        DPRINT(("%d:Return subarg\n", lvl));
  1521+        IMP("SUBARG");
  1522+}
15131523 
<>1514 -        /* scan the input buffer (until WARN) and save result on heap */
 1515 -        expmac(rp);
 1516 -        free(args);
  1524+/*
  1525+ * Do a (correct) expansion of an argument.
  1526+ * Data is read from the string bp, pushed-back and expanded.
  1527+ * When nothing more to expand, return with expanded arg in lex buffer.
  1528+ */
  1529+void
  1530+exparg(const usch *bp, int lvl)
  1531+{
  1532+        struct symtab *nl;
  1533+        int c, isexp, i, ccnt;
  1534+        usch *och;
  1535+        usch *osb = stringbuf;
  1536+        int anychange;
  1537+        usch savc[100], savn[100];
  1538+
  1539+        if (dflag) {
  1540+                printf("%d:exparg3: Expand '", lvl);
  1541+                prline(bp);
  1542+                printf("' block %d: ", bidx);
  1543+                for (i = 1; i < bidx; i++)
  1544+                        printf("'%s' ", norep[bptr[i]]->namep);
  1545+                printf("\n");
  1546+        }
  1547+
  1548+rescan:
  1549+        cunput(WARN);
  1550+        unpstr(bp);
  1551+        if (dflag>1) {
  1552+                printf("%d:exparg WARN '", lvl);
  1553+                prline(bp);
  1554+                printf("'\n");
  1555+        }
  1556+
  1557+        anychange = 0;
  1558+        readmac++;
  1559+        while ((c = sloscan()) != WARN) {
  1560+                DDPRINT(("%d:exparg swdata %d\n", lvl, c));
  1561+                IMP("EA0");
  1562+                switch (c) {
  1563+                case NEX:
  1564+                        DDPRINT(("%d:exparg donex\n", lvl));
  1565+                        savch(NEX);
  1566+                        savch(donex());
  1567+                        break;
  1568+
  1569+                case EXP:
  1570+                        DDPRINT(("%d:exparg doexp\n", lvl));
  1571+                        savch(EXP);
  1572+                        savch(doexp());
  1573+                        break;
  1574+
  1575+                case NUMBER: /* handled as ident if no .+- in it */
  1576+                        if (!mayid((usch *)yytext))
  1577+                                goto def;
  1578+                        /* FALLTHROUGH */
  1579+                case IDENT:
  1580+                        /*
  1581+                         * Handle argument concatenation here.
  1582+                         */
  1583+                        DDPRINT(("%d:exparg ident %d\n", lvl, c));
  1584+                        och = stringbuf;
  1585+                        isexp = ccnt = 0;
  1586+                        savstr((usch *)yytext);
  1587+
  1588+                        /* Must see if ident was expandable before EXP */
  1589+                        if ((nl = lookup(och, FIND)) && okexp(nl))
  1590+                                isexp = 1;
  1591+
  1592+                        DPRINT(("%d:exparg: '%s' isexp %d\n", lvl, och, isexp));
  1593+
  1594+                        while ((c = cinput()) == EXP || c == NEX) {
  1595+                                savc[ccnt] = c;
  1596+                                savn[ccnt] = cinput();
  1597+                                ccnt++;
  1598+                        }
  1599+                        cunput(c);
  1600+                        c = sloscan();
  1601+
  1602+                        DPRINT(("%d:exparg neoent %d %d\n", lvl, ccnt, c));
  1603+
  1604+                        if (c == IDENT ||
  1605+                            (c == NUMBER && mayid((usch *)yytext))) {
  1606+                                DPRINT(("id2: str %s\n", yytext));
  1607+                                /* OK to always expand here? */
  1608+                                /* push back exp/noexp */
  1609+                                for (i = ccnt-1; i >= 0; i--)
  1610+                                        cunput(savn[i]), cunput(savc[i]);
  1611+                                savstr((usch *)yytext);
  1612+                                unpstr(och);
  1613+                                stringbuf = och;
  1614+                                continue; /* Refetch new longer identifier */
  1615+                        }
  1616+
  1617+                        unpstr((const usch *)yytext);
  1618+
  1619+                        /* push back exp/noexp */
  1620+                        for (i = ccnt-1; i >= 0; i--)
  1621+                                cunput(savn[i]), cunput(savc[i]);
  1622+
  1623+                        DPRINT(("%d:exparg: pb '%s' str '%s'\n", lvl, yytext, och));
  1624+                        IMP("EA1");
  1625+                        /* try to expand the string we have */
  1626+                        if (isexp) {
  1627+                                /* expand the previous IDENT */
  1628+                                if (submac(nl, lvl+1)) {
  1629+                                        /* Could expand, result on lexbuffer */
  1630+                                        stringbuf = och; /* clear saved name */
  1631+                                        anychange = 1;
  1632+                                }
  1633+                                
  1634+                        }
  1635+                        IMP("EA2");
  1636+                        break;
  1637+
  1638+                case CMNT:
  1639+                        getcmnt();
  1640+                        break;
  1641+
  1642+                case '\n':
  1643+                        cinput();
  1644+                        savch(' ');
  1645+                        break;
  1646+
  1647+def:            default:
  1648+                        savstr((usch *)yytext);
  1649+                        break;
  1650+                }
  1651+        }
  1652+        *stringbuf = 0;
  1653+        if (dflag) {
  1654+                printf("%d:exparg return: change %d final '", lvl, anychange);
  1655+                prline(osb);
  1656+                printf("'\n");
  1657+        }
  1658+        bp = stringbuf = osb;
  1659+        if (anychange)
  1660+                goto rescan;
  1661+        readmac--;
15171662 }
 15181663 
<> 1664+void
  1665+imp(char *str)
  1666+{
  1667+        printf("%s (%d) '", str, bidx);
  1668+        prline(ifiles->curptr);
  1669+        printf("'\n");
  1670+}
  1671+
  1672+void
  1673+prrep(const usch *s)
  1674+{
  1675+        while (*s) {
  1676+                switch (*s) {
  1677+                case WARN: printf("<ARG(%d)>", *--s); break;
  1678+                case CONC: printf("<CONC>"); break;
  1679+                case SNUFF: printf("<SNUFF>"); break;
  1680+                case NEX: printf("<NEX(%d)>",*--s); break;
  1681+                case EXP: printf("<EXP(%d)>",*--s); break;
  1682+                default: printf("%c", *s); break;
  1683+                }
  1684+                s--;
  1685+        }
  1686+}
  1687+
  1688+void
  1689+prline(const usch *s)
  1690+{
  1691+        while (*s) {
  1692+                switch (*s) {
  1693+                case WARN: printf("<WARN>"); break;
  1694+                case CONC: printf("<CONC>"); break;
  1695+                case SNUFF: printf("<SNUFF>"); break;
  1696+                case NEX: printf("<NEX(%d)>",*++s); break;
  1697+                case EXP: printf("<EXP(%d)>",*++s); break;
  1698+                case '\n': printf("<NL>"); break;
  1699+                default: printf("%c", *s); break;
  1700+                }
  1701+                s++;
  1702+        }
  1703+}
  1704+
15191705 usch *
 15201706 savstr(const usch *str)
 15211707 {
     
 !
15311717         return rv;
 15321718 }
 15331719 
<>1534 -int
 1535 -canexpand(struct recur *rp, struct symtab *np)
 1536 -{
 1537 -        struct recur *w;
 1538 -
 1539 -        for (w = rp; w && w->sp != np; w = w->next)
 1540 -                ;
 1541 -        if (w != NULL)
 1542 -                return 0;
 1543 -        return 1;
 1544 -}
 1545 -
15461720 void
 15471721 unpstr(const usch *c)
 15481722 {
 15491723         const usch *d = c;
 15501724 
<> 1725+        if (dflag>1) {
  1726+                printf("Xunpstr: '");
  1727+                prline(c);
  1728+                printf("'\n");
  1729+        }
<_15511730         while (*d)
 15521731                 d++;
 15531732         while (d > c) {
FishEye: Open Source License registered to PCC.
Your maintenance has expired. You can renew your license at http://www.atlassian.com/fisheye/renew
Atlassian FishEye, CVS analysis. (Version:1.6.3 Build:build-336 2008-11-04) - Administration - Page generated 2014-09-01 13:18 +0200