Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:plunky:20110828131934

Diff

Diff from 1.142 to:

Annotations

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

Annotated File View

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