Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20040821095846

Diff

Diff from 1.1 to:

Annotations

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

Annotated File View

ragge
1.1
1 /*      $Id: cpp.c,v 1.1 2004/08/21 09:58:46 ragge Exp $        */
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;
200         register int c;
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                         }
256                         if ((c = yylex()) == WSPACE)
257                                 c = yylex();
258                         if (c != EXPAND) {
259                                 unpstr(yytext);
260                                 cunput(' ');
261                                 unpstr(nl->namep);
262                                 (void)yylex(); /* get yytext correct */
263                                 nl = 0/* ignore */
264                         } else
265                                 thisnl = NULL;
266
267 found:                  if (nl == 0 || subst(yytextnlNULL) == 0) {
268                                 fputs(yytextobuf);
269                         } else if (osp != stringbuf) {
270                                 cunput(EXPAND);
271                                 while (stringbuf > osp)
272                                         cunput(*--stringbuf);
273                                 thisnl = nl;
274                         }
275                         stringbuf = osp/* clean up heap */
276                         break;
277
278                 case EXPAND:
279                         thisnl = NULL;
280                         break;
281
282                 case CHARCON:
283                 case NUMBER:
284                 case FPOINT:
285                 case STRING:
286                 case WSPACE:
287                 case NL:
288                         fputs(yytextobuf);
289                         break;
290
291                 default:
292                         putc(cobuf);
293                         break;
294                 }
295         }
296         fclose(obuf);
297 }
298
299 /*
300  * do something when a '#' is found.
301  */
302 void
303 control()
304 {
305         struct symtab *np;
306         int t;
307
308         if ((t = yylex()) == WSPACE)
309                 t = yylex();
310         if (t != IDENT)
311                 return error("bad control '%s'"yytext);
312
313         np = lookup(yytextFIND);
314         if (np == 0)
315                 return/* ignore empty controls */
316         if (np == incloc) {
317                 if (flslvl)
318                         goto exit;
319                 if (yylex() != WSPACE || yylex() != STRING)
320                         return error("bad include");
321                 yytext[strlen(yytext)-1] = 0;
322                 pushfile(&yytext[1]);
323                 return;
324         } else if (np == elsloc) {
325                 if (flslvl) {
326                         if (--flslvl!=0)
327                                 flslvl++;
328                         else
329                                 trulvl++;
330                 } else if (trulvl) {
331                         flslvl++;
332                         trulvl--;
333                 } else
334                         error("If-less else");
335         } else {
336                 if (yylex() != WSPACE || yylex() != IDENT)
337                         return error("bad control2");
338                 
339                 if (np == defloc) {
340                         define();
341                         return;
342                 } else if (np == ifdloc) {
343                         if (flslvl == 0 && lookup(yytextFIND) != 0)
344                                 trulvl++;
345                         else
346                                 flslvl++;
347                 } else if (np == ifnloc) {
348                         if (flslvl == 0 && lookup(yytextFIND) == 0)
349                                 trulvl++;
350                         else
351                                 flslvl++;
352                 } else if (np == eifloc) {
353                         if (flslvl)
354                                 flslvl--;
355                         else if (trulvl)
356                                 trulvl--;
357                         else
358                                 error("If-less endif");
359                 } else if (np == undloc) {
360                         if (flslvl == 0 && (np = lookup(yytextFIND)))
361                                 np->value = 0;
362                 } else if (np == elfloc) {
363
364                 } else if (np == ifloc) {
365
366                 } else
367                         error("undefined control '%s'"np->namep);
368         }
369
370 exit:
371         while (yylex() != NL)
372                 ;
373 }
374
375 void
376 define()
377 {
378         struct symtab *np;
379         usch *args[MAXARG], *obuf;
380         int ci;
381         int mkstr = 0narg = -1;
382
383         np = lookup(yytextENTER);
384
385         if ((c = yylex()) == '(') {
386                 narg = 0;
387                 /* function-like macros, deal with identifiers */
388                 while ((c = yylex()) != ')') {
389                         if (c == WSPACEc = yylex();
390                         if (c == ','c = yylex();
391                         if (c == WSPACEc = yylex();
392                         if (c == ')')
393                                 break;
394                                 if (c != IDENT)
395                         error("define error");
396                         args[narg] = alloca(strlen(yytext)+1);
397                         strcpy(args[narg], yytext);
398                         narg++;
399                 }
400         } else if (c != WSPACE)
401                 error("bad define");
402
403         if ((c = yylex()) == WSPACE)
404                 c = yylex();
405
406         /* parse replacement-list, substituting arguments */
407         savch('\0');
408         while (c != NL) {
409                 switch (c) {
410                 case WSPACE:
411                         /* remove spaces if it surrounds a ## directive */
412                         obuf = stringbuf;
413                         savstr(yytext);
414                         c = yylex();
415                         if (c == CONCAT) {
416                                 stringbuf = obuf;
417                                 savch(CONC);
418                                 if ((c = yylex()) == WSPACE)
419                                         c = yylex();
420                         }
421                         continue;
422
423                 case CONCAT:
424                         /* No spaces before concat op */
425                         savch(CONC);
426                         if ((c = yylex()) == WSPACE)
427                                 c = yylex();
428                         continue;
429
430                 case MKSTR:
431                         if (narg < 0) {
432                                 /* no meaning in object-type macro */
433                                 savch('#');
434                                 break;
435                         }
436                         /* remove spaces between # and arg */
437                         savch(SNUFF);
438                         if ((c = yylex()) == WSPACE)
439                                 c = yylex(); /* whitespace, ignore */
440                         mkstr = 1;
441
442                         /* FALLTHROUGH */
443                 case IDENT:
444                         if (narg < 0)
445                                 goto id/* just add it if object */
446                         /* check if its an argument */
447                         for (i = 0i < nargi++)
448                                 if (strcmp(yytextargs[i]) == 0)
449                                         break;
450                         if (i == narg) {
451                                 if (mkstr)
452                                         error("not argument");
453                                 goto id;
454                         }
455                         savch(i);
456                         savch(WARN);
457                         if (mkstr)
458                                 savch(SNUFF), mkstr = 0;
459                         break;
460
461                 default:
462 id:                     savstr(yytext);
463                         break;
464                 }
465                 c = yylex();
466         }
467         savch(narg < 0 ? OBJCT : narg);
468         np->value = stringbuf-1;
469
470 #ifdef CPP_DEBUG
471         if (dflag) {
472                 usch *w = np->value;
473
474                 printf("!define: ");
475                 if (*w == OBJCT)
476                         printf("[object]");
477                 else
478                         printf("[%d]", *w);
479                 while (*--w) {
480                         switch (*w) {
481                         case WARNprintf("<%d>", *--w); break;
482                         case CONCprintf("<##>"); break;
483                         case SNUFFprintf("<\">"); break;
484                         defaultputchar(*w); break;
485                         }
486                 }
487                 putchar('\n');
488         }
489 #endif
490 }
491
492 void
493 insym(spnamep)
494 struct symtab **sp;
495 char *namep;
496 {
497         register struct symtab *np;
498
499         *sp = np = lookup(namepENTER);
500         np->value = np->namep/* XXX */
501 }
502
503 void
504 error(char *s, ...)
505 {
506         va_list ap;
507
508         va_start(aps);
509         fprintf(stderr"%s:%d: "curfile(), curline());
510         vfprintf(stderrsap);
511         fputc('\n'stderr);
512         exfail++;
513         va_end(ap);
514         exit(8);
515 }
516
517 /*
518  * store a character into the "define" buffer.
519  */
520 void
521 savch(c)
522 {
523         *stringbuf++ = c;
524         if (stringbuf-sbf < SBSIZE)
525                 return;
526         error("Too much defining");
527         exit(1);
528 }
529
530 /*
531  * Do a symbol lookup.
532  * If enterf == FIND, only lookup.
533  */
534 struct symtab *
535 lookup(namepenterf)
536         char *namep;
537 {
538         register char *np;
539         register struct symtab *sp;
540         int icaround;
541
542 if (dflag)printf("lookup\n");
543         np = namep;
544         around = i = 0;
545         while ((c = *np++))
546                 i =+ c;
547         i %= SYMSIZ;
548         sp = &symtab[i];
549
550         while (sp->namep) {
551                 if (*sp->namep == *namep && strcmp(sp->namepnamep) == 0)
552                         return(sp);
553                 if (++sp >= &symtab[SYMSIZ]) {
554                         if (around++)
555                                 error("too many defines");
556                         else
557                                 sp = symtab;
558                 }
559         }
560         if (enterf == ENTER)
561                 sp->namep = savstr(namep), savch('\0');
562         return(sp->namep ? sp : 0);
563 }
564
565 /*
566  * substitute namep for sp->value.
567  */
568 int
569 subst(npsprp)
570 char *np;
571 struct symtab *sp;
572 struct recur *rp;
573 {
574         struct recur rp2;
575         register usch *vp, *cp;
576         int crv = 0;
577
578 if (dflag)printf("subst\n");
579         if ((vp = sp->value) == 0)
580                 return 0;
581         if (sp == filloc) {
582                 fprintf(obuf"\"%s\""curfile());
583                 return 1;
584         } else if (sp == linloc) {
585                 fprintf(obuf"%d"curline());
586                 return 1;
587         }
588
589         rp2.next = rp;
590         rp2.sp = sp;
591
592         if (*vp-- != OBJCT) {
593                 int gotwarn = 0;
594
595                 /* should we be here at all? */
596                 /* check if identifier is followed by parentheses */
597                 rv = 1;
598                 do {
599                         if ((c = yylex()) == NL)
600                                 putc('\n'obuf);
601                         if (c == WARN) {
602                                 gotwarn++;
603                                 if (rp == NULL)
604                                         goto noid;
605                         }
606                 } while (c == WSPACE || c == NL || c == WARN);
607
608                 cp = yytext;
609                 while (*cp)
610                         cp++;
611                 while ((char *)cp > yytext)
612                         cunput(*--cp);
613 if (dflag)printf("c %d\n"c);
614                 if (c == '(' ) {
615                         expdef(vp, &rp2gotwarn);
616                         return rv;
617                 } else {
618                         /* restore identifier */
619 noid:                   while (gotwarn--)
620                                 cunput(WARN);
621                         cunput(' ');
622                         cp = sp->namep;
623                         while (*cp)
624                                 cp++;
625                         while (cp > sp->namep)
626                                 cunput(*--cp);
627                         if ((c = yylex()) != IDENT)
628                                 error("internal sync error");
629                         return 0;
630                 }
631         } else {
632                 cunput(WARN);
633                 cp = vp;
634                 while (*cp) {
635                         if (*cp != CONC)
636                                 cunput(*cp);
637                         cp--;
638                 }
639                 expmac(&rp2);
640         }
641         return 1;
642 }
643
644 /*
645  * do macro-expansion until WARN character read.
646  * will recurse into lookup() for recursive expansion.
647  * when returning all expansions on the token list is done.
648  */
649 void
650 expmac(struct recur *rp)
651 {
652         struct symtab *nl;
653         int cnoexp = 0;
654
655 if (dflag)printf("expmac\n");
656 if (dflag && rp)printf("do not expand %s\n"rp->sp->namep);
657         while ((c = yylex()) != WARN) {
658                 switch (c) {
659                 case NOEXPnoexp++; break;
660                 case EXPANDnoexp--; break;
661
662                 case IDENT:
663                         if ((nl = lookup(yytextFIND)) == NULL)
664                                 goto def;
665                         if (canexpand(rpnl) == 0)
666                                 goto def;
667                         if (noexp == 0) {
668                                 if ((c = subst(nl->namepnlrp)) == 0)
669                                         goto def;
670                                 break;
671                         }
672                         if (noexp != 1)
673                                 error("bad noexp %d"noexp);
674                         if ((c = yylex()) == WSPACE)
675                                 c = yylex();
676                         if (c == EXPAND) {
677                                 noexp--;
678                                 if (subst(nl->namepnlrp))
679                                         break;
680                                 savstr(nl->namep);
681                                 savch(' ');
682                         } else {
683                                 unpstr(yytext);
684                                 cunput(' ');
685                                 savstr(nl->namep);
686                         }
687                         break;
688
689 def:            default:
690                         savstr(yytext);
691                         break;
692                 }
693         }
694 if (dflag)printf("return from expmac\n");
695 }
696
697 /*
698  * expand a function-like macro.
699  * vp points to end of replacement-list
700  * reads function arguments from yylex()
701  * result is written on top of heap
702  */
703 void
704 expdef(vprpgotwarn)
705         usch *vp;
706         struct recur *rp;
707 {
708         usch **args, *obuf, *ap, *bp, *sp;
709         int nargciplevinstrsnuff;
710
711 if (dflag)printf("expdef %s rp %s\n"vp, (rp ? (char *)rp->sp->namep : ""));
712         if ((c = yylex()) != '(')
713                 error("got %c, expected )"c);
714         narg = vp[1];
715         args = alloca(sizeof(usch *) * narg);
716
717
718         /*
719          * read arguments and store them on heap.
720          * will be removed just before return from this function.
721          */
722         obuf = stringbuf;
723         for (i = 0i < narg && c != ')'i++) {
724                 args[i] = stringbuf;
725                 plev = 0;
726                 for (;;) {
727                         c = yylex();
728                         if (plev == 0 && (c == ')' || c == ','))
729                                 break;
730                         if (c == '(')
731                                 plev++;
732                         if (c == ')')
733                                 plev--;
734                         savstr(yytext);
735                 }
736                 savch('\0');
737         }
738         if (narg == 0)
739                 c = yylex();
740         if (c != ')' || i != narg)
741                 error("wrong arg count");
742
743         while (gotwarn--)
744                 cunput(WARN);
745
746 #ifdef CPP_DEBUG
747         if (dflag) {
748
749         }
750 #endif
751         sp = vp;
752         instr = snuff = 0;
753
754         /*
755          * push-back replacement-list onto lex buffer while replacing
756          * arguments. 
757          */
758         cunput(WARN);
759         while (*sp != 0) {
760                 if (*sp == SNUFF)
761                         cunput('\"'), snuff ^= 1;
762                 else if (*sp == CONC)
763                         ;
764                 else if (*sp == WARN) {
765
766                         bp = ap = args[(int)*--sp];
767                         if (sp[2] != CONC && !snuff && sp[-1] != CONC) {
768                                 cunput(WARN);
769                                 while (*bp)
770                                         bp++;
771                                 while (bp > ap)
772                                         cunput(*--bp);
773 if (dflagprintf("expand arg %d string %s\n", *spap);
774                                 bp = ap = stringbuf;
775                                 savch(NOEXP);
776                                 expmac(NULL);
777                                 savch(EXPAND);
778                                 savch('\0');
779                         }
780                         while (*bp)
781                                 bp++;
782                         while (bp > ap) {
783                                 cunput(*--bp);
784                                 if (snuff && (*bp == '\\' || *bp == '"'))
785                                         cunput('\\');
786                         }
787                 } else {
788                         cunput(*sp);
789                         if (instr && (*sp == '"' || *sp == '\\'))
790                                         cunput('\\');
791                 }
792                 sp--;
793         }
794         stringbuf = obuf;
795
796         /* scan the input buffer (until WARN) and save result on heap */
797         expmac(rp);
798 }
799
800 usch *
801 savstr(usch *str)
802 {
803         char *rv = stringbuf;
804
805         while ((*stringbuf++ = *str++))
806                 if (stringbuf >= &sbf[SBSIZE])
807                         error("out of macro space!");
808         stringbuf--;
809         return rv;
810 }
811
812 int
813 canexpand(struct recur *rpstruct symtab *np)
814 {
815         struct recur *w;
816
817         for (w = rpw && w->sp != npw = w->next)
818                 ;
819         if (w != NULL)
820                 return 0;
821         return 1;
822 }
823
824 void
825 unpstr(usch *c)
826 {
827         usch *d = c;
828
829         while (*d)
830                 d++;
831         while (d > c) {
832                 cunput(*--d);
833         }
834 }
FishEye: Open Source License registered to PCC.
Your maintenance has expired. You can renew your license at http://www.atlassian.com/fisheye/renew
Atlassian FishEye, CVS analysis. (Version:1.6.3 Build:build-336 2008-11-04) - Administration - Page generated 2014-09-03 09:05 +0200