Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20040828131747

Diff

Diff from 1.10 to:

Annotations

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

Annotated File View

ragge
1.10
1 /*      $Id: cpp.c,v 1.10 2004/08/28 13:17:47 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  */
68 #include <sys/wait.h>
69
70 #include <fcntl.h>
71 #include <unistd.h>
72 #include <stdio.h>
73 #include <stdarg.h>
74 #include <stdlib.h>
75 #include <string.h>
ragge
1.9
76 #include <time.h>
ragge
1.1
77 #include <unistd.h>
78
79 #include "cpp.h"
80
81 #define MAXARG  250     /* # of args to a macro, limited by char value */
82 #define SBSIZE  2000
83 #define SYMSIZ  200
84
85 static usch     sbf[SBSIZE];
86 /* C command */
87
88 /* buffer used internally */
89 #ifndef CPPBUF
90 #define CPPBUF  BUFSIZ
91 #endif
92
93 int tflag;      /* traditional cpp syntax */
94 #ifdef CPP_DEBUG
95 int dflag;      /* debug printouts */
96 #endif
97 FILE *obuf;
98 static int exfail;
ragge
1.10
99 struct symtab symtab[SYMSIZ];
ragge
1.1
100
101 /* avoid recursion */
102 struct recur {
103         struct recur *next;
104         struct symtab *sp;
105 };
106
ragge
1.10
107 /* include dirs */
108 struct incs {
109         struct incs *next;
110         char *dir;
111 } *incdir[2];
112 #define INCINC 0
113 #define SYSINC 1
114
ragge
1.1
115 static struct symtab *filloc;
116 static struct symtab *linloc;
ragge
1.9
117 static struct symtab *datloc;
118 static struct symtab *timloc;
ragge
1.10
119 int     trulvl;
120 int     flslvl;
121 int     elflvl;
122 int     elslvl;
123 usch *stringbuf = sbf;
ragge
1.1
124
125 /*
126  * Macro replacement list syntax:
127  * - For object-type macros, replacement strings are stored as-is.
128  * - For function-type macros, macro args are substituted for the
129  *   character WARN followed by the argument number.
130  * 
131  * The first character in the replacement list is the number of arguments:
132  *   OBJCT - object-type macro
133  *   0     - empty parenthesis, foo()
134  *   1->   - number of args.
135  */
136
137 #define OBJCT   0xff
138 #define WARN    1       /* SOH, not legal char */
139 #define CONC    2       /* STX, not legal char */
140 #define SNUFF   3       /* ETX, not legal char */
141 #define NOEXP   4       /* EOT, not legal char */
142 #define EXPAND  5       /* ENQ, not legal char */
143
144 /* args for lookup() */
145 #define FIND    0
146 #define ENTER   1
147 #define FORGET  3
148
149 static void expdef(usch *protostruct recur *, int gotwarn);
150 static void savch(int c);
151 static void insym(struct symtab **spchar *namep);
152 static void control(void);
153 static usch *savstr(usch *str);
154 static void define(void);
155 static void expmac(struct recur *);
156 static int canexpand(struct recur *, struct symtab *np);
ragge
1.3
157 static void include(void);
ragge
1.9
158 static void line(void);
ragge
1.1
159
160 int
161 main(int argcchar **argv)
162 {
ragge
1.10
163         struct incs *w, *w2;
ragge
1.7
164         struct symtab *nl, *thisnl;
165         register int cgotspcch;
166         usch *osp;
ragge
1.1
167
ragge
1.7
168         while ((ch = getopt(argcargv"D:I:S:U:td")) != -1)
ragge
1.1
169                 switch (ch) {
ragge
1.7
170                 case 'D'/* Define something */
171                         osp = optarg;
172                         while (*osp && *osp != '=')
173                                 osp++;
174                         if (*osp == '=') {
ragge
1.10
175                                 *osp++ = 0;
176                                 while (*osp)
177                                         osp++;
178                                 *osp = OBJCT;
ragge
1.7
179                         } else {
ragge
1.10
180                                 static char c[3] = { 0'1'OBJCT };
181                                 osp = &c[2];
ragge
1.7
182                         }
183                         nl = lookup(optargENTER);
184                         if (nl->value)
185                                 error("%s redefined"optarg);
186                         nl->value = osp;
187                         break;
188
189                 case 'S':
ragge
1.10
190                 case 'I':
191                         w = calloc(sizeof(struct incs), 1);
192                         w->dir = optarg;
193                         w2 = incdir[ch == 'I' ? INCINC : SYSINC];
194                         if (w2 != NULL) {
195                                 while (w2->next)
196                                         w2 = w2->next;
197                                 w2->next = w;
198                         } else
199                                 incdir[ch == 'I' ? INCINC : SYSINC] = w;
ragge
1.7
200                         break;
201
202                 case 'U':
203                         nl = lookup(optargFIND);
204                         if (nl && nl->value)
205                                 nl->value = NULL;
206                         break;
ragge
1.1
207 #ifdef CPP_DEBUG
208                 case 'd':
209                         dflag = 1;
210                         break;
211 #endif
212                 case 't':
213                         tflag = 1;
214                         break;
215
216                 default:
217                         fprintf(stderr"bad arg %c\n"ch);
218                         exit(1);
219                 }
220         argc -= optind;
221         argv += optind;
222
223         exfail = 0;
ragge
1.7
224         if (argc) {
225                 if (freopen(argv[0], "r"stdin) == NULL) {
226                         fprintf(stderr"Can't open %s"argv[0]);
ragge
1.1
227                         exit(8);
228                 }
229         }
ragge
1.10
230         if (pushfile(argc ? argv[0] : "<stdin>"))
231                 error("cannot open %s"argv[0]);
ragge
1.1
232
ragge
1.7
233         if (argc == 2) {
234                 if ((obuf = fopen(argv[1], "w")) == 0) {
235                         fprintf(stderr"Can't creat %s\n"argv[1]);
ragge
1.1
236                         exit(8);
237                 }
238         } else
239                 obuf = stdout;
240
241         prtline();
242
243         insym(&filloc"__FILE__");
244         insym(&linloc"__LINE__");
ragge
1.9
245         insym(&datloc"__DATE__");
246         insym(&timloc"__TIME__");
ragge
1.1
247
248         thisnl = NULL;
249         while ((c = yylex()) != 0) {
250                 switch (c) {
251                 case CONTROL:
252                         control();
253                         break;
254
255                 case IDENT:
ragge
1.8
256                         if (flslvl)
257                                 break;
ragge
1.1
258                         osp = stringbuf;
259                         nl = lookup(yytextFIND);
260                         if (nl == 0 || thisnl == 0)
261                                 goto found;
262                         if (thisnl == nl) {
263                                 nl = 0;
264                                 goto found;
265                         }
ragge
1.2
266                         gotspc = 0;
ragge
1.1
267                         if ((c = yylex()) == WSPACE)
ragge
1.2
268                                 gotspc = 1c = yylex();
ragge
1.1
269                         if (c != EXPAND) {
270                                 unpstr(yytext);
ragge
1.2
271                                 if (gotspc)
272                                         cunput(' ');
ragge
1.1
273                                 unpstr(nl->namep);
274                                 (void)yylex(); /* get yytext correct */
275                                 nl = 0/* ignore */
276                         } else
277                                 thisnl = NULL;
278
279 found:                  if (nl == 0 || subst(yytextnlNULL) == 0) {
280                                 fputs(yytextobuf);
281                         } else if (osp != stringbuf) {
282                                 cunput(EXPAND);
283                                 while (stringbuf > osp)
284                                         cunput(*--stringbuf);
285                                 thisnl = nl;
286                         }
287                         stringbuf = osp/* clean up heap */
288                         break;
289
290                 case EXPAND:
291                         thisnl = NULL;
292                         break;
293
294                 case CHARCON:
295                 case NUMBER:
296                 case FPOINT:
297                 case STRING:
298                 case WSPACE:
299                 case NL:
ragge
1.3
300                 default:
ragge
1.8
301                         if (flslvl == 0)
302                                 fputs(yytextobuf);
ragge
1.1
303                         break;
304                 }
305         }
306         fclose(obuf);
ragge
1.7
307         return exfail;
ragge
1.1
308 }
309
310 /*
311  * do something when a '#' is found.
312  */
313 void
314 control()
315 {
316         struct symtab *np;
317         int t;
318
ragge
1.8
319 #define CHECK(x) (yytext[0] == #x[0]) && strcmp(yytext, #x) == 0
320
ragge
1.1
321         if ((t = yylex()) == WSPACE)
322                 t = yylex();
323         if (t != IDENT)
324                 return error("bad control '%s'"yytext);
325
ragge
1.8
326         if (CHECK(include)) {
ragge
1.1
327                 if (flslvl)
328                         goto exit;
ragge
1.3
329                 include();
ragge
1.1
330                 return;
ragge
1.8
331         } else if (CHECK(else)) {
ragge
1.1
332                 if (flslvl) {
ragge
1.10
333                         if (elflvl > trulvl)
334                                 ;
335                         else if (--flslvl!=0) {
ragge
1.1
336                                 flslvl++;
ragge
1.8
337                         } else {
ragge
1.1
338                                 trulvl++;
ragge
1.8
339                                 prtline();
340                         }
ragge
1.1
341                 } else if (trulvl) {
342                         flslvl++;
343                         trulvl--;
344                 } else
345                         error("If-less else");
ragge
1.10
346                 if (elslvl==trulvl+flslvlerror("Too many else");
347                 elslvl=trulvl+flslvl;
ragge
1.8
348         } else if (CHECK(endif)) {
349                 if (flslvl) {
350                         flslvl--;
351                         if (flslvl == 0)
352                                 prtline();
353                 } else if (trulvl)
354                         trulvl--;
355                 else
356                         error("If-less endif");
ragge
1.10
357                 if (flslvl == 0)
358                         elflvl = 0;
359                 elslvl = 0;
ragge
1.8
360         } else if (CHECK(error)) {
361                 usch *ch = stringbuf;
362                 while (yylex() != NL)
363                         savstr(yytext);
364                 savch('\n');
365                 error("error: %s"ch);
ragge
1.9
366 #define GETID() if (yylex() != WSPACE || yylex() != IDENT) goto cfail
367         } else if (CHECK(define)) {
ragge
1.10
368                 if (flslvl)
369                         goto exit;
ragge
1.9
370                 GETID();
371                 define();
372         } else if (CHECK(ifdef)) {
373                 GETID();
374                 if (flslvl == 0 && lookup(yytextFIND) != 0)
375                         trulvl++;
376                 else
377                         flslvl++;
378         } else if (CHECK(ifndef)) {
379                 GETID();
380                 if (flslvl == 0 && lookup(yytextFIND) == 0)
381                         trulvl++;
382                 else
383                         flslvl++;
384         } else if (CHECK(undef)) {
385                 GETID();
386                 if (flslvl == 0 && (np = lookup(yytextFIND)))
387                         np->value = 0;
388         } else if (CHECK(line)) {
ragge
1.10
389                 if (flslvl)
390                         goto exit;
ragge
1.9
391                 line();
ragge
1.10
392         } else if (CHECK(if)) {
393                 if (flslvl==0 && yyparse())
394                         ++trulvl;
395                 else
396                         ++flslvl;
397         } else if (CHECK(elif)) {
398                 if (flslvl == 0)
399                         elflvl = trulvl;
400                 if (flslvl) {
401                         if (elflvl > trulvl)
402                                 ;
403                         else if (--flslvl!=0)
404                                 ++flslvl;
405                         else {
406                                 if (yyparse()) {
407                                         ++trulvl;
408                                         prtline();
409                                 } else
410                                         ++flslvl;
411                         }
412                 } else if (trulvl) {
413                         ++flslvl;
414                         --trulvl;
415                 } else
416                         error("If-less elif");
ragge
1.9
417         } else
418                 error("undefined control '%s'"yytext);
419
420         return;
421
422 cfail:
423         error("control line syntax error");
ragge
1.1
424
425 exit:
426         while (yylex() != NL)
427                 ;
ragge
1.10
428         putc('\n'obuf);
ragge
1.8
429 #undef CHECK
ragge
1.1
430 }
431
432 void
ragge
1.9
433 line()
434 {
435         struct symtab *nl;
436         int c;
437
438         if (yylex() != WSPACE)
439                 goto bad;
440         if ((c = yylex()) == IDENT) {
441                 /* Do macro preprocessing first */
442                 usch *osp = stringbuf;
443                 if ((nl = lookup(yytextFIND)) == NULL)
444                         goto bad;
445                 if (subst(yytextnlNULL) == 0)
446                         goto bad;
447                 while (stringbuf > osp)
448                         cunput(*--stringbuf);
449                 c = yylex();
450         }
451
452         if (c != NUMBER)
453                 goto bad;
454         setline(atoi(yytext));
455
456         if ((c = yylex()) != NL && c != WSPACE)
457                 goto bad;
458         if (c == NL)
459                 return setline(curline()+1);
460         if (yylex() != STRING)
461                 goto bad;
462         yytext[strlen(yytext)-1] = 0;
463         setfile(&yytext[1]);
464         return;
465
466 bad:    error("bad line directive");
467 }
468
ragge
1.10
469 /*
470  * Include a file. Include order:
471  * - if name inside <>, only search system includes.
472  * - if name inside "", first search current dir, then -I dirs, 
473  *   then system includes.
474  */
ragge
1.9
475 void
ragge
1.3
476 include()
477 {
ragge
1.10
478         struct incs *w;
ragge
1.3
479         struct symtab *nl;
ragge
1.10
480         usch *osp;
481         char *fn;
482         int icit;
ragge
1.3
483
ragge
1.10
484         osp = stringbuf;
ragge
1.3
485         if (yylex() != WSPACE)
486                 goto bad;
ragge
1.10
487 again:  if ((c = yylex()) != STRING && c != '<' && c != IDENT)
ragge
1.3
488                 goto bad;
489
490         if (c == IDENT) {
491                 if ((nl = lookup(yytextFIND)) == NULL)
492                         goto bad;
493                 if (subst(yytextnlNULL) == 0)
494                         goto bad;
495                 savch('\0');
ragge
1.10
496                 unpstr(osp);
497                 goto again;
498         } else if (c == '<') {
499                 fn = stringbuf;
500                 while ((c = yylex()) != '>' && c != NL) {
501                         if (c == NL)
502                                 goto bad;
503                         savstr(yytext);
504                 }
505                 savch('\0');
506                 it = SYSINC;
ragge
1.3
507         } else {
508                 yytext[strlen(yytext)-1] = 0;
ragge
1.10
509                 fn = &yytext[1];
510                 it = INCINC;
511         }
512
513         /* create search path and try to open file */
514         for (i = iti < 2i++) {
515                 for (w = incdir[i]; ww = w->next) {
516                         usch *nm = stringbuf;
517
518                         savstr(w->dir); savch('/');
519                         savstr(fn); savch(0);
520                         if (pushfile(nm) == 0)
521                                 goto ret;
522                         stringbuf = nm;
523                 }
ragge
1.3
524         }
ragge
1.10
525         error("cannot find '%s'"fn);
526         stringbuf = osp;
ragge
1.3
527         return;
528
529 bad:    error("bad include");
ragge
1.10
530 ret:    prtline();
531         stringbuf = osp;
ragge
1.3
532 }
533
534 void
ragge
1.1
535 define()
536 {
537         struct symtab *np;
ragge
1.2
538         usch *args[MAXARG], *ubuf;
ragge
1.1
539         int ci;
540         int mkstr = 0narg = -1;
541
542         np = lookup(yytextENTER);
ragge
1.7
543         if (np->value)
544                 error("%s redefined"np->namep);
ragge
1.1
545
546         if ((c = yylex()) == '(') {
547                 narg = 0;
548                 /* function-like macros, deal with identifiers */
549                 while ((c = yylex()) != ')') {
550                         if (c == WSPACEc = yylex();
551                         if (c == ','c = yylex();
552                         if (c == WSPACEc = yylex();
553                         if (c == ')')
554                                 break;
555                                 if (c != IDENT)
556                         error("define error");
557                         args[narg] = alloca(strlen(yytext)+1);
558                         strcpy(args[narg], yytext);
559                         narg++;
560                 }
ragge
1.8
561         } else if (c == NL) {
562                 /* #define foo */
563                 cunput('\n');
ragge
1.1
564         } else if (c != WSPACE)
565                 error("bad define");
566
567         if ((c = yylex()) == WSPACE)
568                 c = yylex();
569
570         /* parse replacement-list, substituting arguments */
571         savch('\0');
572         while (c != NL) {
573                 switch (c) {
574                 case WSPACE:
575                         /* remove spaces if it surrounds a ## directive */
ragge
1.2
576                         ubuf = stringbuf;
ragge
1.1
577                         savstr(yytext);
578                         c = yylex();
579                         if (c == CONCAT) {
ragge
1.2
580                                 stringbuf = ubuf;
ragge
1.1
581                                 savch(CONC);
582                                 if ((c = yylex()) == WSPACE)
583                                         c = yylex();
584                         }
585                         continue;
586
587                 case CONCAT:
588                         /* No spaces before concat op */
589                         savch(CONC);
590                         if ((c = yylex()) == WSPACE)
591                                 c = yylex();
592                         continue;
593
594                 case MKSTR:
595                         if (narg < 0) {
596                                 /* no meaning in object-type macro */
597                                 savch('#');
598                                 break;
599                         }
600                         /* remove spaces between # and arg */
601                         savch(SNUFF);
602                         if ((c = yylex()) == WSPACE)
603                                 c = yylex(); /* whitespace, ignore */
604                         mkstr = 1;
605
606                         /* FALLTHROUGH */
607                 case IDENT:
608                         if (narg < 0)
609                                 goto id/* just add it if object */
610                         /* check if its an argument */
611                         for (i = 0i < nargi++)
612                                 if (strcmp(yytextargs[i]) == 0)
613                                         break;
614                         if (i == narg) {
615                                 if (mkstr)
616                                         error("not argument");
617                                 goto id;
618                         }
619                         savch(i);
620                         savch(WARN);
621                         if (mkstr)
622                                 savch(SNUFF), mkstr = 0;
623                         break;
624
625                 default:
626 id:                     savstr(yytext);
627                         break;
628                 }
629                 c = yylex();
630         }
631         savch(narg < 0 ? OBJCT : narg);
632         np->value = stringbuf-1;
ragge
1.2
633         putc('\n'obuf);
ragge
1.1
634
635 #ifdef CPP_DEBUG
636         if (dflag) {
637                 usch *w = np->value;
638
639                 printf("!define: ");
640                 if (*w == OBJCT)
641                         printf("[object]");
642                 else
643                         printf("[%d]", *w);
644                 while (*--w) {
645                         switch (*w) {
646                         case WARNprintf("<%d>", *--w); break;
647                         case CONCprintf("<##>"); break;
648                         case SNUFFprintf("<\">"); break;
649                         defaultputchar(*w); break;
650                         }
651                 }
652                 putchar('\n');
653         }
654 #endif
655 }
656
657 void
658 insym(spnamep)
659 struct symtab **sp;
660 char *namep;
661 {
662         register struct symtab *np;
663
664         *sp = np = lookup(namepENTER);
ragge
1.7
665         np->value = NULL;
ragge
1.1
666 }
667
668 void
669 error(char *s, ...)
670 {
671         va_list ap;
672
673         va_start(aps);
674         fprintf(stderr"%s:%d: "curfile(), curline());
675         vfprintf(stderrsap);
676         fputc('\n'stderr);
677         exfail++;
678         va_end(ap);
679         exit(8);
680 }
681
682 /*
683  * store a character into the "define" buffer.
684  */
685 void
686 savch(c)
687 {
688         *stringbuf++ = c;
689         if (stringbuf-sbf < SBSIZE)
690                 return;
691         error("Too much defining");
692         exit(1);
693 }
694
695 /*
696  * Do a symbol lookup.
697  * If enterf == FIND, only lookup.
698  */
699 struct symtab *
700 lookup(namepenterf)
701         char *namep;
702 {
703         register char *np;
704         register struct symtab *sp;
705         int icaround;
706
ragge
1.3
707 if (dflag)printf("lookup '%s'\n"namep);
ragge
1.1
708         np = namep;
709         around = i = 0;
710         while ((c = *np++))
711                 i =+ c;
712         i %= SYMSIZ;
713         sp = &symtab[i];
714
715         while (sp->namep) {
716                 if (*sp->namep == *namep && strcmp(sp->namepnamep) == 0)
717                         return(sp);
718                 if (++sp >= &symtab[SYMSIZ]) {
719                         if (around++)
720                                 error("too many defines");
721                         else
722                                 sp = symtab;
723                 }
724         }
ragge
1.7
725         if (enterf == ENTER) {
ragge
1.1
726                 sp->namep = savstr(namep), savch('\0');
ragge
1.7
727         }
ragge
1.1
728         return(sp->namep ? sp : 0);
729 }
730
731 /*
732  * substitute namep for sp->value.
733  */
734 int
735 subst(npsprp)
736 char *np;
737 struct symtab *sp;
738 struct recur *rp;
739 {
740         struct recur rp2;
741         register usch *vp, *cp;
742         int crv = 0;
743
744 if (dflag)printf("subst\n");
ragge
1.9
745         if ((vp = sp->value) == 0) {
746                 /*
747                  * If no value is assigned, it may be a special macro,
748                  * otherwise a deleted macro.
749                  */
750                 if (sp == filloc) {
751                         savch('"');
752                         savstr(curfile());
753                         savch('"');
754                 } else if (sp == linloc) {
755                         char buf[12];
756                         sprintf(buf"%d"curline());
757                         savstr(buf);
758                 } else if (sp == datloc) {
759                         time_t t = time(NULL);
760                         char *n = ctime(&t);
761                         savch('"');
762                         n[24] = n[11] = 0;
763                         savstr(&n[4]);
764                         savstr(&n[20]);
765                         savch('"');
766                 } else if (sp == timloc) {
767                         time_t t = time(NULL);
768                         char *n = ctime(&t);
769                         savch('"');  
770                         n[19] = 0;
771                         savstr(&n[11]);
772                         savch('"');
773                 } else
774                         return 0;
ragge
1.1
775                 return 1;
776         }
777
778         rp2.next = rp;
779         rp2.sp = sp;
780
781         if (*vp-- != OBJCT) {
782                 int gotwarn = 0;
783
784                 /* should we be here at all? */
785                 /* check if identifier is followed by parentheses */
786                 rv = 1;
787                 do {
788                         if ((c = yylex()) == NL)
789                                 putc('\n'obuf);
790                         if (c == WARN) {
791                                 gotwarn++;
792                                 if (rp == NULL)
793                                         goto noid;
794                         }
795                 } while (c == WSPACE || c == NL || c == WARN);
796
797                 cp = yytext;
798                 while (*cp)
799                         cp++;
800                 while ((char *)cp > yytext)
801                         cunput(*--cp);
802 if (dflag)printf("c %d\n"c);
803                 if (c == '(' ) {
804                         expdef(vp, &rp2gotwarn);
805                         return rv;
806                 } else {
807                         /* restore identifier */
808 noid:                   while (gotwarn--)
809                                 cunput(WARN);
810                         cunput(' ');
811                         cp = sp->namep;
812                         while (*cp)
813                                 cp++;
814                         while (cp > sp->namep)
815                                 cunput(*--cp);
816                         if ((c = yylex()) != IDENT)
817                                 error("internal sync error");
818                         return 0;
819                 }
820         } else {
821                 cunput(WARN);
822                 cp = vp;
823                 while (*cp) {
824                         if (*cp != CONC)
825                                 cunput(*cp);
826                         cp--;
827                 }
828                 expmac(&rp2);
829         }
830         return 1;
831 }
832
833 /*
834  * do macro-expansion until WARN character read.
835  * will recurse into lookup() for recursive expansion.
836  * when returning all expansions on the token list is done.
837  */
838 void
839 expmac(struct recur *rp)
840 {
841         struct symtab *nl;
ragge
1.2
842         int cnoexp = 0gotspc;
ragge
1.4
843         usch *och;
ragge
1.1
844
845 if (dflag)printf("expmac\n");
846 if (dflag && rp)printf("do not expand %s\n"rp->sp->namep);
847         while ((c = yylex()) != WARN) {
848                 switch (c) {
849                 case NOEXPnoexp++; break;
850                 case EXPANDnoexp--; break;
851
852                 case IDENT:
ragge
1.4
853                         /* workaround if an arg will be concatenated */
854                         och = stringbuf;
855                         savstr(yytext);
856                         savch('\0');
857 //printf("id: str %s\n", och);
858                         if ((c = yylex()) == EXPAND) {
859 //printf("funnet expand\n");
860                                 if ((c = yylex()) == NOEXP) {
861 //printf("funnet noexp\n");
862                                         if ((c = yylex()) == IDENT) {
863 //printf("funnet ident %s%s\n", och, yytext);
864                                                 stringbuf--;
865                                                 savstr(yytext);
866                                                 savch('\0');
867                                                 cunput(NOEXP);
868                                                 unpstr(och);
869                                                 noexp--;
870                                                 stringbuf = och;
871                                                 continue;
872                                         } else {
873 //printf("ofunnet ident\n");
874                                                 unpstr(yytext);
875                                                 unpstr(och);
876                                                 stringbuf = och;
877                                                 continue;
878                                         }
879                                 } else {
880 //printf("ofunnet inoexp\n");
881                                         unpstr(yytext);
882                                         cunput(EXPAND);
883                                         unpstr(och);
884                                         yylex();
885                                 }
886                         } else {
887                                 unpstr(yytext);
888                                 unpstr(och);
889                                 yylex();
890 //printf("ofunnet expand: yytext %s\n", yytext);
891                         }
892                         stringbuf = och;
893
ragge
1.1
894                         if ((nl = lookup(yytextFIND)) == NULL)
895                                 goto def;
ragge
1.4
896
ragge
1.1
897                         if (canexpand(rpnl) == 0)
898                                 goto def;
899                         if (noexp == 0) {
900                                 if ((c = subst(nl->namepnlrp)) == 0)
901                                         goto def;
902                                 break;
903                         }
904                         if (noexp != 1)
905                                 error("bad noexp %d"noexp);
ragge
1.2
906                         gotspc = 0;
ragge
1.1
907                         if ((c = yylex()) == WSPACE)
ragge
1.2
908                                 gotspc = 1c = yylex();
ragge
1.1
909                         if (c == EXPAND) {
910                                 noexp--;
911                                 if (subst(nl->namepnlrp))
912                                         break;
913                                 savstr(nl->namep);
ragge
1.2
914                                 if (gotspc)
915                                         savch(' ');
ragge
1.1
916                         } else {
917                                 unpstr(yytext);
ragge
1.2
918                                 if (gotspc)
919                                         cunput(' ');
ragge
1.1
920                                 savstr(nl->namep);
921                         }
922                         break;
923
924 def:            default:
925                         savstr(yytext);
926                         break;
927                 }
928         }
929 if (dflag)printf("return from expmac\n");
930 }
931
932 /*
933  * expand a function-like macro.
934  * vp points to end of replacement-list
935  * reads function arguments from yylex()
936  * result is written on top of heap
937  */
938 void
939 expdef(vprpgotwarn)
940         usch *vp;
941         struct recur *rp;
942 {
ragge
1.6
943         usch **args, *sptr, *ap, *bp, *sp;
ragge
1.5
944         int nargciplevsnuffinstr;
ragge
1.1
945
946 if (dflag)printf("expdef %s rp %s\n"vp, (rp ? (char *)rp->sp->namep : ""));
947         if ((c = yylex()) != '(')
948                 error("got %c, expected )"c);
949         narg = vp[1];
950         args = alloca(sizeof(usch *) * narg);
951
952
953         /*
954          * read arguments and store them on heap.
955          * will be removed just before return from this function.
956          */
ragge
1.6
957         sptr = stringbuf;
ragge
1.1
958         for (i = 0i < narg && c != ')'i++) {
959                 args[i] = stringbuf;
960                 plev = 0;
ragge
1.2
961                 if ((c = yylex()) == WSPACE)
962                         c = yylex();
ragge
1.1
963                 for (;;) {
964                         if (plev == 0 && (c == ')' || c == ','))
965                                 break;
966                         if (c == '(')
967                                 plev++;
968                         if (c == ')')
969                                 plev--;
970                         savstr(yytext);
ragge
1.2
971                         c = yylex();
ragge
1.1
972                 }
ragge
1.2
973                 while (args[i] < stringbuf &&
974                     (stringbuf[-1] == ' ' || stringbuf[-1] == '\t'))
975                         stringbuf--;
ragge
1.1
976                 savch('\0');
977         }
978         if (narg == 0)
979                 c = yylex();
980         if (c != ')' || i != narg)
981                 error("wrong arg count");
982
983         while (gotwarn--)
984                 cunput(WARN);
985
986 #ifdef CPP_DEBUG
987         if (dflag) {
988
989         }
990 #endif
991         sp = vp;
ragge
1.5
992         instr = snuff = 0;
ragge
1.1
993
994         /*
995          * push-back replacement-list onto lex buffer while replacing
996          * arguments. 
997          */
998         cunput(WARN);
999         while (*sp != 0) {
1000                 if (*sp == SNUFF)
1001                         cunput('\"'), snuff ^= 1;
1002                 else if (*sp == CONC)
1003                         ;
1004                 else if (*sp == WARN) {
1005
1006                         bp = ap = args[(int)*--sp];
1007                         if (sp[2] != CONC && !snuff && sp[-1] != CONC) {
1008                                 cunput(WARN);
1009                                 while (*bp)
1010                                         bp++;
1011                                 while (bp > ap)
1012                                         cunput(*--bp);
1013 if (dflagprintf("expand arg %d string %s\n", *spap);
1014                                 bp = ap = stringbuf;
1015                                 savch(NOEXP);
1016                                 expmac(NULL);
1017                                 savch(EXPAND);
1018                                 savch('\0');
1019                         }
1020                         while (*bp)
1021                                 bp++;
1022                         while (bp > ap) {
ragge
1.6
1023                                 bp--;
1024 //printf("*bp %d\n", *bp);
1025                                 if (snuff && !instr && 
1026                                     (*bp == ' ' || *bp == '\t' || *bp == '\n')){
1027                                         while (*bp == ' ' || *bp == '\t' ||
1028                                             *bp == '\n') {
1029                                                 if (*bp == '\n')
1030                                                         putc('\n'obuf);
1031                                                 bp--;
1032                                         }
1033                                         cunput(' ');
1034                                 }
1035                                 cunput(*bp);
1036                                 if ((*bp == '\'' || *bp == '"')
1037                                      && bp[-1] != '\\' && snuff) {
ragge
1.5
1038                                         instr ^= 1;
ragge
1.6
1039                                         if (instr == 0 && *bp == '"')
ragge
1.5
1040                                                 cunput('\\');
1041                                 }
1042                                 if (instr && (*bp == '\\' || *bp == '"'))
ragge
1.1
1043                                         cunput('\\');
1044                         }
ragge
1.4
1045                 } else
ragge
1.1
1046                         cunput(*sp);
1047                 sp--;
1048         }
ragge
1.6
1049         stringbuf = sptr;
ragge
1.1
1050
1051         /* scan the input buffer (until WARN) and save result on heap */
1052         expmac(rp);
1053 }
1054
1055 usch *
1056 savstr(usch *str)
1057 {
1058         char *rv = stringbuf;
1059
1060         while ((*stringbuf++ = *str++))
1061                 if (stringbuf >= &sbf[SBSIZE])
1062                         error("out of macro space!");
1063         stringbuf--;
1064         return rv;
1065 }
1066
1067 int
1068 canexpand(struct recur *rpstruct symtab *np)
1069 {
1070         struct recur *w;
1071
1072         for (w = rpw && w->sp != npw = w->next)
1073                 ;
1074         if (w != NULL)
1075                 return 0;
1076         return 1;
1077 }
1078
1079 void
1080 unpstr(usch *c)
1081 {
1082         usch *d = c;
1083
1084         while (*d)
1085                 d++;
1086         while (d > c) {
1087                 cunput(*--d);
1088         }
1089 }
FishEye: Open Source License registered to PCC.
Your maintenance has expired. You can renew your license at http://www.atlassian.com/fisheye/renew
Atlassian FishEye, CVS analysis. (Version:1.6.3 Build:build-336 2008-11-04) - Administration - Page generated 2014-09-02 20:58 +0200