|
|
1.1 root 1: /*#ident "@(#)cpp:common/cpp.c 1.44" */
2:
3:
4: #ifdef FLEXNAMES
5: # define NCPS 128
6: #else
7: # define NCPS 8
8: #endif
9: int ncps = NCPS; /* default name length */
10:
11: # include <stdio.h>
12: # include <ctype.h>
13: # include <libc.h>
14: # include <sys/types.h> /* needed by stat.h */
15: # include <sys/stat.h> /* needed by option -M */
16: /* C command - C preprocessor */
17:
18: /*
19: * See if necessary defines are given
20: */
21: #if !defined( PD_MACH ) || !defined( PD_SYS )
22: # include "*** Must define PD_MACH and PD_SYS ***"
23: #endif
24: /*
25: * These defines are used to enter new machines and/or systems
26: * to the two lists. To create a new instance of cpp in a cross
27: * compilation environment, set PD_MY_MACH=\"your-new-machine\"
28: * and/or PD_MY_SYS=\"your-new-os\" and set PD_MACH=MAX_PD_MACH
29: * and PD_SYS=MAX_PD_SYS.
30: */
31: #ifndef PD_MY_MACH
32: # define PD_MY_MACH 0
33: #endif
34: #ifndef PD_MY_SYS
35: # define PD_MY_SYS 0
36: #endif
37:
38: #define STATIC
39:
40: #define STDIN 0
41: #define STDOUT 1
42: #define STDERR 2
43:
44: #define CLASSCODE 27 /* exit status if #class seen */
45:
46: #define READ "r"
47: #define WRITE "w"
48: #define SALT '#'
49:
50: #ifndef BUFSIZ
51: # define BUFSIZ 512
52: #endif
53:
54: char *pbeg, *pbuf, *pend;
55: char *outp, *inp;
56: char *newp;
57: char cinit;
58:
59: #ifdef CXREF
60: char *xcopy();
61: FILE *outfp;
62: static int ready = 0;
63: int xline;
64: #endif
65:
66: /* some code depends on whether characters are sign or zero extended */
67: /* #if '\377' < 0 not used here, old cpp doesn't understand */
68: #if pdp11 | vax
69: # define COFF 128
70: #else
71: # define COFF 0
72: #endif
73:
74: # if gcos
75: # define ALFSIZ 512 /* alphabet size */
76: # else
77: # define ALFSIZ 256 /* alphabet size */
78: # endif
79: char macbit[ ALFSIZ + 11 ];
80: char toktyp[ ALFSIZ ];
81: #define BLANK 1
82: #define IDENT 2
83: #define NUMBR 3
84:
85: /* a superimposed code is used to reduce the number of calls to the
86: /* symbol table lookup routine. (if the kth character of an identifier
87: /* is 'a' and there are no macro names whose kth character is 'a'
88: /* then the identifier cannot be a macro name, hence there is no need
89: /* to look in the symbol table.) 'scw1' enables the test based on
90: /* single characters and their position in the identifier. 'scw2'
91: /* enables the test based on adjacent pairs of characters and their
92: /* position in the identifier. scw1 typically costs 1 indexed fetch,
93: /* an AND, and a jump per character of identifier, until the identifier
94: /* is known as a non-macro name or until the end of the identifier.
95: /* scw1 is inexpensive. scw2 typically costs 4 indexed fetches,
96: /* an add, an AND, and a jump per character of identifier, but it is also
97: /* slightly more effective at reducing symbol table searches.
98: /* scw2 usually costs too much because the symbol table search is
99: /* usually short; but if symbol table search should become expensive,
100: /* the code is here.
101: /* using both scw1 and scw2 is of dubious value.
102: */
103: #define scw1 1
104: #define scw2 0
105:
106: #if scw2
107: char t21[ ALFSIZ ], t22[ ALFSIZ ], t23[ ALFSIZ + NCPS ];
108: #endif
109:
110: #if scw1
111: # define b0 1
112: # define b1 2
113: # define b2 4
114: # define b3 8
115: # define b4 16
116: # define b5 32
117: # define b6 64
118: # define b7 128
119: #endif
120:
121: #define IB 1
122: #define SB 2
123: #define NB 4
124: #define CB 8
125: #define QB 16
126: #define WB 32
127: char fastab[ ALFSIZ ];
128: char slotab[ ALFSIZ ];
129: char *ptrtab;
130: #define isslo ( ptrtab == ( slotab + COFF ) )
131: #define isid(a) ( ( fastab + COFF )[a] & IB )
132: #define isspc(a) ( ptrtab[a] & SB )
133: #define isnum(a) ( ( fastab + COFF )[a] & NB )
134: #define iscom(a) ( ( fastab + COFF )[a] & CB )
135: #define isquo(a) ( ( fastab + COFF )[a] & QB )
136: #define iswarn(a) ( ( fastab + COFF )[a] & WB )
137:
138: #define eob(a) ( ( a ) >= pend )
139: #define bob(a) ( pbeg >= ( a ) )
140:
141: char buffer[ NCPS + BUFSIZ + BUFSIZ + NCPS ];
142:
143: # define MAXNEST 12 /* max number of nested #include's */
144: # define MAXFRE 14 /* max buffers of macro pushback */
145:
146: #ifdef pdp11
147: # define SBSIZE 24000
148: #else
149: /* The idea here is to define the buffer to have a certain size
150: ** (the literal number) plus enough room for slop and taking side buffers
151: ** out to hold processing interrupted by #include's. The cost of side
152: ** buffers is particularly noticable on an Amdahl, where BUFSIZ is 4096.
153: */
154: # define SBSIZE (21000 + (MAXFRE+1)*BUFSIZ)
155: #endif
156:
157: char sbf[ SBSIZE ];
158: char *savch = sbf;
159:
160: # define DROP '\376' /* special character not legal ASCII or EBCDIC */
161: # define WARN DROP
162: # define SAME 0
163: # define MAXINC 100 /* max number of directories for -I options */
164: # define MAXFRM 31 /* max number of formals/actuals to a macro */
165:
166: static char warnc = WARN;
167:
168: int mactop, fretop;
169: char *instack[ MAXFRE ], *bufstack[ MAXFRE ], *endbuf[ MAXFRE ];
170:
171: int plvl; /* parenthesis level during scan for macro actuals */
172: int maclin; /* line number of macro call requiring actuals */
173: char *macfil; /* file name of macro call requiring actuals */
174: char *macnam; /* name of macro requiring actuals */
175: int maclvl; /* # calls since last decrease in nesting level */
176: char *macforw; /* pointer which must be exceeded to decrease nesting level */
177: int macdam; /* offset to macforw due to buffer shifting */
178:
179: #if tgp
180: int tgpscan; /* flag for dump(); */
181: #endif
182:
183: STATIC int inctop[ MAXNEST ];
184: STATIC char *fnames[ MAXNEST ];
185: STATIC char *fdates[ MAXNEST ]; /* for -M option */
186: STATIC char *dirnams[ MAXNEST ]; /* actual directory of #include files */
187: STATIC FILE *fins[ MAXNEST ];
188: STATIC int lineno[ MAXNEST ];
189:
190: STATIC char *dirs[ MAXINC ]; /* -I and <> directories */
191: STATIC char *dfltdir = (char *) 0; /* user-supplied default (like /usr/include) */
192: char *copy(), *subst(), *trmdir(), *strchr();
193: char *chkend(), *getfdate(), *findfdate();
194: struct symtab *stsym();
195: STATIC FILE *fin = stdin;
196: STATIC FILE *fout = stdout;
197: STATIC int nd = 1;
198: STATIC int pflag; /* don't put out lines "# 12 foo.c" */
199: STATIC int mflag;
200: STATIC int passcom; /* don't delete comments */
201: STATIC int incomm; /* set while in comment so that EOF can be detected */
202: STATIC int rflag; /* allow macro recursion */
203: STATIC int print_incs; /* set to print out included filenames */
204: STATIC int ifno;
205: # define NPREDEF 20
206: STATIC char *prespc[ NPREDEF ];
207: STATIC char **predef = prespc;
208: STATIC char *punspc[ NPREDEF ];
209: STATIC char **prund = punspc;
210: STATIC int exfail;
211: struct symtab
212: {
213: char *name;
214: char *value;
215: } *lastsym, *lookup(), *slookup();
216:
217: # if gcos
218: # include <setjmp.h>
219: static jmp_buf env;
220: # define main mainpp
221: # undef exit
222: # define exit(S) longjmp(env, 1)
223: # define symsiz 500
224: # define LINEFORM "# %d %s\n"
225: # define ERRFORM "*%c* %s, line "
226: # else
227: # define symsiz 2000
228: # define LINEFORM "# %d \"%s%s\"\n"
229: # define ERRFORM "*%c* \"%s%s\", line "
230: # endif
231: STATIC struct symtab stab[ symsiz ];
232:
233: STATIC struct symtab *defloc;
234: STATIC struct symtab *udfloc;
235: STATIC struct symtab *incloc;
236: STATIC struct symtab *ifloc;
237: STATIC struct symtab *elsloc;
238: STATIC struct symtab *eifloc;
239: STATIC struct symtab *elifloc;
240: STATIC struct symtab *ifdloc;
241: STATIC struct symtab *ifnloc;
242: STATIC struct symtab *ysysloc;
243: STATIC struct symtab *varloc;
244: STATIC struct symtab *lneloc;
245: STATIC struct symtab *ulnloc;
246: STATIC struct symtab *uflloc;
247: STATIC struct symtab *clsloc;
248: STATIC struct symtab *idtloc;
249: STATIC struct symtab *pragmaloc;
250: STATIC int trulvl;
251: STATIC int flslvl;
252: #define MAX_DEPTH 500 /* max of trulvl + flslvl */
253: #define SEEN_ELSE 0x1
254: #define TRUE_ELIF 0x2
255: STATIC char ifelstk[MAX_DEPTH];
256:
257: /*
258: * To facilitate the handling of different cpp's and cross cpp's,
259: * the sets of mutually exclusive predefined are placed into lists.
260: * The value used from these lists are set when building from the
261: * command line.
262: */
263: #define MAX_PD_MACH 13 /* set so it is where PD_MY_MACH is at */
264: #define D_tss 0 /*define table indexes */
265: #define D_os 1
266: #define D_mert 2
267: #define D_RT 3
268: #define D_RES 4
269: #define D_interdata 5
270: #define D_pdp11 6
271: #define D_vax 7
272: #define D_u370 8
273: #define D_u3b 9
274: #define D_u3b5 10
275: #define D_u3b2 11
276: #define D_u3b20d 12
277: #define D_newmach MAX_PD_MACH
278: #define D_nomach MAX_PD_MACH
279:
280: char *pdef_mach[MAX_PD_MACH+2] = /* choose using PD_MACH */
281: {
282: /*
283: * The following are ``machines'' for historical reasons only.
284: */
285: "tss", "os", "mert",
286: "RT", "RES",
287: /* These are the currently supported machines */
288: "interdata", "pdp11", "vax",
289: "u370", "u3b", "u3b5",
290: "u3b2", "u3b20d",
291: PD_MY_MACH, /* for adding "own" machine */
292: 0
293: };
294:
295: #define MAX_PD_SYS 4 /* set so that it is where PD_MY_SYS is at */
296: #define D_unix 0
297: #define D_gcos 1
298: #define D_ibm 2
299: #define D_DMERT 3
300: #define D_newsys MAX_PD_SYS
301: #define D_nosys MAX_PD_SYS
302:
303: char *pdef_sys[MAX_PD_SYS+2] = /* choose using PD_SYS */
304: {
305: "unix",
306: "gcos",
307: "ibm",
308: "DMERT",
309: PD_MY_SYS, /* for adding "own" system */
310: 0
311: };
312: #if PD_MACH < 0 || PD_MACH > MAX_PD_MACH
313: # include "*** PD_MACH set illegally ***"
314: #endif
315: #if PD_SYS < 0 || PD_SYS > MAX_PD_SYS
316: # include "*** PD_SYS set illegally ***"
317: #endif
318:
319:
320:
321: sayline()
322: {
323: if ( pflag == 0 )
324: fprintf( fout, LINEFORM, lineno[ifno], fnames[ifno] ,fdates[ifno] );
325: }
326:
327: /* data structure guide
328: /*
329: /* most of the scanning takes place in the buffer:
330: /*
331: /* (low address) (high address)
332: /* pbeg pbuf pend
333: /* | <-- BUFSIZ chars --> | <-- BUFSIZ chars --> |
334: /* _______________________________________________________________________
335: /* |_______________________________________________________________________|
336: /* | | |
337: /* |<-- waiting -->| |<-- waiting -->
338: /* | to be |<-- current -->| to be
339: /* | written | token | scanned
340: /* | | |
341: /* outp inp p
342: /*
343: /* *outp first char not yet written to output file
344: /* *inp first char of current token
345: /* *p first char not yet scanned
346: /*
347: /* macro expansion: write from *outp to *inp (chars waiting to be written),
348: /* ignore from *inp to *p (chars of the macro call), place generated
349: /* characters in front of *p (in reverse order), update pointers,
350: /* resume scanning.
351: /*
352: /* symbol table pointers point to just beyond the end of macro definitions;
353: /* the first preceding character is the number of formal parameters.
354: /* the appearance of a formal in the body of a definition is marked by
355: /* 2 chars: the char WARN, and a char containing the parameter number.
356: /* the first char of a definition is preceded by a zero character.
357: /*
358: /* when macro expansion attempts to back up over the beginning of the
359: /* buffer, some characters preceding *pend are saved in a side buffer,
360: /* the address of the side buffer is put on 'instack', and the rest
361: /* of the main buffer is moved to the right. the end of the saved buffer
362: /* is kept in 'endbuf' since there may be nulls in the saved buffer.
363: /*
364: /* similar action is taken when an 'include' statement is processed,
365: /* except that the main buffer must be completely emptied. the array
366: /* element 'inctop[ifno]' records the last side buffer saved when
367: /* file 'ifno' was included. these buffers remain dormant while
368: /* the file is being read, and are reactivated at end-of-file.
369: /*
370: /* instack[0 : mactop] holds the addresses of all pending side buffers.
371: /* instack[inctop[ifno]+1 : mactop-1] holds the addresses of the side
372: /* buffers which are "live"; the side buffers instack[0 : inctop[ifno]]
373: /* are dormant, waiting for end-of-file on the current file.
374: /*
375: /* space for side buffers is obtained from 'savch' and is never returned.
376: /* bufstack[0:fretop-1] holds addresses of side buffers which
377: /* are available for use.
378: */
379:
380: dump()
381: {
382: /* write part of buffer which lies between outp and inp .
383: /* this should be a direct call to 'write', but the system slows
384: /* to a crawl if it has to do an unaligned copy. thus we buffer.
385: /*? this silly loop is 15% of the total time, thus even the 'putc'
386: /*? macro is too slow.
387: */
388: register char *p1;
389: register FILE *f;
390: #if tgp
391: register char *p2;
392: #endif
393:
394: if ( ( p1 = outp ) == inp || flslvl != 0 )
395: return;
396: #if tgp
397: # define MAXOUT 80
398: if ( !tgpscan ) /* scan again to insure <= MAXOUT
399: { /* chars between linefeeds */
400: register char c, *pblank;
401: char savc, stopc, brk;
402:
403: tgpscan = 1;
404: brk = stopc = pblank = 0;
405: p2 = inp;
406: savc = *p2;
407: *p2 = '\0';
408: while ( c = *p1++ )
409: {
410: if ( c == '\\' )
411: c = *p1++;
412: if ( stopc == c )
413: stopc = 0;
414: else if ( c == '"' || c == '\'' )
415: stopc = c;
416: if ( p1 - outp > MAXOUT && pblank != 0 )
417: {
418: *pblank++ = '\n';
419: inp = pblank;
420: dump();
421: brk = 1;
422: pblank = 0;
423: }
424: if ( c == ' ' && stopc == 0 )
425: pblank = p1 - 1;
426: }
427: if ( brk )
428: sayline();
429: *p2 = savc;
430: inp = p2;
431: p1 = outp;
432: tgpscan = 0;
433: }
434: #endif
435: f = fout;
436: # if gcos
437: /* filter out "$ program c" card if first line of input */
438: /* gmatch is a simple pattern matcher in the GCOS Standard Library */
439: {
440: static int gmfirst = 0;
441:
442: if ( !gmfirst )
443: {
444: ++gmfirst;
445: if ( gmatch( p1, "^$*program[ \t]*c*") )
446: p1 = strchr( p1, '\n' );
447: }
448: }
449: # endif
450: while (p1 < inp)
451: putc(*p1++, f);
452: outp = p1;
453: }
454:
455: char *
456: refill( p )
457: register char *p;
458: {
459: /* dump buffer. save chars from inp to p. read into buffer at pbuf,
460: /* contiguous with p. update pointers, return new p.
461: */
462: register char *np, *op;
463: register int ninbuf;
464:
465: dump();
466: /* slide current token to left of pbuf */
467: ninbuf = p - inp;
468: np = pbuf - ninbuf;
469: if ( bob( np + 1 ) )
470: {
471: pperror( "token too long" );
472: np = pbeg;
473: p = inp + BUFSIZ;
474: }
475: macdam += np - inp;
476: memcpy(np, inp, ninbuf);
477: p = np + ninbuf; /* usually pbuf - ninbuf */
478: outp = inp = np;
479: for ( ;; )
480: {
481: /* retrieve hunk of pushed-back macro text */
482: if ( mactop > inctop[ifno] )
483: {
484: op = instack[ --mactop ];
485: memcpy(pbuf, op, endbuf[mactop] - op);
486: pend = pbuf + (endbuf[mactop] - op) - 1;
487: /* make buffer space avail for 'include' processing */
488: if ( fretop < MAXFRE )
489: bufstack[fretop++] = instack[mactop];
490: return( p );
491: }
492: else /* get more text from file(s) */
493: {
494: maclvl = 0;
495: #if NOTDEF
496: if ( 0 < ( ninbuf = fread( pbuf, sizeof( char ), BUFSIZ, fin ) ) )
497: {
498: #else
499: /*
500: * very much faster, but don't remove stdio completely for now
501: * in vague search for compatibility
502: */
503: if ((ninbuf = read(fileno(fin), pbuf, BUFSIZ)) > 0) {
504: #endif
505: pend = pbuf + ninbuf;
506: *pend = '\0';
507: return( p );
508: }
509: /* end of #include file */
510: if ( ifno == 0 ) /* end of input */
511: {
512: if ( plvl != 0 )
513: {
514: int n = plvl, tlin = lineno[ifno];
515: char *tfil = fnames[ifno];
516:
517: lineno[ifno] = maclin;
518: fnames[ifno] = macfil;
519: pperror( "%s: unterminated macro call",
520: macnam );
521: lineno[ifno] = tlin;
522: fnames[ifno] = tfil;
523: np = p;
524: /*shut off unterminated quoted string*/
525: *np++ = '\n';
526: /* supply missing parens */
527: while ( --n >= 0 )
528: *np++ = ')';
529: pend = np;
530: *np = '\0';
531: if ( plvl < 0 )
532: plvl = 0;
533: return( p );
534: }
535: if ( incomm ) {
536: pperror( "Unexpected EOF in comment" );
537: /* undo flslvl bump when comment started */
538: if (flslvl) --flslvl;
539: }
540: if ( trulvl +flslvl > 0 )
541: pperror( "Unexpected EOF within #if, #ifdef or #ifndef" );
542: inp = p;
543: dump();
544: if ( fout && ferror( fout ) )
545: pperror( "Problems with writing output file; probably out of temp space" );
546: exit( exfail ? ( exfail ==
547: CLASSCODE ? CLASSCODE : 2 ) : 0 );
548: }
549: fclose( fin );
550: fin = fins[--ifno];
551: dirs[0] = dirnams[ifno];
552: sayline();
553: #ifdef CXREF
554: fprintf(outfp, "\"%s\"\n", fnames[ifno]);
555: #endif
556: }
557: }
558: }
559:
560: #define BEG 0
561: #define LF 1
562:
563: char *
564: cotoken( p )
565: register char *p;
566: {
567: register int c, i;
568: char quoc;
569: static int state = BEG;
570: static int speakup = 0;
571:
572: if ( state != BEG )
573: goto prevlf;
574: for ( ;; )
575: {
576: again:
577: while ( !isspc( c = *p++ ) )
578: ;
579: inp = p - 1;
580: switch ( c )
581: {
582: case 0:
583: if ( eob( --p ) )
584: {
585: p = refill( p );
586: goto again;
587: }
588: else
589: ++p; /* ignore null byte */
590: break;
591: case '|':
592: case '&':
593: for ( ;; ) /* sloscan only */
594: {
595: if ( *p++ == *inp )
596: break;
597: if ( eob( --p ) )
598: p = refill( p );
599: else
600: break;
601: }
602: break;
603: case '=':
604: case '!':
605: for ( ;; ) /* sloscan only */
606: {
607: if ( *p++ == '=' )
608: break;
609: if ( eob( --p ) )
610: p = refill( p );
611: else
612: break;
613: }
614: break;
615: case '<':
616: case '>':
617: for ( ;; ) /* sloscan only */
618: {
619: if ( *p++ == '=' || p[-2] == p[-1] )
620: break;
621: if ( eob( --p ) )
622: p = refill( p );
623: else
624: break;
625: }
626: break;
627: case '\\':
628: for ( ;; )
629: {
630: if ( *p++ == '\n' )
631: {
632: ++lineno[ifno];
633: break;
634: }
635: if ( eob( --p ) )
636: p = refill( p );
637: else
638: {
639: ++p;
640: break;
641: }
642: }
643: break;
644: case '/':
645: for ( ;; )
646: {
647: if ( *p++ == '*' ) /* comment */
648: {
649: incomm = 1;
650: if ( !passcom )
651: {
652: inp = p - 2;
653: dump();
654: ++flslvl;
655: }
656: for ( ;; )
657: {
658: while ( !iscom( *p++ ) )
659: ;
660: if ( p[-1] == '*' )
661: for ( ;; )
662: {
663: if ( *p++ == '/' )
664: goto endcom;
665: if ( eob( --p ) )
666: {
667: if ( !passcom )
668: {
669: inp = p;
670: p = refill( p );
671: }
672: /* split long comment */
673: else if ( ( p - inp ) >= BUFSIZ )
674: {
675: *p++ = '*';
676: *p++ = '/';
677: inp = p;
678: p = refill( p );
679: outp = inp = p -= 2;
680: *p++ = '/';
681: *p++ = '*';
682: }
683: else
684: p = refill( p );
685: }
686: else
687: break;
688: }
689: else if ( p[-1] == '\n' )
690: {
691: ++lineno[ifno];
692: if ( !passcom && flslvl <= 1 )
693: putc( '\n', fout );
694: }
695: else if ( eob( --p ) )
696: {
697: if ( !passcom )
698: {
699: inp = p;
700: p = refill( p );
701: }
702: /* split long comment */
703: else if ( ( p - inp ) >= BUFSIZ )
704: {
705: *p++ = '*';
706: *p++ = '/';
707: inp = p;
708: p = refill( p );
709: outp = inp = p -= 2;
710: *p++ = '/';
711: *p++ = '*';
712: }
713: else
714: p = refill( p );
715: }
716: else
717: ++p; /* ignore null byte */
718: }
719: endcom:
720: incomm = 0;
721: if ( !passcom )
722: {
723: outp = inp = p;
724: --flslvl;
725: goto again;
726: }
727: break;
728: }
729: if ( eob( --p ) )
730: p = refill( p );
731: else
732: break;
733: }
734: break;
735: # if gcos
736: case '`':
737: # endif
738: case '"':
739: case '\'':
740: quoc = p[-1];
741: for ( ;; )
742: {
743: while ( !isquo( *p++ ) )
744: ;
745: if ( p[-1] == quoc )
746: break;
747: if ( p[-1] == '\n' ) /* bare \n terminates quotation */
748: {
749: --p;
750: break;
751: }
752: if ( p[-1] == '\\' )
753: for ( ;; )
754: {
755: if ( *p++ == '\n' ) /* escaped \n ignored */
756: {
757: ++lineno[ifno];
758: break;
759: }
760: if ( eob( --p ) )
761: p = refill( p );
762: else
763: {
764: ++p;
765: break;
766: }
767: }
768: else if ( eob( --p ) )
769: p = refill( p );
770: else
771: ++p; /* it was a different quote character */
772: }
773: break;
774: case WARN:
775: {
776: int ii;
777:
778: dump();
779: speakup = 0;
780: for ( ii = sizeof(int) / sizeof(char); --ii >= 0; )
781: {
782: if ( eob( p ) )
783: p = refill( p );
784: speakup |= ( *p++ & 0xFF ) << ( ii * 8 );
785: }
786: inp = outp = p;
787: break;
788: }
789: case '\n':
790: ++lineno[ifno];
791: if ( isslo )
792: {
793: state=LF;
794: return( p );
795: }
796: prevlf:
797: if ( speakup )
798: {
799: inp = p;
800: dump();
801: lineno[ifno] = speakup + 1;
802: sayline();
803: speakup = 0;
804: }
805: state = BEG;
806: for ( ;; )
807: {
808: /*
809: * ignore formfeeds and vertical tabs
810: * which may be just before the SALT
811: */
812: #if NOTDEF
813: if ( *p == '\f' || *p == '\v' )
814: {
815: register char *s = p;
816:
817: while ( *++s == '\f' || *s == '\v' )
818: ;
819: if ( *s == SALT )
820: {
821: /*
822: * get the SALT to the front!
823: */
824: *s = *p;
825: *p = SALT;
826: }
827: }
828: #endif
829: if ( *p++ == SALT )
830: return( p );
831: if ( eob( inp = --p ) )
832: p = refill( p );
833: else
834: goto again;
835: }
836: case '0': case '1': case '2': case '3': case '4':
837: case '5': case '6': case '7': case '8': case '9':
838: for ( ;; )
839: {
840: while ( isnum( *p++ ) )
841: ;
842: if ( eob( --p ) )
843: p = refill( p );
844: else
845: break;
846: }
847: break;
848: case 'A': case 'B': case 'C': case 'D': case 'E':
849: case 'F': case 'G': case 'H': case 'I': case 'J':
850: case 'K': case 'L': case 'M': case 'N': case 'O':
851: case 'P': case 'Q': case 'R': case 'S': case 'T':
852: case 'U': case 'V': case 'W': case 'X': case 'Y':
853: case 'Z': case '_':
854: case 'a': case 'b': case 'c': case 'd': case 'e':
855: case 'f': case 'g': case 'h': case 'i': case 'j':
856: case 'k': case 'l': case 'm': case 'n': case 'o':
857: case 'p': case 'q': case 'r': case 's': case 't':
858: case 'u': case 'v': case 'w': case 'x': case 'y':
859: case 'z':
860: #if scw1
861: # define tmac1( c, bit ) if ( !xmac1( c, bit, & ) ) \
862: goto nomac
863: # define xmac1( c, bit, op ) ( ( macbit + COFF )[c] op ( bit ) )
864: #else
865: # define tmac1( c, bit )
866: # define xmac1( c, bit, op )
867: #endif
868:
869: #if scw2
870: # define tmac2( c0, c1, cpos ) if ( !xmac2( c0, c1, cpos, & ) ) \
871: goto nomac
872: # define xmac2( c0, c1, cpos, op ) \
873: ( ( macbit + COFF )[ ( t21 + COFF )[c0] + \
874: ( t22 + COFF )[c1]] op ( t23 + COFF + cpos )[c0] )
875: #else
876: # define tmac2( c0, c1, cpos )
877: # define xmac2( c0, c1, cpos, op )
878: #endif
879:
880: if ( flslvl )
881: goto nomac;
882: for ( ;; )
883: {
884: c = p[-1];
885: tmac1( c, b0 );
886: i = *p++;
887: if ( !isid( i ) )
888: goto endid;
889: tmac1( i, b1 );
890: tmac2( c, i, 0 );
891: c = *p++;
892: if ( !isid( c ) )
893: goto endid;
894: tmac1( c, b2 );
895: tmac2( i, c, 1 );
896: i = *p++;
897: if ( !isid( i ) )
898: goto endid;
899: tmac1( i, b3 );
900: tmac2( c, i, 2 );
901: c = *p++;
902: if ( !isid( c ) )
903: goto endid;
904: tmac1( c, b4 );
905: tmac2( i, c, 3 );
906: i = *p++;
907: if ( !isid( i ) )
908: goto endid;
909: tmac1( i, b5 );
910: tmac2( c, i, 4 );
911: c = *p++;
912: if ( !isid( c ) )
913: goto endid;
914: tmac1( c, b6 );
915: tmac2( i, c, 5 );
916: i = *p++;
917: if ( !isid( i ) )
918: goto endid;
919: tmac1( i, b7 );
920: tmac2( c, i, 6 );
921: tmac2( i, 0, 7 );
922: while ( isid( *p++ ) )
923: ;
924: if ( eob( --p ) )
925: {
926: refill( p );
927: p = inp + 1;
928: continue;
929: }
930: goto lokid;
931: endid:
932: if ( eob( --p ) )
933: {
934: refill( p );
935: p = inp + 1;
936: continue;
937: }
938: tmac2( p[-1], 0, -1 + ( p - inp ) );
939: lokid:
940: slookup( inp, p, 0 );
941: if ( newp )
942: {
943: p = newp;
944: goto again;
945: }
946: else
947: break;
948: nomac:
949: while ( isid( *p++ ) )
950: ;
951: if ( eob( --p ) )
952: {
953: p = refill( p );
954: goto nomac;
955: }
956: else
957: break;
958: }
959: break;
960: } /* end of switch */
961:
962: if ( isslo )
963: return( p );
964: } /* end of infinite loop */
965: }
966:
967: char *
968: skipbl( p ) /* get next non-blank token */
969: register char *p;
970: {
971: do
972: {
973: outp = inp = p;
974: p = cotoken( p );
975: }
976: while ( ( toktyp + COFF )[*inp] == BLANK );
977: return( p );
978: }
979:
980: char *
981: unfill( p )
982: register char *p;
983: {
984: /* take <= BUFSIZ chars from right end of buffer and put
985: /* them on instack. slide rest of buffer to the right,
986: /* update pointers, return new p.
987: */
988: register char *np, *op;
989: register int d;
990:
991: if ( mactop >= MAXFRE )
992: {
993: pperror( "%s: too much pushback", macnam );
994: p = inp = pend; /* begin flushing pushback */
995: dump();
996: while ( mactop > inctop[ifno] )
997: {
998: (void) refill( p );
999: p = inp = pend;
1000: dump();
1001: }
1002: }
1003: if ( fretop > 0 )
1004: np = bufstack[--fretop];
1005: else
1006: {
1007: np = savch;
1008: savch += BUFSIZ;
1009: if ( savch >= sbf + SBSIZE )
1010: {
1011: pperror( "no space" );
1012: exit( exfail ? ( exfail == CLASSCODE ? CLASSCODE : 2 )
1013: : 0 );
1014: }
1015: *savch++ = '\0';
1016: }
1017: instack[mactop] = np;
1018: op = pend - BUFSIZ;
1019: if ( op < p )
1020: op = p;
1021: memcpy(np, op, pend - op);
1022: np += pend - op;
1023: *np++ = 0;
1024: endbuf[mactop++] = np; /* mark end of saved text */
1025: np = pbuf + BUFSIZ;
1026: op = pend - BUFSIZ;
1027: pend = np;
1028: if ( op < p )
1029: op = p;
1030: while ( outp < op ) /* slide over new */
1031: *--np = *--op;
1032: if ( bob( np ) )
1033: pperror( "token too long" );
1034: d = np - outp;
1035: outp += d;
1036: inp += d;
1037: macdam += d;
1038: return( p + d );
1039: }
1040:
1041: char *
1042: doincl( p )
1043: register char *p;
1044: {
1045: int filok, inctype;
1046: register char *cp;
1047: char **dirp, *nfil;
1048: char filname[BUFSIZ];
1049:
1050: p = skipbl( p );
1051: cp = filname;
1052: if ( *inp++ == '<' ) /* special <> syntax */
1053: {
1054: inctype = 1;
1055: ++flslvl; /* prevent macro expansion */
1056: for ( ;; )
1057: {
1058: outp = inp = p;
1059: p = cotoken( p );
1060: if ( *inp == '\n' )
1061: {
1062: --p;
1063: *cp = '\0';
1064: break;
1065: }
1066: if ( *inp == '>' )
1067: {
1068: *cp = '\0';
1069: break;
1070: }
1071: # ifdef gimpel
1072: if ( *inp == '.' && !intss() )
1073: *inp = '#';
1074: # endif
1075: while ( inp < p )
1076: *cp++ = *inp++;
1077: }
1078: --flslvl; /* reenable macro expansion */
1079: }
1080: else if ( inp[-1] == '"' ) /* regular "" syntax */
1081: {
1082: inctype = 0;
1083: # ifdef gimpel
1084: while ( inp < p )
1085: {
1086: if ( *inp == '.' && !intss() )
1087: *inp = '#';
1088: *cp++ = *inp++;
1089: }
1090: # else
1091: while ( inp < p )
1092: *cp++ = *inp++;
1093: # endif
1094: if ( *--cp == '"' )
1095: *cp = '\0';
1096: }
1097: else
1098: {
1099: int ppwarn(), pperror();
1100: /* This is a warning if we're skipping, error if not. */
1101: (*(flslvl ? ppwarn : pperror))( "bad include syntax", 0 );
1102: inctype = 2;
1103: }
1104: /* flush current file to \n , then write \n */
1105:
1106: p = chkend( p, 1 );
1107:
1108: outp = inp = p;
1109:
1110: dump();
1111: if ( inctype == 2 || flslvl != 0 )
1112: return( p );
1113: /* look for included file */
1114: if ( ifno + 1 >= MAXNEST )
1115: {
1116: pperror( "Unreasonable include nesting", 0 );
1117: return( p );
1118: }
1119: if ( ( nfil = savch ) > sbf + SBSIZE - BUFSIZ )
1120: {
1121: pperror( "no space" );
1122: exit( exfail ? ( exfail == CLASSCODE ? CLASSCODE : 2 ) : 0 );
1123: }
1124:
1125: /* check for #include "/usr/include/..." */
1126: if (strncmp(filname, "/usr/include/", 13) == 0)
1127: ppwarn("#include of /usr/include/... may be non-portable");
1128:
1129: filok = 0;
1130: for ( dirp = dirs + inctype; *dirp; ++dirp )
1131: {
1132: if (
1133: # if gcos
1134: strchr( filname, '/' )
1135: # else
1136: filname[0] == '/'
1137: # endif
1138: || **dirp == '\0' )
1139: {
1140: strcpy( nfil, filname );
1141: }
1142: else
1143: {
1144: strcpy( nfil, *dirp );
1145: # if unix || gcos || DMERT
1146: strcat( nfil, "/" );
1147: # endif
1148: #ifdef ibm
1149: # ifndef gimpel
1150: strcat( nfil, "." );
1151: # endif
1152: #endif
1153: strcat( nfil, filname );
1154: }
1155: if ( NULL != ( fins[ifno + 1] = fopen( nfil, READ ) ) )
1156: {
1157: filok = 1;
1158: fin = fins[++ifno];
1159: if ( print_incs )
1160: fprintf( stderr, "%s\n", nfil );
1161: break;
1162: }
1163: }
1164: if ( filok == 0 )
1165: pperror( "Can't find include file %s", filname );
1166: else
1167: {
1168: lineno[ifno] = 1;
1169: fnames[ifno] = cp = nfil;
1170: while ( *cp++)
1171: ;
1172: savch = cp;
1173: fdates[ifno] = getfdate( fin );
1174: dirnams[ifno] = dirs[0] = trmdir( copy( nfil ) );
1175: sayline();
1176: #ifdef CXREF
1177: fprintf(outfp, "\"%s\"\n", fnames[ifno]);
1178: #endif
1179: /* save current contents of buffer */
1180: while ( !eob( p ) )
1181: p = unfill( p );
1182: inctop[ifno] = mactop;
1183: }
1184: return( p );
1185: }
1186:
1187: equfrm( a, p1, p2 )
1188: register char *a, *p1, *p2;
1189: {
1190: register char c;
1191: int flag;
1192:
1193: c = *p2;
1194: *p2 = '\0';
1195: flag = strcmp( a, p1 );
1196: *p2 = c;
1197: return( flag == SAME );
1198: }
1199:
1200: char *
1201: dodef( p ) /* process '#define' */
1202: char *p;
1203: {
1204: register char *pin, *psav, *cf;
1205: char **pf, **qf;
1206: int b, c, params;
1207: int ex_blank; /* used to ignore extra blanks in token-string */
1208: int sav_passcom = passcom; /* saved passcom, used to reset it */
1209: struct symtab *np;
1210: char *oldval, *oldsavch;
1211: char *formal[MAXFRM]; /* formal[n] is name of nth formal */
1212: char formtxt[BUFSIZ]; /* space for formal names */
1213:
1214: if ( savch > sbf + SBSIZE - BUFSIZ )
1215: {
1216: pperror( "too much defining" );
1217: return( p );
1218: }
1219: oldsavch = savch; /* to reclaim space if redefinition */
1220: ++flslvl; /* prevent macro expansion during 'define' */
1221: p = skipbl( p );
1222: pin = inp;
1223: if ( ( toktyp + COFF )[*pin] != IDENT )
1224: {
1225: if (*pin == '\n') --lineno[ifno];
1226: ppwarn( "illegal/missing macro name" );
1227: if (*pin == '\n') ++lineno[ifno];
1228: while ( *inp != '\n' )
1229: p = skipbl( p );
1230: --flslvl; /* restore expansion */
1231: return( p );
1232: }
1233: np = slookup( pin, p, 1 );
1234: if ( oldval = np->value ) /* was previously defined */
1235: savch = oldsavch;
1236: #ifdef CXREF
1237: def(np->name, lineno[ifno]);
1238: #endif
1239: b = 1;
1240: cf = pin;
1241: while ( cf < p ) /* update macbit */
1242: {
1243: c = *cf++;
1244: xmac1( c, b, |= );
1245: b = ( b + b ) & 0xFF;
1246: if ( cf != p )
1247: xmac2( c, *cf, -1 + ( cf - pin ), |= );
1248: else
1249: xmac2( c, 0, -1 + ( cf - pin ), |= );
1250: }
1251: params = 0;
1252: outp = inp = p;
1253: p = cotoken( p );
1254: pin = inp;
1255: if ( *pin == '(' ) /* with parameters; identify the formals */
1256: {
1257: #ifdef CXREF
1258: newf(np->name, lineno[ifno]);
1259: #endif
1260: cf = formtxt;
1261: pf = formal;
1262: for ( ;; )
1263: {
1264: p = skipbl( p );
1265: pin = inp;
1266: if ( *pin == '\n' )
1267: {
1268: --lineno[ifno];
1269: --p;
1270: pperror( "%s: missing )", np->name );
1271: break;
1272: }
1273: if ( *pin == ')' )
1274: break;
1275: if ( *pin == ',' )
1276: continue;
1277: if ( ( toktyp + COFF )[*pin] != IDENT )
1278: {
1279: c = *p;
1280: *p = '\0';
1281: pperror( "bad formal: %s", pin );
1282: *p = c;
1283: }
1284: else if ( pf >= &formal[MAXFRM] )
1285: {
1286: c = *p;
1287: *p = '\0';
1288: pperror( "too many formals: %s", pin );
1289: *p = c;
1290: }
1291: else
1292: {
1293: *pf++ = cf;
1294: while ( pin < p )
1295: *cf++ = *pin++;
1296: *cf++ = '\0';
1297: ++params;
1298: #ifdef CXREF
1299: def(*(pf-1), lineno[ifno]);
1300: #endif
1301: }
1302: }
1303: if ( params == 0 ) /* #define foo() ... */
1304: --params;
1305: }
1306: else if ( *pin == '\n' )
1307: {
1308: --lineno[ifno];
1309: --p;
1310: }
1311: else
1312: p = inp; /* back up to scan non-blank next token */
1313: /*
1314: * remember beginning of macro body, so that we can
1315: * warn if a redefinition is different from old value.
1316: */
1317: oldsavch = psav = savch;
1318: passcom = 1; /* make cotoken() return comments as tokens */
1319: ex_blank = 1; /* must have some delimiter - might as well be blank */
1320: for ( ;; ) /* accumulate definition until linefeed */
1321: {
1322: outp = inp = p;
1323: p = cotoken( p );
1324: pin = inp;
1325: if ( *pin == '\\' && pin[1] == '\n' ) /* ignore escaped lf */
1326: {
1327: if ( !ex_blank ) /* replace it with a blank */
1328: {
1329: *psav++ = ' ';
1330: ex_blank = 1;
1331: }
1332: putc( '\n', fout );
1333: continue;
1334: }
1335: if ( *pin == '\n' )
1336: break;
1337: if ( ( toktyp + COFF )[*pin] == BLANK ) /* skip extra blanks */
1338: {
1339: if ( ex_blank )
1340: continue;
1341: *pin = ' '; /* force it to be a "real" blank */
1342: ex_blank = 1;
1343: }
1344: else
1345: ex_blank = 0;
1346: if ( *pin == '/' && pin[1] == '*' ) /* skip comment */
1347: { /* except for \n's */
1348: while ( pin < p )
1349: if ( *pin++ == '\n' )
1350: putc( '\n', fout );
1351: continue;
1352: }
1353: if ( params ) /* mark the appearance of formals in the definiton */
1354: {
1355: if ( ( toktyp + COFF )[*pin] == IDENT )
1356: {
1357: for ( qf = pf; --qf >= formal; )
1358: {
1359: if ( equfrm( *qf, pin, p ) )
1360: {
1361: #ifdef CXREF
1362: #ifndef NO_MACRO_FORMAL
1363: ref(*qf, lineno[ifno]);
1364: #endif
1365: #endif
1366: *psav++ = qf - formal + 1;
1367: *psav++ = WARN;
1368: pin = p;
1369: break;
1370: }
1371: }
1372: }
1373: /* inside quotation marks, too */
1374: else if ( *pin == '"' || *pin == '\''
1375: # if gcos
1376: || *pin == '`'
1377: # endif
1378: )
1379: {
1380: char quoc = *pin;
1381:
1382: for ( *psav++ = *pin++; pin < p && *pin != quoc; )
1383: {
1384: while ( pin < p && !isid( *pin ) )
1385: {
1386: if ( *pin == '\n'
1387: && pin[-1] == '\\' )
1388: {
1389: putc( '\n', fout );
1390: psav--; /* no \ */
1391: pin++; /* no \n */
1392: }
1393: else
1394: *psav++ = *pin++;
1395: }
1396: cf = pin;
1397: while ( cf < p && isid( *cf ) )
1398: ++cf;
1399: for ( qf = pf; --qf >= formal; )
1400: {
1401: if ( equfrm( *qf, pin, cf ) )
1402: {
1403: *psav++ = qf - formal + 1;
1404: *psav++ = WARN;
1405: pin = cf;
1406: break;
1407: }
1408: }
1409: while ( pin < cf )
1410: *psav++ = *pin++;
1411: }
1412: }
1413: }
1414: while ( pin < p )
1415: if ( *pin == '\n' && pin[-1] == '\\' )
1416: {
1417: putc( '\n', fout );
1418: psav--; /* no \ */
1419: pin++; /* no \n */
1420: }
1421: else
1422: *psav++ = *pin++;
1423: }
1424: passcom = sav_passcom; /* restore to "real" value */
1425: if ( psav[-1] == ' ' ) /* if token-string ended with a blank */
1426: psav--; /* then it is unnecessary - throw away */
1427: *psav++ = params;
1428: *psav++ = '\0';
1429: if ( ( cf = oldval ) != NULL ) /* redefinition */
1430: {
1431: --cf; /* skip no. of params, which may be zero */
1432: while ( *--cf ) /* go back to the beginning */
1433: ;
1434: if ( 0 != strcmp( ++cf, oldsavch ) ) /* redefinition different from old */
1435: {
1436: --lineno[ifno];
1437: ppwarn( "%s redefined", np->name );
1438: ++lineno[ifno];
1439: np->value = psav - 1;
1440: }
1441: else
1442: psav = oldsavch; /* identical redef.; reclaim space */
1443: }
1444: else
1445: np->value = psav - 1;
1446: --flslvl;
1447: inp = pin;
1448: savch = psav;
1449: return( p );
1450: }
1451:
1452: #define fasscan() ptrtab = fastab + COFF
1453: #define sloscan() ptrtab = slotab + COFF
1454: /* this macro manages the lookup of a macro name and produces
1455: ** a warning if the name is missing
1456: */
1457: #define LOOKUP(skipblank, flag) \
1458: ++flslvl; if (skipblank) p = skipbl(p); \
1459: if ( ( toktyp + COFF )[*inp] != IDENT ) \
1460: { \
1461: if (*inp == '\n') --lineno[ifno];\
1462: ppwarn( "illegal/missing macro name" ); \
1463: if (*inp == '\n') ++lineno[ifno];\
1464: while ( *inp != '\n' ) \
1465: p = skipbl( p ); \
1466: --flslvl; \
1467: continue; \
1468: } \
1469: np = slookup(inp,p,flag); --flslvl
1470:
1471: control( p ) /* find and handle preprocessor control lines */
1472: register char *p;
1473: {
1474: register struct symtab *np;
1475:
1476: for ( ;; )
1477: {
1478: fasscan();
1479: p = cotoken( p );
1480: if ( *inp == '\n' )
1481: ++inp;
1482: dump();
1483: sloscan();
1484: p = skipbl( p );
1485: *--inp = SALT;
1486: outp = inp;
1487: ++flslvl;
1488: np = slookup( inp, p, 0 );
1489: --flslvl;
1490: if ( np == defloc ) /* define */
1491: {
1492: if ( flslvl == 0 )
1493: {
1494: p = dodef( p );
1495: continue;
1496: }
1497: }
1498: else if ( np == incloc ) /* include */
1499: {
1500: p = doincl( p );
1501: continue;
1502: }
1503: else if ( np == ifnloc ) /* ifndef */
1504: {
1505: LOOKUP(1/*skipbl*/, 0/*flag*/); /* sets "np" */
1506: if ( flslvl == 0 && np->value == 0 )
1507: ++trulvl;
1508: else
1509: ++flslvl;
1510: if ( trulvl + flslvl >= MAX_DEPTH )
1511: pperror( "#if,ifdef,ifndef nesting too deep" );
1512: else
1513: ifelstk[trulvl + flslvl] =
1514: flslvl ? 0 : TRUE_ELIF;
1515: #ifdef CXREF
1516: ref(xcopy(inp, p), lineno[ifno]);
1517: #endif
1518: p = chkend( p, 1 );
1519: }
1520: else if ( np == ifdloc ) /* ifdef */
1521: {
1522: LOOKUP(1/*skipbl*/, 0/*flag*/); /* sets "np" */
1523: if ( flslvl == 0 && np->value != 0 )
1524: ++trulvl;
1525: else
1526: ++flslvl;
1527: if ( trulvl + flslvl >= MAX_DEPTH )
1528: pperror( "#if,ifdef,ifndef nesting too deep" );
1529: else
1530: ifelstk[trulvl + flslvl] =
1531: flslvl ? 0 : TRUE_ELIF;
1532: #ifdef CXREF
1533: ref(xcopy(inp, p), lineno[ifno]);
1534: #endif
1535: p = chkend( p, 1 );
1536: }
1537: else if ( np == eifloc ) /* endif */
1538: {
1539: if ( flslvl )
1540: {
1541: if ( --flslvl == 0 )
1542: sayline();
1543: }
1544: else if ( trulvl )
1545: --trulvl;
1546: else
1547: pperror( "If-less endif", 0 );
1548: p = chkend( p, 2 ); /* research mod; summit uses 1 */
1549: }
1550: else if ( np == elifloc ) /* elif */
1551: {
1552: if ( ifelstk[trulvl + flslvl] & SEEN_ELSE )
1553: pperror( "#elif following #else", 0 );
1554: if ( flslvl )
1555: {
1556: if ( --flslvl != 0 )
1557: ++flslvl;
1558: else
1559: {
1560: newp = p;
1561: #ifdef CXREF
1562: xline = lineno[ifno];
1563: #endif
1564: if ( ifelstk[trulvl + flslvl + 1] == 0
1565: && yyparse() )
1566: {
1567: ++trulvl;
1568: ifelstk[trulvl + flslvl] =
1569: TRUE_ELIF;
1570: sayline();
1571: }
1572: else
1573: ++flslvl;
1574: p = newp;
1575: }
1576: }
1577: else if ( trulvl )
1578: {
1579: ++flslvl;
1580: --trulvl;
1581: }
1582: else
1583: pperror( "If-less elif", 0 );
1584: }
1585: else if ( np == elsloc ) /* else */
1586: {
1587: if ( ifelstk[trulvl + flslvl] & SEEN_ELSE )
1588: pperror( "too many #else's", 0 );
1589: if ( flslvl )
1590: {
1591: if ( --flslvl != 0 )
1592: ++flslvl;
1593: else if ( ifelstk[trulvl + flslvl + 1] == 0 )
1594: {
1595: ++trulvl;
1596: sayline();
1597: }
1598: else
1599: ++flslvl;
1600: }
1601: else if ( trulvl )
1602: {
1603: ++flslvl;
1604: --trulvl;
1605: }
1606: else
1607: pperror( "If-less else", 0 );
1608: ifelstk[trulvl + flslvl] |= SEEN_ELSE;
1609: p = chkend( p, 1 );
1610: }
1611: else if ( np == udfloc ) /* undefine */
1612: {
1613: if ( flslvl == 0 )
1614: {
1615: LOOKUP(1/*skipbl*/, DROP); /* sets "np" */
1616: p = chkend( p, 1 );
1617: }
1618: else
1619: p = chkend( p, 2 );
1620: #ifdef CXREF
1621: ref(xcopy(inp, p), lineno[ifno]);
1622: #endif
1623: }
1624: else if ( np == ifloc ) /* if */
1625: {
1626: #if tgp
1627: pperror( " IF not implemented, true assumed", 0 );
1628: if ( flslvl == 0 )
1629: ++trulvl;
1630: else
1631: ++flslvl;
1632: #else
1633: newp = p;
1634: #ifdef CXREF
1635: xline = lineno[ifno];
1636: #endif
1637: if ( flslvl == 0 && yyparse() )
1638: ++trulvl;
1639: else
1640: ++flslvl;
1641: p = newp;
1642: if ( trulvl + flslvl >= MAX_DEPTH )
1643: pperror( "#if,ifdef,ifndef nesting too deep" );
1644: else
1645: ifelstk[trulvl + flslvl] =
1646: flslvl ? 0 : TRUE_ELIF;
1647: #endif
1648: }
1649: else if ( np == lneloc ) /* line */
1650: {
1651: if ( flslvl == 0 && pflag == 0 )
1652: {
1653: register char *s;
1654: register int ln;
1655:
1656: outp = inp = p;
1657: do_line:
1658: *--outp = '#';
1659: /*
1660: * make sure that the whole
1661: * directive has been read
1662: */
1663: s = p;
1664: while ( *s && *s != '\n' )
1665: s++;
1666: if ( eob( s ) )
1667: p = refill( s );
1668: /*
1669: * eat the line number
1670: */
1671: s = inp;
1672: while ( ( toktyp + COFF )[*s] == BLANK )
1673: s++;
1674: ln = 0;
1675: while ( isdigit( *s ) )
1676: ln = ln * 10 + *s++ - '0';
1677: if ( ln )
1678: lineno[ifno] = ln - 1;
1679: else
1680: pperror( "bad number for #line" );
1681: /*
1682: * eat the optional "filename"
1683: */
1684: while ( ( toktyp + COFF )[*s] == BLANK )
1685: s++;
1686: if ( *s != '\n' )
1687: {
1688: if ( *s != '"' )
1689: pperror( "bad file for #line" );
1690: else
1691: {
1692: register char *t = savch;
1693:
1694: for ( ;; )
1695: {
1696: if ( *++s == '"' )
1697: break;
1698: else if ( *s == '\n' ||
1699: *s == '\0' )
1700: {
1701: pperror( "bad file for #line" );
1702: break;
1703: }
1704: *t++ = *s;
1705: }
1706: *t++ = '\0';
1707: if ( strcmp( savch, fnames[ifno] ) )
1708: {
1709: fnames[ifno] = savch;
1710: fdates[ifno] = findfdate( &fnames[ifno] );
1711: savch = t;
1712: }
1713: }
1714: }
1715: /*
1716: * push it all along to be eventually printed
1717: */
1718: while ( *inp != '\n' )
1719: p = cotoken( p );
1720: continue;
1721: }
1722: }
1723: else if ( np == clsloc ) /* class */
1724: exfail = CLASSCODE; /* return value */
1725: else if ( np == idtloc ) /* ident */
1726: {
1727: if ( pflag == 0 )
1728: while ( *inp != '\n' ) /* just pass it along */
1729: p = cotoken( p );
1730: }
1731: #ifdef PRAGMA
1732: else if ( np == pragmaloc ) { /* pragma */
1733: while ( *inp != '\n' ) /* pass it all along */
1734: p = cotoken( p );
1735: }
1736: #endif
1737: else if ( *++inp == '\n' ) /* allows blank line after # */
1738: outp = inp;
1739: else if ( isdigit( *inp ) ) /* pass thru line directives */
1740: {
1741: outp = p = inp;
1742: goto do_line;
1743: }
1744: else
1745: pperror( "undefined control", 0 );
1746: /* flush to lf */
1747: ++flslvl;
1748: while ( *inp != '\n' )
1749: {
1750: outp = inp = p;
1751: p = cotoken( p );
1752: }
1753: --flslvl;
1754: }
1755: }
1756:
1757: struct symtab *
1758: stsym( s )
1759: register char *s;
1760: {
1761: char buf[BUFSIZ];
1762: register char *p;
1763:
1764: /* make definition look exactly like end of #define line */
1765: /* copy to avoid running off end of world when param list is at end */
1766: p = buf;
1767: while ( *p++ = *s++ )
1768: ;
1769: p = buf;
1770: while ( isid( *p++ ) ) /* skip first identifier */
1771: ;
1772: if ( *--p == '=' )
1773: {
1774: *p++ = ' ';
1775: while ( *p++ )
1776: ;
1777: }
1778: else
1779: {
1780: s = " 1";
1781: while ( *p++ = *s++ )
1782: ;
1783: }
1784: pend = p;
1785: *--p = '\n';
1786: sloscan();
1787: dodef( buf );
1788: return( lastsym );
1789: }
1790:
1791: struct symtab *
1792: ppsym( s ) /* kludge */
1793: char *s;
1794: {
1795: register struct symtab *sp;
1796:
1797: cinit = SALT;
1798: *savch++ = SALT;
1799: sp = stsym( s );
1800: --sp->name;
1801: cinit = 0;
1802: return( sp );
1803: }
1804:
1805:
1806: int yy_errflag; /* TRUE when pperror called by yyerror() */
1807:
1808: /* VARARGS1 */
1809: pperror( s, x, y )
1810: char *s;
1811: {
1812: if ( fnames[ifno][0] )
1813: # if gcos
1814: fprintf( stderr, ERRFORM, exfail >= 0 ? 'F' : 'W',fnames[ifno]);
1815: # else
1816: fprintf( stderr, "%s: ", fnames[ifno] );
1817: # endif
1818: fprintf( stderr, "%d: ", lineno[ifno] );
1819: fprintf( stderr, s, x, y );
1820: if ( yy_errflag )
1821: fprintf( stderr, " (in preprocessor if)\n" );
1822: else
1823: fprintf( stderr, "\n" );
1824: if ( exfail < CLASSCODE - 1 )
1825: ++exfail;
1826: }
1827:
1828: yyerror( s, a, b )
1829: char *s;
1830: {
1831: yy_errflag = 1;
1832: pperror( s, a, b );
1833: yy_errflag = 0;
1834: }
1835:
1836: ppwarn( s, x )
1837: char *s;
1838: {
1839: int fail = exfail;
1840:
1841: exfail = -1;
1842: pperror( s, x );
1843: exfail = fail;
1844: }
1845:
1846: struct symtab *
1847: lookup( namep, enterf )
1848: char *namep;
1849: {
1850: register char *np, *snp;
1851: register int c, i;
1852: int around;
1853: register struct symtab *sp;
1854:
1855: /* namep had better not be too long (currently, <=ncps chars) */
1856: np = namep;
1857: around = 0;
1858: i = cinit;
1859: while ( c = *np++ )
1860: i += i + c;
1861: c = i; /* c=i for register usage on pdp11 */
1862: c %= symsiz;
1863: if ( c < 0 )
1864: c += symsiz;
1865: sp = &stab[c];
1866: while ( snp = sp->name )
1867: {
1868: np = namep;
1869: while ( *snp++ == *np )
1870: if ( *np++ == '\0' )
1871: {
1872: if ( enterf == DROP )
1873: {
1874: sp->name[0] = DROP;
1875: sp->value = 0;
1876: }
1877: return( lastsym = sp );
1878: }
1879: if ( --sp < &stab[0] )
1880: if ( around )
1881: {
1882: pperror( "too many defines", 0 );
1883: exit( exfail ? ( exfail ==
1884: CLASSCODE ? CLASSCODE : 2 ) : 0 );
1885: }
1886: else
1887: {
1888: ++around;
1889: sp = &stab[symsiz - 1];
1890: }
1891: }
1892: if ( enterf == 1 )
1893: sp->name = namep;
1894: return( lastsym = sp );
1895: }
1896:
1897: struct symtab *
1898: slookup( p1, p2, enterf )
1899: register char *p1, *p2;
1900: int enterf;
1901: {
1902: register char *p3;
1903: char c2, c3;
1904: struct symtab *np;
1905:
1906: c2 = *p2; /* mark end of token */
1907: *p2 ='\0';
1908: if ( ( p2 - p1 ) > ncps )
1909: p3 = p1 + ncps;
1910: else
1911: p3 = p2;
1912: c3 = *p3; /* truncate to ncps chars or less */
1913: *p3 ='\0';
1914: if ( enterf == 1 )
1915: p1 = copy( p1 );
1916: np = lookup( p1, enterf );
1917: *p3 = c3;
1918: *p2 = c2;
1919: if ( np->value != 0 && flslvl == 0 )
1920: newp = subst( p2, np );
1921: else
1922: newp = 0;
1923: return( np );
1924: }
1925:
1926: char *
1927: subst( p, sp )
1928: register char *p;
1929: struct symtab *sp;
1930: {
1931: static char match[] = "%s: argument mismatch";
1932: register char *ca, *vp;
1933: int params;
1934: char *actual[MAXFRM]; /* actual[n] is text of nth actual */
1935: char acttxt[BUFSIZ]; /* space for actuals */
1936:
1937: if ( 0 == ( vp = sp->value ) )
1938: return( p );
1939: if ( ( p - macforw ) <= macdam )
1940: {
1941: if ( ++maclvl > symsiz && !rflag )
1942: {
1943: pperror( "%s: macro recursion", sp->name );
1944: return( p );
1945: }
1946: }
1947: else
1948: maclvl = 0; /* level decreased */
1949: macforw = p; /* new target for decrease in level */
1950: macdam = 0;
1951: macnam = sp->name;
1952: #ifdef CXREF
1953: ref(macnam, lineno[ifno]);
1954: #endif
1955: dump();
1956: if ( sp == ulnloc )
1957: {
1958: vp = acttxt;
1959: *vp++ = '\0';
1960: sprintf( vp, "%d", lineno[ifno] );
1961: while ( *vp++ )
1962: ;
1963: }
1964: else if ( sp == uflloc )
1965: {
1966: vp = acttxt;
1967: *vp++ = '\0';
1968: sprintf( vp, "\"%s\"", fnames[ifno] );
1969: while ( *vp++ )
1970: ;
1971: }
1972: if ( 0 != ( params = *--vp & 0xFF ) ) /*definition calls for params */
1973: {
1974: register char **pa;
1975: int dparams; /* parameters in definition */
1976:
1977: ca = acttxt;
1978: pa = actual;
1979: if ( params == 0xFF ) /* #define foo() ... */
1980: params = 0;
1981: dparams = params;
1982: sloscan();
1983: ++flslvl; /* no expansion during search for actuals */
1984: plvl = -1;
1985: maclin = lineno[ifno];
1986: macfil = fnames[ifno];
1987: do
1988: {
1989: p = skipbl( p );
1990: }
1991: while ( *inp == '\n' ); /* skip \n too */
1992: if ( *inp == '(' )
1993: {
1994: for ( plvl = 1; plvl != 0; )
1995: {
1996: *ca++ = '\0';
1997: for ( ;; )
1998: {
1999: outp = inp = p;
2000: p = cotoken( p );
2001: if ( *inp == '(' )
2002: ++plvl;
2003: if ( *inp == ')' && --plvl == 0 )
2004: {
2005: if ( ca > acttxt+1 )
2006: --params;
2007: break;
2008: }
2009: if ( plvl == 1 && *inp == ',' )
2010: {
2011: --params;
2012: break;
2013: }
2014: while ( inp < p )
2015: {
2016: /*
2017: * toss newlines in arguments
2018: * to macros - keep problems
2019: * to a minimum.
2020: * if a backslash is just
2021: * before the newline, assume
2022: * it is in a string and
2023: * leave it in.
2024: */
2025: if ( *inp == '\n'
2026: && inp[-1] != '\\' )
2027: {
2028: *inp = ' ';
2029: }
2030: *ca++ = *inp++;
2031: }
2032: if ( ca > &acttxt[BUFSIZ] )
2033: pperror( "%s: actuals too long", sp->name );
2034: }
2035: if ( pa >= &actual[MAXFRM] )
2036: ppwarn( match, sp->name );
2037: else
2038: *pa++ = ca;
2039: }
2040: }
2041: else { /* should have seen (, because def
2042: ** had args
2043: */
2044: ppwarn( match, sp->name );
2045: p = inp; /* back up to current token */
2046: }
2047: if ( maclin != lineno[ifno] ) /* embedded linefeeds in macro call */
2048: {
2049: int i, j = lineno[ifno];
2050:
2051: for ( i = sizeof( int ) / sizeof( char ); --i >= 0; )
2052: {
2053: if ( bob( p ) )
2054: {
2055: outp = inp = p;
2056: p = unfill( p );
2057: }
2058: *--p = j;
2059: j >>= 8;
2060: }
2061: if ( bob( p ) )
2062: {
2063: outp = inp = p;
2064: p = unfill( p );
2065: }
2066: *--p = warnc;
2067: }
2068: /* def with one arg and use with zero args is special ok case */
2069: if ( params < 0 || (params > 0 && dparams != 1) )
2070: ppwarn( match, sp->name );
2071: while ( --params >= 0 )
2072: *pa++ = "" + 1; /* null string for missing actuals */
2073: --flslvl;
2074: fasscan();
2075: }
2076: for ( ;; ) /* push definition onto front of input stack */
2077: {
2078: while ( !iswarn( *--vp ) )
2079: {
2080: if ( bob( p ) )
2081: {
2082: outp = inp = p;
2083: p = unfill( p );
2084: }
2085: *--p = *vp;
2086: }
2087: if ( *vp == warnc ) /* insert actual param */
2088: {
2089: ca = actual[*--vp - 1];
2090: while ( *--ca )
2091: {
2092: if ( bob( p ) )
2093: {
2094: outp = inp = p;
2095: p = unfill( p );
2096: }
2097: *--p = *ca;
2098: }
2099: }
2100: else
2101: break;
2102: }
2103: outp = inp = p;
2104: return( p );
2105: }
2106:
2107:
2108:
2109:
2110: char *
2111: trmdir( s )
2112: register char *s;
2113: {
2114: register char *p = s;
2115:
2116: while ( *p++ )
2117: ;
2118: --p;
2119: while ( p > s && *--p != '/' )
2120: ;
2121: # if unix || DMERT
2122: if ( p == s )
2123: *p++ = '.';
2124: # endif
2125: *p = '\0';
2126: return( s );
2127: }
2128:
2129: STATIC char *
2130: copy( s )
2131: register char *s;
2132: {
2133: register char *old;
2134:
2135: old = savch;
2136: while ( *savch++ = *s++ )
2137: ;
2138: return( old );
2139: }
2140:
2141: yywrap()
2142: {
2143: return( 1 );
2144: }
2145:
2146: main( argc, argv )
2147: char *argv[];
2148: {
2149: register int i, c;
2150: register char *p;
2151: char *tf, **cp2;
2152: int forclass = 0; /* 1 if C-with-classes selected */
2153:
2154: # if gcos
2155: if ( setjmp( env ) )
2156: return( exfail ? ( exfail == CLASSCODE ? CLASSCODE : 2 ) : 0 );
2157: # endif
2158: p = "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
2159: i = 0;
2160: while ( c = *p++ )
2161: {
2162: ( fastab + COFF )[c] |= IB | NB | SB;
2163: ( toktyp + COFF )[c] = IDENT;
2164: #if scw2
2165: /* 53 == 63-10; digits rarely appear in identifiers,
2166: /* and can never be the first char of an identifier.
2167: /* 11 == 53*53/sizeof(macbit) .
2168: */
2169: ++i;
2170: ( t21 + COFF )[c] = ( 53 * i ) / 11;
2171: ( t22 + COFF )[c] = i % 11;
2172: #endif
2173: }
2174: p = "0123456789.";
2175: while ( c = *p++ )
2176: {
2177: ( fastab + COFF )[c] |= NB | SB;
2178: ( toktyp + COFF )[c] = NUMBR;
2179: }
2180: # if gcos
2181: p = "\n\"'`/\\";
2182: # else
2183: p = "\n\"'/\\";
2184: # endif
2185: while ( c = *p++ )
2186: ( fastab + COFF )[c] |= SB;
2187: # if gcos
2188: p = "\n\"'`\\";
2189: # else
2190: p = "\n\"'\\";
2191: # endif
2192: while ( c = *p++ )
2193: ( fastab + COFF )[c] |= QB;
2194: p = "*\n";
2195: while ( c = *p++ )
2196: ( fastab + COFF)[c] |= CB;
2197: ( fastab + COFF )[warnc] |= WB | SB;
2198: ( fastab + COFF )['\0'] |= CB | QB | SB | WB;
2199: for ( i = ALFSIZ; --i >= 0; )
2200: slotab[i] = fastab[i] | SB;
2201: p = " \t\v\f\r"; /* note no \n; */
2202: while ( c = *p++ )
2203: ( toktyp + COFF )[c] = BLANK;
2204: #if scw2
2205: for ( ( t23 + COFF )[i = ALFSIZ + 7 - COFF] = 1; --i >= -COFF; )
2206: if ( ( ( t23 + COFF )[i] = ( t23 + COFF + 1 )[i] << 1 ) == 0 )
2207: ( t23 + COFF )[i] = 1;
2208: #endif
2209:
2210: # if unix || DMERT
2211: fnames[ifno = 0] = "";
2212: fdates[ifno = 0] = "";
2213: dirnams[0] = dirs[0] = ".";
2214: # endif
2215: # if ibm
2216: fnames[ifno = 0] = "";
2217: fdates[ifno = 0] = "";
2218: # endif
2219: # if gcos
2220: if ( inquire( stdin, _TTY ) )
2221: freopen( "*src", "rt", stdin );
2222: # endif
2223: # if gimpel || gcos
2224: fnames[ifno = 0] = (char *) inquire( stdin, _FILENAME );
2225: dirnams[0] = dirs[0] = trmdir( copy( fnames[0] ) );
2226: # endif
2227: for ( i = 1; i < argc; i++ )
2228: {
2229: switch ( argv[i][0] )
2230: {
2231: case '-':
2232: # if gcos
2233: /* case-independent on GCOS */
2234: switch ( toupper( argv[i][1] ) )
2235: # else
2236: switch( argv[i][1] )
2237: # endif
2238: {
2239: case 'M': /* research: filename+moddate*/
2240: mflag++;
2241: continue;
2242: case 'P':
2243: pflag++;
2244: case 'E':
2245: continue;
2246: case 'R':
2247: ++rflag;
2248: continue;
2249: case 'C':
2250: passcom++;
2251: continue;
2252: #ifdef CXREF
2253: case 'F':
2254: if ((outfp = fopen(argv[++i],"w")) == NULL)
2255: {
2256: fprintf(stderr, "Can't open %s\n",
2257: argv[i]);
2258: exit(1);
2259: }
2260: continue;
2261: #endif
2262: case 'D':
2263: if ( predef > prespc + NPREDEF )
2264: {
2265: pperror( "too many -D options, ignoring %s", argv[i] );
2266: continue;
2267: }
2268: /* ignore plain "-D" (no argument) */
2269: if ( *( argv[i] + 2 ) )
2270: *predef++ = argv[i] + 2;
2271: continue;
2272: case 'U':
2273: if ( prund > punspc + NPREDEF )
2274: {
2275: pperror( "too many -U options, ignoring %s", argv[i] );
2276: continue;
2277: }
2278: *prund++ = argv[i] + 2;
2279: continue;
2280: case 'I':
2281: if ( nd > MAXINC - 4 )
2282: pperror( "excessive -I file (%s) ignored", argv[i] );
2283: else
2284: dirs[nd++] = argv[i] + 2;
2285: continue;
2286: case 'Y':
2287: dfltdir = argv[i] + 2;
2288: continue;
2289: case '\0':
2290: continue;
2291: case 'T':
2292: ncps = 8; /* backward name compatabilty */
2293: continue;
2294: case 'H': /* print included filenames */
2295: print_incs++;
2296: continue;
2297: case 'W': /* enable C with classes */
2298: forclass = 1;
2299: continue;
2300: default:
2301: pperror( "unknown flag %s", argv[i] );
2302: continue;
2303: }
2304: default:
2305: if ( fin == stdin )
2306: {
2307: if ( NULL == ( fin = fopen( argv[i], READ ) ) )
2308: {
2309: pperror( "No source file %s", argv[i] );
2310: exit(2);
2311: }
2312: fnames[ifno] = copy( argv[i] );
2313: fdates[ifno] = getfdate( fin );
2314: #ifdef CXREF
2315: fprintf(outfp,"\"%s\"\n", fnames[ifno]);
2316: #endif
2317: dirs[0] = dirnams[ifno] = trmdir( argv[i] );
2318: # ifndef gcos
2319: /* too dangerous to have file name in same syntactic position
2320: be input or output file depending on file redirections,
2321: so force output to stdout, willy-nilly
2322: [i don't see what the problem is. jfr]
2323: */
2324: }
2325: else if ( fout == stdout )
2326: {
2327: static char _sobuf[BUFSIZ];
2328:
2329: if ( NULL == ( fout = fopen( argv[i], WRITE ) ) )
2330: {
2331: pperror( "Can't create %s", argv[i] );
2332: exit(2);
2333: }
2334: else
2335: {
2336: fclose( stdout );
2337: setbuf( fout, _sobuf );
2338: }
2339: # endif
2340: }
2341: else
2342: pperror( "extraneous name %s", argv[i] );
2343: }
2344: }
2345:
2346: fins[ifno] = fin;
2347: exfail = 0;
2348: /* after user -I files here are the standard include libraries */
2349: /* use user-supplied default first */
2350: if (dfltdir != (char *) 0)
2351: dirs[nd++] = dfltdir;
2352: else {
2353: # if unix || DMERT
2354: # if defined(SGSINC) || defined(DMERT)
2355: if ( strlen( SGSINC ) != 0 )
2356: dirs[nd++] = SGSINC; /* For cross cpp's */
2357: # endif
2358: # ifdef USRINC
2359: if ( strlen( USRINC ) != 0 )
2360: dirs[nd++] = USRINC; /* usually /usr/include */
2361: # endif
2362: # if !defined( SGSINC ) && !defined( USRINC )
2363: dirs[nd++] = "/usr/include";
2364: # endif
2365: # endif
2366: # if gcos
2367: dirs[nd++] = "cc/include";
2368: # endif
2369: # if ibm
2370: # ifndef gimpel
2371: dirs[nd++] = "BTL$CLIB";
2372: # endif
2373: # endif
2374: # ifdef gimpel
2375: dirs[nd++] = intss() ? "SYS3.C." : "";
2376: # endif
2377: # ifdef compool
2378: dirs[nd++] = "/compool";
2379: # endif
2380: }
2381: dirs[nd++] = 0;
2382: defloc = ppsym( "define" );
2383: udfloc = ppsym( "undef" );
2384: incloc = ppsym( "include" );
2385: elsloc = ppsym( "else" );
2386: eifloc = ppsym( "endif" );
2387: elifloc = ppsym( "elif" );
2388: ifdloc = ppsym( "ifdef" );
2389: ifnloc = ppsym( "ifndef" );
2390: ifloc = ppsym( "if" );
2391: lneloc = ppsym( "line" );
2392: if (forclass) /* only when C with classes enabled */
2393: clsloc = ppsym( "class" );
2394: idtloc = ppsym( "ident" );
2395: #ifdef PRAGMA
2396: pragmaloc = ppsym( "pragma" );
2397: #endif
2398: for ( i = sizeof( macbit ) / sizeof( macbit[0] ); --i >= 0; )
2399: macbit[i] = 0;
2400:
2401: if ( pdef_mach[PD_MACH] )
2402: ysysloc = stsym( pdef_mach[PD_MACH] );
2403: if ( pdef_sys[PD_SYS] )
2404: varloc = stsym( pdef_sys[PD_SYS] );
2405:
2406: tf = fnames[ifno]; /* do the -D and -U options now */
2407: fnames[ifno] = "command line";
2408: lineno[ifno] = 1;
2409: cp2 = prespc;
2410: while ( cp2 < predef )
2411: stsym( *cp2++ );
2412: cp2 = punspc;
2413: while ( cp2 < prund )
2414: {
2415: if ( p = strchr( *cp2, '=' ) )
2416: *p = '\0';
2417: /*
2418: * Truncate to ncps characters if needed.
2419: */
2420: if ( strlen( *cp2 ) > ncps )
2421: (*cp2)[ncps] = '\0';
2422: lookup( *cp2++, DROP );
2423: }
2424:
2425: ulnloc = stsym( "__LINE__" );
2426: uflloc = stsym( "__FILE__" );
2427: fnames[ifno] = tf;
2428: pbeg = buffer + ncps;
2429: pbuf = pbeg + BUFSIZ;
2430: pend = pbuf + BUFSIZ;
2431:
2432: trulvl = 0;
2433: flslvl = 0;
2434: lineno[0] = 1;
2435: sayline();
2436: outp = inp = pend;
2437: #ifdef CXREF
2438: ready = 1;
2439: #endif
2440: control( pend );
2441: if ( fout && ferror( fout ) )
2442: pperror( "Problems with output file; probably out of temp space" );
2443: exit( exfail ? ( exfail == CLASSCODE ? CLASSCODE : 2 ) : 0 );
2444: }
2445:
2446: #ifdef CXREF
2447: ref( name, line )
2448: char *name;
2449: int line;
2450: {
2451: #ifdef FLEXNAMES
2452: fprintf(outfp, "R%s\t%05d\n", name, line);
2453: #else
2454: fprintf(outfp, "R%.8s\t%05d\n", name, line);
2455: #endif
2456: }
2457:
2458: def( name, line )
2459: char *name;
2460: int line;
2461: {
2462: if (ready)
2463: #ifdef FLEXNAMES
2464: fprintf(outfp, "D%s\t%05d\n", name, line);
2465: #else
2466: fprintf(outfp, "D%.8s\t%05d\n", name, line);
2467: #endif
2468: }
2469:
2470: newf( name, line )
2471: char *name;
2472: int line;
2473: {
2474: #ifdef FLEXNAMES
2475: fprintf(outfp, "F%s\t%05d\n", name, line);
2476: #else
2477: fprintf(outfp, "F%.8s\t%05d\n", name, line);
2478: #endif
2479: }
2480:
2481: char *
2482: xcopy( ptr1, ptr2 )
2483: register char *ptr1, *ptr2;
2484: {
2485: static char name[NCPS];
2486: char *saveptr, ch;
2487: register char *ptr3 = name;
2488:
2489: /* locate end of name; save character there */
2490: if ((ptr2 - ptr1) > ncps)
2491: {
2492: saveptr = ptr1 + ncps;
2493: ch = *saveptr;
2494: *saveptr = '\0';
2495: }
2496: else {
2497: ch = *ptr2;
2498: *ptr2 = '\0';
2499: saveptr = ptr2;
2500: }
2501: while (*ptr3++ = *ptr1++) ; /* copy name */
2502: *saveptr = ch; /* replace character */
2503: return( name );
2504: }
2505: #endif
2506:
2507: /* Scan over the end of a directive, making sure there's no
2508: ** residual junk.
2509: **
2510: ** This code is a little messier than you might expect. To avoid bumping
2511: ** the line number when we hit the newline, print the message the first time
2512: ** we find we've got too many tokens.
2513: */
2514:
2515: char *
2516: chkend( p, ntoken )
2517: char * p;
2518: int ntoken; /* number of tokens at which to warn */
2519: {
2520: int extratokens = 0;
2521: int save_passcom = passcom;
2522:
2523: passcom = 0; /* ignore comments in this context */
2524: ++flslvl; /* don't expand anything */
2525:
2526: /* if at newline, force rescan to do end-of-line stuff */
2527: if (*inp == '\n')
2528: p = inp;
2529:
2530: for (;;) {
2531: p = skipbl(p); /* get next token */
2532: if (*inp == '\n')
2533: break; /* reached end */
2534: if(++extratokens == ntoken) /* hit number of extras; flag here */
2535: ppwarn("extra tokens (ignored) after directive");
2536: }
2537:
2538: /* restore comment flag */
2539: passcom = save_passcom;
2540: --flslvl; /* back to previous expansion level */
2541:
2542: return( p );
2543: }
2544:
2545: char *
2546: getfdate( fin )
2547: FILE *fin;
2548: {
2549: char date[ 10 ];
2550: struct stat sb;
2551: if ( !mflag )
2552: return "";
2553: fstat( fileno( fin ), &sb );
2554: sprintf( date, "@%ld", sb.st_mtime );
2555: return copy( date );
2556: }
2557:
2558: char *
2559: findfdate( fname )
2560: char *fname;
2561: {
2562: register char *s;
2563: for ( s = fname; *s; s++ )
2564: if ( *s == '@' ) {
2565: *s++ = 0;
2566: break;
2567: }
2568: return s;
2569: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.