Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20040821124805

Diff

Diff from 1.2 to:

Annotations

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

Annotated File View

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