Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20100608163831

Diff

Diff from 1.105 to:

Annotations

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

Annotated File View

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