Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20110124145259

Diff

Diff from 1.118 to:

Annotations

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

Annotated File View

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