Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20110111095948

Diff

Diff from 1.114 to:

Annotations

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

Annotated File View

ragge
1.114
1 /*      $Id: cpp.c,v 1.114 2011/01/11 09:59:48 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);
ragge
1.108
136 static void addidir(char *idirstruct incs **ww);
ragge
1.113
137 void imp(const char *);
ragge
1.112
138 #define IMP(x) if (dflag>1) imp(x)
ragge
1.1
139
140 int
141 main(int argcchar **argv)
142 {
ragge
1.53
143         struct initar *it;
ragge
1.26
144         struct symtab *nl;
145         register int ch;
ragge
1.103
146         const usch *fn1, *fn2;
ragge
1.15
147
ragge
1.94
148 #ifdef TIMING
149         struct timeval t1t2;
150
151         (void)gettimeofday(&t1NULL);
152 #endif
153
gmcgarry
1.85
154         while ((ch = getopt(argcargv"CD:I:MPS:U:d:i:tvV?")) != -1)
ragge
1.1
155                 switch (ch) {
ragge
1.22
156                 case 'C'/* Do not discard comments */
157                         Cflag++;
158                         break;
159
ragge
1.53
160                 case 'i'/* include */
161                 case 'U'/* undef */
162                 case 'D'/* define something */
ragge
1.58
163                         /* XXX should not need malloc() here */
164                         if ((it = malloc(sizeof(struct initar))) == NULL)
165                                 error("couldn't apply -%c %s"choptarg);
ragge
1.53
166                         it->type = ch;
167                         it->str = optarg;
168                         it->next = initar;
169                         initar = it;
ragge
1.7
170                         break;
171
ragge
1.51
172                 case 'M'/* Generate dependencies for make */
173                         Mflag++;
174                         break;
175
gmcgarry
1.85
176                 case 'P'/* Inhibit generation of line numbers */
177                         Pflag++;
178                         break;
179
ragge
1.7
180                 case 'S':
ragge
1.10
181                 case 'I':
ragge
1.108
182                         addidir(optarg, &incdir[ch == 'I' ? INCINC : SYSINC]);
ragge
1.7
183                         break;
184
ragge
1.1
185 #ifdef CPP_DEBUG
ragge
1.64
186                 case 'V':
ragge
1.18
187                         dflag++;
ragge
1.1
188                         break;
189 #endif
ragge
1.64
190                 case 'v':
191                         printf("cpp: %s\n"VERSSTR);
192                         break;
ragge
1.60
193                 case 'd':
194                         if (optarg[0] == 'M') {
195                                 dMflag = 1;
196                                 Mflag = 1;
197                         }
198                         /* ignore others */
199                         break;
200
ragge
1.1
201                 case 't':
202                         tflag = 1;
203                         break;
204
ragge
1.37
205                 case '?':
206                         usage();
ragge
1.1
207                 default:
ragge
1.37
208                         error("bad arg %c\n"ch);
ragge
1.1
209                 }
210         argc -= optind;
211         argv += optind;
212
ragge
1.103
213         filloc = lookup((const usch *)"__FILE__"ENTER);
214         linloc = lookup((const usch *)"__LINE__"ENTER);
ragge
1.114
215         filloc->value = linloc->value = stringbuf;
216         savch(OBJCT);
217
218         /* create a complete macro for pragma */
ragge
1.103
219         pragloc = lookup((const usch *)"_Pragma"ENTER);
ragge
1.114
220         savch(0);
221         savstr("_Pragma(");
222         savch(0);
223         savch(WARN);
224         savch(')');
225         pragloc->value = stringbuf;
226         savch(1);
ragge
1.15
227
ragge
1.12
228         if (tflag == 0) {
229                 time_t t = time(NULL);
ragge
1.39
230                 usch *n = (usch *)ctime(&t);
ragge
1.12
231
232                 /*
233                  * Manually move in the predefined macros.
234                  */
ragge
1.103
235                 nl = lookup((const usch *)"__TIME__"ENTER);
ragge
1.13
236                 savch(0); savch('"');  n[19] = 0savstr(&n[11]); savch('"');
ragge
1.12
237                 savch(OBJCT);
238                 nl->value = stringbuf-1;
239
ragge
1.103
240                 nl = lookup((const usch *)"__DATE__"ENTER);
ragge
1.13
241                 savch(0); savch('"'); n[24] = n[11] = 0savstr(&n[4]);
242                 savstr(&n[20]); savch('"'); savch(OBJCT);
ragge
1.12
243                 nl->value = stringbuf-1;
244
ragge
1.103
245                 nl = lookup((const usch *)"__STDC__"ENTER);
ragge
1.13
246                 savch(0); savch('1'); savch(OBJCT);
ragge
1.12
247                 nl->value = stringbuf-1;
ragge
1.73
248
ragge
1.103
249                 nl = lookup((const usch *)"__STDC_VERSION__"ENTER);
250                 savch(0); savstr((const usch *)"199901L"); savch(OBJCT);
ragge
1.73
251                 nl->value = stringbuf-1;
ragge
1.12
252         }
ragge
1.1
253
ragge
1.60
254         if (Mflag && !dMflag) {
ragge
1.51
255                 usch *c;
256
257                 if (argc < 1)
258                         error("-M and no infile");
259                 if ((c = (usch *)strrchr(argv[0], '/')) == NULL)
260                         c = (usch *)argv[0];
261                 else
262                         c++;
263                 Mfile = stringbuf;
264                 savstr(c); savch(0);
265                 if ((c = (usch *)strrchr((char *)Mfile'.')) == NULL)
266                         error("-M and no extension: ");
267                 c[1] = 'o';
268                 c[2] = 0;
269         }
270
ragge
1.26
271         if (argc == 2) {
ragge
1.37
272                 if ((ofd = open(argv[1], O_WRONLY|O_CREAT0600)) < 0)
273                         error("Can't creat %s"argv[1]);
ragge
1.26
274         } else
ragge
1.37
275                 ofd = 1/* stdout */
276         istty = isatty(ofd);
ragge
1.26
277
ragge
1.102
278         if (argc && strcmp(argv[0], "-")) {
279                 fn1 = fn2 = (usch *)argv[0];
280         } else {
281                 fn1 = NULL;
ragge
1.103
282                 fn2 = (const usch *)"";
ragge
1.102
283         }
284         if (pushfile(fn1fn20NULL))
ragge
1.26
285                 error("cannot open %s"argv[0]);
286
ragge
1.37
287         flbuf();
288         close(ofd);
ragge
1.94
289 #ifdef TIMING
290         (void)gettimeofday(&t2NULL);
291         t2.tv_sec -= t1.tv_sec;
292         t2.tv_usec -= t1.tv_usec;
293         if (t2.tv_usec < 0) {
294                 t2.tv_usec += 1000000;
295                 t2.tv_sec -= 1;
296         }
297         fprintf(stderr"cpp total time: %ld s %ld us\n",
298              t2.tv_sect2.tv_usec);
299 #endif
ragge
1.37
300         return 0;
ragge
1.26
301 }
302
ragge
1.108
303 static void
304 addidir(char *idirstruct incs **ww)
305 {
306         struct incs *w;
307         struct stat st;
308
309         if (stat(idir, &st) == -1 || S_ISDIR(st.st_mode) == 0)
310                 return/* ignore */
311         if (*ww != NULL) {
312                 for (w = *www->nextw = w->next) {
313                         if (w->dev == st.st_dev && w->ino == st.st_ino)
314                                 return;
315                 }
316                 if (w->dev == st.st_dev && w->ino == st.st_ino)
317                         return;
318                 ww = &w->next;
319         }
320         if ((w = calloc(sizeof(struct incs), 1)) == NULL)
321                 error("couldn't add path %s"idir);
322         w->dir = (usch *)idir;
323         w->dev = st.st_dev;
324         w->ino = st.st_ino;
325         *ww = w;
326 }
327
ragge
1.1
328 void
ragge
1.9
329 line()
330 {
ragge
1.37
331         static usch *lbuf;
332         static int llen;
ragge
1.97
333         usch *p;
ragge
1.9
334         int c;
335
ragge
1.97
336         if ((c = yylex()) != NUMBER)
ragge
1.9
337                 goto bad;
gmcgarry
1.100
338         ifiles->lineno = (int)(yylval.node.nd_val - 1);
ragge
1.9
339
ragge
1.97
340         if ((c = yylex()) == '\n')
ragge
1.37
341                 return;
ragge
1.97
342
343         if (c != STRING)
ragge
1.9
344                 goto bad;
ragge
1.97
345
346         p = (usch *)yytext;
347         if (*p == 'L')
348                 p++;
349         c = strlen((char *)p);
ragge
1.37
350         if (llen < c) {
ragge
1.52
351                 /* XXX may loose heap space */
ragge
1.37
352                 lbuf = stringbuf;
353                 stringbuf += c;
354                 llen = c;
355         }
ragge
1.97
356         p[strlen((char *)p)-1] = 0;
357         if (strlcpy((char *)lbuf, (char *)&p[1], SBSIZE) >= SBSIZE)
ragge
1.63
358                 error("line exceeded buffer size");
359
ragge
1.37
360         ifiles->fname = lbuf;
ragge
1.97
361         if (yylex() == '\n')
362                 return;
ragge
1.9
363
364 bad:    error("bad line directive");
365 }
366
ragge
1.10
367 /*
ragge
1.102
368  * Search for and include next file.
369  * Return 1 on success.
370  */
371 static int
ragge
1.103
372 fsrch(const usch *fnint idxstruct incs *w)
ragge
1.102
373 {
374         int i;
375
376         for (i = idxi < 2i++) {
377                 if (i > idx)
378                         w = incdir[i];
379                 for (; ww = w->next) {
380                         usch *nm = stringbuf;
381
382                         savstr(w->dir); savch('/');
383                         savstr(fn); savch(0);
384                         if (pushfile(nmfniw->next) == 0)
385                                 return 1;
386                         stringbuf = nm;
387                 }
388         }
389         return 0;
390 }
391
392 /*
ragge
1.10
393  * Include a file. Include order:
ragge
1.20
394  * - For <...> files, first search -I directories, then system directories.
395  * - For "..." files, first search "current" dir, then as <...> files.
ragge
1.10
396  */
ragge
1.9
397 void
ragge
1.3
398 include()
399 {
ragge
1.101
400         struct symtab *nl;
ragge
1.10
401         usch *osp;
ragge
1.62
402         usch *fn, *safefn;
ragge
1.102
403         int cit;
ragge
1.3
404
ragge
1.37
405         if (flslvl)
406                 return;
ragge
1.10
407         osp = stringbuf;
ragge
1.97
408
ragge
1.101
409         while ((c = sloscan()) == WSPACE)
410                 ;
411         if (c == IDENT) {
412                 /* sloscan() will not expand idents */
413                 if ((nl = lookup((usch *)yytextFIND)) == NULL)
414                         goto bad;
ragge
1.112
415                 if (kfind(nl))
416                         unpstr(stringbuf);
417                 else
418                         unpstr(nl->namep);
ragge
1.101
419                 stringbuf = osp;
420                 c = yylex();
421         }
422         if (c != STRING && c != '<')
ragge
1.3
423                 goto bad;
424
ragge
1.97
425         if (c == '<') {
ragge
1.10
426                 fn = stringbuf;
ragge
1.97
427                 while ((c = sloscan()) != '>' && c != '\n') {
ragge
1.105
428                         if (c == '\n'/* XXX check - cannot reach */
ragge
1.10
429                                 goto bad;
ragge
1.39
430                         savstr((usch *)yytext);
ragge
1.10
431                 }
432                 savch('\0');
ragge
1.97
433                 while ((c = sloscan()) == WSPACE)
ragge
1.37
434                         ;
435                 if (c != '\n')
436                         goto bad;
ragge
1.20
437                 it = SYSINC;
ragge
1.62
438                 safefn = fn;
ragge
1.3
439         } else {
ragge
1.20
440                 usch *nm = stringbuf;
441
ragge
1.36
442                 yytext[strlen(yytext)-1] = 0;
ragge
1.39
443                 fn = (usch *)&yytext[1];
ragge
1.20
444                 /* first try to open file relative to previous file */
ragge
1.53
445                 /* but only if it is not an absolute path */
446                 if (*fn != '/') {
447                         savstr(ifiles->orgfn);
448                         if ((stringbuf =
449                             (usch *)strrchr((char *)nm'/')) == NULL)
450                                 stringbuf = nm;
451                         else
452                                 stringbuf++;
453                 }
ragge
1.62
454                 safefn = stringbuf;
ragge
1.20
455                 savstr(fn); savch(0);
ragge
1.97
456                 c = yylex();
ragge
1.37
457                 if (c != '\n')
458                         goto bad;
ragge
1.102
459                 if (pushfile(nmsafefn0NULL) == 0)
ragge
1.97
460                         goto okret;
ragge
1.62
461                 /* XXX may loose stringbuf space */
ragge
1.10
462         }
463
ragge
1.102
464         if (fsrch(safefn0incdir[0]))
465                 goto okret;
ragge
1.10
466
ragge
1.62
467         error("cannot find '%s'"safefn);
ragge
1.37
468         /* error() do not return */
ragge
1.3
469
470 bad:    error("bad include");
ragge
1.37
471         /* error() do not return */
ragge
1.97
472 okret:
473         prtline();
ragge
1.37
474 }
475
ragge
1.102
476 void
477 include_next()
478 {
ragge
1.105
479         struct symtab *nl;
480         usch *osp;
481         usch *fn;
482         int c;
483
ragge
1.107
484         if (flslvl)
485                 return;
ragge
1.105
486         osp = stringbuf;
487         while ((c = sloscan()) == WSPACE)
488                 ;
489         if (c == IDENT) {
490                 /* sloscan() will not expand idents */
491                 if ((nl = lookup((usch *)yytextFIND)) == NULL)
492                         goto bad;
ragge
1.112
493                 if (kfind(nl))
494                         unpstr(stringbuf);
495                 else
496                         unpstr(nl->namep);
ragge
1.105
497                 stringbuf = osp;
498                 c = yylex();
499         }
500         if (c != STRING && c != '<')
501                 goto bad;
502
503         fn = stringbuf;
504         if (c == STRING) {
505                 savstr((usch *)&yytext[1]);
506                 stringbuf[-1] = 0;
507         } else { /* < > */
508                 while ((c = sloscan()) != '>') {
509                         if (c == '\n')
510                                 goto bad;
511                         savstr((usch *)yytext);
512                 }
513                 savch('\0');
514         }
515         while ((c = sloscan()) == WSPACE)
516                 ;
517         if (c != '\n')
518                 goto bad;
519
520         if (fsrch(fnifiles->idxifiles->incs) == 0)
521                 error("cannot find '%s'"fn);
522         prtline();
523         return;
524
525 bad:    error("bad include");
526         /* error() do not return */
ragge
1.102
527 }
528
ragge
1.37
529 static int
530 definp(void)
531 {
532         int c;
533
534         do
ragge
1.97
535                 c = sloscan();
ragge
1.37
536         while (c == WSPACE);
537         return c;
ragge
1.3
538 }
539
ragge
1.80
540 void
ragge
1.79
541 getcmnt(void)
542 {
543         int c;
544
545         savstr((usch *)yytext);
ragge
1.104
546         savch(cinput()); /* Lost * */
ragge
1.79
547         for (;;) {
548                 c = cinput();
549                 if (c == '*') {
550                         c = cinput();
551                         if (c == '/') {
ragge
1.103
552                                 savstr((const usch *)"*/");
ragge
1.79
553                                 return;
554                         }
555                         cunput(c);
556                         c = '*';
557                 }
558                 savch(c);
559         }
560 }
561
562 /*
563  * Compare two replacement lists, taking in account comments etc.
564  */
565 static int
ragge
1.103
566 cmprepl(const usch *oconst usch *n)
ragge
1.79
567 {
568         for (; *oo--, n--) {
569                 /* comment skip */
570                 if (*o == '/' && o[-1] == '*') {
571                         while (*o != '*' || o[-1] != '/')
572                                 o--;
573                         o -= 2;
574                 }
575                 if (*n == '/' && n[-1] == '*') {
576                         while (*n != '*' || n[-1] != '/')
577                                 n--;
578                         n -= 2;
579                 }
580                 while (*o == ' ' || *o == '\t')
581                         o--;
582                 while (*n == ' ' || *n == '\t')
583                         n--;
584                 if (*o != *n)
585                         return 1;
586         }
587         return 0;
588 }
589
ragge
1.97
590 static int
591 isell(void)
592 {
593         int ch;
594
595         if ((ch = cinput()) != '.') {
596                 cunput(ch);
597                 return 0;
598         }
599         if ((ch = cinput()) != '.') {
600                 cunput(ch);
601                 cunput('.');
602                 return 0;
603         }
604         return 1;
605 }
606
ragge
1.3
607 void
ragge
1.1
608 define()
609 {
610         struct symtab *np;
ragge
1.112
611         usch *args[MAXARGS+1], *ubuf, *sbeg;
ragge
1.15
612         int ciredef;
ragge
1.1
613         int mkstr = 0narg = -1;
ragge
1.37
614         int ellips = 0;
ragge
1.86
615 #ifdef GCC_VARI
616         usch *gccvari = NULL;
ragge
1.91
617         int wascon;
ragge
1.86
618 #endif
ragge
1.1
619
ragge
1.37
620         if (flslvl)
621                 return;
ragge
1.97
622         if (sloscan() != WSPACE || sloscan() != IDENT)
ragge
1.37
623                 goto bad;
ragge
1.36
624
ragge
1.51
625         if (isdigit((int)yytext[0]))
626                 goto bad;
627
ragge
1.39
628         np = lookup((usch *)yytextENTER);
ragge
1.15
629         redef = np->value != NULL;
ragge
1.1
630
ragge
1.79
631         readmac = 1;
ragge
1.15
632         sbeg = stringbuf;
ragge
1.97
633         if ((c = sloscan()) == '(') {
ragge
1.1
634                 narg = 0;
635                 /* function-like macros, deal with identifiers */
ragge
1.72
636                 c = definp();
ragge
1.37
637                 for (;;) {
ragge
1.1
638                         if (c == ')')
639                                 break;
ragge
1.97
640                         if (c == '.' && isell()) {
ragge
1.37
641                                 ellips = 1;
642                                 if (definp() != ')')
643                                         goto bad;
644                                 break;
645                         }
646                         if (c == IDENT) {
ragge
1.72
647                                 /* make sure there is no arg of same name */
648                                 for (i = 0i < nargi++)
649                                         if (!strcmp((char *) args[i], yytext))
650                                                 error("Duplicate macro "
651                                                   "parameter \"%s\""yytext);
ragge
1.112
652                                 if (narg == MAXARGS)
653                                         error("Too many macro args");
ragge
1.90
654                                 args[narg++] = xstrdup(yytext);
ragge
1.72
655                                 if ((c = definp()) == ',') {
656                                         if ((c = definp()) == ')')
657                                                 goto bad;
ragge
1.37
658                                         continue;
ragge
1.72
659                                 }
ragge
1.86
660 #ifdef GCC_VARI
ragge
1.97
661                                 if (c == '.' && isell()) {
ragge
1.86
662                                         if (definp() != ')')
663                                                 goto bad;
664                                         gccvari = args[--narg];
665                                         break;
666                                 }
667 #endif
ragge
1.37
668                                 if (c == ')')
669                                         break;
670                         }
671                         goto bad;
ragge
1.1
672                 }
ragge
1.97
673                 c = sloscan();
ragge
1.36
674         } else if (c == '\n') {
ragge
1.8
675                 /* #define foo */
ragge
1.36
676                 ;
ragge
1.1
677         } else if (c != WSPACE)
ragge
1.37
678                 goto bad;
ragge
1.1
679
ragge
1.31
680         while (c == WSPACE)
ragge
1.97
681                 c = sloscan();
ragge
1.1
682
ragge
1.72
683         /* replacement list cannot start with ## operator */
ragge
1.97
684         if (c == '#') {
685                 if ((c = sloscan()) == '#')
686                         goto bad;
687                 savch('\0');
688 #ifdef GCC_VARI
689                 wascon = 0;
690 #endif
691                 goto in2;
692         }
ragge
1.72
693
ragge
1.1
694         /* parse replacement-list, substituting arguments */
695         savch('\0');
ragge
1.36
696         while (c != '\n') {
ragge
1.91
697 #ifdef GCC_VARI
698                 wascon = 0;
699 loop:
700 #endif
ragge
1.1
701                 switch (c) {
702                 case WSPACE:
703                         /* remove spaces if it surrounds a ## directive */
ragge
1.2
704                         ubuf = stringbuf;
ragge
1.39
705                         savstr((usch *)yytext);
ragge
1.97
706                         c = sloscan();
707                         if (c == '#') {
708                                 if ((c = sloscan()) != '#')
709                                         goto in2;
ragge
1.2
710                                 stringbuf = ubuf;
ragge
1.1
711                                 savch(CONC);
ragge
1.97
712                                 if ((c = sloscan()) == WSPACE)
713                                         c = sloscan();
ragge
1.91
714 #ifdef GCC_VARI
715                                 if (c == '\n')
716                                         break;
717                                 wascon = 1;
718                                 goto loop;
719 #endif
ragge
1.1
720                         }
721                         continue;
722
ragge
1.97
723                 case '#':
724                         c = sloscan();
725                         if (c == '#') {
726                                 /* concat op */
727                                 savch(CONC);
728                                 if ((c = sloscan()) == WSPACE)
729                                         c = sloscan();
ragge
1.91
730 #ifdef GCC_VARI
ragge
1.97
731                                 if (c == '\n')
732                                         break;
733                                 wascon = 1;
734                                 goto loop;
ragge
1.91
735 #else
ragge
1.97
736                                 continue;
ragge
1.91
737 #endif
ragge
1.97
738                         } 
739 in2:                    if (narg < 0) {
ragge
1.1
740                                 /* no meaning in object-type macro */
741                                 savch('#');
ragge
1.97
742                                 continue;
ragge
1.1
743                         }
744                         /* remove spaces between # and arg */
745                         savch(SNUFF);
ragge
1.97
746                         if (c == WSPACE)
747                                 c = sloscan(); /* whitespace, ignore */
ragge
1.1
748                         mkstr = 1;
ragge
1.97
749                         if (c == IDENT && strcmp(yytext"__VA_ARGS__") == 0)
ragge
1.37
750                                 continue;
ragge
1.1
751
752                         /* FALLTHROUGH */
753                 case IDENT:
ragge
1.97
754                         if (strcmp(yytext"__VA_ARGS__") == 0) {
755                                 if (ellips == 0)
756                                         error("unwanted %s"yytext);
757                                 savch(VARG);
758                                 savch(WARN);
759                                 if (mkstr)
760                                         savch(SNUFF), mkstr = 0;
761                                 break;
762                         }
ragge
1.1
763                         if (narg < 0)
764                                 goto id/* just add it if object */
765                         /* check if its an argument */
766                         for (i = 0i < nargi++)
ragge
1.39
767                                 if (strcmp(yytext, (char *)args[i]) == 0)
ragge
1.1
768                                         break;
769                         if (i == narg) {
ragge
1.86
770 #ifdef GCC_VARI
ragge
1.87
771                                 if (gccvari &&
772                                     strcmp(yytext, (char *)gccvari) == 0) {
ragge
1.91
773                                         savch(wascon ? GCCARG : VARG);
ragge
1.86
774                                         savch(WARN);
775                                         if (mkstr)
776                                                 savch(SNUFF), mkstr = 0;
777                                         break;
778                                 }
779 #endif
ragge
1.1
780                                 if (mkstr)
781                                         error("not argument");
782                                 goto id;
783                         }
784                         savch(i);
785                         savch(WARN);
786                         if (mkstr)
787                                 savch(SNUFF), mkstr = 0;
788                         break;
789
ragge
1.79
790                 case CMNT/* save comments */
791                         getcmnt();
792                         break;
793
ragge
1.1
794                 default:
ragge
1.39
795 id:                     savstr((usch *)yytext);
ragge
1.1
796                         break;
797                 }
ragge
1.97
798                 c = sloscan();
ragge
1.1
799         }
ragge
1.79
800         readmac = 0;
ragge
1.20
801         /* remove trailing whitespace */
802         while (stringbuf > sbeg) {
803                 if (stringbuf[-1] == ' ' || stringbuf[-1] == '\t')
804                         stringbuf--;
ragge
1.72
805                 /* replacement list cannot end with ## operator */
806                 else if (stringbuf[-1] == CONC)
807                         goto bad;
ragge
1.20
808                 else
809                         break;
810         }
ragge
1.86
811 #ifdef GCC_VARI
812         if (gccvari) {
813                 savch(narg);
814                 savch(VARG);
815         } else
816 #endif
ragge
1.37
817         if (ellips) {
818                 savch(narg);
819                 savch(VARG);
820         } else
821                 savch(narg < 0 ? OBJCT : narg);
ragge
1.15
822         if (redef) {
ragge
1.79
823                 if (cmprepl(np->valuestringbuf-1))
ragge
1.53
824                         error("%s redefined\nprevious define: %s:%d",
825                             np->namepnp->filenp->line);
ragge
1.15
826                 stringbuf = sbeg;  /* forget this space */
827         } else
828                 np->value = stringbuf-1;
ragge
1.1
829
830 #ifdef CPP_DEBUG
831         if (dflag) {
ragge
1.103
832                 const usch *w = np->value;
ragge
1.1
833
834                 printf("!define: ");
835                 if (*w == OBJCT)
836                         printf("[object]");
ragge
1.37
837                 else if (*w == VARG)
838                         printf("[VARG%d]", *--w);
ragge
1.1
839                 while (*--w) {
840                         switch (*w) {
841                         case WARNprintf("<%d>", *--w); break;
842                         case CONCprintf("<##>"); break;
843                         case SNUFFprintf("<\">"); break;
844                         defaultputchar(*w); break;
845                         }
846                 }
847                 putchar('\n');
848         }
849 #endif
ragge
1.90
850         for (i = 0i < nargi++)
851                 free(args[i]);
ragge
1.37
852         return;
853
854 bad:    error("bad define");
ragge
1.1
855 }
856
857 void
stefan
1.68
858 xwarning(usch *s)
stefan
1.67
859 {
860         usch *t;
861         usch *sb = stringbuf;
ragge
1.96
862         int dummy;
stefan
1.67
863
864         flbuf();
865         savch(0);
866         if (ifiles != NULL) {
867                 t = sheap("%s:%d: warning: "ifiles->fnameifiles->lineno);
868                 write (2tstrlen((char *)t));
869         }
ragge
1.96
870         dummy = write (2sstrlen((char *)s));
871         dummy = write (2"\n"1);
stefan
1.67
872         stringbuf = sb;
873 }
874
875 void
ragge
1.37
876 xerror(usch *s)
ragge
1.1
877 {
ragge
1.37
878         usch *t;
ragge
1.96
879         int dummy;
ragge
1.1
880
ragge
1.48
881         flbuf();
ragge
1.38
882         savch(0);
ragge
1.37
883         if (ifiles != NULL) {
ragge
1.70
884                 t = sheap("%s:%d: error: "ifiles->fnameifiles->lineno);
ragge
1.96
885                 dummy = write (2tstrlen((char *)t));
ragge
1.37
886         }
ragge
1.96
887         dummy = write (2sstrlen((char *)s));
888         dummy = write (2"\n"1);
ragge
1.37
889         exit(1);
ragge
1.1
890 }
891
ragge
1.112
892 static int
893 addmac(struct symtab *sp)
894 {
895         int ci;
896
897         /* Check if it exists; then save some space */
898         /* May be more difficult to debug cpp */
899         for (i = 1i < norepptri++)
900                 if (norep[i] == sp)
901                         return i;
902         if ((c = norepptr) == RECMAX)
903                 error("too many macros");
904         norep[norepptr++] = sp;
905         return c;
906 }
907
908 /* Allow next nr in lex buffer to expand */
909 int
910 doexp(void)
911 {
912         int in = cinput();
913         DDPRINT(("doexp %s(%d) blocking:"norep[n]->namepn));
914         if (n != bptr[--bidx])
915                 error("expansion sync error");
916         if (dflag>1) {
917                 for (i = bidx-1i >= 0i--)
918                         printf(" '%s'"norep[bptr[i]]->namep);
919                 printf("\n");
920         }
921         return n;
922 }
923
924 /* Block next nr in lex buffer to expand */
925 int
926 donex(void)
927 {
928         int ni;