Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20110109152539

Diff

Diff from 1.112 to:

Annotations

Annotate by Age | Author | Mixed | None
/fisheye/browse/pcc/pcc/cc/cpp/cpp.c

Annotated File View

ragge
1.112
1 /*      $Id: cpp.c,v 1.112 2011/01/09 15:25:39 ragge Exp $      */
ragge
1.1
2
3 /*
ragge
1.109
4  * Copyright (c) 2004,2010 Anders Magnusson (ragge@ludd.luth.se).
ragge
1.1
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 /*
29  * The C preprocessor.
30  * This code originates from the V6 preprocessor with some additions
31  * from V7 cpp, and at last ansi/c99 support.
32  */
pj
1.23
33
ragge
1.74
34 #include "config.h"
pj
1.23
35
gmcgarry
1.81
36 #ifdef HAVE_SYS_WAIT_H
ragge
1.1
37 #include <sys/wait.h>
gmcgarry
1.81
38 #endif
ragge
1.108
39 #include <sys/stat.h>
ragge
1.1
40
41 #include <fcntl.h>
gmcgarry
1.81
42 #ifdef HAVE_UNISTD_H
ragge
1.1
43 #include <unistd.h>
gmcgarry
1.81
44 #endif
ragge
1.1
45 #include <stdio.h>
46 #include <stdarg.h>
47 #include <stdlib.h>
48 #include <string.h>
ragge
1.9
49 #include <time.h>
ragge
1.51
50 #include <ctype.h>
ragge
1.1
51
ragge
1.74
52 #include "compat.h"
ragge
1.1
53 #include "cpp.h"
ragge
1.36
54 #include "y.tab.h"
ragge
1.1
55
ragge
1.52
56 #define SBSIZE  600000
ragge
1.1
57
58 static usch     sbf[SBSIZE];
59 /* C command */
60
61 int tflag;      /* traditional cpp syntax */
62 #ifdef CPP_DEBUG
63 int dflag;      /* debug printouts */
ragge
1.36
64 #define DPRINT(x) if (dflag) printf x
65 #define DDPRINT(x) if (dflag > 1) printf x
66 #else
67 #define DPRINT(x)
68 #define DDPRINT(x)
ragge
1.1
69 #endif
ragge
1.36
70
ragge
1.86
71 #define GCC_VARI
72
ragge
1.51
73 int ofd;
ragge
1.56
74 usch outbuf[CPPBUF];
ragge
1.97
75 int obufpistty;
gmcgarry
1.85
76 int CflagMflagdMflagPflag;
ragge
1.51
77 usch *Mfile;
ragge
1.53
78 struct initar *initar;
ragge
1.79
79 int readmac;
ragge
1.1
80
ragge
1.10
81 /* include dirs */
82 struct incs {
83         struct incs *next;
ragge
1.39
84         usch *dir;
ragge
1.108
85         dev_t dev;
86         ino_t ino;
ragge
1.20
87 } *incdir[2];
88 #define INCINC 0
89 #define SYSINC 1
ragge
1.10
90
ragge
1.1
91 static struct symtab *filloc;
92 static struct symtab *linloc;
ragge
1.65
93 static struct symtab *pragloc;
ragge
1.10
94 int     trulvl;
95 int     flslvl;
96 int     elflvl;
97 int     elslvl;
98 usch *stringbuf = sbf;
ragge
1.1
99
100 /*
101  * Macro replacement list syntax:
102  * - For object-type macros, replacement strings are stored as-is.
103  * - For function-type macros, macro args are substituted for the
104  *   character WARN followed by the argument number.
ragge
1.12
105  * - The value element points to the end of the string, to simplify
106  *   pushback onto the input queue.
ragge
1.1
107  * 
ragge
1.12
108  * The first character (from the end) in the replacement list is
109  * the number of arguments:
ragge
1.37
110  *   VARG  - ends with ellipsis, next char is argcount without ellips.
ragge
1.1
111  *   OBJCT - object-type macro
112  *   0     - empty parenthesis, foo()
113  *   1->   - number of args.
ragge
1.109
114  *
115  * WARN is used:
116  *      - in stored replacement lists to tell that an argument comes
117  *      - When expanding replacement lists to tell that the list ended.
ragge
1.1
118  */
119
120 /* args for lookup() */
121 #define FIND    0
122 #define ENTER   1
123
ragge
1.112
124 static int readargs(struct symtab *spconst usch **args);
125 void prline(const usch *s);
126 static void prrep(const usch *s);
127 static void exparg(const usch *bpint);
128 static void subarg(struct symtab *spconst usch **argsint);
ragge
1.36
129 void define(void);
130 void include(void);
ragge
1.102
131 void include_next(void);
ragge
1.36
132 void line(void);
ragge
1.37
133 void flbuf(void);
134 void usage(void);
ragge
1.103
135 usch *xstrdup(const char *str);
136 const usch *prtprag(const usch *opb);
ragge
1.108
137 static void addidir(char *idirstruct incs **ww);
ragge
1.112
138 void imp(char *);
139 #define IMP(x) if (dflag>1) imp(x)
ragge
1.1
140
141 int
142 main(int argcchar **argv)
143 {
ragge
1.53
144         struct initar *it;
ragge
1.26
145         struct symtab *nl;
146         register int ch;
ragge
1.103
147         const usch *fn1, *fn2;
ragge
1.15
148
ragge
1.94
149 #ifdef TIMING
150         struct timeval t1t2;
151
152         (void)gettimeofday(&t1NULL);
153 #endif
154
gmcgarry
1.85
155         while ((ch = getopt(argcargv"CD:I:MPS:U:d:i:tvV?")) != -1)
ragge
1.1
156                 switch (ch) {
ragge
1.22
157                 case 'C'/* Do not discard comments */
158                         Cflag++;
159                         break;
160
ragge
1.53
161                 case 'i'/* include */
162                 case 'U'/* undef */
163                 case 'D'/* define something */
ragge
1.58
164                         /* XXX should not need malloc() here */
165                         if ((it = malloc(sizeof(struct initar))) == NULL)
166                                 error("couldn't apply -%c %s"choptarg);
ragge
1.53
167                         it->type = ch;
168                         it->str = optarg;
169                         it->next = initar;
170                         initar = it;
ragge
1.7
171                         break;
172
ragge
1.51
173                 case 'M'/* Generate dependencies for make */
174                         Mflag++;
175                         break;
176
gmcgarry
1.85
177                 case 'P'/* Inhibit generation of line numbers */
178                         Pflag++;
179                         break;
180
ragge
1.7
181                 case 'S':
ragge
1.10
182                 case 'I':
ragge
1.108
183                         addidir(optarg, &incdir[ch == 'I' ? INCINC : SYSINC]);
ragge
1.7
184                         break;
185
ragge
1.1
186 #ifdef CPP_DEBUG
ragge
1.64
187                 case 'V':
ragge
1.18
188                         dflag++;
ragge
1.1
189                         break;
190 #endif
ragge
1.64
191                 case 'v':
192                         printf("cpp: %s\n"VERSSTR);
193                         break;
ragge
1.60
194                 case 'd':
195                         if (optarg[0] == 'M') {
196                                 dMflag = 1;
197                                 Mflag = 1;
198                         }
199                         /* ignore others */
200                         break;
201
ragge
1.1
202                 case 't':
203                         tflag = 1;
204                         break;
205
ragge
1.37
206                 case '?':
207                         usage();
ragge
1.1
208                 default:
ragge
1.37
209                         error("bad arg %c\n"ch);
ragge
1.1
210                 }
211         argc -= optind;
212         argv += optind;
213
ragge
1.103
214         filloc = lookup((const usch *)"__FILE__"ENTER);
215         linloc = lookup((const usch *)"__LINE__"ENTER);
216         pragloc = lookup((const usch *)"_Pragma"ENTER);
ragge
1.112
217         pragloc->value = filloc->value = linloc->value = stringbuf;
218         savch(OBJCT);
ragge
1.15
219
ragge
1.12
220         if (tflag == 0) {
221                 time_t t = time(NULL);
ragge
1.39
222                 usch *n = (usch *)ctime(&t);
ragge
1.12
223
224                 /*
225                  * Manually move in the predefined macros.
226                  */
ragge
1.103
227                 nl = lookup((const usch *)"__TIME__"ENTER);
ragge
1.13
228                 savch(0); savch('"');  n[19] = 0savstr(&n[11]); savch('"');
ragge
1.12
229                 savch(OBJCT);
230                 nl->value = stringbuf-1;
231
ragge
1.103
232                 nl = lookup((const usch *)"__DATE__"ENTER);
ragge
1.13
233                 savch(0); savch('"'); n[24] = n[11] = 0savstr(&n[4]);
234                 savstr(&n[20]); savch('"'); savch(OBJCT);
ragge
1.12
235                 nl->value = stringbuf-1;
236
ragge
1.103
237                 nl = lookup((const usch *)"__STDC__"ENTER);
ragge
1.13
238                 savch(0); savch('1'); savch(OBJCT);
ragge
1.12
239                 nl->value = stringbuf-1;
ragge
1.73
240
ragge
1.103
241                 nl = lookup((const usch *)"__STDC_VERSION__"ENTER);
242                 savch(0); savstr((const usch *)"199901L"); savch(OBJCT);
ragge
1.73
243                 nl->value = stringbuf-1;
ragge
1.12
244         }
ragge
1.1
245
ragge
1.60
246         if (Mflag && !dMflag) {
ragge
1.51
247                 usch *c;
248
249                 if (argc < 1)
250                         error("-M and no infile");
251                 if ((c = (usch *)strrchr(argv[0], '/')) == NULL)
252                         c = (usch *)argv[0];
253                 else
254                         c++;
255                 Mfile = stringbuf;
256                 savstr(c); savch(0);
257                 if ((c = (usch *)strrchr((char *)Mfile'.')) == NULL)
258                         error("-M and no extension: ");
259                 c[1] = 'o';
260                 c[2] = 0;
261         }
262
ragge
1.26
263         if (argc == 2) {
ragge
1.37
264                 if ((ofd = open(argv[1], O_WRONLY|O_CREAT0600)) < 0)
265                         error("Can't creat %s"argv[1]);
ragge
1.26
266         } else
ragge
1.37
267                 ofd = 1/* stdout */
268         istty = isatty(ofd);
ragge
1.26
269
ragge
1.102
270         if (argc && strcmp(argv[0], "-")) {
271                 fn1 = fn2 = (usch *)argv[0];
272         } else {
273                 fn1 = NULL;
ragge
1.103
274                 fn2 = (const usch *)"";
ragge
1.102
275         }
276         if (pushfile(fn1fn20NULL))
ragge
1.26
277                 error("cannot open %s"argv[0]);
278
ragge
1.37
279         flbuf();
280         close(ofd);
ragge
1.94
281 #ifdef TIMING
282         (void)gettimeofday(&t2NULL);
283         t2.tv_sec -= t1.tv_sec;
284         t2.tv_usec -= t1.tv_usec;
285         if (t2.tv_usec < 0) {
286                 t2.tv_usec += 1000000;
287                 t2.tv_sec -= 1;
288         }
289         fprintf(stderr"cpp total time: %ld s %ld us\n",
290              t2.tv_sect2.tv_usec);
291 #endif
ragge
1.37
292         return 0;
ragge
1.26
293 }
294
ragge
1.108
295 static void
296 addidir(char *idirstruct incs **ww)
297 {
298         struct incs *w;
299         struct stat st;
300
301         if (stat(idir, &st) == -1 || S_ISDIR(st.st_mode) == 0)
302                 return/* ignore */
303         if (*ww != NULL) {
304                 for (w = *www->nextw = w->next) {
305                         if (w->dev == st.st_dev && w->ino == st.st_ino)
306                                 return;
307                 }
308                 if (w->dev == st.st_dev && w->ino == st.st_ino)
309                         return;
310                 ww = &w->next;
311         }
312         if ((w = calloc(sizeof(struct incs), 1)) == NULL)
313                 error("couldn't add path %s"idir);
314         w->dir = (usch *)idir;
315         w->dev = st.st_dev;
316         w->ino = st.st_ino;
317         *ww = w;
318 }
319
ragge
1.1
320 void
ragge
1.9
321 line()
322 {
ragge
1.37
323         static usch *lbuf;
324         static int llen;
ragge
1.97
325         usch *p;
ragge
1.9
326         int c;
327
ragge
1.97
328         if ((c = yylex()) != NUMBER)
ragge
1.9
329                 goto bad;
gmcgarry
1.100
330         ifiles->lineno = (int)(yylval.node.nd_val - 1);
ragge
1.9
331
ragge
1.97
332         if ((c = yylex()) == '\n')
ragge
1.37
333                 return;
ragge
1.97
334
335         if (c != STRING)
ragge
1.9
336                 goto bad;
ragge
1.97
337
338         p = (usch *)yytext;
339         if (*p == 'L')
340                 p++;
341         c = strlen((char *)p);
ragge
1.37
342         if (llen < c) {
ragge
1.52
343                 /* XXX may loose heap space */
ragge
1.37
344                 lbuf = stringbuf;
345                 stringbuf += c;
346                 llen = c;
347         }
ragge
1.97
348         p[strlen((char *)p)-1] = 0;
349         if (strlcpy((char *)lbuf, (char *)&p[1], SBSIZE) >= SBSIZE)
ragge
1.63
350                 error("line exceeded buffer size");
351
ragge
1.37
352         ifiles->fname = lbuf;
ragge
1.97
353         if (yylex() == '\n')
354                 return;
ragge
1.9
355
356 bad:    error("bad line directive");
357 }
358
ragge
1.10
359 /*
ragge
1.102
360  * Search for and include next file.
361  * Return 1 on success.
362  */
363 static int
ragge
1.103
364 fsrch(const usch *fnint idxstruct incs *w)
ragge
1.102
365 {
366         int i;
367
368         for (i = idxi < 2i++) {
369                 if (i > idx)
370                         w = incdir[i];
371                 for (; ww = w->next) {
372                         usch *nm = stringbuf;
373
374                         savstr(w->dir); savch('/');
375                         savstr(fn); savch(0);
376                         if (pushfile(nmfniw->next) == 0)
377                                 return 1;
378                         stringbuf = nm;
379                 }
380         }
381         return 0;
382 }
383
384 /*
ragge
1.10
385  * Include a file. Include order:
ragge
1.20
386  * - For <...> files, first search -I directories, then system directories.
387  * - For "..." files, first search "current" dir, then as <...> files.
ragge
1.10
388  */
ragge
1.9
389 void
ragge
1.3
390 include()
391 {
ragge
1.101
392         struct symtab *nl;
ragge
1.10
393         usch *osp;
ragge
1.62
394         usch *fn, *safefn;
ragge
1.102
395         int cit;
ragge
1.3
396
ragge
1.37
397         if (flslvl)
398                 return;
ragge
1.10
399         osp = stringbuf;
ragge
1.97
400
ragge
1.101
401         while ((c = sloscan()) == WSPACE)
402                 ;
403         if (c == IDENT) {
404                 /* sloscan() will not expand idents */
405                 if ((nl = lookup((usch *)yytextFIND)) == NULL)
406                         goto bad;
ragge
1.112
407                 if (kfind(nl))
408                         unpstr(stringbuf);
409                 else
410                         unpstr(nl->namep);
ragge
1.101
411                 stringbuf = osp;
412                 c = yylex();
413         }
414         if (c != STRING && c != '<')
ragge
1.3
415                 goto bad;
416
ragge
1.97
417         if (c == '<') {
ragge
1.10
418                 fn = stringbuf;
ragge
1.97
419                 while ((c = sloscan()) != '>' && c != '\n') {
ragge
1.105
420                         if (c == '\n'/* XXX check - cannot reach */
ragge
1.10
421                                 goto bad;
ragge
1.39
422                         savstr((usch *)yytext);
ragge
1.10
423                 }
424                 savch('\0');
ragge
1.97
425                 while ((c = sloscan()) == WSPACE)
ragge
1.37
426                         ;
427                 if (c != '\n')
428                         goto bad;
ragge
1.20
429                 it = SYSINC;
ragge
1.62
430                 safefn = fn;
ragge
1.3
431         } else {
ragge
1.20
432                 usch *nm = stringbuf;
433
ragge
1.36
434                 yytext[strlen(yytext)-1] = 0;
ragge
1.39
435                 fn = (usch *)&yytext[1];
ragge
1.20
436                 /* first try to open file relative to previous file */
ragge
1.53
437                 /* but only if it is not an absolute path */
438                 if (*fn != '/') {
439                         savstr(ifiles->orgfn);
440                         if ((stringbuf =
441                             (usch *)strrchr((char *)nm'/')) == NULL)
442                                 stringbuf = nm;
443                         else
444                                 stringbuf++;
445                 }
ragge
1.62
446                 safefn = stringbuf;
ragge
1.20
447                 savstr(fn); savch(0);
ragge
1.97
448                 c = yylex();
ragge
1.37
449                 if (c != '\n')
450                         goto bad;
ragge
1.102
451                 if (pushfile(nmsafefn0NULL) == 0)
ragge
1.97
452                         goto okret;
ragge
1.62
453                 /* XXX may loose stringbuf space */
ragge
1.10
454         }
455
ragge
1.102
456         if (fsrch(safefn0incdir[0]))
457                 goto okret;
ragge
1.10
458
ragge
1.62
459         error("cannot find '%s'"safefn);
ragge
1.37
460         /* error() do not return */
ragge
1.3
461
462 bad:    error("bad include");
ragge
1.37
463         /* error() do not return */
ragge
1.97
464 okret:
465         prtline();
ragge
1.37
466 }
467
ragge
1.102
468 void
469 include_next()
470 {
ragge
1.105
471         struct symtab *nl;
472         usch *osp;
473         usch *fn;
474         int c;
475
ragge
1.107
476         if (flslvl)
477                 return;
ragge
1.105
478         osp = stringbuf;
479         while ((c = sloscan()) == WSPACE)
480                 ;
481         if (c == IDENT) {
482                 /* sloscan() will not expand idents */
483                 if ((nl = lookup((usch *)yytextFIND)) == NULL)
484                         goto bad;
ragge
1.112
485                 if (kfind(nl))
486                         unpstr(stringbuf);
487                 else
488                         unpstr(nl->namep);
ragge
1.105
489                 stringbuf = osp;
490                 c = yylex();
491         }
492         if (c != STRING && c != '<')
493                 goto bad;
494
495         fn = stringbuf;
496         if (c == STRING) {
497                 savstr((usch *)&yytext[1]);
498                 stringbuf[-1] = 0;
499         } else { /* < > */
500                 while ((c = sloscan()) != '>') {
501                         if (c == '\n')
502                                 goto bad;
503                         savstr((usch *)yytext);
504                 }
505                 savch('\0');
506         }
507         while ((c = sloscan()) == WSPACE)
508                 ;
509         if (c != '\n')
510                 goto bad;
511
512         if (fsrch(fnifiles->idxifiles->incs) == 0)
513                 error("cannot find '%s'"fn);
514         prtline();
515         return;
516
517 bad:    error("bad include");
518         /* error() do not return */
ragge
1.102
519 }
520
ragge
1.37
521 static int
522 definp(void)
523 {
524         int c;
525
526         do
ragge
1.97
527                 c = sloscan();
ragge
1.37
528         while (c == WSPACE);
529         return c;
ragge
1.3
530 }
531
ragge
1.80
532 void
ragge
1.79
533 getcmnt(void)
534 {
535         int c;
536
537         savstr((usch *)yytext);
ragge
1.104
538         savch(cinput()); /* Lost * */
ragge
1.79
539         for (;;) {
540                 c = cinput();
541                 if (c == '*') {
542                         c = cinput();
543                         if (c == '/') {
ragge
1.103
544                                 savstr((const usch *)"*/");
ragge
1.79
545                                 return;
546                         }
547                         cunput(c);
548                         c = '*';
549                 }
550                 savch(c);
551         }
552 }
553
554 /*
555  * Compare two replacement lists, taking in account comments etc.
556  */
557 static int
ragge
1.103
558 cmprepl(const usch *oconst usch *n)
ragge
1.79
559 {
560         for (; *oo--, n--) {
561                 /* comment skip */
562                 if (*o == '/' && o[-1] == '*') {
563                         while (*o != '*' || o[-1] != '/')
564                                 o--;
565                         o -= 2;
566                 }
567                 if (*n == '/' && n[-1] == '*') {
568                         while (*n != '*' || n[-1] != '/')
569                                 n--;
570                         n -= 2;
571                 }
572                 while (*o == ' ' || *o == '\t')
573                         o--;
574                 while (*n == ' ' || *n == '\t')
575                         n--;
576                 if (*o != *n)
577                         return 1;
578         }
579         return 0;
580 }
581
ragge
1.97
582 static int
583 isell(void)
584 {
585         int ch;
586
587         if ((ch = cinput()) != '.') {
588                 cunput(ch);
589                 return 0;
590         }
591         if ((ch = cinput()) != '.') {
592                 cunput(ch);
593                 cunput('.');
594                 return 0;
595         }
596         return 1;
597 }
598
ragge
1.3
599 void
ragge
1.1
600 define()
601 {
602         struct symtab *np;
ragge
1.112
603         usch *args[MAXARGS+1], *ubuf, *sbeg;
ragge
1.15
604         int ciredef;
ragge
1.1
605         int mkstr = 0narg = -1;
ragge
1.37
606         int ellips = 0;
ragge
1.86
607 #ifdef GCC_VARI
608         usch *gccvari = NULL;
ragge
1.91
609         int wascon;
ragge
1.86
610 #endif
ragge
1.1
611
ragge
1.37
612         if (flslvl)
613                 return;
ragge
1.97
614         if (sloscan() != WSPACE || sloscan() != IDENT)
ragge
1.37
615                 goto bad;
ragge
1.36
616
ragge
1.51
617         if (isdigit((int)yytext[0]))
618                 goto bad;
619
ragge
1.39
620         np = lookup((usch *)yytextENTER);
ragge
1.15
621         redef = np->value != NULL;
ragge
1.1
622
ragge
1.79
623         readmac = 1;
ragge
1.15
624         sbeg = stringbuf;
ragge
1.97
625         if ((c = sloscan()) == '(') {
ragge
1.1
626                 narg = 0;
627                 /* function-like macros, deal with identifiers */
ragge
1.72
628                 c = definp();
ragge
1.37
629                 for (;;) {
ragge
1.1
630                         if (c == ')')
631                                 break;
ragge
1.97
632                         if (c == '.' && isell()) {
ragge
1.37
633                                 ellips = 1;
634                                 if (definp() != ')')
635                                         goto bad;
636                                 break;
637                         }
638                         if (c == IDENT) {
ragge
1.72
639                                 /* make sure there is no arg of same name */
640                                 for (i = 0i < nargi++)
641                                         if (!strcmp((char *) args[i], yytext))
642                                                 error("Duplicate macro "
643                                                   "parameter \"%s\""yytext);
ragge
1.112
644                                 if (narg == MAXARGS)
645                                         error("Too many macro args");
ragge
1.90
646                                 args[narg++] = xstrdup(yytext);
ragge
1.72
647                                 if ((c = definp()) == ',') {
648                                         if ((c = definp()) == ')')
649                                                 goto bad;
ragge
1.37
650                                         continue;
ragge
1.72
651                                 }
ragge
1.86
652 #ifdef GCC_VARI
ragge
1.97
653                                 if (c == '.' && isell()) {
ragge
1.86
654                                         if (definp() != ')')
655                                                 goto bad;
656                                         gccvari = args[--narg];
657                                         break;
658                                 }
659 #endif
ragge
1.37
660                                 if (c == ')')
661                                         break;
662                         }
663                         goto bad;
ragge
1.1
664                 }
ragge
1.97
665                 c = sloscan();
ragge
1.36
666         } else if (c == '\n') {
ragge
1.8
667                 /* #define foo */
ragge
1.36
668                 ;
ragge
1.1
669         } else if (c != WSPACE)
ragge
1.37
670                 goto bad;
ragge
1.1
671
ragge
1.31
672         while (c == WSPACE)
ragge
1.97
673                 c = sloscan();
ragge
1.1
674
ragge
1.72
675         /* replacement list cannot start with ## operator */
ragge
1.97
676         if (c == '#') {
677                 if ((c = sloscan()) == '#')
678                         goto bad;
679                 savch('\0');
680 #ifdef GCC_VARI
681                 wascon = 0;
682 #endif
683                 goto in2;
684         }
ragge
1.72
685
ragge
1.1
686         /* parse replacement-list, substituting arguments */
687         savch('\0');
ragge
1.36
688         while (c != '\n') {
ragge
1.91
689 #ifdef GCC_VARI
690                 wascon = 0;
691 loop:
692 #endif
ragge
1.1
693                 switch (c) {
694                 case WSPACE:
695                         /* remove spaces if it surrounds a ## directive */
ragge
1.2
696                         ubuf = stringbuf;
ragge
1.39
697                         savstr((usch *)yytext);
ragge
1.97
698                         c = sloscan();
699                         if (c == '#') {
700                                 if ((c = sloscan()) != '#')
701                                         goto in2;
ragge
1.2
702                                 stringbuf = ubuf;
ragge
1.1
703                                 savch(CONC);
ragge
1.97
704                                 if ((c = sloscan()) == WSPACE)
705                                         c = sloscan();
ragge
1.91
706 #ifdef GCC_VARI
707                                 if (c == '\n')
708                                         break;
709                                 wascon = 1;
710                                 goto loop;
711 #endif
ragge
1.1
712                         }
713                         continue;
714
ragge
1.97
715                 case '#':
716                         c = sloscan();
717                         if (c == '#') {
718                                 /* concat op */
719                                 savch(CONC);
720                                 if ((c = sloscan()) == WSPACE)
721                                         c = sloscan();
ragge
1.91
722 #ifdef GCC_VARI
ragge
1.97
723                                 if (c == '\n')
724                                         break;
725                                 wascon = 1;
726                                 goto loop;
ragge
1.91
727 #else
ragge
1.97
728                                 continue;
ragge
1.91
729 #endif
ragge
1.97
730                         } 
731 in2:                    if (narg < 0) {
ragge
1.1
732                                 /* no meaning in object-type macro */
733                                 savch('#');
ragge
1.97
734                                 continue;
ragge
1.1
735                         }
736                         /* remove spaces between # and arg */
737                         savch(SNUFF);
ragge
1.97
738                         if (c == WSPACE)
739                                 c = sloscan(); /* whitespace, ignore */
ragge
1.1
740                         mkstr = 1;
ragge
1.97
741                         if (c == IDENT && strcmp(yytext"__VA_ARGS__") == 0)
ragge
1.37
742                                 continue;
ragge
1.1
743
744                         /* FALLTHROUGH */
745                 case IDENT:
ragge
1.97
746                         if (strcmp(yytext"__VA_ARGS__") == 0) {
747                                 if (ellips == 0)
748                                         error("unwanted %s"yytext);
749                                 savch(VARG);
750                                 savch(WARN);
751                                 if (mkstr)
752                                         savch(SNUFF), mkstr = 0;
753                                 break;
754                         }
ragge
1.1
755                         if (narg < 0)
756                                 goto id/* just add it if object */
757                         /* check if its an argument */
758                         for (i = 0i < nargi++)
ragge
1.39
759                                 if (strcmp(yytext, (char *)args[i]) == 0)
ragge
1.1
760                                         break;
761                         if (i == narg) {
ragge
1.86
762 #ifdef GCC_VARI
ragge
1.87
763                                 if (gccvari &&
764                                     strcmp(yytext, (char *)gccvari) == 0) {
ragge
1.91
765                                         savch(wascon ? GCCARG : VARG);
ragge
1.86
766                                         savch(WARN);
767                                         if (mkstr)
768                                                 savch(SNUFF), mkstr = 0;
769                                         break;
770                                 }
771 #endif
ragge
1.1
772                                 if (mkstr)
773                                         error("not argument");
774                                 goto id;
775                         }
776                         savch(i);
777                         savch(WARN);
778                         if (mkstr)
779                                 savch(SNUFF), mkstr = 0;
780                         break;
781
ragge
1.79
782                 case CMNT/* save comments */
783                         getcmnt();
784                         break;
785
ragge
1.1
786                 default:
ragge
1.39
787 id:                     savstr((usch *)yytext);
ragge
1.1
788                         break;
789                 }
ragge
1.97
790                 c = sloscan();
ragge
1.1
791         }
ragge
1.79
792         readmac = 0;
ragge
1.20
793         /* remove trailing whitespace */
794         while (stringbuf > sbeg) {
795                 if (stringbuf[-1] == ' ' || stringbuf[-1] == '\t')
796                         stringbuf--;
ragge
1.72
797                 /* replacement list cannot end with ## operator */
798                 else if (stringbuf[-1] == CONC)
799                         goto bad;
ragge
1.20
800                 else
801                         break;
802         }
ragge
1.86
803 #ifdef GCC_VARI
804         if (gccvari) {
805                 savch(narg);
806                 savch(VARG);
807         } else
808 #endif
ragge
1.37
809         if (ellips) {
810                 savch(narg);
811                 savch(VARG);
812         } else
813                 savch(narg < 0 ? OBJCT : narg);
ragge
1.15
814         if (redef) {
ragge
1.79
815                 if (cmprepl(np->valuestringbuf-1))
ragge
1.53
816                         error("%s redefined\nprevious define: %s:%d",
817                             np->namepnp->filenp->line);
ragge
1.15
818                 stringbuf = sbeg;  /* forget this space */
819         } else
820                 np->value = stringbuf-1;
ragge
1.1
821
822 #ifdef CPP_DEBUG
823         if (dflag) {
ragge
1.103
824                 const usch *w = np->value;
ragge
1.1
825
826                 printf("!define: ");
827                 if (*w == OBJCT)
828                         printf("[object]");
ragge
1.37
829                 else if (*w == VARG)
830                         printf("[VARG%d]", *--w);
ragge
1.1
831                 while (*--w) {
832                         switch (*w) {
833                         case WARNprintf("<%d>", *--w); break;
834                         case CONCprintf("<##>"); break;
835                         case SNUFFprintf("<\">"); break;
836                         defaultputchar(*w); break;
837                         }
838                 }
839                 putchar('\n');
840         }
841 #endif
ragge
1.90
842         for (i = 0i < nargi++)
843                 free(args[i]);
ragge
1.37
844         return;
845
846 bad:    error("bad define");
ragge
1.1
847 }
848
849 void
stefan
1.68
850 xwarning(usch *s)
stefan
1.67
851 {
852         usch *t;
853         usch *sb = stringbuf;
ragge
1.96
854         int dummy;
stefan
1.67
855
856         flbuf();
857         savch(0);
858         if (ifiles != NULL) {
859                 t = sheap("%s:%d: warning: "ifiles->fnameifiles->lineno);
860                 write (2tstrlen((char *)t));
861         }
ragge
1.96
862         dummy = write (2sstrlen((char *)s));
863         dummy = write (2"\n"1);
stefan
1.67
864         stringbuf = sb;
865 }
866
867 void
ragge
1.37
868 xerror(usch *s)
ragge
1.1
869 {
ragge
1.37
870         usch *t;
ragge
1.96
871         int dummy;
ragge
1.1
872
ragge
1.48
873         flbuf();
ragge
1.38
874         savch(0);
ragge
1.37
875         if (ifiles != NULL) {
ragge
1.70
876                 t = sheap("%s:%d: error: "ifiles->fnameifiles->lineno);
ragge
1.96
877                 dummy = write (2tstrlen((char *)t));
ragge
1.37
878         }
ragge
1.96
879         dummy = write (2sstrlen((char *)s));
880         dummy = write (2"\n"1);
ragge
1.37
881         exit(1);
ragge
1.1
882 }
883
ragge
1.112
884 static int
885 addmac(struct symtab *sp)
886 {
887         int ci;
888
889         /* Check if it exists; then save some space */
890         /* May be more difficult to debug cpp */
891         for (i = 1i < norepptri++)
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 in = cinput();
905         DDPRINT(("doexp %s(%d) blocking:"norep[n]->namepn));
906         if (n != bptr[--bidx])
907                 error("expansion sync error");
908         if (dflag>1) {
909                 for (i = bidx-1i >= 0i--)
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 ni;
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"bidxn);
928                 printf("donex %s(%d) blocking:"norep[n]->