Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20040823065413

Diff

Diff from 1.8 to:

Annotations

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

Annotated File View

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