Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20040826162445

Diff

Diff from 1.9 to:

Annotations

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

Annotated File View

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