Annotation of OpenXM_contrib2/asir2000/parse/cpp.c, Revision 1.3
1.2 noro 1: /*
2: * Copyright (c) 1994-2000 FUJITSU LABORATORIES LIMITED
3: * All rights reserved.
4: *
5: * FUJITSU LABORATORIES LIMITED ("FLL") hereby grants you a limited,
6: * non-exclusive and royalty-free license to use, copy, modify and
7: * redistribute, solely for non-commercial and non-profit purposes, the
8: * computer program, "Risa/Asir" ("SOFTWARE"), subject to the terms and
9: * conditions of this Agreement. For the avoidance of doubt, you acquire
10: * only a limited right to use the SOFTWARE hereunder, and FLL or any
11: * third party developer retains all rights, including but not limited to
12: * copyrights, in and to the SOFTWARE.
13: *
14: * (1) FLL does not grant you a license in any way for commercial
15: * purposes. You may use the SOFTWARE only for non-commercial and
16: * non-profit purposes only, such as academic, research and internal
17: * business use.
18: * (2) The SOFTWARE is protected by the Copyright Law of Japan and
19: * international copyright treaties. If you make copies of the SOFTWARE,
20: * with or without modification, as permitted hereunder, you shall affix
21: * to all such copies of the SOFTWARE the above copyright notice.
22: * (3) An explicit reference to this SOFTWARE and its copyright owner
23: * shall be made on your publication or presentation in any form of the
24: * results obtained by use of the SOFTWARE.
25: * (4) In the event that you modify the SOFTWARE, you shall notify FLL by
1.3 ! noro 26: * e-mail at risa-admin@sec.flab.fujitsu.co.jp of the detailed specification
1.2 noro 27: * for such modification or the source code of the modified part of the
28: * SOFTWARE.
29: *
30: * THE SOFTWARE IS PROVIDED AS IS WITHOUT ANY WARRANTY OF ANY KIND. FLL
31: * MAKES ABSOLUTELY NO WARRANTIES, EXPRESSED, IMPLIED OR STATUTORY, AND
32: * EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS
33: * FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT OF THIRD PARTIES'
34: * RIGHTS. NO FLL DEALER, AGENT, EMPLOYEES IS AUTHORIZED TO MAKE ANY
35: * MODIFICATIONS, EXTENSIONS, OR ADDITIONS TO THIS WARRANTY.
36: * UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, TORT, CONTRACT,
37: * OR OTHERWISE, SHALL FLL BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY
38: * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, PUNITIVE OR CONSEQUENTIAL
39: * DAMAGES OF ANY CHARACTER, INCLUDING, WITHOUT LIMITATION, DAMAGES
40: * ARISING OUT OF OR RELATING TO THE SOFTWARE OR THIS AGREEMENT, DAMAGES
41: * FOR LOSS OF GOODWILL, WORK STOPPAGE, OR LOSS OF DATA, OR FOR ANY
42: * DAMAGES, EVEN IF FLL SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF
43: * SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. EVEN IF A PART
44: * OF THE SOFTWARE HAS BEEN DEVELOPED BY A THIRD PARTY, THE THIRD PARTY
45: * DEVELOPER SHALL HAVE NO LIABILITY IN CONNECTION WITH THE USE,
46: * PERFORMANCE OR NON-PERFORMANCE OF THE SOFTWARE.
47: *
1.3 ! noro 48: * $OpenXM: OpenXM_contrib2/asir2000/parse/cpp.c,v 1.2 2000/08/21 08:31:46 noro Exp $
1.2 noro 49: */
1.1 noro 50: #if defined(__MWERKS__)
51: #define THINK_C
52: #endif
53:
54: #include <stdio.h>
55: #include <ctype.h>
56: #include <setjmp.h>
57: jmp_buf cpp_env;
58:
59: #if 0
60: #include "accum.h"
61: #include "expr.h"
62: #include "if.h"
63: #include "io.h"
64: #include "is.h"
65: #include "malloc.h"
66: #include "stats.h"
67: #include "symtbl.h"
68: #include "unctrl.h"
69: #endif
70:
71: #if defined(THINK_C)
72: #include <string.h>
73:
74: int define(char *,int,unsigned char *,int);
75: void Bcopy(char *,char *,int);
76: #endif
77:
78:
79: #include "cpp.h"
80:
81: char *init_accum(void)
82: {
83: ACCUM *a;
84:
85: a = NEW(ACCUM);
86: check_malloc(a);
87: a->used = 0;
88: a->have = 8;
89: a->buf = malloc(8);
90: check_malloc(a->buf);
91: return((char *)a);
92: }
93:
94: void accum_char(char *A, char c)
95:
96: #define a ((ACCUM *)A)
97:
98: {
99: while (a->used >= a->have)
100: { a->buf = realloc(a->buf,a->have+=8);
101: check_malloc(a->buf);
102: }
103: a->buf[a->used++] = c;
104: }
105: #undef a
106:
107: char accum_regret(char *A)
108:
109: #define a ((ACCUM *)A)
110: {
111: if (a->used > 0)
112: { return(a->buf[--a->used]);
113: }
114: else
115: { return(0);
116: }
117: }
118: #undef a
119:
120: char *accum_result(char *A)
121:
122: #define a ((ACCUM *)A)
123: {
124: char *cp;
125:
126: cp = realloc(a->buf,a->used+1);
127: check_malloc(cp);
128: cp[a->used] = '\0';
129: OLD(a);
130: return(cp);
131: }
132: #undef a
133:
134: char *accum_sofar(char *A)
135:
136: #define a ((ACCUM *)A)
137: {
138: char *cp;
139:
140: cp = malloc(a->used+1);
141: check_malloc(cp);
142: Bcopy(a->buf,cp,a->used);
143: cp[a->used] = '\0';
144: return(cp);
145: }
146: #undef a
147:
148: char *accum_buf(char *A)
149:
150: #define a ((ACCUM *)A)
151: {
152: return(a->buf);
153: }
154: #undef a
155:
156: int accum_howfar(char *A)
157:
158: #define a ((ACCUM *)A)
159: {
160: return(a->used);
161: }
162: #undef a
163:
164: void do_at(void)
165: {
166: char *w;
167:
168: w = read_ctrl();
169: if (strcmp(w,"include") == 0)
170: { do_include(0);
171: }
172: else if (strcmp(w,"define") == 0)
173: { do_define(0,0);
174: }
175: else if (strcmp(w,"undef") == 0)
176: { do_undef(0);
177: }
178: else if (strcmp(w,"redefine") == 0)
179: { do_define(0,1);
180: }
181: else if (strcmp(w,"ifdef") == 0)
182: { do_ifdef(0);
183: }
184: else if (strcmp(w,"ifndef") == 0)
185: { do_ifndef(0);
186: }
187: else if (strcmp(w,"if") == 0)
188: { do_if(0);
189: }
190: else if (strcmp(w,"else") == 0)
191: { do_else(0);
192: }
193: else if (strcmp(w,"elif") == 0)
194: { do_elif(0);
195: }
196: else if (strcmp(w,"endif") == 0)
197: { do_endif(0);
198: }
199: else if (strcmp(w,"set") == 0)
200: { do_set();
201: }
202: else if (strcmp(w,"while") == 0)
203: { do_while();
204: }
205: else if (strcmp(w,"endwhile") == 0)
206: { do_endwhile();
207: }
208: else if (strcmp(w,"dump") == 0)
209: { do_dump();
210: }
211: else if (strcmp(w,"debug") == 0)
212: { do_debug();
213: }
214: else if (strcmp(w,"eval") == 0)
215: { do_eval();
216: }
217: else
218: { if (! in_false_if())
219: { err_head();
220: fprintf(stderr,"unknown control `%s'\n",w);
221: }
222: }
223: free(w);
224: }
225:
226: static char *temp;
227:
228: void autodef_file(char *f)
229: {
230: int i;
231:
232: i = strlen(f);
233: temp = malloc(i+2+1);
234: check_malloc(temp);
235: sprintf(temp,"\"%s\"",f);
236: undef("__FILE__");
237: define("__FILE__",-1,(unsigned char *)temp,0);
238: }
239:
240: void autodef_line(int l)
241: {
242: defd("__LINE__",l);
243: }
244:
245: char *copyofstr(char *str)
246: {
247: char *cp;
248:
249: if (str == 0)
250: { return(0);
251: }
252: cp = malloc(strlen(str)+1);
253: if (cp == 0)
254: { return(0);
255: }
256: strcpy(cp,str);
257: return(cp);
258: }
259:
260: char *copyofblk(char *blk, int len)
261: {
262: char *cp;
263:
264: if (blk == 0)
265: { return(0);
266: }
267: cp = malloc(len);
268: if (cp == 0)
269: { return(0);
270: }
271: Bcopy(blk,cp,len);
272: return(cp);
273: }
274:
275: /* these really don't beint here; they should be in their own file */
276:
277: #if 0
278: char *malloc(nb)
279: #undef malloc
280: int nb;
281: {
282: extern char *malloc();
283:
284: return(malloc(nb?nb:1));
285: }
286:
287: char *realloc(old,nb)
288: #undef realloc
289: char *old;
290: int nb;
291: {
292: extern char *realloc();
293:
294: return(realloc(old,(nb?nb:1)));
295: }
296: #endif
297:
298: static char buf[BUFSIZ];
299:
300: int debugging = 0;
301:
302: void do_debug(void)
303: {
304: char c;
305:
306: fflush(outfile);
307: c = getnonspace();
308: switch (c)
309: { case '1':
310: case 'y':
311: case 'Y':
312: debugging = 1;
313: break;
314: default:
315: debugging = 0;
316: break;
317: }
318: setbuf(outfile,debugging?NULL:buf);
319: }
320:
321: static int nargs;
322: static int nfound;
323: static char **argnames;
324:
325: void read_formals(void)
326: {
327: char *arg;
328: char c;
329:
330: nargs = 0;
331: argnames = (char **) malloc(1);
332: check_malloc(argnames);
333: while (1)
334: { arg = read_ident();
335: if (arg)
336: { argnames = (char **) realloc((char *)argnames,(nargs+1)*sizeof(char *));
337: check_malloc(argnames);
338: argnames[nargs] = arg;
339: nargs ++;
340: c = getnonspace();
341: if (c == ')')
342: { return;
343: }
344: else if (c != ',')
345: { err_head();
346: fprintf(stderr,"invalid macro parameter delimiter\n");
347: }
348: }
349: else
350: { c = Get();
351: if ((c == ')') && (nargs == 0))
352: { return;
353: }
354: else
355: { Push(c);
356: }
357: err_head();
358: fprintf(stderr,"missing/illegal macro parameter\n");
359: while (1)
360: { c = Get();
361: if (c == ')')
362: { return;
363: }
364: if (isbsymchar(c))
365: { Push(c);
366: break;
367: }
368: }
369: }
370: }
371: }
372:
373: void do_define(int sharp, int redef)
374: {
375: char *mac;
376: char c;
377: char *acc;
378: unsigned char *repl;
379: int quoted;
380: int incomment;
381: unsigned char *f;
382: unsigned char *t;
383: unsigned char *g;
384: int i;
385:
386: if (in_false_if())
387: { char e = '\0';
388: if (sharp)
389: { while (1)
390: { c = e;
391: e = Get();
392: if (e == '\n')
393: { if (c == '\\')
394: { maybe_print('\n');
395: }
396: else
397: { break;
398: }
399: }
400: }
401: }
402: else
403: { do
404: { c = e;
405: e = Get();
406: } while ((c != '@') || (e == '@'));
407: Push(e);
408: }
409: return;
410: }
411: mac = read_ident();
412: if (! mac)
413: { err_head();
414: fprintf(stderr,"missing/illegal macro name\n");
415: flush_sharp_line();
416: return;
417: }
418: c = Get();
419: if (c == '(')
420: { read_formals();
421: nfound = nargs;
422: if (nargs > 128)
423: { err_head();
424: fprintf(stderr,"too many macro formals, more than 128 ignored\n");
425: nargs = 128;
426: }
427: }
428: else
429: { argnames = 0;
430: nargs = -1;
431: nfound = -1;
432: if ((c != ' ') && (c != '\t'))
433: { Push(c);
434: }
435: }
436: quoted = 0;
437: incomment = 0;
438: acc = init_accum();
439: if (sharp)
440: { while (1)
441: { c = Get();
442: if (quoted && (c == '\n'))
443: { quoted = 0;
444: maybe_print('\n');
445: }
446: else if (quoted)
447: { accum_char(acc,'\\');
448: accum_char(acc,c);
449: quoted = 0;
450: }
451: else if (c == '/')
452: { char d = Get();
453: accum_char(acc,'/');
454: if (d == '*')
455: { accum_char(acc,'*');
456: incomment = 1;
457: }
458: else
459: { Push(d);
460: }
461: }
462: else if (incomment)
463: { accum_char(acc,c);
464: if (c == '*')
465: { char d = Get();
466: if (d == '/')
467: { accum_char(acc,'/');
468: incomment = 0;
469: }
470: else
471: { Push(d);
472: }
473: }
474: else if (c == '\n')
475: { maybe_print('\n');
476: }
477: }
478: else if (c == '\\')
479: { quoted = 1;
480: }
481: else if (c == '\n')
482: { break;
483: }
484: else
485: { accum_char(acc,c);
486: }
487: }
488: }
489: else
490: { while (1)
491: { c = Get();
492: if (quoted && (c == '@'))
493: { accum_char(acc,'@');
494: quoted = 0;
495: }
496: else if (quoted)
497: { Push(c);
498: break;
499: }
500: else if (c == '/')
501: { char d = Get();
502: accum_char(acc,'/');
503: if (d == '*')
504: { accum_char(acc,'*');
505: incomment = 1;
506: }
507: else
508: { Push(d);
509: }
510: }
511: else if (incomment)
512: { accum_char(acc,c);
513: if (c == '*')
514: { char d = Get();
515: if (d == '/')
516: { accum_char(acc,'/');
517: incomment = 0;
518: }
519: else
520: { Push(d);
521: }
522: }
523: else if (c == '\n')
524: { maybe_print('\n');
525: }
526: }
527: else if (c == '@')
528: { quoted = 1;
529: }
530: else
531: { if (c == '\n')
532: { maybe_print('\n');
533: }
534: accum_char(acc,c);
535: }
536: }
537: }
538: repl = (unsigned char *) accum_result(acc);
539: f = repl;
540: t = repl;
541: while (*f)
542: { if (isbsymchar(*f) && !incomment)
543: { for (g=f;issymchar(*g);g++) ;
544: c = *g;
545: *g = '\0';
546: for (i=0;i<nargs;i++)
547: { if (strcmp((char *)f,argnames[i]) == 0)
548: { break;
549: }
550: }
551: if (i < nargs)
552: { *t++ = 0x80 | i;
553: f = g;
554: }
555: else
556: { while (*t++ = *f++) ;
557: f --;
558: t --;
559: }
560: *g = c;
561: }
562: else if ((f[0] == '/') && (f[1] == '*'))
563: { f += 2;
564: *t++ = '/';
565: *t++ = '*';
566: incomment = 1;
567: }
568: else if (incomment && (f[0] == '*') && (f[1] == '/'))
569: { f += 2;
570: *t++ = '*';
571: *t++ = '/';
572: incomment = 0;
573: }
574: else
575: { *t++ = *f++;
576: }
577: }
578: *t++ = '\0';
579: repl = (unsigned char *) realloc((char *)repl,t-repl);
580: check_malloc(repl);
581: if (redef)
582: { undef(mac);
583: }
584: n_defines ++;
585: define(mac,nargs,repl,DEF_DEFINE);
586: if (argnames)
587: { for (i=0;i<nfound;i++)
588: { free(argnames[i]);
589: }
590: free((char *)argnames);
591: }
592: free(mac);
593: }
594:
595: void do_dump(void)
596: {
597: int i;
598: DEF *d;
599: extern char *cur_incldir;
600: extern char *incldir[];
601: extern int fstackdepth;
602:
603: fprintf(stderr,
604: "\n\n\tDump of definition table (%d entries in %d buckets):\n\n",
605: n_in_table,symtbl_size);
606: for (i=0;i<symtbl_size;i++)
607: { fprintf(stderr,"Bucket %d:\n",i);
608: for (d=symtbl[i];d;d=d->link)
609: { dump_single(d);
610: putc('\n',stderr);
611: }
612: }
613: fprintf(stderr,"\n\tInclude directory stack:\n\n");
614: for (i=0;i<fstackdepth;i++)
615: { fprintf(stderr,"\t\t%s\n",incldir[i]);
616: }
617: fprintf(stderr,"\t\t%s\n",cur_incldir);
618: }
619:
620: void dump_single(DEF *d)
621: {
622: unsigned char *cp;
623:
624: fprintf(stderr,"\t%s",d->name);
625: if (d->nargs == 0)
626: { fprintf(stderr,"()");
627: }
628: else if (d->nargs > 0)
629: { int i;
630: for (i=0;i<d->nargs;i++)
631: { fprintf(stderr,"%c#%d",i?',':'(',i);
632: }
633: putc(')',stderr);
634: }
635: putc(' ',stderr);
636: for (cp=d->repl;*cp;cp++)
637: { if (*cp & 0x80)
638: { fprintf(stderr,"#%d",(*cp)&~0x80);
639: }
640: else
641: { putc(*cp,stderr);
642: }
643: }
644: }
645:
646: void err_head(void)
647: {
648: fprintf(stderr,"\"%s\", line %d: ",curfile(),curline());
649: }
650:
651: void Check_malloc(char *ptr)
652: {
653: if (ptr == 0)
654: { fprintf(stderr,"out of memory!\n");
655: abort();
656: }
657: }
658:
659: void do_eval(void)
660: {
661: char c;
662: char temp[64];
663: int i;
664:
665: if (! in_false_if())
666: { c = getnonspace();
667: if (c != '(')
668: { err_head();
669: fprintf(stderr,"@eval must have ()s\n");
670: Push(c);
671: return;
672: }
673: sprintf(temp,"%d",eval_expr(0,1));
674: for (i=strlen(temp)-1;i>=0;i--)
675: { Push(temp[i]);
676: }
677: }
678: }
679:
680: #define DEBUG_EXPAND/**/
681:
682: #ifdef DEBUG_EXPAND
683: extern int debugging;
684: #endif
685:
686: extern int keep_comments;
687:
688: static char **actuals;
689: static int *actlens;
690:
691: void read_actuals(DEF *d)
692: {
693: int n;
694: int i;
695: int pc;
696: char c;
697: char last;
698: char quote;
699: int backslash;
700: int comment;
701: char *acc;
702:
703: n = d->nargs;
704: actuals = (char **) malloc(n*sizeof(char *));
705: check_malloc(actuals);
706: actlens = (int *) malloc(n*sizeof(int));
707: check_malloc(actlens);
708: c = getnonspace();
709: if (c != '(')
710: { err_head();
711: if (n == 0)
712: { fprintf(stderr,"missing () on %s\n",d->name);
713: }
714: else
715: { fprintf(stderr,"missing argument%s to %s\n",(n==1)?"":"s",d->name);
716: }
717: for (i=0;i<n;i++)
718: { actuals[i] = copyofstr("");
719: check_malloc(actuals[i]);
720: actlens[i] = 0;
721: }
722: Push(c);
723: return;
724: }
725: if (n == 0)
726: { c = getnonspace();
727: if (c != ')')
728: { err_head();
729: fprintf(stderr,"unwanted argument to %s\n",d->name);
730: Push(c);
731: }
732: return;
733: }
734: i = 0;
735: while (1)
736: { pc = 0;
737: quote = 0;
738: backslash = 0;
739: comment = 0;
740: c = 0;
741: acc = init_accum();
742: while (1)
743: { last = c;
744: c = Get();
745: accum_char(acc,c);
746: if (comment)
747: { if ((last == '*') && (c == '/'))
748: { comment = 0;
749: }
750: }
751: else
752: { if (backslash)
753: { backslash = 0;
754: }
755: else if (quote && (c == quote))
756: { quote = 0;
757: }
758: else if (c == '\\')
759: { backslash = 1;
760: }
761: else if (quote)
762: {
763: }
764: else if ((last == '/') && (c == '*'))
765: { comment = 1;
766: }
767: else if ((c == '\'') || (c == '"'))
768: { quote = c;
769: }
770: else if (c == '(')
771: { pc ++;
772: }
773: else if (c == ')')
774: { if (pc > 0)
775: { pc --;
776: }
777: else
778: { accum_regret(acc);
779: break;
780: }
781: }
782: else if ((c == ',') && (pc == 0))
783: { accum_regret(acc);
784: break;
785: }
786: }
787: }
788: if (i < n)
789: { actuals[i] = accum_result(acc);
790: actlens[i] = strlen(actuals[i]);
791: i ++;
792: }
793: else if (i == n)
794: { err_head();
795: fprintf(stderr,"too many arguments to %s\n",d->name);
796: i ++;
797: }
798: if (c == ')')
799: { break;
800: }
801: }
802: if (i < n)
803: { err_head();
804: fprintf(stderr,"too few arguments to %s\n",d->name);
805: for (;i<n;i++)
806: { actuals[i] = copyofstr("");
807: check_malloc(actuals[i]);
808: actlens[i] = 0;
809: }
810: }
811: }
812:
813: void expand_def(DEF *d)
814: {
815: unsigned char *cp;
816: char *dp;
817: char *ep;
818: char *result;
819: int ok;
820: int incomm;
821: char last;
822:
823: if (d->nargs >= 0)
824: { read_actuals(d);
825: }
826: #ifdef DEBUG_EXPAND
827: if (debugging)
828: { char *cp;
829: outputs("~EXPAND:");
830: outputs(d->name);
831: if (d->nargs == 0)
832: { outputs("()");
833: }
834: else if (d->nargs > 0)
835: { int i;
836: for (i=0;i<d->nargs;i++)
837: { outputc((char)(i?',':'('));
838: outputs(actuals[i]);
839: }
840: outputc(')');
841: }
842: outputs("-->");
843: for (cp=(char *)d->repl;*cp;cp++)
844: { outputs(unctrl(*cp));
845: }
846: outputc('~');
847: }
848: #endif
849: result = init_accum();
850: for (cp=d->repl;*cp;cp++)
851: { if (*cp & 0x80)
852: { char *dp;
853: int i;
854: i = *cp & ~0x80;
855: for (dp=actuals[i];*dp;dp++)
856: { accum_char(result,*dp);
857: }
858: }
859: else
860: { accum_char(result,*cp);
861: }
862: }
863: dp = accum_result(result);
864: #ifdef DEBUG_EXPAND
865: if (debugging)
866: { outputs("first:");
867: for (ep=dp;*ep;ep++)
868: { outputs(unctrl(*ep));
869: }
870: outputc('~');
871: }
872: #endif
873: result = init_accum();
874: last = '\0';
875: ok = 1;
876: incomm = 0;
877: for (ep=dp;*ep;ep++)
878: { if (!incomm && (last == '/') && (*ep == '*'))
879: { incomm = 1;
880: if (!keep_comments || (strncmp(ep,"**/",3) == 0))
881: { accum_regret(result);
882: ok = 0;
883: }
884: }
885: if (ok)
886: { accum_char(result,*ep);
887: }
888: if ((last == '*') && (*ep == '/'))
889: { incomm = 0;
890: ok = 1;
891: }
892: last = *ep;
893: }
894: free(dp);
895: result = accum_result(result);
896: #ifdef DEBUG_EXPAND
897: if (debugging)
898: { outputs("/**/strip:");
899: outputs(result);
900: outputc('~');
901: }
902: #endif
903: for (dp=result+strlen(result)-1;dp>=result;dp--)
904: { Push(*dp);
905: }
906: free(result);
907: if (d->nargs >= 0)
908: { int i;
909: for (i=0;i<d->nargs;i++)
910: { free(actuals[i]);
911: }
912: free((char *)actuals);
913: }
914: }
915:
916: #define DEBUG_EXPR/**/
917:
918: #define TWOCHAR(c1,c2) (((c1)<<8)|(c2))
919: #define LSH TWOCHAR('<','<')
920: #define RSH TWOCHAR('>','>')
921: #define LEQ TWOCHAR('<','=')
922: #define GEQ TWOCHAR('>','=')
923: #define EQL TWOCHAR('=','=')
924: #define NEQ TWOCHAR('!','=')
925: #define AND TWOCHAR('&','&')
926: #define OR TWOCHAR('|','|')
927:
928: #define ALLBINS \
929: BIN('*',*) \
930: BIN('/',/) \
931: BIN('%',%) \
932: BIN('+',+) \
933: BIN(LSH,<<) \
934: BIN(RSH,>>) \
935: BIN('<',<) \
936: BIN('>',>) \
937: BIN(LEQ,<=) \
938: BIN(GEQ,>=) \
939: BIN(EQL,==) \
940: BIN(NEQ,!=) \
941: BIN('&',&) \
942: BIN('^',^) \
943: BIN('|',|) \
944: BIN(AND,&&) \
945: BIN(OR ,||)
946:
947: char *Index(char *s, int c);
948:
949: static NODE *expr;
950: int expr_sharp;
951: #define sharp expr_sharp
952: static int complain;
953:
954: #ifdef DEBUG_EXPR
955: extern int debugging;
956: #endif
957:
958: void free_expr(NODE *n)
959: {
960: switch (n->op)
961: { case 0:
962: break;
963: case '-':
964: if (n->left)
965: { free_expr(n->left);
966: }
967: free_expr(n->right);
968: break;
969: case '!':
970: case '~':
971: free_expr(n->right);
972: break;
973: case 'd':
974: free(n->name);
975: break;
976: default:
977: free_expr(n->left);
978: free_expr(n->right);
979: break;
980: }
981: OLD(n);
982: }
983:
984: int exec_free(NODE *n)
985: {
986: int rv;
987: int l;
988: int r;
989:
990: switch (n->op)
991: { case 0:
992: rv = n->leaf;
993: break;
994: case '-':
995: if (n->left)
996: { rv = exec_free(n->left);
997: }
998: else
999: { rv = 0;
1000: }
1001: rv -= exec_free(n->right);
1002: break;
1003: case '!':
1004: rv = ! exec_free(n->right);
1005: break;
1006: case '~':
1007: rv = ~ exec_free(n->right);
1008: break;
1009: case 'd':
1010: rv = !! find_def(n->name);
1011: free(n->name);
1012: break;
1013: #define BIN(key,op) case key:l=exec_free(n->left);r=exec_free(n->right);rv=l op r;break;
1014: ALLBINS
1015: #undef BIN
1016: }
1017: OLD(n);
1018: return(rv);
1019: }
1020:
1021: int exec_nofree(NODE *n)
1022: {
1023: int rv;
1024:
1025: switch (n->op)
1026: { case 0:
1027: rv = n->leaf;
1028: break;
1029: case '-':
1030: if (n->left)
1031: { rv = exec_nofree(n->left);
1032: }
1033: else
1034: { rv = 0;
1035: }
1036: rv -= exec_nofree(n->right);
1037: break;
1038: case '!':
1039: rv = ! exec_nofree(n->right);
1040: break;
1041: case '~':
1042: rv = ~ exec_nofree(n->right);
1043: break;
1044: case 'd':
1045: rv = !! find_def(n->name);
1046: free(n->name);
1047: break;
1048: #define BIN(key,op) case key:rv=(exec_nofree(n->left)op exec_nofree(n->right));break;
1049: ALLBINS
1050: #undef BIN
1051: }
1052: return(rv);
1053: }
1054:
1055: NODE *newnode(NODE *l, int c, NODE *r)
1056: {
1057: NODE *n;
1058:
1059: n = NEW(NODE);
1060: check_malloc(n);
1061: n->left = l;
1062: n->right = r;
1063: n->op = c;
1064: return(n);
1065: }
1066:
1067: NODE *newleaf(int v)
1068: {
1069: NODE *n;
1070:
1071: n = NEW(NODE);
1072: check_malloc(n);
1073: n->op = 0;
1074: n->left = 0;
1075: n->right = 0;
1076: n->leaf = v;
1077: return(n);
1078: }
1079:
1080: NODE *newname(char *name)
1081: {
1082: NODE *n;
1083:
1084: n = NEW(NODE);
1085: check_malloc(n);
1086: n->op = 'd';
1087: n->name = copyofstr(name);
1088: check_malloc(n->name);
1089: return(n);
1090: }
1091:
1092: int get_quote_char(void)
1093: {
1094: char c;
1095: char d;
1096:
1097: c = Get();
1098: if (c == '\'')
1099: { return(-1);
1100: }
1101: if (c == '\n')
1102: { err_head();
1103: fprintf(stderr,"newline in character constant\n");
1104: return(-1);
1105: }
1106: if (c != '\\')
1107: { return(0xff&(int)c);
1108: }
1109: c = Get();
1110: if ((c >= '0') && (c <= '7'))
1111: { d = c - '0';
1112: c = Get();
1113: if ((c >= '0') && (c <= '7'))
1114: { d = (d << 3) + c - '0';
1115: c = Get();
1116: if ((c >= '0') && (c <= '7'))
1117: { d = (d << 3) + c - '0';
1118: }
1119: else
1120: { Push(c);
1121: }
1122: }
1123: else
1124: { Push(c);
1125: }
1126: return(0xff&(int)d);
1127: }
1128: switch (c)
1129: { case 'n':
1130: return('\n');
1131: break;
1132: case 'r':
1133: return('\r');
1134: break;
1135: case 'e':
1136: return('\033');
1137: break;
1138: case 'f':
1139: return('\f');
1140: break;
1141: case 't':
1142: return('\t');
1143: break;
1144: case 'b':
1145: return('\b');
1146: break;
1147: case 'v':
1148: return('\v');
1149: break;
1150: default:
1151: return(0xff&(int)c);
1152: break;
1153: }
1154: }
1155:
1156: NODE *read_expr_11(void)
1157: {
1158: char c;
1159:
1160: #ifdef DEBUG_EXPR
1161: if (debugging)
1162: { outputs("~E11:");
1163: }
1164: #endif
1165: while (1)
1166: { c = getnhsexpand();
1167: if (c == '(')
1168: { NODE *n;
1169: NODE *read_expr_(void);
1170: #ifdef DEBUG_EXPR
1171: if (debugging)
1172: { outputs("()");
1173: }
1174: #endif
1175: n = read_expr_();
1176: c = getnhsexpand();
1177: if (c != ')')
1178: { err_head();
1179: fprintf(stderr,"expression syntax error -- missing ) supplied\n");
1180: Push(c);
1181: }
1182: #ifdef DEBUG_EXPR
1183: if (debugging)
1184: { outputs("~");
1185: }
1186: #endif
1187: return(n);
1188: }
1189: else if (isdigit(c))
1190: { int base;
1191: static char digits[] = "0123456789abcdefABCDEF";
1192: static char values[] =
1193: "\0\1\2\3\4\5\6\7\10\11\12\13\14\15\16\17\12\13\14\15\16\17";
1194: char *d;
1195: int v;
1196: #ifdef DEBUG_EXPR
1197: if (debugging)
1198: { outputs("N");
1199: }
1200: #endif
1201: base = 10;
1202: if (c == '0')
1203: { base = 8;
1204: c = Get();
1205: if ((c == 'x') || (c == 'X'))
1206: { base = 16;
1207: c = Get();
1208: }
1209: }
1210: v = 0;
1211: while (1)
1212: { d = Index(digits,c);
1213: if (d == 0)
1214: { Push(c);
1215: #ifdef DEBUG_EXPR
1216: if (debugging)
1217: { outputd(v);
1218: outputs("~");
1219: }
1220: #endif
1221: return(newleaf(v));
1222: }
1223: else if (values[d-digits] >= base)
1224: { err_head();
1225: fprintf(stderr,"warning: illegal %sdigit `%c'\n",
1226: (base==16)?"hex ":(base==8)?"octal ":"",c);
1227: }
1228: v = (v * base) + values[d-digits];
1229: c = Get();
1230: }
1231: }
1232: else if (c == '\'')
1233: { int i;
1234: int j;
1235: int n;
1236: i = 0;
1237: n = 0;
1238: while (1)
1239: { j = get_quote_char();
1240: if (j < 0)
1241: { break;
1242: }
1243: i = (i << 8) | j;
1244: n ++;
1245: }
1246: if (n > 4)
1247: { err_head();
1248: fprintf(stderr,"warning: too many characters in character constant\n");
1249: }
1250: return(newleaf(i));
1251: }
1252: else if ((c == '\n') && !sharp)
1253: {
1254: }
1255: else
1256: { char *id;
1257: if (complain)
1258: { err_head();
1259: fprintf(stderr,"expression syntax error -- number expected\n");
1260: }
1261: if (isbsymchar(c))
1262: { Push(c);
1263: id = read_ident();
1264: }
1265: else
1266: { id = 0;
1267: }
1268: #ifdef DEBUG_EXPR
1269: if (debugging)
1270: { outputs("0(");
1271: outputc(c);
1272: outputs(":");
1273: outputs(id?id:"(none)");
1274: outputs(")~");
1275: }
1276: #endif
1277: if (id)
1278: { free(id);
1279: }
1280: return(newleaf(0));
1281: }
1282: }
1283: }
1284:
1285: NODE *read_expr_10(void)
1286: {
1287: char c;
1288: char *w;
1289: NODE *n;
1290:
1291: #ifdef DEBUG_EXPR
1292: if (debugging)
1293: { outputs("~E10:");
1294: }
1295: #endif
1296: while (1)
1297: { c = getnhsexpand();
1298: switch (c)
1299: { case '-':
1300: case '~':
1301: case '!':
1302: #ifdef DEBUG_EXPR
1303: if (debugging)
1304: { outputc(c);
1305: }
1306: #endif
1307: n = read_expr_10();
1308: #ifdef DEBUG_EXPR
1309: if (debugging)
1310: { outputs("~");
1311: }
1312: #endif
1313: return(newnode(0,c,n));
1314: break;
1315: case 'd':
1316: Push(c);
1317: input_mark();
1318: w = read_ident();
1319: if (strcmp(w,"defined") == 0)
1320: { c = getnonspace();
1321: if (c == '(')
1322: { char *id;
1323: id = read_ident();
1324: if (id)
1325: { c = getnonspace();
1326: if (c == ')')
1327: { input_unmark();
1328: #ifdef DEBUG_EXPR
1329: if (debugging)
1330: { outputs("ifdef");
1331: }
1332: #endif
1333: return(newname(id));
1334: }
1335: }
1336: }
1337: else if (isbsymchar(c))
1338: { char *id;
1339: Push(c);
1340: id = read_ident();
1341: if (id)
1342: { input_unmark();
1343: #ifdef DEBUG_EXPR
1344: if (debugging)
1345: { outputs("ifdef");
1346: }
1347: #endif
1348: return(newname(id));
1349: }
1350: }
1351: }
1352: input_recover();
1353: n = read_expr_11();
1354: #ifdef DEBUG_EXPR
1355: if (debugging)
1356: { outputs("~");
1357: }
1358: #endif
1359: return(n);
1360: break;
1361: default:
1362: Push(c);
1363: n = read_expr_11();
1364: #ifdef DEBUG_EXPR
1365: if (debugging)
1366: { outputs("~");
1367: }
1368: #endif
1369: return(n);
1370: break;
1371: }
1372: }
1373: }
1374:
1375: NODE *read_expr_9(void)
1376: {
1377: NODE *l;
1378: NODE *r;
1379: char c;
1380:
1381: #ifdef DEBUG_EXPR
1382: if (debugging)
1383: { outputs("~E9:");
1384: }
1385: #endif
1386: l = read_expr_10();
1387: while (1)
1388: { c = getnhsexpand();
1389: switch (c)
1390: { case '*':
1391: case '/':
1392: case '%':
1393: #ifdef DEBUG_EXPR
1394: if (debugging)
1395: { outputc(c);
1396: }
1397: #endif
1398: r = read_expr_10();
1399: l = newnode(l,c,r);
1400: break;
1401: default:
1402: #ifdef DEBUG_EXPR
1403: if (debugging)
1404: { outputs("~");
1405: }
1406: #endif
1407: Push(c);
1408: return(l);
1409: break;
1410: }
1411: }
1412: }
1413:
1414: NODE *read_expr_8(void)
1415: {
1416: NODE *l;
1417: NODE *r;
1418: char c;
1419:
1420: #ifdef DEBUG_EXPR
1421: if (debugging)
1422: { outputs("~E8:");
1423: }
1424: #endif
1425: l = read_expr_9();
1426: while (1)
1427: { c = getnhsexpand();
1428: switch (c)
1429: { case '+':
1430: case '-':
1431: #ifdef DEBUG_EXPR
1432: if (debugging)
1433: { outputc(c);
1434: }
1435: #endif
1436: r = read_expr_9();
1437: l = newnode(l,c,r);
1438: break;
1439: default:
1440: #ifdef DEBUG_EXPR
1441: if (debugging)
1442: { outputs("~");
1443: }
1444: #endif
1445: Push(c);
1446: return(l);
1447: break;
1448: }
1449: }
1450: }
1451:
1452: NODE *read_expr_7(void)
1453: {
1454: NODE *l;
1455: NODE *r;
1456: char c;
1457: char d;
1458:
1459: #ifdef DEBUG_EXPR
1460: if (debugging)
1461: { outputs("~E7:");
1462: }
1463: #endif
1464: l = read_expr_8();
1465: while (1)
1466: { c = getnhsexpand();
1467: switch (c)
1468: { case '<':
1469: case '>':
1470: d = Get();
1471: if (d == c)
1472: {
1473: #ifdef DEBUG_EXPR
1474: if (debugging)
1475: { outputc(c);
1476: outputc(d);
1477: }
1478: #endif
1479: r = read_expr_8();
1480: l = newnode(l,(c=='<')?LSH:RSH,r);
1481: break;
1482: }
1483: Push(d);
1484: /* fall through ... */
1485: default:
1486: #ifdef DEBUG_EXPR
1487: if (debugging)
1488: { outputs("~");
1489: }
1490: #endif
1491: Push(c);
1492: return(l);
1493: break;
1494: }
1495: }
1496: }
1497:
1498: NODE *read_expr_6(void)
1499: {
1500: NODE *l;
1501: NODE *r;
1502: char c;
1503: char d;
1504:
1505: #ifdef DEBUG_EXPR
1506: if (debugging)
1507: { outputs("~E6:");
1508: }
1509: #endif
1510: l = read_expr_7();
1511: while (1)
1512: { c = getnhsexpand();
1513: switch (c)
1514: { case '<':
1515: case '>':
1516: d = Get();
1517: if (d == '=')
1518: {
1519: #ifdef DEBUG_EXPR
1520: if (debugging)
1521: { outputc(c);
1522: outputc(d);
1523: }
1524: #endif
1525: r = read_expr_7();
1526: l = newnode(l,(c=='<')?LEQ:GEQ,r);
1527: }
1528: else
1529: {
1530: #ifdef DEBUG_EXPR
1531: if (debugging)
1532: { outputc(c);
1533: }
1534: #endif
1535: Push(d);
1536: r = read_expr_7();
1537: l = newnode(l,c,r);
1538: }
1539: break;
1540: default:
1541: #ifdef DEBUG_EXPR
1542: if (debugging)
1543: { outputs("~");
1544: }
1545: #endif
1546: Push(c);
1547: return(l);
1548: break;
1549: }
1550: }
1551: }
1552:
1553: NODE *read_expr_5(void)
1554: {
1555: NODE *l;
1556: NODE *r;
1557: char c;
1558: char d;
1559:
1560: #ifdef DEBUG_EXPR
1561: if (debugging)
1562: { outputs("~E5:");
1563: }
1564: #endif
1565: l = read_expr_6();
1566: while (1)
1567: { c = getnhsexpand();
1568: switch (c)
1569: { case '=':
1570: case '!':
1571: d = Get();
1572: if (d == '=')
1573: {
1574: #ifdef DEBUG_EXPR
1575: if (debugging)
1576: { outputc(c);
1577: outputc(d);
1578: }
1579: #endif
1580: r = read_expr_6();
1581: l = newnode(l,(c=='=')?EQL:NEQ,r);
1582: break;
1583: }
1584: Push(d);
1585: /* fall through ... */
1586: default:
1587: #ifdef DEBUG_EXPR
1588: if (debugging)
1589: { outputs("~");
1590: }
1591: #endif
1592: Push(c);
1593: return(l);
1594: break;
1595: }
1596: }
1597: }
1598:
1599: NODE *read_expr_4(void)
1600: {
1601: NODE *l;
1602: NODE *r;
1603: char c;
1604: char d;
1605:
1606: #ifdef DEBUG_EXPR
1607: if (debugging)
1608: { outputs("~E4:");
1609: }
1610: #endif
1611: l = read_expr_5();
1612: while (1)
1613: { c = getnhsexpand();
1614: switch (c)
1615: { case '&':
1616: d = Get();
1617: if (d != '&')
1618: {
1619: #ifdef DEBUG_EXPR
1620: if (debugging)
1621: { outputc(c);
1622: outputc(d);
1623: }
1624: #endif
1625: r = read_expr_5();
1626: l = newnode(l,c,r);
1627: break;
1628: }
1629: Push(d);
1630: /* fall through ... */
1631: default:
1632: #ifdef DEBUG_EXPR
1633: if (debugging)
1634: { outputs("~");
1635: }
1636: #endif
1637: Push(c);
1638: return(l);
1639: break;
1640: }
1641: }
1642: }
1643:
1644: NODE *read_expr_3(void)
1645: {
1646: NODE *l;
1647: NODE *r;
1648: char c;
1649:
1650: #ifdef DEBUG_EXPR
1651: if (debugging)
1652: { outputs("~E3:");
1653: }
1654: #endif
1655: l = read_expr_4();
1656: while (1)
1657: { c = getnhsexpand();
1658: switch (c)
1659: { case '^':
1660: #ifdef DEBUG_EXPR
1661: if (debugging)
1662: { outputc(c);
1663: }
1664: #endif
1665: r = read_expr_4();
1666: l = newnode(l,c,r);
1667: break;
1668: default:
1669: #ifdef DEBUG_EXPR
1670: if (debugging)
1671: { outputs("~");
1672: }
1673: #endif
1674: Push(c);
1675: return(l);
1676: break;
1677: }
1678: }
1679: }
1680:
1681: NODE *read_expr_2(void)
1682: {
1683: NODE *l;
1684: NODE *r;
1685: char c;
1686: char d;
1687:
1688: #ifdef DEBUG_EXPR
1689: if (debugging)
1690: { outputs("~E2:");
1691: }
1692: #endif
1693: l = read_expr_3();
1694: while (1)
1695: { c = getnhsexpand();
1696: switch (c)
1697: { case '|':
1698: d = Get();
1699: if (d != '|')
1700: { Push(d);
1701: #ifdef DEBUG_EXPR
1702: if (debugging)
1703: { outputc(c);
1704: }
1705: #endif
1706: r = read_expr_3();
1707: l = newnode(l,c,r);
1708: break;
1709: }
1710: Push(d);
1711: /* fall through ... */
1712: default:
1713: #ifdef DEBUG_EXPR
1714: if (debugging)
1715: { outputs("~");
1716: }
1717: #endif
1718: Push(c);
1719: return(l);
1720: break;
1721: }
1722: }
1723: }
1724:
1725: NODE *read_expr_1(void)
1726: {
1727: NODE *l;
1728: NODE *r;
1729: char c;
1730: char d;
1731:
1732: #ifdef DEBUG_EXPR
1733: if (debugging)
1734: { outputs("~E1:");
1735: }
1736: #endif
1737: l = read_expr_2();
1738: while (1)
1739: { c = getnhsexpand();
1740: switch (c)
1741: { case '&':
1742: d = Get();
1743: if (d == c)
1744: {
1745: #ifdef DEBUG_EXPR
1746: if (debugging)
1747: { outputc(c);
1748: outputc(d);
1749: }
1750: #endif
1751: r = read_expr_2();
1752: l = newnode(l,AND,r);
1753: break;
1754: }
1755: Push(d);
1756: /* fall through ... */
1757: default:
1758: #ifdef DEBUG_EXPR
1759: if (debugging)
1760: { outputs("~");
1761: }
1762: #endif
1763: Push(c);
1764: return(l);
1765: break;
1766: }
1767: }
1768: }
1769:
1770: NODE *read_expr_0(void)
1771: {
1772: NODE *l;
1773: NODE *r;
1774: char c;
1775: char d;
1776:
1777: #ifdef DEBUG_EXPR
1778: if (debugging)
1779: { outputs("~E0:");
1780: }
1781: #endif
1782: l = read_expr_1();
1783: while (1)
1784: { c = getnhsexpand();
1785: switch (c)
1786: { case '|':
1787: d = Get();
1788: if (d == c)
1789: {
1790: #ifdef DEBUG_EXPR
1791: if (debugging)
1792: { outputc(c);
1793: outputc(d);
1794: }
1795: #endif
1796: r = read_expr_1();
1797: l = newnode(l,OR,r);
1798: break;
1799: }
1800: Push(d);
1801: /* fall through ... */
1802: default:
1803: #ifdef DEBUG_EXPR
1804: if (debugging)
1805: { outputs("~");
1806: }
1807: #endif
1808: Push(c);
1809: return(l);
1810: break;
1811: }
1812: }
1813: }
1814:
1815: NODE *read_expr_(void)
1816: {
1817: NODE *l;
1818: NODE *r;
1819: char c;
1820:
1821: #ifdef DEBUG_EXPR
1822: if (debugging)
1823: { outputs("~E");
1824: }
1825: #endif
1826: l = read_expr_0();
1827: while (1)
1828: { c = getnhsexpand();
1829: switch (c)
1830: { case '\n':
1831: case ')':
1832: Push(c);
1833: return(l);
1834: break;
1835: case ',':
1836: r = read_expr_0();
1837: l = newnode(l,c,r);
1838: break;
1839: default:
1840: err_head();
1841: fprintf(stderr,"expression syntax error -- bad operator `%c'\n",c);
1842: return(l);
1843: break;
1844: }
1845: }
1846: }
1847:
1848: NODE *read_expr_p(void)
1849: {
1850: char c;
1851: NODE *rv;
1852:
1853: sharp = 0;
1854: complain = 1;
1855: c = getnonspace();
1856: if (c != '(')
1857: { Push(c);
1858: return(0);
1859: }
1860: rv = read_expr_();
1861: c = getnonspace();
1862: if (c != ')')
1863: { err_head();
1864: fprintf(stderr,"junk after expression\n");
1865: }
1866: return(rv);
1867: }
1868:
1869: int eval_expr(int Sharp, int Complain)
1870: {
1871: char c;
1872: char d;
1873: int rv;
1874:
1875: sharp = Sharp;
1876: complain = Complain;
1877: expr = read_expr_();
1878: if (sharp)
1879: { c = getnonhspace();
1880: d = '\n';
1881: }
1882: else
1883: { c = getnonspace();
1884: d = ')';
1885: }
1886: if (c != d)
1887: { if (complain)
1888: { err_head();
1889: fprintf(stderr,"expression syntax error -- junk after expression\n");
1890: }
1891: while (Get() != d) ;
1892: }
1893: #ifdef DEBUG_EXPR
1894: if (debugging)
1895: { outputc('<');
1896: dump_expr(expr);
1897: outputc('=');
1898: rv = exec_free(expr);
1899: outputd(rv);
1900: outputc('>');
1901: }
1902: else
1903: { rv = exec_free(expr);
1904: }
1905: return(rv);
1906: #else
1907: return(exec_free(expr));
1908: #endif
1909: }
1910:
1911: #ifdef DEBUG_EXPR
1912: void dump_expr(NODE *n)
1913: {
1914: switch (n->op)
1915: { case 0:
1916: outputd(n->leaf);
1917: break;
1918: case '-':
1919: if (n->left)
1920: { dump_expr(n->left);
1921: }
1922: outputc('-');
1923: dump_expr(n->right);
1924: break;
1925: case '!':
1926: outputc('!');
1927: dump_expr(n->right);
1928: break;
1929: case '~':
1930: outputc('~');
1931: dump_expr(n->right);
1932: break;
1933: case 'd':
1934: outputs("defined(");
1935: outputs(n->name);
1936: outputc(')');
1937: break;
1938: #define BIN(key,op) case key:dump_expr(n->left);\
1939: putx(key);\
1940: dump_expr(n->right);\
1941: break;
1942: ALLBINS
1943: #undef BIN
1944: }
1945: }
1946:
1947: void putx(int i)
1948: {
1949: if (i > 0xff) outputc((char)(i>>8));
1950: outputc((char)(i&0xff));
1951: }
1952: #endif
1953:
1954: /*#define DEBUG_IF/**/
1955:
1956: #ifdef DEBUG_IF
1957: extern int debugging;
1958: #endif
1959:
1960: void do_if(int expr_sharp)
1961: {
1962: char c;
1963: char d;
1964:
1965: #ifdef DEBUG_IF
1966: if (debugging)
1967: { outputc('<');
1968: outputc(sharp?'#':'@');
1969: outputs("if: ");
1970: fflush(outfile);
1971: }
1972: #endif
1973: if (in_false_if())
1974: { n_skipped_ifs ++;
1975: #ifdef DEBUG_IF
1976: if (debugging)
1977: { outputs("in-false, skipped>");
1978: fflush(outfile);
1979: }
1980: #endif
1981: if (sharp)
1982: { d = '\0';
1983: do
1984: { c = d;
1985: d = Get();
1986: } while ((c == '\\') || (d != '\n'));
1987: }
1988: return;
1989: }
1990: if (! sharp)
1991: { c = getnonspace();
1992: if (c != '(')
1993: { err_head();
1994: fprintf(stderr,"@if must have ()s\n");
1995: Push(c);
1996: iffalse();
1997: #ifdef DEBUG_IF
1998: if (debugging)
1999: { outputc('>');
2000: fflush(outfile);
2001: }
2002: #endif
2003: return;
2004: }
2005: }
2006: if (eval_expr(sharp,0))
2007: { iftrue();
2008: }
2009: else
2010: { iffalse();
2011: }
2012: #ifdef DEBUG_IF
2013: if (debugging)
2014: { outputc('>');
2015: fflush(outfile);
2016: }
2017: #endif
2018: }
2019:
2020: void do_ifdef(int expr_sharp)
2021: {
2022: char *w;
2023:
2024: #ifdef DEBUG_IF
2025: if (debugging)
2026: { outputc('<');
2027: outputc(sharp?'#':'@');
2028: outputs("ifdef: ");
2029: fflush(outfile);
2030: }
2031: #endif
2032: if (in_false_if())
2033: { n_skipped_ifs ++;
2034: #ifdef DEBUG_IF
2035: if (debugging)
2036: { outputs("in-false, skipped>");
2037: fflush(outfile);
2038: }
2039: #endif
2040: }
2041: else
2042: { w = read_ident();
2043: if (! w)
2044: {
2045: #ifdef DEBUG_IF
2046: if (debugging)
2047: { outputs("no ident ");
2048: fflush(outfile);
2049: }
2050: #endif
2051: iffalse();
2052: }
2053: else
2054: {
2055: #ifdef DEBUG_IF
2056: if (debugging)
2057: { outputs(w);
2058: outputc(' ');
2059: fflush(outfile);
2060: }
2061: #endif
2062: if (find_def(w))
2063: { iftrue();
2064: }
2065: else
2066: { iffalse();
2067: }
2068: free(w);
2069: }
2070: #ifdef DEBUG_IF
2071: if (debugging)
2072: { outputc('>');
2073: fflush(outfile);
2074: }
2075: #endif
2076: }
2077: if (sharp)
2078: { flush_sharp_line();
2079: }
2080: }
2081:
2082: void do_ifndef(int expr_sharp)
2083: {
2084: char *w;
2085:
2086: #ifdef DEBUG_IF
2087: if (debugging)
2088: { outputc('<');
2089: outputc(sharp?'#':'@');
2090: outputs("ifndef: ");
2091: fflush(outfile);
2092: }
2093: #endif
2094: if (in_false_if())
2095: { n_skipped_ifs ++;
2096: #ifdef DEBUG_IF
2097: if (debugging)
2098: { outputs("in-false, skipped>");
2099: fflush(outfile);
2100: }
2101: #endif
2102: }
2103: else
2104: { w = read_ident();
2105: if (! w)
2106: {
2107: #ifdef DEBUG_IF
2108: if (debugging)
2109: { outputs("no ident ");
2110: fflush(outfile);
2111: }
2112: #endif
2113: iftrue();
2114: }
2115: else
2116: {
2117: #ifdef DEBUG_IF
2118: if (debugging)
2119: { outputs(w);
2120: outputc(' ');
2121: fflush(outfile);
2122: }
2123: #endif
2124: if (find_def(w))
2125: { iffalse();
2126: }
2127: else
2128: { iftrue();
2129: }
2130: free(w);
2131: }
2132: #ifdef DEBUG_IF
2133: if (debugging)
2134: { outputc('>');
2135: fflush(outfile);
2136: }
2137: #endif
2138: }
2139: if (sharp)
2140: { flush_sharp_line();
2141: }
2142: }
2143:
2144: void do_else(int expr_sharp)
2145: {
2146: #ifdef DEBUG_IF
2147: if (debugging)
2148: { outputc('<');
2149: outputc(sharp?'#':'@');
2150: outputs("else: ");
2151: fflush(outfile);
2152: }
2153: #endif
2154: if (n_skipped_ifs == 0)
2155: { if (ifstack)
2156: {
2157: #ifdef DEBUG_IF
2158: if (debugging)
2159: { outputs("top ");
2160: output_ifstate(ifstack->condstate);
2161: fflush(outfile);
2162: }
2163: #endif
2164: switch (ifstack->condstate)
2165: { case IFSTATE_TRUE:
2166: ifstack->condstate = IFSTATE_STAYFALSE;
2167: break;
2168: case IFSTATE_FALSE:
2169: ifstack->condstate = IFSTATE_TRUE;
2170: break;
2171: }
2172: #ifdef DEBUG_IF
2173: if (debugging)
2174: { outputs(" now ");
2175: output_ifstate(ifstack->condstate);
2176: outputc('>');
2177: fflush(outfile);
2178: }
2179: #endif
2180: }
2181: else
2182: {
2183: #ifdef DEBUG_IF
2184: if (debugging)
2185: { outputs(" no if>");
2186: fflush(outfile);
2187: }
2188: #endif
2189: err_head();
2190: fprintf(stderr,"if-less else\n");
2191: }
2192: }
2193: else
2194: {
2195: #ifdef DEBUG_IF
2196: if (debugging)
2197: { outputs("in-false, forgetting>");
2198: fflush(outfile);
2199: }
2200: #endif
2201: }
2202: if (sharp)
2203: { flush_sharp_line();
2204: }
2205: }
2206:
2207: #ifdef DEBUG_IF
2208: void output_ifstate(state)
2209: int state;
2210: {
2211: switch (state)
2212: { case IFSTATE_TRUE:
2213: outputs("TRUE");
2214: break;
2215: case IFSTATE_FALSE:
2216: outputs("FALSE");
2217: break;
2218: case IFSTATE_STAYFALSE:
2219: outputs("STAYFALSE");
2220: break;
2221: default:
2222: outputs("BAD");
2223: outputd(state);
2224: break;
2225: }
2226: }
2227: #endif
2228:
2229: void do_elif(int expr_sharp)
2230: {
2231: char c;
2232: char d;
2233: int e;
2234:
2235: #ifdef DEBUG_IF
2236: if (debugging)
2237: { outputc('<');
2238: outputc(sharp?'#':'@');
2239: outputs("elif: ");
2240: fflush(outfile);
2241: }
2242: #endif
2243: if (ifstack == 0)
2244: { err_head();
2245: fprintf(stderr,"if-less elif converted to normal if\n");
2246: iffalse();
2247: }
2248: if (n_skipped_ifs > 0)
2249: {
2250: #ifdef DEBUG_IF
2251: if (debugging)
2252: { outputs("being skipped, ignoring>");
2253: fflush(outfile);
2254: }
2255: #endif
2256: if (sharp)
2257: { d = '\0';
2258: do
2259: { c = d;
2260: d = Get();
2261: } while ((c == '\\') || (d != '\n'));
2262: }
2263: return;
2264: }
2265: if (! sharp)
2266: { c = getnonspace();
2267: if (c != '(')
2268: { err_head();
2269: fprintf(stderr,"@elif must have ()s\n");
2270: Push(c);
2271: ifstack->condstate = IFSTATE_STAYFALSE;
2272: #ifdef DEBUG_IF
2273: if (debugging)
2274: { outputs("forcing STAYFALSE>");
2275: fflush(outfile);
2276: }
2277: #endif
2278: return;
2279: }
2280: }
2281: e = eval_expr(sharp,0);
2282: #ifdef DEBUG_IF
2283: if (debugging)
2284: { outputs("expr ");
2285: outputd(e);
2286: outputc(' ');
2287: fflush(outfile);
2288: }
2289: #endif
2290: #ifdef DEBUG_IF
2291: if (debugging)
2292: { outputs(" top ");
2293: output_ifstate(ifstack->condstate);
2294: fflush(outfile);
2295: }
2296: #endif
2297: switch (ifstack->condstate)
2298: { case IFSTATE_TRUE:
2299: ifstack->condstate = IFSTATE_STAYFALSE;
2300: break;
2301: case IFSTATE_FALSE:
2302: if (e)
2303: { ifstack->condstate = IFSTATE_TRUE;
2304: }
2305: break;
2306: }
2307: #ifdef DEBUG_IF
2308: if (debugging)
2309: { outputs(" now ");
2310: output_ifstate(ifstack->condstate);
2311: outputc('>');
2312: fflush(outfile);
2313: }
2314: #endif
2315: }
2316:
2317: void do_endif(int expr_sharp)
2318: {
2319: IF *i;
2320:
2321: #ifdef DEBUG_IF
2322: if (debugging)
2323: { outputc('<');
2324: outputc(sharp?'#':'@');
2325: outputs("endif: ");
2326: fflush(outfile);
2327: }
2328: #endif
2329: if (n_skipped_ifs > 0)
2330: { n_skipped_ifs --;
2331: #ifdef DEBUG_IF
2332: if (debugging)
2333: { outputs("n_skipped -->");
2334: fflush(outfile);
2335: }
2336: #endif
2337: }
2338: else if (ifstack)
2339: { i = ifstack->next;
2340: OLD(ifstack);
2341: ifstack = i;
2342: #ifdef DEBUG_IF
2343: if (debugging)
2344: { outputs("popping stack>");
2345: fflush(outfile);
2346: }
2347: #endif
2348: }
2349: else
2350: { err_head();
2351: fprintf(stderr,"if-less endif\n");
2352: #ifdef DEBUG_IF
2353: if (debugging)
2354: { outputc('>');
2355: fflush(outfile);
2356: }
2357: #endif
2358: }
2359: if (sharp)
2360: { flush_sharp_line();
2361: }
2362: }
2363:
2364: void iftrue(void)
2365: {
2366: IF *i;
2367:
2368: i = NEW(IF);
2369: check_malloc(i);
2370: i->next = ifstack;
2371: ifstack = i;
2372: i->condstate = IFSTATE_TRUE;
2373: #ifdef DEBUG_IF
2374: if (debugging)
2375: { outputs("IFTRUE");
2376: fflush(outfile);
2377: }
2378: #endif
2379: }
2380:
2381: void iffalse(void)
2382: {
2383: IF *i;
2384:
2385: i = NEW(IF);
2386: check_malloc(i);
2387: i->next = ifstack;
2388: ifstack = i;
2389: i->condstate = IFSTATE_FALSE;
2390: #ifdef DEBUG_IF
2391: if (debugging)
2392: { outputs("IFFALSE");
2393: fflush(outfile);
2394: }
2395: #endif
2396: }
2397:
2398: int in_false_if(void)
2399: {
2400: return(ifstack && (ifstack->condstate != IFSTATE_TRUE));
2401: }
2402:
2403: void maybe_print(char c)
2404: {
2405: extern int incldep;
2406:
2407: if (incldep)
2408: { return;
2409: }
2410: if ((c == '\n') || !in_false_if())
2411: { outputc(c);
2412: }
2413: }
2414:
2415: char *Rindex(char *s, int c);
2416:
2417: int nIfiles;
2418: char **Ifiles;
2419:
2420: void init_include(void)
2421: {
2422: nIfiles = 0;
2423: Ifiles = (char **) malloc(1);
2424: check_malloc(Ifiles);
2425: }
2426:
2427: void Ifile(char *f)
2428: {
2429: Ifiles = (char **) realloc((char *)Ifiles,(nIfiles+1)*sizeof(char *));
2430: check_malloc(Ifiles);
2431: Ifiles[nIfiles] = copyofstr(f);
2432: check_malloc(Ifiles[nIfiles]);
2433: nIfiles ++;
2434: }
2435:
2436: void do_include(int expr_sharp)
2437: {
2438: char c;
2439: char *acc;
2440:
2441: if (in_false_if())
2442: { if (sharp)
2443: { flush_sharp_line();
2444: }
2445: return;
2446: }
2447: while (1)
2448: { c = getnonspace();
2449: if (isbsymchar(c))
2450: { char *cp;
2451: DEF *d;
2452: cp = init_accum();
2453: while (issymchar(c))
2454: { accum_char(cp,c);
2455: c = Get();
2456: }
2457: Push(c);
2458: cp = accum_result(cp);
2459: d = find_def(cp);
2460: if (d)
2461: { expand_def(d);
2462: n_hits ++;
2463: }
2464: else
2465: { char *dp;
2466: for (dp=cp+strlen(cp);dp>cp;dp--) Push(*dp);
2467: n_misses ++;
2468: }
2469: }
2470: else
2471: { break;
2472: }
2473: }
2474: acc = init_accum();
2475: if (c == '"')
2476: { while (1)
2477: { c = Get();
2478: if (c == '\n')
2479: { Push('\n');
2480: c = '"';
2481: err_head();
2482: fprintf(stderr,"warning: unterminated %cinclude filename\n",
2483: sharp?'#':'@');
2484: }
2485: if (c == '"')
2486: { break;
2487: }
2488: accum_char(acc,c);
2489: }
2490: if (sharp)
2491: { flush_sharp_line();
2492: }
2493: read_include_file(accum_result(acc),1,sharp);
2494: }
2495: else if (c == '<')
2496: { while (1)
2497: { c = Get();
2498: if (c == '\n')
2499: { Push('\n');
2500: c = '>';
2501: err_head();
2502: fprintf(stderr,"warning: unterminated %cinclude filename\n",
2503: sharp?'#':'@');
2504: }
2505: if (c == '>')
2506: { break;
2507: }
2508: accum_char(acc,c);
2509: }
2510: if (sharp)
2511: { flush_sharp_line();
2512: }
2513: read_include_file(accum_result(acc),0,sharp);
2514: }
2515: else
2516: { free(accum_result(acc));
2517: err_head();
2518: fprintf(stderr,"illegal %cinclude filename delimiter\n",sharp?'#':'@');
2519: }
2520: }
2521:
2522: #if defined(THINK_C)
2523: #if defined(DELIM)
2524: #undef DELIM
2525: #endif
2526: #define DELIM ':'
2527: #endif
2528:
2529: #if defined(SYSV)
2530: #else
2531: #if defined(DELIM)
2532: #undef DELIM
2533: #endif
2534: #define DELIM '/'
2535: #endif
2536:
2537: #if defined(VISUAL)
2538: #if defined(DELIM)
2539: #undef DELIM
2540: #endif
2541: #define DELIM '\\'
2542: #endif
2543:
2544: void read_include_file(char *name, int dohere, int expr_sharp)
2545: {
2546: FILE *f;
2547: char *n;
2548: char temp[1024];
2549: char *cp;
2550: extern int incldep;
2551: extern char *incldep_o;
2552:
2553: f = NULL;
2554: if (dohere)
2555: { if ((strcmp(curdir(),".") != 0) && (name[0] != DELIM))
2556: { sprintf(temp,"%s%c%s",curdir(),DELIM,name);
2557: n = temp;
2558: }
2559: else
2560: { n = name;
2561: }
2562: f = fopen(n,"r");
2563: }
2564: if (f == NULL)
2565: { if (name[0] == DELIM)
2566: { f = fopen(name,"r");
2567: n = name;
2568: }
2569: else
2570: { int i;
2571: n = temp;
2572: for (i=0;i<nIfiles;i++)
2573: { sprintf(temp,"%s%c%s",Ifiles[i],DELIM,name);
2574: f = fopen(temp,"r");
2575: if (f != NULL)
2576: { break;
2577: }
2578: }
2579: }
2580: }
2581: if (f == NULL)
2582: { err_head();
2583: fprintf(stderr,"can't find include file %s\n",name);
2584: free(name);
2585: return;
2586: }
2587: if (incldep)
2588: { printf("%s: %s\n",incldep_o,n);
2589: }
2590: out_at(!sharp,n);
2591: autodef_file(n);
2592: autodef_line(1);
2593: Push('\n');
2594: Get();
2595: push_new_file(n,f);
2596: cp = Rindex(n,DELIM);
2597: if (cp)
2598: { *cp = '\0';
2599: cp = copyofstr(n);
2600: }
2601: else
2602: { cp = copyofstr(".");
2603: }
2604: check_malloc(cp);
2605: *Curdir() = cp;
2606: free(name);
2607: return;
2608: }
2609:
2610: /*#define DEBUG_IO/**/
2611: /*#define DEBUG_INCL/**/
2612:
2613: #if defined(DEBUG_IO) || defined(DEBUG_INCL)
2614: extern int debugging;
2615: #endif
2616:
2617: extern int no_line_lines;
2618:
2619: int linefirst;
2620: int willbefirst;
2621: int lineno[MAXFILES];
2622: FILE *fstack[MAXFILES];
2623: int fstackdepth;
2624: char *fn[MAXFILES];
2625: int npushed[MAXFILES];
2626: char pushback[MAXFILES][MAX_PUSHBACK];
2627: char *incldir[MAXFILES];
2628: FILE *outfile;
2629:
2630: char *cur_pushback;
2631: int cur_npushed;
2632: FILE *cur_fstack;
2633: char *cur_fn;
2634: char *cur_incldir;
2635: int cur_lineno;
2636:
2637: typedef struct _mark {
2638: struct _mark *link;
2639: char *acc;
2640: int startdepth;
2641: int incs[MAXFILES];
2642: int nincs;
2643: int nignore; } MARK;
2644:
2645: static MARK *marks;
2646: static int atline;
2647: static char *atfile;
2648: static int done_line;
2649: static int nnls;
2650:
2651: /* XXX these definitions assume no input chars are 81, 82, 83 */
2652: #define NOEXPAND ((char)0x81)
2653: #define MARKLINE ((char)0x82)
2654: #define MARKLEND ((char)0x83)
2655:
2656: void init_io(FILE *f, char *fnname)
2657: {
2658: register int i;
2659:
2660: fstackdepth = 0;
2661: cur_pushback = pushback[0];
2662: cur_npushed = 0;
2663: cur_fstack = f;
2664: cur_fn = copyofstr(fnname);
2665: check_malloc(cur_fn);
2666: cur_lineno = 1;
2667: nnls = 0;
2668: atfile = copyofstr("");
2669: check_malloc(atfile);
2670: for (i=0;i<MAXFILES;i++)
2671: { npushed[i] = 0;
2672: }
2673: marks = 0;
2674: }
2675:
2676: void init_incldir(char *d)
2677: {
2678: cur_incldir = copyofstr(d);
2679: check_malloc(cur_incldir);
2680: }
2681:
2682: void change_fstackdepth(int delta)
2683: {
2684: npushed[fstackdepth] = cur_npushed;
2685: fstack[fstackdepth] = cur_fstack;
2686: fn[fstackdepth] = cur_fn;
2687: incldir[fstackdepth] = cur_incldir;
2688: lineno[fstackdepth] = cur_lineno;
2689: fstackdepth += delta;
2690: cur_pushback = pushback[fstackdepth];
2691: cur_npushed = npushed[fstackdepth];
2692: cur_fstack = fstack[fstackdepth];
2693: cur_fn = fn[fstackdepth];
2694: cur_incldir = incldir[fstackdepth];
2695: cur_lineno = lineno[fstackdepth];
2696: }
2697:
2698: #define GET() (cur_pushback[--cur_npushed])
2699: #define PUSH() (cur_pushback[cur_npushed++])
2700:
2701: char Get(void)
2702: {
2703: char c;
2704:
2705: linefirst = willbefirst;
2706: willbefirst = 0;
2707: while (1)
2708: { if (cur_npushed > 0)
2709: { do
2710: { c = GET();
2711: } while (c == NOEXPAND);
2712: if (c == MARKLINE)
2713: { mark_get_line();
2714: continue;
2715: }
2716: mark_got_from_pushback(c);
2717: #ifdef DEBUG_IO
2718: if (debugging)
2719: { outputc('(');
2720: outputs(unctrl(c));
2721: outputc(')');
2722: fflush(outfile);
2723: }
2724: #endif
2725: break;
2726: }
2727: else
2728: { c = getc(cur_fstack);
2729: if (feof(cur_fstack))
2730: { if (fstackdepth > 0)
2731: {
2732: #ifdef DEBUG_INCL
2733: if (debugging)
2734: { outputs("--eof:");
2735: outputs(cur_fn);
2736: outputs("--");
2737: }
2738: #endif
2739: fclose(cur_fstack);
2740: free(cur_fn);
2741: free(cur_incldir);
2742: change_fstackdepth(-1);
2743: mark_file_ending();
2744: out_at(cur_lineno,cur_fn);
2745: autodef_file(curfile());
2746: autodef_line(curline());
2747: continue;
2748: }
2749: else
2750: { flush_final_nl();
2751: save_stats();
2752: #if 0
2753: exit(0);
2754: #endif
2755: longjmp(cpp_env,1);
2756: }
2757: }
2758: mark_got_from_file(c);
2759: #ifdef DEBUG_IO
2760: if (debugging)
2761: { outputc('<');
2762: outputs(unctrl(c));
2763: outputc('>');
2764: fflush(outfile);
2765: }
2766: #endif
2767: break;
2768: }
2769: }
2770: if (c == '\n')
2771: { cur_lineno ++;
2772: autodef_line(curline());
2773: willbefirst = 1;
2774: }
2775: return(c);
2776: }
2777:
2778: void push_new_file(char *name, FILE *f)
2779: {
2780: change_fstackdepth(1);
2781: cur_fn = copyofstr(name);
2782: check_malloc(cur_fn);
2783: cur_lineno = 1;
2784: cur_fstack = f;
2785: cur_npushed = 0;
2786: #ifdef DEBUG_INCL
2787: if (debugging)
2788: { outputs("--newfile:");
2789: outputs(name);
2790: outputs("--");
2791: }
2792: #endif
2793: mark_file_beginning();
2794: }
2795:
2796: void Push(char c)
2797: {
2798: if (cur_npushed > MAX_PUSHBACK)
2799: { fprintf(stderr,"too much pushback\n");
2800: cur_npushed = 0;
2801: }
2802: PUSH() = c;
2803: mark_charpushed();
2804: willbefirst = 0;
2805: if (c == '\n')
2806: { cur_lineno --;
2807: autodef_line(curline());
2808: }
2809: #ifdef DEBUG_IO
2810: if (debugging)
2811: { outputc('[');
2812: outputs(unctrl(c));
2813: outputc(']');
2814: fflush(outfile);
2815: }
2816: #endif
2817: }
2818:
2819: char *curfile(void)
2820: {
2821: return(cur_fn);
2822: }
2823:
2824: char **Curfile(void)
2825: {
2826: return(&cur_fn);
2827: }
2828:
2829: int curline(void)
2830: {
2831: return(cur_lineno);
2832: }
2833:
2834: int *Curline(void)
2835: {
2836: return(&cur_lineno);
2837: }
2838:
2839: char *curdir(void)
2840: {
2841: return(cur_incldir);
2842: }
2843:
2844: char **Curdir(void)
2845: {
2846: return(&cur_incldir);
2847: }
2848:
2849: char getnonspace(void)
2850: {
2851: char c;
2852:
2853: while (isspace(c=Get())) ;
2854: return(c);
2855: }
2856:
2857: char getnonhspace(void)
2858: {
2859: char c;
2860:
2861: while (ishspace(c=Get())) ;
2862: return(c);
2863: }
2864:
2865: char getnhsexpand(void)
2866: {
2867: char c;
2868:
2869: while (1)
2870: { c = getexpand();
2871: if (ishspace(c))
2872: { continue;
2873: }
2874: if (expr_sharp && (c == '\\'))
2875: { c = Get();
2876: if (c == '\n')
2877: { continue;
2878: }
2879: else
2880: { Push(c);
2881: c = '\\';
2882: }
2883: }
2884: break;
2885: }
2886: return(c);
2887: }
2888:
2889: char getexpand(void)
2890: {
2891: char c;
2892: char *str;
2893: DEF *d;
2894:
2895: while (1)
2896: { c = Get();
2897: if (c == '/')
2898: { char d;
2899: d = Get();
2900: if (d == '*')
2901: { d = '\0';
2902: do
2903: { c = d;
2904: d = Get();
2905: } while ((c != '*') || (d != '/'));
2906: continue;
2907: }
2908: else
2909: { Push(d);
2910: return('/');
2911: }
2912: }
2913: else if (c == NOEXPAND)
2914: { c = Get();
2915: if (issymchar(c))
2916: { Push(NOEXPAND);
2917: }
2918: return(c);
2919: }
2920: else if (! isbsymchar(c))
2921: {
2922: return(c);
2923: }
2924: str = init_accum();
2925: do
2926: { accum_char(str,c);
2927: } while (issymchar(c=Get()));
2928: Push(c);
2929: str = accum_result(str);
2930: if (d = find_def(str))
2931: { expand_def(d);
2932: free(str);
2933: }
2934: else
2935: { int i;
2936: for (i=strlen(str)-1;i>0;i--)
2937: { Push(str[i]);
2938: }
2939: Push(NOEXPAND);
2940: c = str[0];
2941: free(str);
2942: return(c);
2943: }
2944: }
2945: }
2946:
2947: char *read_ctrl(void)
2948: {
2949: char c;
2950: char *acc;
2951:
2952: acc = init_accum();
2953: while (ishspace(c=Get())) ;
2954: Push(c);
2955: while (1)
2956: { c = Get();
2957: if (islower(c))
2958: { accum_char(acc,c);
2959: }
2960: else
2961: { Push(c);
2962: return(accum_result(acc));
2963: }
2964: }
2965: }
2966:
2967: char *read_ident(void)
2968: {
2969: char *acc;
2970: char c;
2971:
2972: c = getnonspace();
2973: if (! isbsymchar(c))
2974: { Push(c);
2975: return(0);
2976: }
2977: acc = init_accum();
2978: do
2979: { accum_char(acc,c);
2980: } while (issymchar(c=Get()));
2981: Push(c);
2982: return(accum_result(acc));
2983: }
2984:
2985: void out_at(int line, char *file)
2986: {
2987: if ((line-nnls != atline) || strcmp(file,atfile))
2988: { free(atfile);
2989: atline = line - nnls;
2990: atfile = copyofstr(file);
2991: check_malloc(atfile);
2992: done_line = 0;
2993: }
2994: }
2995:
2996: void outputc(char c)
2997: {
2998: extern int incldep;
2999: static char *white = 0;
3000:
3001: if (incldep)
3002: { return;
3003: }
3004: if (c == '\n')
3005: { nnls ++;
3006: if (white)
3007: { free(accum_result(white));
3008: white = 0;
3009: }
3010: }
3011: else if ((nnls > 0) && ((c == ' ') || (c == '\t')))
3012: { if (! white)
3013: { white = init_accum();
3014: }
3015: accum_char(white,c);
3016: }
3017: else
3018: { if ((nnls > 2) || !done_line)
3019: { atline += nnls;
3020: nnls = 0;
3021: if (no_line_lines)
3022: { fprintf(outfile,"\n");
3023: }
3024: else
3025: { fprintf(outfile,"\n# %d \"%s\"\n",atline,atfile);
3026: }
3027: done_line = 1;
3028: }
3029: for (;nnls;nnls--)
3030: { atline ++;
3031: putc('\n',outfile);
3032: }
3033: if (white)
3034: { white = accum_result(white);
3035: fputs(white,outfile);
3036: free(white);
3037: white = 0;
3038: }
3039: putc(c,outfile);
3040: }
3041: }
3042:
3043: void flush_final_nl(void)
3044: {
3045: if (nnls > 0)
3046: { putc('\n',outfile);
3047: }
3048: }
3049:
3050: void outputs(char *s)
3051: {
3052: for (;*s;s++)
3053: { outputc(*s);
3054: }
3055: }
3056:
3057: void outputd(int n)
3058: {
3059: char temp[64];
3060:
3061: sprintf(temp,"%d",n);
3062: outputs(temp);
3063: }
3064:
3065: void mark_push_here(MARK *,int,char *);
3066:
3067: void input_mark(void)
3068: {
3069: MARK *m;
3070:
3071: m = NEW(MARK);
3072: check_malloc(m);
3073: m->link = marks;
3074: marks = m;
3075: m->startdepth = fstackdepth;
3076: m->acc = init_accum();
3077: m->nignore = 0;
3078: m->nincs = 0;
3079: mark_push_here(m,curline(),curfile());
3080: #ifdef DEBUG_IO
3081: if (debugging)
3082: { outputs("~MARK~");
3083: }
3084: #endif
3085: }
3086:
3087: void input_unmark(void)
3088: {
3089: MARK *m;
3090:
3091: if (marks)
3092: { m = marks;
3093: marks = m->link;
3094: free(accum_result(m->acc));
3095: OLD(m);
3096: #ifdef DEBUG_IO
3097: if (debugging)
3098: { outputs("~UNMARK~");
3099: }
3100: #endif
3101: }
3102: }
3103:
3104: void input_recover(void)
3105: {
3106: register MARK *m;
3107: register char *txt;
3108: register int i;
3109: register int l;
3110: char c;
3111:
3112: if (marks)
3113: { m = marks;
3114: marks = m->link;
3115: #ifdef DEBUG_IO
3116: if (debugging)
3117: { outputs("~RECOVER~");
3118: }
3119: #endif
3120: for (;m->nignore>0;m->nignore--)
3121: { accum_regret(m->acc);
3122: }
3123: txt = accum_result(m->acc);
3124: i = strlen(txt) - 1;
3125: while (m->nincs > 0)
3126: { l = m->incs[--m->nincs];
3127: for (;i>=l;i--)
3128: { Push(txt[i]);
3129: }
3130: Push(MARKLEND);
3131: c = txt[i];
3132: for (i--;txt[i]!=c;i--)
3133: { Push(txt[i]);
3134: }
3135: Push('A');
3136: Push('@');
3137: Push('@');
3138: Push('@');
3139: Push('@');
3140: Push('@');
3141: Push('@');
3142: Push('@');
3143: for (;(txt[i]!='#')&&(txt[i]!='@');i--) ;
3144: Push(MARKLINE);
3145: i --;
3146: }
3147: for (;i>=0;i--)
3148: { Push(txt[i]);
3149: }
3150: free(txt);
3151: OLD(m);
3152: }
3153: }
3154:
3155: void mark_file_beginning(void)
3156: {
3157: register MARK *m;
3158:
3159: for (m=marks;m;m=m->link)
3160: { m->incs[m->nincs++] = accum_howfar(m->acc);
3161: }
3162: }
3163:
3164: void mark_file_ending(void)
3165: {
3166: register MARK *m;
3167: register int i;
3168: register int to;
3169: register char *acc;
3170:
3171: for (m=marks;m;m=m->link)
3172: { if (m->startdepth > fstackdepth)
3173: { m->startdepth = fstackdepth;
3174: mark_push_here(m,curline(),curfile());
3175: }
3176: else if (m->nincs <= 0)
3177: { fprintf(stderr,"INTERNAL BUG: nincs<0 in mark_file_ending\n");
3178: abort();
3179: }
3180: else
3181: { to = m->incs[--m->nincs];
3182: acc = m->acc;
3183: for (i=accum_howfar(acc);i>to;i--)
3184: { accum_regret(acc);
3185: }
3186: }
3187: }
3188: }
3189:
3190: void mark_charpushed(void)
3191: {
3192: register MARK *m;
3193:
3194: for (m=marks;m;m=m->link)
3195: { m->nignore ++;
3196: }
3197: }
3198:
3199: void mark_got_from_pushback(char c)
3200: {
3201: mark_got(c);
3202: }
3203:
3204: void mark_got_from_file(char c)
3205: {
3206: mark_got(c);
3207: }
3208:
3209: void mark_got(char c)
3210: {
3211: register MARK *m;
3212:
3213: for (m=marks;m;m=m->link)
3214: { if (m->nignore > 0)
3215: { m->nignore --;
3216: }
3217: else
3218: { accum_char(m->acc,c);
3219: }
3220: }
3221: }
3222:
3223: void mark_push_here(MARK *m, int l, char *f)
3224: {
3225: int i;
3226: char c;
3227:
3228: switch (c=accum_regret(m->acc))
3229: { case 0:
3230: break;
3231: case MARKLEND:
3232: while (accum_regret(m->acc) != MARKLINE) ;
3233: break;
3234: default:
3235: accum_char(m->acc,c);
3236: break;
3237: }
3238: accum_char(m->acc,MARKLINE);
3239: for (i=28;i>=0;i-=4)
3240: { accum_char(m->acc,(char)('@'+((l>>i)&0xf)));
3241: }
3242: for (;*f;f++)
3243: { accum_char(m->acc,*f);
3244: }
3245: accum_char(m->acc,MARKLEND);
3246: }
3247:
3248: void mark_get_line(void)
3249: {
3250: int l;
3251: char *f;
3252: int i;
3253: char c;
3254: MARK *m;
3255:
3256: l = 0;
3257: for (i=0;i<8;i++)
3258: { l = (l << 4) + (GET() & 0xf);
3259: }
3260: f = init_accum();
3261: while ((c=GET()) != MARKLEND)
3262: { accum_char(f,c);
3263: }
3264: f = accum_result(f);
3265: out_at(l,f);
3266: for (m=marks;m;m=m->link)
3267: { mark_push_here(m,l,f);
3268: }
3269: free(f);
3270: }
3271:
3272: int ishspace(char c)
3273: {
3274: return((c == ' ') || (c == '\t'));
3275: }
3276:
3277: int isbsymchar(char c)
3278: {
3279: return(isalpha(c) || (c == '_'));
3280: }
3281:
3282: int issymchar(char c)
3283: {
3284: return(isalnum(c) || (c == '_') || (c == '$'));
3285: }
3286:
3287: void do_line(void)
3288: {
3289: char c;
3290:
3291: outputc('#');
3292: while ((c=Get()) != '\n')
3293: { outputc(c);
3294: }
3295: }
3296:
3297: #define DEBUG_MAIN/**/
3298:
3299: extern char **argvec;
3300:
3301: char *Index(char *s, int c);
3302: char *Rindex(char *s, int c);
3303:
3304: #ifdef DEBUG_MAIN
3305: extern int debugging;
3306: #endif
3307:
3308: static char quote;
3309:
3310: IF *ifstack;
3311: int n_skipped_ifs;
3312:
3313: int keep_comments;
3314: int no_line_lines;
3315: int incldep;
3316: char *incldep_o;
3317: int do_at_ctrls;
3318: extern char *predefs[];
3319:
3320: #if defined(SYSV)
3321: void main(ac,av)
3322: #else
3323: void cpp_main(int ac, char **av)
3324: #endif
3325: {
3326: int argno;
3327: int rest;
3328: char *cp;
3329: static FILE *inf;
3330: static FILE *outf;
3331: char *inname;
3332: int backslash;
3333: int i;
3334:
3335: if ( setjmp(cpp_env) ) {
3336: if ( inf != stdin )
3337: fclose(inf);
3338: if ( outf == stdout )
3339: fflush(outf);
3340: else
3341: fclose(outf);
3342: return;
3343: }
3344:
3345: init_symtbl();
3346: #define predef(str) ( (cp=copyofstr("1")), \
3347: check_malloc(cp), \
3348: define((str),-1,(unsigned char *)cp,DEF_PREDEF) )
3349: for (i=0;predefs[i];i++)
3350: { predef(predefs[i]);
3351: }
3352: init_include();
3353: inf = stdin;
3354: outf = stdout;
3355: inname = "";
3356: keep_comments = 0;
3357: no_line_lines = 0;
3358: do_at_ctrls = 0;
3359: incldep = 0;
3360: argno = 0;
3361: for (ac--,av++;ac;ac--,av++)
3362: { if (**av == '-')
3363: { rest = 0;
3364: if (!strcmp(*av,"-undef"))
3365: { undef_predefs();
3366: }
3367: else
3368: { for (++*av;(**av)&&!rest;++*av)
3369: { switch (**av)
3370: { case 'C':
3371: keep_comments = 1;
3372: break;
3373: case 'D':
3374: rest = 1;
3375: ++*av;
3376: if (strcmp(*av,"@") == 0)
3377: { do_at_ctrls = 1;
3378: }
3379: else
3380: { cp = Index(*av,'=');
3381: if (cp)
3382: { if (cp != *av)
3383: { char *dp;
3384: *cp++ = '\0';
3385: dp = copyofstr(cp);
3386: check_malloc(dp);
3387: define(*av,-1,(unsigned char *)dp,DEF_CMDLINE);
3388: }
3389: else
3390: { fprintf(stderr,"Must give a name for -D\n");
3391: }
3392: }
3393: else
3394: { char *dp;
3395: dp = copyofstr("1");
3396: check_malloc(dp);
3397: define(*av,-1,(unsigned char *)dp,DEF_CMDLINE);
3398: }
3399: }
3400: break;
3401: case 'E':
3402: break;
3403: case 'I':
3404: rest = 1;
3405: ++*av;
3406: if (**av)
3407: { Ifile(*av);
3408: }
3409: else
3410: { fprintf(stderr,"Must give a directory name for -I\n");
3411: }
3412: break;
3413: case 'M':
3414: incldep = 1;
3415: break;
3416: case 'P':
3417: no_line_lines = 1;
3418: break;
3419: case 'R':
3420: break;
3421: case 'U':
3422: rest = 1;
3423: ++*av;
3424: if (**av)
3425: { undef(*av);
3426: }
3427: else
3428: { fprintf(stderr,"Must give a name for -U\n");
3429: }
3430: break;
3431: default:
3432: fprintf(stderr,"Unknown flag -%c\n",**av);
3433: break;
3434: }
3435: }
3436: }
3437: }
3438: else
3439: { switch (argno++)
3440: { case 0:
3441: if (strcmp(*av,"-") != 0)
3442: { FILE *f;
3443: f = fopen(*av,"r");
3444: if (f == NULL)
3445: { fprintf(stderr,"Cannot open source file %s\n",*av);
3446: }
3447: else
3448: { inf = f;
3449: inname = *av;
3450: }
3451: }
3452: break;
3453: case 1:
3454: if (strcmp(*av,"-") != 0)
3455: { FILE *f;
3456: f = fopen(*av,"w");
3457: if (f == NULL)
3458: { fprintf(stderr,"Can't create %s\n",*av);
3459: }
3460: else
3461: { outf = f;
3462: }
3463: }
3464: break;
3465: default:
3466: fprintf(stderr,"Extra name %s ignored\n",*av);
3467: break;
3468: }
3469: }
3470: }
3471: if (incldep && !inname[0])
3472: { fprintf(stderr,"No input file for -M flag\n");
3473: #if 0
3474: exit(1);
3475: #endif
3476: longjmp(cpp_env,1);
3477: }
3478: if (do_at_ctrls)
3479: { predef("at_sign_ctrls");
3480: }
3481: Ifile("/local/include");
3482: Ifile("/usr/include");
3483: willbefirst = 1;
3484: quote = 0;
3485: backslash = 0;
3486: init_io(inf,inname);
3487: outfile = outf;
3488: ifstack = 0;
3489: n_skipped_ifs = 0;
3490: cp = Rindex(inname,'/');
3491: if (cp)
3492: { *cp = '\0';
3493: init_incldir(inname);
3494: *cp = '/';
3495: }
3496: else
3497: { init_incldir(".");
3498: }
3499: autodef_file(inname);
3500: autodef_line(1);
3501: out_at(1,inname);
3502: if (incldep)
3503: { char *dp;
3504: cp = Rindex(inname,'/');
3505: if (cp)
3506: { cp ++;
3507: }
3508: else
3509: { cp = inname;
3510: }
3511: dp = cp + strlen(cp) - 2;
3512: if ((dp < cp) || strcmp(dp,".c"))
3513: { fprintf(stderr,"Missing .c in %s\n",inname);
3514: #if 0
3515: exit(1);
3516: #endif
3517: longjmp(cpp_env,1);
3518: }
3519: incldep_o = copyofstr(cp);
3520: incldep_o[dp+1-cp] = 'o';
3521: fprintf(outfile,"%s: ",incldep_o);
3522: fprintf(outfile,"%s\n",inname);
3523: }
3524: init_stats();
3525: while (1)
3526: { char c;
3527: int haddigit;
3528: c = Get();
3529: if (backslash)
3530: { maybe_print(c);
3531: backslash = 0;
3532: continue;
3533: }
3534: if (!incldep && (isdigit(c) || (c == '.')))
3535: { haddigit = 0;
3536: while (isdigit(c) || (c == '.'))
3537: { haddigit |= isdigit(c);
3538: maybe_print(c);
3539: c = Get();
3540: }
3541: if (haddigit && ((c == 'e') || (c == 'E')))
3542: { maybe_print(c);
3543: c = Get();
3544: while (isdigit(c))
3545: { maybe_print(c);
3546: c = Get();
3547: }
3548: }
3549: Push(c);
3550: continue;
3551: }
3552: if (quote)
3553: { if (c == '\\')
3554: { maybe_print(c);
3555: backslash = 1;
3556: continue;
3557: }
3558: else if ((c == quote) || (c == '\n'))
3559: { maybe_print(c);
3560: quote = 0;
3561: continue;
3562: }
3563: else
3564: { maybe_print(c);
3565: continue;
3566: }
3567: }
3568: if (c == '\\') /* this weirdness is Reiser semantics.... */
3569: { backslash = 1;
3570: maybe_print(c);
3571: continue;
3572: }
3573: if ((c == '\'') || (c == '"'))
3574: { quote = c;
3575: maybe_print(c);
3576: }
3577: else if (linefirst && (c == '#'))
3578: { do_sharp();
3579: }
3580: else if (do_at_ctrls && (c == '@'))
3581: { do_at();
3582: }
3583: else if (! incldep)
3584: { if (isbsymchar(c) && !in_false_if())
3585: { char *cp;
3586: DEF *d;
3587: cp = init_accum();
3588: while (issymchar(c))
3589: { accum_char(cp,c);
3590: c = Get();
3591: }
3592: Push(c);
3593: cp = accum_result(cp);
3594: #ifdef DEBUG_MAIN
3595: if (debugging)
3596: { outputs("<word:");
3597: outputs(cp);
3598: outputs(">");
3599: }
3600: #endif
3601: d = find_def(cp);
3602: if (d)
3603: { expand_def(d);
3604: n_hits ++;
3605: }
3606: else
3607: { for (;*cp;cp++)
3608: { maybe_print(*cp);
3609: }
3610: n_misses ++;
3611: }
3612: }
3613: else if (c == '/')
3614: { char d;
3615: d = Get();
3616: if (d == '*')
3617: { d = '\0';
3618: if (keep_comments)
3619: { maybe_print('/');
3620: maybe_print('*');
3621: }
3622: do
3623: { c = d;
3624: d = Get();
3625: if ((d == '\n') || keep_comments)
3626: { maybe_print(d);
3627: }
3628: } while ((c != '*') || (d != '/'));
3629: }
3630: else
3631: { Push(d);
3632: maybe_print(c);
3633: }
3634: }
3635: else
3636: { maybe_print(c);
3637: }
3638: }
3639: }
3640: }
3641:
3642: void do_pragma(void)
3643: {
3644: char c;
3645:
3646: if (in_false_if())
3647: { while ((c=Get()) != '\n') ;
3648: }
3649: else
3650: { outputc('#');
3651: outputc('p');
3652: outputc('r');
3653: outputc('a');
3654: outputc('g');
3655: outputc('m');
3656: outputc('a');
3657: outputc(' ');
3658: while ((c=Get()) != '\n')
3659: { outputc(c);
3660: }
3661: }
3662: }
3663:
3664: char *predefs[] = {
3665: "mc68000",
3666: "unix",
3667: "NeXT",
3668: "__MACH__",
3669: 0
3670: };
3671:
3672: void do_set(void)
3673: {
3674: char *mac;
3675: char c;
3676: char temp[64];
3677:
3678: mac = read_ident();
3679: if (! mac)
3680: { err_head();
3681: fprintf(stderr,"@set: missing/illegal macro name\n");
3682: return;
3683: }
3684: if (! in_false_if())
3685: { char *cp;
3686: c = getnonspace();
3687: if (c != '(')
3688: { err_head();
3689: fprintf(stderr,"@set must have ()s\n");
3690: Push(c);
3691: return;
3692: }
3693: sprintf(temp,"%d",eval_expr(0,1));
3694: undef(mac);
3695: cp = copyofstr(temp);
3696: check_malloc(cp);
3697: define(mac,-1,(unsigned char *)cp,DEF_DEFINE);
3698: }
3699: free(mac);
3700: }
3701:
3702: void do_sharp(void)
3703: {
3704: char *w;
3705: char c;
3706:
3707: w = read_ctrl();
3708: if (strcmp(w,"ifdef") == 0)
3709: { do_ifdef(1);
3710: }
3711: else if (strcmp(w,"ifndef") == 0)
3712: { do_ifndef(1);
3713: }
3714: else if (strcmp(w,"if") == 0)
3715: { do_if(1);
3716: }
3717: else if (strcmp(w,"else") == 0)
3718: { do_else(1);
3719: }
3720: else if (strcmp(w,"elif") == 0)
3721: { do_elif(1);
3722: }
3723: else if (strcmp(w,"endif") == 0)
3724: { do_endif(1);
3725: }
3726: else if (strcmp(w,"include") == 0)
3727: { do_include(1);
3728: }
3729: else if (strcmp(w,"define") == 0)
3730: { do_define(1,0);
3731: }
3732: else if (strcmp(w,"undef") == 0)
3733: { do_undef(1);
3734: }
3735: else if (strcmp(w,"line") == 0)
3736: { do_line();
3737: }
3738: else if (strcmp(w,"pragma") == 0)
3739: { do_pragma();
3740: }
3741: else if (strcmp(w,"") == 0)
3742: {
3743: }
3744: else
3745: { int isnull;
3746: isnull = 0;
3747: if (strcmp(w,"") == 0)
3748: { c = Get();
3749: if (c != '\n')
3750: { Push(c);
3751: }
3752: else
3753: { isnull = 1;
3754: }
3755: }
3756: if (!isnull && !in_false_if())
3757: { err_head();
3758: fprintf(stderr,"unknown control `%s'\n",w);
3759: flush_sharp_line();
3760: }
3761: }
3762: maybe_print('\n');
3763: free(w);
3764: }
3765:
3766: void flush_sharp_line(void)
3767: {
3768: int quote;
3769: int backslash;
3770: int comment;
3771: int lastc;
3772: int c;
3773:
3774: quote = 0;
3775: backslash = 0;
3776: comment = 0;
3777: c = 'x';
3778: while (1)
3779: { lastc = c;
3780: c = Get();
3781: if (backslash)
3782: { backslash = 0;
3783: continue;
3784: }
3785: if (comment)
3786: { if (c == '\\')
3787: { backslash = 1;
3788: }
3789: else if ((c == '/') && (lastc == '*'))
3790: { comment = 0;
3791: }
3792: continue;
3793: }
3794: if (quote)
3795: { if (c == '\\')
3796: { backslash = 1;
3797: }
3798: else if (c == quote)
3799: { quote = 0;
3800: }
3801: }
3802: switch (c)
3803: { case '\\':
3804: backslash = 1;
3805: continue;
3806: break;
3807: case '"': case '\'':
3808: quote = c;
3809: continue;
3810: break;
3811: case '*':
3812: comment = (lastc == '/');
3813: continue;
3814: break;
3815: default:
3816: continue;
3817: break;
3818: case '\n':
3819: break;
3820: }
3821: break;
3822: }
3823: }
3824:
3825:
3826: int n_defines;
3827: int n_undefines;
3828: int n_hits;
3829: int n_misses;
3830:
3831: void init_stats(void)
3832: {
3833: n_defines = 0;
3834: n_undefines = 0;
3835: n_hits = 0;
3836: n_misses = 0;
3837: }
3838:
3839: void save_stats(void)
3840: {
3841: FILE *f;
3842:
3843: f = fopen("/@larry/u1/mouse/Mouse-C/cpp.stats","a");
3844: if (f)
3845: { fprintf(f,"%d def, %d undef, %d hits, %d misses\n",
3846: n_defines,n_undefines,n_hits,n_misses);
3847: fclose(f);
3848: }
3849: }
3850:
3851: DEF **symtbl;
3852: int symtbl_size;
3853: int n_in_table;
3854:
3855: static int size_index;
3856: static int sizes[] = { 7, 37, 179, 719, 2003, 8009, 30011, 120011, 0 };
3857:
3858: static int hash(unsigned char *s)
3859: {
3860: register unsigned int i;
3861:
3862: for (i=0;*s;s++)
3863: { i = (i >> 8) + (i << 3) + *s;
3864: }
3865: i &= ~0x80000000;
3866: return(i%symtbl_size);
3867: }
3868:
3869: void init_symtbl(void)
3870: {
3871: int i;
3872:
3873: symtbl_size = sizes[size_index=0];
3874: symtbl = (DEF **) malloc(symtbl_size*sizeof(DEF *));
3875: check_malloc(symtbl);
3876: for (i=0;i<symtbl_size;i++)
3877: { symtbl[i] = 0;
3878: }
3879: n_in_table = 0;
3880: }
3881:
3882: static void rehash_up(void)
3883: {
3884: int osize;
3885: DEF **otbl;
3886: int i;
3887: DEF *d;
3888: DEF *n;
3889: int h;
3890:
3891: if ((sizes[size_index] == 0) || (sizes[++size_index] == 0))
3892: { return;
3893: }
3894: osize = symtbl_size;
3895: otbl = symtbl;
3896: symtbl_size = sizes[size_index];
3897: symtbl = (DEF **) malloc(symtbl_size*sizeof(DEF *));
3898: check_malloc(symtbl);
3899: for (i=0;i<symtbl_size;i++)
3900: { symtbl[i] = 0;
3901: }
3902: for (i=0;i<osize;i++)
3903: { for (d=otbl[i];d;d=n)
3904: { n = d->link;
3905: h = hash((unsigned char *)d->name);
3906: d->link = symtbl[h];
3907: symtbl[h] = d;
3908: }
3909: }
3910: free((char *)otbl);
3911: }
3912:
3913: void define(char *name, int nargs, unsigned char *repl, int how)
3914: {
3915: int h;
3916: DEF *d;
3917: char *n;
3918:
3919: n = copyofstr(name);
3920: h = hash((unsigned char *)n);
3921: for (d=symtbl[h];d;d=d->link)
3922: { if (strcmp(d->name,n) == 0)
3923: { break;
3924: }
3925: }
3926: if (d)
3927: { if ( (nargs != d->nargs) || strcmp((char *)repl,(char *)d->repl) )
3928: { err_head();
3929: fprintf(stderr,"%s redefined\n",n);
3930: }
3931: free((char *)d->repl);
3932: free(d->name);
3933: d->name = n;
3934: d->nargs = nargs;
3935: d->repl = repl;
3936: d->how = how;
3937: }
3938: else
3939: { d = NEW(DEF);
3940: check_malloc(d);
3941: d->name = n;
3942: d->nargs = nargs;
3943: d->repl = repl;
3944: d->how = how;
3945: d->link = symtbl[h];
3946: symtbl[h] = d;
3947: n_in_table ++;
3948: if (n_in_table > 2*symtbl_size)
3949: { rehash_up();
3950: }
3951: }
3952: if (strcmp(n,"at_sign_ctrls") == 0)
3953: { extern int do_at_ctrls;
3954: do_at_ctrls = 1;
3955: }
3956: }
3957:
3958: int undef(char *name)
3959: {
3960: int h;
3961: DEF **D;
3962: DEF *d;
3963: int rv;
3964:
3965: h = hash((unsigned char *)name);
3966: for (D=symtbl+h;*D;D= &(*D)->link)
3967: { if (strcmp((*D)->name,name) == 0)
3968: { break;
3969: }
3970: }
3971: rv = 0;
3972: if (d = *D)
3973: { *D = d->link;
3974: free(d->name);
3975: free((char *)d->repl);
3976: OLD(d);
3977: n_in_table --;
3978: rv = 1;
3979: }
3980: if (strcmp(name,"at_sign_ctrls") == 0)
3981: { extern int do_at_ctrls;
3982: do_at_ctrls = 0;
3983: }
3984: return rv;
3985: }
3986:
3987: DEF *find_def(char *name)
3988: {
3989: int h;
3990: DEF *d;
3991:
3992: h = hash((unsigned char *)name);
3993: for (d=symtbl[h];d;d=d->link)
3994: { if (strcmp(d->name,name) == 0)
3995: { break;
3996: }
3997: }
3998: return(d);
3999: }
4000:
4001: void defd(char *name, int value)
4002: {
4003: char temp[64];
4004: char *cp;
4005:
4006: sprintf(temp,"%d",value);
4007: undef(name);
4008: cp = copyofstr(temp);
4009: check_malloc(cp);
4010: define(name,-1,(unsigned char *)cp,DEF_DEFINE);
4011: }
4012:
4013: void undef_predefs(void)
4014: {
4015: int h;
4016: DEF **D;
4017: DEF *d;
4018:
4019: for (h=symtbl_size-1;h>=0;h--)
4020: { D = symtbl + h;
4021: while (*D)
4022: { d = *D;
4023: if (d->how == DEF_PREDEF)
4024: { free(d->name);
4025: free((char *)d->repl);
4026: *D = d->link;
4027: OLD(d);
4028: n_in_table --;
4029: }
4030: else
4031: { D = &d->link;
4032: }
4033: }
4034: }
4035: }
4036:
4037: char *_unctrl[0400] = { "^@",
4038: "^A",
4039: "^B",
4040: "^C",
4041: "^D",
4042: "^E",
4043: "^F",
4044: "^G",
4045: "^H",
4046: "^I",
4047: "^J",
4048: "^K",
4049: "^L",
4050: "^M",
4051: "^N",
4052: "^O",
4053: "^P",
4054: "^Q",
4055: "^R",
4056: "^S",
4057: "^T",
4058: "^U",
4059: "^V",
4060: "^W",
4061: "^X",
4062: "^Y",
4063: "^Z",
4064: "^[",
4065: "^\\",
4066: "^]",
4067: "^^",
4068: "^_",
4069: " ",
4070: "!",
4071: "\"",
4072: "#",
4073: "$",
4074: "%",
4075: "&",
4076: "'",
4077: "(",
4078: ")",
4079: "*",
4080: "+",
4081: ",",
4082: "-",
4083: ".",
4084: "/",
4085: "0",
4086: "1",
4087: "2",
4088: "3",
4089: "4",
4090: "5",
4091: "6",
4092: "7",
4093: "8",
4094: "9",
4095: ":",
4096: ";",
4097: "<",
4098: "=",
4099: ">",
4100: "?",
4101: "@",
4102: "A",
4103: "B",
4104: "C",
4105: "D",
4106: "E",
4107: "F",
4108: "G",
4109: "H",
4110: "I",
4111: "J",
4112: "K",
4113: "L",
4114: "M",
4115: "N",
4116: "O",
4117: "P",
4118: "Q",
4119: "R",
4120: "S",
4121: "T",
4122: "U",
4123: "V",
4124: "W",
4125: "X",
4126: "Y",
4127: "Z",
4128: "[",
4129: "\\",
4130: "]",
4131: "^",
4132: "_",
4133: "`",
4134: "a",
4135: "b",
4136: "c",
4137: "d",
4138: "e",
4139: "f",
4140: "g",
4141: "h",
4142: "i",
4143: "j",
4144: "k",
4145: "l",
4146: "m",
4147: "n",
4148: "o",
4149: "p",
4150: "q",
4151: "r",
4152: "s",
4153: "t",
4154: "u",
4155: "v",
4156: "w",
4157: "x",
4158: "y",
4159: "z",
4160: "{"/*}*/,
4161: "|",
4162: /*{*/"}",
4163: "~",
4164: "^?",
4165: "|^@",
4166: "|^A",
4167: "|^B",
4168: "|^C",
4169: "|^D",
4170: "|^E",
4171: "|^F",
4172: "|^G",
4173: "|^H",
4174: "|^I",
4175: "|^J",
4176: "|^K",
4177: "|^L",
4178: "|^M",
4179: "|^N",
4180: "|^O",
4181: "|^P",
4182: "|^Q",
4183: "|^R",
4184: "|^S",
4185: "|^T",
4186: "|^U",
4187: "|^V",
4188: "|^W",
4189: "|^X",
4190: "|^Y",
4191: "|^Z",
4192: "|^[",
4193: "|^\\",
4194: "|^]",
4195: "|^^",
4196: "|^_",
4197: "| ",
4198: "|!",
4199: "|\"",
4200: "|#",
4201: "|$",
4202: "|%",
4203: "|&",
4204: "|'",
4205: "|(",
4206: "|)",
4207: "|*",
4208: "|+",
4209: "|,",
4210: "|-",
4211: "|.",
4212: "|/",
4213: "|0",
4214: "|1",
4215: "|2",
4216: "|3",
4217: "|4",
4218: "|5",
4219: "|6",
4220: "|7",
4221: "|8",
4222: "|9",
4223: "|:",
4224: "|;",
4225: "|<",
4226: "|=",
4227: "|>",
4228: "|?",
4229: "|@",
4230: "|A",
4231: "|B",
4232: "|C",
4233: "|D",
4234: "|E",
4235: "|F",
4236: "|G",
4237: "|H",
4238: "|I",
4239: "|J",
4240: "|K",
4241: "|L",
4242: "|M",
4243: "|N",
4244: "|O",
4245: "|P",
4246: "|Q",
4247: "|R",
4248: "|S",
4249: "|T",
4250: "|U",
4251: "|V",
4252: "|W",
4253: "|X",
4254: "|Y",
4255: "|Z",
4256: "|[",
4257: "|\\",
4258: "|]",
4259: "|^",
4260: "|_",
4261: "|`",
4262: "|a",
4263: "|b",
4264: "|c",
4265: "|d",
4266: "|e",
4267: "|f",
4268: "|g",
4269: "|h",
4270: "|i",
4271: "|j",
4272: "|k",
4273: "|l",
4274: "|m",
4275: "|n",
4276: "|o",
4277: "|p",
4278: "|q",
4279: "|r",
4280: "|s",
4281: "|t",
4282: "|u",
4283: "|v",
4284: "|w",
4285: "|x",
4286: "|y",
4287: "|z",
4288: "|{"/*}*/,
4289: "||",
4290: /*{*/"|}",
4291: "|~",
4292: "|^?" };
4293:
4294: char *_Unctrl[0400] = { "^@",
4295: "^A",
4296: "^B",
4297: "^C",
4298: "^D",
4299: "^E",
4300: "^F",
4301: "^G",
4302: "^H",
4303: "^I",
4304: "^J",
4305: "^K",
4306: "^L",
4307: "^M",
4308: "^N",
4309: "^O",
4310: "^P",
4311: "^Q",
4312: "^R",
4313: "^S",
4314: "^T",
4315: "^U",
4316: "^V",
4317: "^W",
4318: "^X",
4319: "^Y",
4320: "^Z",
4321: "^[",
4322: "^\\",
4323: "^]",
4324: "^^",
4325: "^_",
4326: "sp",
4327: "!",
4328: "\"",
4329: "#",
4330: "$",
4331: "%",
4332: "&",
4333: "'",
4334: "(",
4335: ")",
4336: "*",
4337: "+",
4338: ",",
4339: "-",
4340: ".",
4341: "/",
4342: "0",
4343: "1",
4344: "2",
4345: "3",
4346: "4",
4347: "5",
4348: "6",
4349: "7",
4350: "8",
4351: "9",
4352: ":",
4353: ";",
4354: "<",
4355: "=",
4356: ">",
4357: "?",
4358: "@",
4359: "A",
4360: "B",
4361: "C",
4362: "D",
4363: "E",
4364: "F",
4365: "G",
4366: "H",
4367: "I",
4368: "J",
4369: "K",
4370: "L",
4371: "M",
4372: "N",
4373: "O",
4374: "P",
4375: "Q",
4376: "R",
4377: "S",
4378: "T",
4379: "U",
4380: "V",
4381: "W",
4382: "X",
4383: "Y",
4384: "Z",
4385: "[",
4386: "\\",
4387: "]",
4388: "^",
4389: "_",
4390: "`",
4391: "a",
4392: "b",
4393: "c",
4394: "d",
4395: "e",
4396: "f",
4397: "g",
4398: "h",
4399: "i",
4400: "j",
4401: "k",
4402: "l",
4403: "m",
4404: "n",
4405: "o",
4406: "p",
4407: "q",
4408: "r",
4409: "s",
4410: "t",
4411: "u",
4412: "v",
4413: "w",
4414: "x",
4415: "y",
4416: "z",
4417: "{"/*}*/,
4418: "|",
4419: /*{*/"}",
4420: "~",
4421: "^?",
4422: "|^@",
4423: "|^A",
4424: "|^B",
4425: "|^C",
4426: "|^D",
4427: "|^E",
4428: "|^F",
4429: "|^G",
4430: "|^H",
4431: "|^I",
4432: "|^J",
4433: "|^K",
4434: "|^L",
4435: "|^M",
4436: "|^N",
4437: "|^O",
4438: "|^P",
4439: "|^Q",
4440: "|^R",
4441: "|^S",
4442: "|^T",
4443: "|^U",
4444: "|^V",
4445: "|^W",
4446: "|^X",
4447: "|^Y",
4448: "|^Z",
4449: "|^[",
4450: "|^\\",
4451: "|^]",
4452: "|^^",
4453: "|^_",
4454: "|sp",
4455: "|!",
4456: "|\"",
4457: "|#",
4458: "|$",
4459: "|%",
4460: "|&",
4461: "|'",
4462: "|(",
4463: "|)",
4464: "|*",
4465: "|+",
4466: "|,",
4467: "|-",
4468: "|.",
4469: "|/",
4470: "|0",
4471: "|1",
4472: "|2",
4473: "|3",
4474: "|4",
4475: "|5",
4476: "|6",
4477: "|7",
4478: "|8",
4479: "|9",
4480: "|:",
4481: "|;",
4482: "|<",
4483: "|=",
4484: "|>",
4485: "|?",
4486: "|@",
4487: "|A",
4488: "|B",
4489: "|C",
4490: "|D",
4491: "|E",
4492: "|F",
4493: "|G",
4494: "|H",
4495: "|I",
4496: "|J",
4497: "|K",
4498: "|L",
4499: "|M",
4500: "|N",
4501: "|O",
4502: "|P",
4503: "|Q",
4504: "|R",
4505: "|S",
4506: "|T",
4507: "|U",
4508: "|V",
4509: "|W",
4510: "|X",
4511: "|Y",
4512: "|Z",
4513: "|[",
4514: "|\\",
4515: "|]",
4516: "|^",
4517: "|_",
4518: "|`",
4519: "|a",
4520: "|b",
4521: "|c",
4522: "|d",
4523: "|e",
4524: "|f",
4525: "|g",
4526: "|h",
4527: "|i",
4528: "|j",
4529: "|k",
4530: "|l",
4531: "|m",
4532: "|n",
4533: "|o",
4534: "|p",
4535: "|q",
4536: "|r",
4537: "|s",
4538: "|t",
4539: "|u",
4540: "|v",
4541: "|w",
4542: "|x",
4543: "|y",
4544: "|z",
4545: "|{"/*}*/,
4546: "||",
4547: /*{*/"|}",
4548: "|~",
4549: "|^?" };
4550:
4551: void do_undef(int expr_sharp)
4552: {
4553: char *mac;
4554:
4555: if (! in_false_if())
4556: { mac = read_ident();
4557: if (! mac)
4558: { err_head();
4559: fprintf(stderr,"missing/illegal macro name\n");
4560: }
4561: else
4562: { if (undef(mac))
4563: { n_undefines ++;
4564: }
4565: }
4566: }
4567: if (sharp)
4568: { flush_sharp_line();
4569: }
4570: }
4571: /*#define DEBUG_WHILE/**/
4572:
4573: #ifdef DEBUG_WHILE
4574: extern int debugging;
4575: #endif
4576:
4577: void do_while(void)
4578: {
4579: input_mark();
4580: do_if(0);
4581: }
4582:
4583: void do_endwhile(void)
4584: {
4585: if (in_false_if())
4586: { do_endif(0);
4587: input_unmark();
4588: #ifdef DEBUG_WHILE
4589: if (debugging)
4590: { outputs("//endwhile:");
4591: outputd(curline());
4592: outputs(",");
4593: outputs(curfile());
4594: outputs("\\\\");
4595: }
4596: #endif
4597: out_at(curline(),curfile());
4598: }
4599: else
4600: { do_endif(0);
4601: input_recover();
4602: input_mark();
4603: do_if(0);
4604: }
4605: }
4606:
4607: char *Index(char *s, int c)
4608: {
4609: return strchr(s,c);
4610: }
4611:
4612: char *Rindex(char *s, int c)
4613: {
4614: return strrchr(s,c);
4615: }
4616:
4617: void Bcopy(char *from, char *to, int len)
4618: {
4619: #if defined(GO32)
4620: bcopy(from,to,len);
4621: #else
4622: memmove((void *)from,(void *)to,(int)len);
4623: #endif
4624: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>