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