Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20040822145925

Diff

Diff from 1.7 to:

Annotations

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

Annotated File View

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