Commit | Line | Data |
---|---|---|
66cbbe7c | 1 | #ifndef lint |
ba27d052 | 2 | static char sccsid[] = "@(#)cpp.c 1.8 %G%"; |
66cbbe7c | 3 | #endif lint |
9372792e | 4 | |
66cbbe7c RH |
5 | #ifdef FLEXNAMES |
6 | #define NCPS 128 | |
7 | #else | |
8 | #define NCPS 8 | |
9 | #endif | |
10 | ||
11 | # include "stdio.h" | |
9372792e | 12 | # include "ctype.h" |
66cbbe7c RH |
13 | /* C command |
14 | /* written by John F. Reiser | |
15 | /* July/August 1978 | |
16 | */ | |
17 | ||
18 | #define STATIC | |
19 | ||
20 | #define STDIN 0 | |
21 | #define STDOUT 1 | |
22 | #define STDERR 2 | |
23 | #define READ 0 | |
24 | #define WRITE 1 | |
25 | #define SALT '#' | |
26 | #ifndef BUFSIZ | |
27 | #define BUFSIZ 512 | |
28 | #endif | |
29 | ||
30 | char *pbeg,*pbuf,*pend; | |
31 | char *outp,*inp; | |
32 | char *newp; | |
33 | char cinit; | |
34 | ||
35 | /* some code depends on whether characters are sign or zero extended */ | |
36 | /* #if '\377' < 0 not used here, old cpp doesn't understand */ | |
8c7b88c5 | 37 | #if pdp11 | vax | mc68000 |
66cbbe7c RH |
38 | #define COFF 128 |
39 | #else | |
40 | #define COFF 0 | |
41 | #endif | |
42 | ||
43 | # if gcos | |
44 | #define ALFSIZ 512 /* alphabet size */ | |
45 | # else | |
46 | #define ALFSIZ 256 /* alphabet size */ | |
47 | # endif | |
48 | char macbit[ALFSIZ+11]; | |
49 | char toktyp[ALFSIZ]; | |
50 | #define BLANK 1 | |
51 | #define IDENT 2 | |
52 | #define NUMBR 3 | |
53 | ||
54 | /* a superimposed code is used to reduce the number of calls to the | |
55 | /* symbol table lookup routine. (if the kth character of an identifier | |
56 | /* is 'a' and there are no macro names whose kth character is 'a' | |
57 | /* then the identifier cannot be a macro name, hence there is no need | |
58 | /* to look in the symbol table.) 'scw1' enables the test based on | |
59 | /* single characters and their position in the identifier. 'scw2' | |
60 | /* enables the test based on adjacent pairs of characters and their | |
61 | /* position in the identifier. scw1 typically costs 1 indexed fetch, | |
62 | /* an AND, and a jump per character of identifier, until the identifier | |
63 | /* is known as a non-macro name or until the end of the identifier. | |
64 | /* scw1 is inexpensive. scw2 typically costs 4 indexed fetches, | |
65 | /* an add, an AND, and a jump per character of identifier, but it is also | |
66 | /* slightly more effective at reducing symbol table searches. | |
67 | /* scw2 usually costs too much because the symbol table search is | |
68 | /* usually short; but if symbol table search should become expensive, | |
69 | /* the code is here. | |
70 | /* using both scw1 and scw2 is of dubious value. | |
71 | */ | |
72 | #define scw1 1 | |
73 | #define scw2 0 | |
74 | ||
75 | #if scw2 | |
76 | char t21[ALFSIZ],t22[ALFSIZ],t23[ALFSIZ+NCPS]; | |
77 | #endif | |
78 | ||
79 | #if scw1 | |
80 | #define b0 1 | |
81 | #define b1 2 | |
82 | #define b2 4 | |
83 | #define b3 8 | |
84 | #define b4 16 | |
85 | #define b5 32 | |
86 | #define b6 64 | |
87 | #define b7 128 | |
88 | #endif | |
89 | ||
90 | #define IB 1 | |
91 | #define SB 2 | |
92 | #define NB 4 | |
93 | #define CB 8 | |
94 | #define QB 16 | |
95 | #define WB 32 | |
96 | char fastab[ALFSIZ]; | |
97 | char slotab[ALFSIZ]; | |
98 | char *ptrtab; | |
99 | #define isslo (ptrtab==(slotab+COFF)) | |
100 | #define isid(a) ((fastab+COFF)[a]&IB) | |
101 | #define isspc(a) (ptrtab[a]&SB) | |
102 | #define isnum(a) ((fastab+COFF)[a]&NB) | |
103 | #define iscom(a) ((fastab+COFF)[a]&CB) | |
104 | #define isquo(a) ((fastab+COFF)[a]&QB) | |
105 | #define iswarn(a) ((fastab+COFF)[a]&WB) | |
106 | ||
107 | #define eob(a) ((a)>=pend) | |
108 | #define bob(a) (pbeg>=(a)) | |
109 | ||
8c7b88c5 SL |
110 | # define cputc(a,b) if(!flslvl) putc(a,b) |
111 | ||
66cbbe7c RH |
112 | char buffer[NCPS+BUFSIZ+BUFSIZ+NCPS]; |
113 | ||
3ddb3a9f | 114 | # define SBSIZE 60000 /* std = 12000, wnj aug 1979 */ |
66cbbe7c RH |
115 | char sbf[SBSIZE]; |
116 | char *savch = sbf; | |
117 | ||
118 | # define DROP 0xFE /* special character not legal ASCII or EBCDIC */ | |
119 | # define WARN DROP | |
120 | # define SAME 0 | |
121 | # define MAXINC 10 | |
122 | # define MAXFRE 14 /* max buffers of macro pushback */ | |
123 | # define MAXFRM 31 /* max number of formals/actuals to a macro */ | |
124 | ||
125 | static char warnc = WARN; | |
126 | ||
127 | int mactop,fretop; | |
128 | char *instack[MAXFRE],*bufstack[MAXFRE],*endbuf[MAXFRE]; | |
129 | ||
130 | int plvl; /* parenthesis level during scan for macro actuals */ | |
131 | int maclin; /* line number of macro call requiring actuals */ | |
132 | char *macfil; /* file name of macro call requiring actuals */ | |
133 | char *macnam; /* name of macro requiring actuals */ | |
134 | int maclvl; /* # calls since last decrease in nesting level */ | |
135 | char *macforw; /* pointer which must be exceeded to decrease nesting level */ | |
136 | int macdam; /* offset to macforw due to buffer shifting */ | |
137 | ||
138 | #if tgp | |
139 | int tgpscan; /* flag for dump(); */ | |
140 | #endif | |
141 | ||
142 | STATIC int inctop[MAXINC]; | |
143 | STATIC char *fnames[MAXINC]; | |
144 | STATIC char *dirnams[MAXINC]; /* actual directory of #include files */ | |
145 | STATIC int fins[MAXINC]; | |
146 | STATIC int lineno[MAXINC]; | |
147 | ||
148 | STATIC char *dirs[10]; /* -I and <> directories */ | |
149 | char *strdex(), *copy(), *subst(), *trmdir(); | |
150 | struct symtab *stsym(); | |
151 | STATIC int fin = STDIN; | |
152 | STATIC FILE *fout = stdout; | |
153 | STATIC int nd = 1; | |
154 | STATIC int pflag; /* don't put out lines "# 12 foo.c" */ | |
8c7b88c5 | 155 | int passcom; /* don't delete comments */ |
66cbbe7c | 156 | STATIC int rflag; /* allow macro recursion */ |
61a8d43d KM |
157 | STATIC int mflag; /* generate makefile dependencies */ |
158 | STATIC char *infile; /* name of .o file to build dependencies from */ | |
159 | STATIC FILE *mout; /* file to place dependencies on */ | |
160 | #define START 1 | |
161 | #define CONT 2 | |
162 | #define BACK 3 | |
66cbbe7c RH |
163 | STATIC int ifno; |
164 | # define NPREDEF 20 | |
165 | STATIC char *prespc[NPREDEF]; | |
166 | STATIC char **predef = prespc; | |
167 | STATIC char *punspc[NPREDEF]; | |
168 | STATIC char **prund = punspc; | |
169 | STATIC int exfail; | |
170 | struct symtab { | |
171 | char *name; | |
172 | char *value; | |
173 | } *lastsym, *lookup(), *slookup(); | |
174 | ||
175 | # if gcos | |
176 | #include <setjmp.h> | |
177 | static jmp_buf env; | |
178 | # define main mainpp | |
179 | # undef exit | |
180 | # define exit(S) longjmp(env, 1) | |
181 | # define open(S,D) fileno(fopen(S, "r")) | |
182 | # define close(F) fclose(_f[F]) | |
183 | extern FILE *_f[]; | |
184 | # define symsiz 500 | |
185 | # else | |
8c7b88c5 | 186 | # define symsiz 2000 /* std = 500, wnj aug 1979 */ |
66cbbe7c RH |
187 | # endif |
188 | STATIC struct symtab stab[symsiz]; | |
189 | ||
190 | STATIC struct symtab *defloc; | |
191 | STATIC struct symtab *udfloc; | |
192 | STATIC struct symtab *incloc; | |
193 | STATIC struct symtab *ifloc; | |
194 | STATIC struct symtab *elsloc; | |
195 | STATIC struct symtab *eifloc; | |
196 | STATIC struct symtab *ifdloc; | |
197 | STATIC struct symtab *ifnloc; | |
198 | STATIC struct symtab *ysysloc; | |
199 | STATIC struct symtab *varloc; | |
200 | STATIC struct symtab *lneloc; | |
201 | STATIC struct symtab *ulnloc; | |
202 | STATIC struct symtab *uflloc; | |
203 | STATIC int trulvl; | |
204 | STATIC int flslvl; | |
205 | ||
61a8d43d KM |
206 | sayline(where) |
207 | int where; | |
208 | { | |
209 | if (mflag && where==START) fprintf(mout, "%s: %s\n", infile, fnames[ifno]); | |
66cbbe7c RH |
210 | if (pflag==0) fprintf(fout,"# %d \"%s\"\n", lineno[ifno], fnames[ifno]); |
211 | } | |
212 | ||
213 | /* data structure guide | |
214 | /* | |
215 | /* most of the scanning takes place in the buffer: | |
216 | /* | |
217 | /* (low address) (high address) | |
218 | /* pbeg pbuf pend | |
219 | /* | <-- BUFSIZ chars --> | <-- BUFSIZ chars --> | | |
220 | /* _______________________________________________________________________ | |
221 | /* |_______________________________________________________________________| | |
222 | /* | | | | |
223 | /* |<-- waiting -->| |<-- waiting --> | |
224 | /* | to be |<-- current -->| to be | |
225 | /* | written | token | scanned | |
226 | /* | | | | |
227 | /* outp inp p | |
228 | /* | |
229 | /* *outp first char not yet written to output file | |
230 | /* *inp first char of current token | |
231 | /* *p first char not yet scanned | |
232 | /* | |
233 | /* macro expansion: write from *outp to *inp (chars waiting to be written), | |
234 | /* ignore from *inp to *p (chars of the macro call), place generated | |
235 | /* characters in front of *p (in reverse order), update pointers, | |
236 | /* resume scanning. | |
237 | /* | |
238 | /* symbol table pointers point to just beyond the end of macro definitions; | |
239 | /* the first preceding character is the number of formal parameters. | |
240 | /* the appearance of a formal in the body of a definition is marked by | |
241 | /* 2 chars: the char WARN, and a char containing the parameter number. | |
242 | /* the first char of a definition is preceded by a zero character. | |
243 | /* | |
244 | /* when macro expansion attempts to back up over the beginning of the | |
245 | /* buffer, some characters preceding *pend are saved in a side buffer, | |
246 | /* the address of the side buffer is put on 'instack', and the rest | |
247 | /* of the main buffer is moved to the right. the end of the saved buffer | |
248 | /* is kept in 'endbuf' since there may be nulls in the saved buffer. | |
249 | /* | |
250 | /* similar action is taken when an 'include' statement is processed, | |
251 | /* except that the main buffer must be completely emptied. the array | |
252 | /* element 'inctop[ifno]' records the last side buffer saved when | |
253 | /* file 'ifno' was included. these buffers remain dormant while | |
254 | /* the file is being read, and are reactivated at end-of-file. | |
255 | /* | |
256 | /* instack[0 : mactop] holds the addresses of all pending side buffers. | |
257 | /* instack[inctop[ifno]+1 : mactop-1] holds the addresses of the side | |
258 | /* buffers which are "live"; the side buffers instack[0 : inctop[ifno]] | |
259 | /* are dormant, waiting for end-of-file on the current file. | |
260 | /* | |
261 | /* space for side buffers is obtained from 'savch' and is never returned. | |
262 | /* bufstack[0:fretop-1] holds addresses of side buffers which | |
263 | /* are available for use. | |
264 | */ | |
265 | ||
266 | dump() { | |
267 | /* write part of buffer which lies between outp and inp . | |
268 | /* this should be a direct call to 'write', but the system slows to a crawl | |
269 | /* if it has to do an unaligned copy. thus we buffer. this silly loop | |
270 | /* is 15% of the total time, thus even the 'putc' macro is too slow. | |
271 | */ | |
272 | register char *p1,*p2; register FILE *f; | |
273 | if ((p1=outp)==inp || flslvl!=0) return; | |
274 | #if tgp | |
275 | #define MAXOUT 80 | |
276 | if (!tgpscan) {/* scan again to insure <= MAXOUT chars between linefeeds */ | |
277 | register char c,*pblank; char savc,stopc,brk; | |
278 | tgpscan=1; brk=stopc=pblank=0; p2=inp; savc= *p2; *p2='\0'; | |
279 | while (c= *p1++) { | |
280 | if (c=='\\') c= *p1++; | |
281 | if (stopc==c) stopc=0; | |
282 | else if (c=='"' || c=='\'') stopc=c; | |
283 | if (p1-outp>MAXOUT && pblank!=0) { | |
284 | *pblank++='\n'; inp=pblank; dump(); brk=1; pblank=0; | |
285 | } | |
286 | if (c==' ' && stopc==0) pblank=p1-1; | |
287 | } | |
61a8d43d | 288 | if (brk) sayline(CONT); |
66cbbe7c RH |
289 | *p2=savc; inp=p2; p1=outp; tgpscan=0; |
290 | } | |
291 | #endif | |
292 | f=fout; | |
293 | # if gcos | |
294 | /* filter out "$ program c" card if first line of input */ | |
295 | /* gmatch is a simple pattern matcher in the GCOS Standard Library */ | |
296 | { static int gmfirst = 0; | |
297 | if (!gmfirst) { | |
298 | ++gmfirst; | |
299 | if (gmatch(p1, "^$*program[ \t]*c*")) | |
300 | p1 = strdex(p1, '\n'); | |
301 | } | |
302 | } | |
303 | # endif | |
304 | while (p1<inp) putc(*p1++,f); | |
305 | outp=p1; | |
306 | } | |
307 | ||
308 | char * | |
309 | refill(p) register char *p; { | |
310 | /* dump buffer. save chars from inp to p. read into buffer at pbuf, | |
311 | /* contiguous with p. update pointers, return new p. | |
312 | */ | |
313 | register char *np,*op; register int ninbuf; | |
314 | dump(); np=pbuf-(p-inp); op=inp; | |
315 | if (bob(np+1)) {pperror("token too long"); np=pbeg; p=inp+BUFSIZ;} | |
316 | macdam += np-inp; outp=inp=np; | |
317 | while (op<p) *np++= *op++; | |
318 | p=np; | |
319 | for (;;) { | |
320 | if (mactop>inctop[ifno]) {/* retrieve hunk of pushed-back macro text */ | |
321 | op=instack[--mactop]; np=pbuf; | |
322 | do {while (*np++= *op++);} while (op<endbuf[mactop]); pend=np-1; | |
323 | /* make buffer space avail for 'include' processing */ | |
324 | if (fretop<MAXFRE) bufstack[fretop++]=instack[mactop]; | |
325 | return(p); | |
326 | } else {/* get more text from file(s) */ | |
327 | maclvl=0; | |
328 | if (0<(ninbuf=read(fin,pbuf,BUFSIZ))) { | |
329 | pend=pbuf+ninbuf; *pend='\0'; | |
330 | return(p); | |
331 | } | |
332 | /* end of #include file */ | |
333 | if (ifno==0) {/* end of input */ | |
334 | if (plvl!=0) { | |
335 | int n=plvl,tlin=lineno[ifno]; char *tfil=fnames[ifno]; | |
336 | lineno[ifno]=maclin; fnames[ifno]=macfil; | |
337 | pperror("%s: unterminated macro call",macnam); | |
338 | lineno[ifno]=tlin; fnames[ifno]=tfil; | |
339 | np=p; *np++='\n'; /* shut off unterminated quoted string */ | |
340 | while (--n>=0) *np++=')'; /* supply missing parens */ | |
341 | pend=np; *np='\0'; if (plvl<0) plvl=0; | |
342 | return(p); | |
343 | } | |
28801486 SL |
344 | if (trulvl || flslvl) |
345 | pperror("missing endif"); | |
66cbbe7c RH |
346 | inp=p; dump(); exit(exfail); |
347 | } | |
61a8d43d | 348 | close(fin); fin=fins[--ifno]; dirs[0]=dirnams[ifno]; sayline(BACK); |
66cbbe7c RH |
349 | } |
350 | } | |
351 | } | |
352 | ||
353 | #define BEG 0 | |
354 | #define LF 1 | |
355 | ||
356 | char * | |
357 | cotoken(p) register char *p; { | |
358 | register int c,i; char quoc; | |
359 | static int state = BEG; | |
360 | ||
361 | if (state!=BEG) goto prevlf; | |
362 | for (;;) { | |
363 | again: | |
364 | while (!isspc(*p++)); | |
365 | switch (*(inp=p-1)) { | |
366 | case 0: { | |
367 | if (eob(--p)) {p=refill(p); goto again;} | |
368 | else ++p; /* ignore null byte */ | |
369 | } break; | |
370 | case '|': case '&': for (;;) {/* sloscan only */ | |
371 | if (*p++== *inp) break; | |
372 | if (eob(--p)) p=refill(p); | |
373 | else break; | |
374 | } break; | |
375 | case '=': case '!': for (;;) {/* sloscan only */ | |
376 | if (*p++=='=') break; | |
377 | if (eob(--p)) p=refill(p); | |
378 | else break; | |
379 | } break; | |
380 | case '<': case '>': for (;;) {/* sloscan only */ | |
381 | if (*p++=='=' || p[-2]==p[-1]) break; | |
382 | if (eob(--p)) p=refill(p); | |
383 | else break; | |
384 | } break; | |
385 | case '\\': for (;;) { | |
386 | if (*p++=='\n') {++lineno[ifno]; break;} | |
387 | if (eob(--p)) p=refill(p); | |
388 | else {++p; break;} | |
389 | } break; | |
390 | case '/': for (;;) { | |
391 | if (*p++=='*') {/* comment */ | |
392 | if (!passcom) {inp=p-2; dump(); ++flslvl;} | |
393 | for (;;) { | |
394 | while (!iscom(*p++)); | |
395 | if (p[-1]=='*') for (;;) { | |
396 | if (*p++=='/') goto endcom; | |
397 | if (eob(--p)) { | |
398 | if (!passcom) {inp=p; p=refill(p);} | |
399 | else if ((p-inp)>=BUFSIZ) {/* split long comment */ | |
400 | inp=p; p=refill(p); /* last char written is '*' */ | |
8c7b88c5 | 401 | cputc('/',fout); /* terminate first part */ |
66cbbe7c RH |
402 | /* and fake start of 2nd */ |
403 | outp=inp=p-=3; *p++='/'; *p++='*'; *p++='*'; | |
404 | } else p=refill(p); | |
405 | } else break; | |
406 | } else if (p[-1]=='\n') { | |
407 | ++lineno[ifno]; if (!passcom) putc('\n',fout); | |
408 | } else if (eob(--p)) { | |
409 | if (!passcom) {inp=p; p=refill(p);} | |
410 | else if ((p-inp)>=BUFSIZ) {/* split long comment */ | |
411 | inp=p; p=refill(p); | |
8c7b88c5 | 412 | cputc('*',fout); cputc('/',fout); |
66cbbe7c RH |
413 | outp=inp=p-=2; *p++='/'; *p++='*'; |
414 | } else p=refill(p); | |
415 | } else ++p; /* ignore null byte */ | |
416 | } | |
417 | endcom: | |
418 | if (!passcom) {outp=inp=p; --flslvl; goto again;} | |
419 | break; | |
420 | } | |
421 | if (eob(--p)) p=refill(p); | |
422 | else break; | |
423 | } break; | |
424 | # if gcos | |
425 | case '`': | |
426 | # endif | |
427 | case '"': case '\'': { | |
428 | quoc=p[-1]; | |
429 | for (;;) { | |
430 | while (!isquo(*p++)); | |
431 | if (p[-1]==quoc) break; | |
432 | if (p[-1]=='\n') {--p; break;} /* bare \n terminates quotation */ | |
433 | if (p[-1]=='\\') for (;;) { | |
434 | if (*p++=='\n') {++lineno[ifno]; break;} /* escaped \n ignored */ | |
435 | if (eob(--p)) p=refill(p); | |
436 | else {++p; break;} | |
437 | } else if (eob(--p)) p=refill(p); | |
438 | else ++p; /* it was a different quote character */ | |
439 | } | |
440 | } break; | |
441 | case '\n': { | |
442 | ++lineno[ifno]; if (isslo) {state=LF; return(p);} | |
443 | prevlf: | |
444 | state=BEG; | |
445 | for (;;) { | |
446 | if (*p++=='#') return(p); | |
447 | if (eob(inp= --p)) p=refill(p); | |
448 | else goto again; | |
449 | } | |
450 | } break; | |
451 | case '0': case '1': case '2': case '3': case '4': | |
452 | case '5': case '6': case '7': case '8': case '9': | |
453 | for (;;) { | |
454 | while (isnum(*p++)); | |
455 | if (eob(--p)) p=refill(p); | |
456 | else break; | |
457 | } break; | |
458 | case 'A': case 'B': case 'C': case 'D': case 'E': | |
459 | case 'F': case 'G': case 'H': case 'I': case 'J': | |
460 | case 'K': case 'L': case 'M': case 'N': case 'O': | |
461 | case 'P': case 'Q': case 'R': case 'S': case 'T': | |
462 | case 'U': case 'V': case 'W': case 'X': case 'Y': | |
463 | case 'Z': case '_': | |
464 | case 'a': case 'b': case 'c': case 'd': case 'e': | |
465 | case 'f': case 'g': case 'h': case 'i': case 'j': | |
466 | case 'k': case 'l': case 'm': case 'n': case 'o': | |
467 | case 'p': case 'q': case 'r': case 's': case 't': | |
468 | case 'u': case 'v': case 'w': case 'x': case 'y': | |
469 | case 'z': | |
470 | #if scw1 | |
471 | #define tmac1(c,bit) if (!xmac1(c,bit,&)) goto nomac | |
472 | #define xmac1(c,bit,op) ((macbit+COFF)[c] op (bit)) | |
473 | #else | |
474 | #define tmac1(c,bit) | |
475 | #define xmac1(c,bit,op) | |
476 | #endif | |
477 | ||
478 | #if scw2 | |
479 | #define tmac2(c0,c1,cpos) if (!xmac2(c0,c1,cpos,&)) goto nomac | |
480 | #define xmac2(c0,c1,cpos,op)\ | |
481 | ((macbit+COFF)[(t21+COFF)[c0]+(t22+COFF)[c1]] op (t23+COFF+cpos)[c0]) | |
482 | #else | |
483 | #define tmac2(c0,c1,cpos) | |
484 | #define xmac2(c0,c1,cpos,op) | |
485 | #endif | |
486 | ||
487 | if (flslvl) goto nomac; | |
488 | for (;;) { | |
489 | c= p[-1]; tmac1(c,b0); | |
490 | i= *p++; if (!isid(i)) goto endid; tmac1(i,b1); tmac2(c,i,0); | |
491 | c= *p++; if (!isid(c)) goto endid; tmac1(c,b2); tmac2(i,c,1); | |
492 | i= *p++; if (!isid(i)) goto endid; tmac1(i,b3); tmac2(c,i,2); | |
493 | c= *p++; if (!isid(c)) goto endid; tmac1(c,b4); tmac2(i,c,3); | |
494 | i= *p++; if (!isid(i)) goto endid; tmac1(i,b5); tmac2(c,i,4); | |
495 | c= *p++; if (!isid(c)) goto endid; tmac1(c,b6); tmac2(i,c,5); | |
496 | i= *p++; if (!isid(i)) goto endid; tmac1(i,b7); tmac2(c,i,6); | |
497 | tmac2(i,0,7); | |
498 | while (isid(*p++)); | |
499 | if (eob(--p)) {refill(p); p=inp+1; continue;} | |
500 | goto lokid; | |
501 | endid: | |
502 | if (eob(--p)) {refill(p); p=inp+1; continue;} | |
503 | tmac2(p[-1],0,-1+(p-inp)); | |
504 | lokid: | |
505 | slookup(inp,p,0); if (newp) {p=newp; goto again;} | |
506 | else break; | |
507 | nomac: | |
508 | while (isid(*p++)); | |
509 | if (eob(--p)) {p=refill(p); goto nomac;} | |
510 | else break; | |
511 | } break; | |
512 | } /* end of switch */ | |
513 | ||
514 | if (isslo) return(p); | |
515 | } /* end of infinite loop */ | |
516 | } | |
517 | ||
518 | char * | |
519 | skipbl(p) register char *p; {/* get next non-blank token */ | |
520 | do {outp=inp=p; p=cotoken(p);} while ((toktyp+COFF)[*inp]==BLANK); | |
521 | return(p); | |
522 | } | |
523 | ||
524 | char * | |
525 | unfill(p) register char *p; { | |
526 | /* take <= BUFSIZ chars from right end of buffer and put them on instack . | |
527 | /* slide rest of buffer to the right, update pointers, return new p. | |
528 | */ | |
529 | register char *np,*op; register int d; | |
530 | if (mactop>=MAXFRE) { | |
531 | pperror("%s: too much pushback",macnam); | |
532 | p=inp=pend; dump(); /* begin flushing pushback */ | |
533 | while (mactop>inctop[ifno]) {p=refill(p); p=inp=pend; dump();} | |
534 | } | |
535 | if (fretop>0) np=bufstack[--fretop]; | |
536 | else { | |
537 | np=savch; savch+=BUFSIZ; | |
538 | if (savch>=sbf+SBSIZE) {pperror("no space"); exit(exfail);} | |
539 | *savch++='\0'; | |
540 | } | |
541 | instack[mactop]=np; op=pend-BUFSIZ; if (op<p) op=p; | |
542 | for (;;) {while (*np++= *op++); if (eob(op)) break;} /* out with old */ | |
543 | endbuf[mactop++]=np; /* mark end of saved text */ | |
544 | np=pbuf+BUFSIZ; op=pend-BUFSIZ; pend=np; if (op<p) op=p; | |
545 | while (outp<op) *--np= *--op; /* slide over new */ | |
546 | if (bob(np)) pperror("token too long"); | |
547 | d=np-outp; outp+=d; inp+=d; macdam+=d; return(p+d); | |
548 | } | |
549 | ||
550 | char * | |
551 | doincl(p) register char *p; { | |
552 | int filok,inctype; | |
553 | register char *cp; char **dirp,*nfil; char filname[BUFSIZ]; | |
554 | ||
555 | p=skipbl(p); cp=filname; | |
556 | if (*inp++=='<') {/* special <> syntax */ | |
557 | inctype=1; | |
558 | ++flslvl; /* prevent macro expansion */ | |
559 | for (;;) { | |
560 | outp=inp=p; p=cotoken(p); | |
561 | if (*inp=='\n') {--p; *cp='\0'; break;} | |
562 | if (*inp=='>') { *cp='\0'; break;} | |
563 | # ifdef gimpel | |
564 | if (*inp=='.' && !intss()) *inp='#'; | |
565 | # endif | |
566 | while (inp<p) *cp++= *inp++; | |
567 | } | |
568 | --flslvl; /* reenable macro expansion */ | |
569 | } else if (inp[-1]=='"') {/* regular "" syntax */ | |
570 | inctype=0; | |
571 | # ifdef gimpel | |
572 | while (inp<p) {if (*inp=='.' && !intss()) *inp='#'; *cp++= *inp++;} | |
573 | # else | |
574 | while (inp<p) *cp++= *inp++; | |
575 | # endif | |
576 | if (*--cp=='"') *cp='\0'; | |
577 | } else {pperror("bad include syntax",0); inctype=2;} | |
578 | /* flush current file to \n , then write \n */ | |
579 | ++flslvl; do {outp=inp=p; p=cotoken(p);} while (*inp!='\n'); --flslvl; | |
580 | inp=p; dump(); if (inctype==2) return(p); | |
581 | /* look for included file */ | |
582 | if (ifno+1 >=MAXINC) { | |
583 | pperror("Unreasonable include nesting",0); return(p); | |
584 | } | |
585 | if((nfil=savch)>sbf+SBSIZE-BUFSIZ) {pperror("no space"); exit(exfail);} | |
586 | filok=0; | |
587 | for (dirp=dirs+inctype; *dirp; ++dirp) { | |
588 | if ( | |
589 | # if gcos | |
590 | strdex(filname, '/') | |
591 | # else | |
592 | filname[0]=='/' | |
593 | # endif | |
594 | || **dirp=='\0') strcpy(nfil,filname); | |
595 | else { | |
596 | strcpy(nfil,*dirp); | |
597 | # if unix || gcos | |
598 | strcat(nfil,"/"); | |
599 | # endif | |
600 | #ifdef ibm | |
601 | #ifndef gimpel | |
602 | strcat(nfil,"."); | |
603 | #endif | |
604 | #endif | |
605 | strcat(nfil,filname); | |
606 | } | |
607 | if (0<(fins[ifno+1]=open(nfil,READ))) { | |
608 | filok=1; fin=fins[++ifno]; break; | |
609 | } | |
610 | } | |
611 | if (filok==0) pperror("Can't find include file %s",filname); | |
612 | else { | |
613 | lineno[ifno]=1; fnames[ifno]=cp=nfil; while (*cp++); savch=cp; | |
614 | dirnams[ifno]=dirs[0]=trmdir(copy(nfil)); | |
61a8d43d | 615 | sayline(START); |
66cbbe7c RH |
616 | /* save current contents of buffer */ |
617 | while (!eob(p)) p=unfill(p); | |
618 | inctop[ifno]=mactop; | |
619 | } | |
620 | return(p); | |
621 | } | |
622 | ||
623 | equfrm(a,p1,p2) register char *a,*p1,*p2; { | |
624 | register char c; int flag; | |
625 | c= *p2; *p2='\0'; | |
626 | flag=strcmp(a,p1); *p2=c; return(flag==SAME); | |
627 | } | |
628 | ||
629 | char * | |
630 | dodef(p) char *p; {/* process '#define' */ | |
631 | register char *pin,*psav,*cf; | |
632 | char **pf,**qf; int b,c,params; struct symtab *np; | |
633 | char *oldval,*oldsavch; | |
634 | char *formal[MAXFRM]; /* formal[n] is name of nth formal */ | |
635 | char formtxt[BUFSIZ]; /* space for formal names */ | |
636 | ||
637 | if (savch>sbf+SBSIZE-BUFSIZ) {pperror("too much defining"); return(p);} | |
638 | oldsavch=savch; /* to reclaim space if redefinition */ | |
639 | ++flslvl; /* prevent macro expansion during 'define' */ | |
640 | p=skipbl(p); pin=inp; | |
641 | if ((toktyp+COFF)[*pin]!=IDENT) { | |
642 | ppwarn("illegal macro name"); while (*inp!='\n') p=skipbl(p); return(p); | |
643 | } | |
644 | np=slookup(pin,p,1); | |
645 | if (oldval=np->value) savch=oldsavch; /* was previously defined */ | |
646 | b=1; cf=pin; | |
647 | while (cf<p) {/* update macbit */ | |
648 | c= *cf++; xmac1(c,b,|=); b=(b+b)&0xFF; | |
649 | if (cf!=p) xmac2(c,*cf,-1+(cf-pin),|=); | |
650 | else xmac2(c,0,-1+(cf-pin),|=); | |
651 | } | |
652 | params=0; outp=inp=p; p=cotoken(p); pin=inp; | |
653 | if (*pin=='(') {/* with parameters; identify the formals */ | |
654 | cf=formtxt; pf=formal; | |
655 | for (;;) { | |
656 | p=skipbl(p); pin=inp; | |
657 | if (*pin=='\n') { | |
658 | --lineno[ifno]; --p; pperror("%s: missing )",np->name); break; | |
659 | } | |
660 | if (*pin==')') break; | |
661 | if (*pin==',') continue; | |
662 | if ((toktyp+COFF)[*pin]!=IDENT) { | |
663 | c= *p; *p='\0'; pperror("bad formal: %s",pin); *p=c; | |
664 | } else if (pf>= &formal[MAXFRM]) { | |
665 | c= *p; *p='\0'; pperror("too many formals: %s",pin); *p=c; | |
666 | } else { | |
667 | *pf++=cf; while (pin<p) *cf++= *pin++; *cf++='\0'; ++params; | |
668 | } | |
669 | } | |
670 | if (params==0) --params; /* #define foo() ... */ | |
671 | } else if (*pin=='\n') {--lineno[ifno]; --p;} | |
672 | /* remember beginning of macro body, so that we can | |
673 | /* warn if a redefinition is different from old value. | |
674 | */ | |
675 | oldsavch=psav=savch; | |
676 | for (;;) {/* accumulate definition until linefeed */ | |
677 | outp=inp=p; p=cotoken(p); pin=inp; | |
678 | if (*pin=='\\' && pin[1]=='\n') {putc('\n',fout); continue;} /* ignore escaped lf */ | |
679 | if (*pin=='\n') break; | |
680 | if (params) {/* mark the appearance of formals in the definiton */ | |
681 | if ((toktyp+COFF)[*pin]==IDENT) { | |
682 | for (qf=pf; --qf>=formal; ) { | |
683 | if (equfrm(*qf,pin,p)) { | |
684 | *psav++=qf-formal+1; *psav++=WARN; pin=p; break; | |
685 | } | |
686 | } | |
687 | } else if (*pin=='"' || *pin=='\'' | |
688 | # if gcos | |
689 | || *pin=='`' | |
690 | # endif | |
691 | ) {/* inside quotation marks, too */ | |
692 | char quoc= *pin; | |
693 | for (*psav++= *pin++; pin<p && *pin!=quoc; ) { | |
694 | while (pin<p && !isid(*pin)) *psav++= *pin++; | |
695 | cf=pin; while (cf<p && isid(*cf)) ++cf; | |
696 | for (qf=pf; --qf>=formal; ) { | |
697 | if (equfrm(*qf,pin,cf)) { | |
698 | *psav++=qf-formal+1; *psav++=WARN; pin=cf; break; | |
699 | } | |
700 | } | |
701 | while (pin<cf) *psav++= *pin++; | |
702 | } | |
703 | } | |
704 | } | |
705 | while (pin<p) *psav++= *pin++; | |
706 | } | |
707 | *psav++=params; *psav++='\0'; | |
708 | if ((cf=oldval)!=NULL) {/* redefinition */ | |
709 | --cf; /* skip no. of params, which may be zero */ | |
710 | while (*--cf); /* go back to the beginning */ | |
711 | if (0!=strcmp(++cf,oldsavch)) {/* redefinition different from old */ | |
712 | --lineno[ifno]; ppwarn("%s redefined",np->name); ++lineno[ifno]; | |
713 | np->value=psav-1; | |
714 | } else psav=oldsavch; /* identical redef.; reclaim space */ | |
715 | } else np->value=psav-1; | |
716 | --flslvl; inp=pin; savch=psav; return(p); | |
717 | } | |
718 | ||
719 | #define fasscan() ptrtab=fastab+COFF | |
720 | #define sloscan() ptrtab=slotab+COFF | |
721 | ||
722 | char * | |
723 | control(p) register char *p; {/* find and handle preprocessor control lines */ | |
724 | register struct symtab *np; | |
725 | for (;;) { | |
726 | fasscan(); p=cotoken(p); if (*inp=='\n') ++inp; dump(); | |
727 | sloscan(); p=skipbl(p); | |
728 | *--inp=SALT; outp=inp; ++flslvl; np=slookup(inp,p,0); --flslvl; | |
729 | if (np==defloc) {/* define */ | |
730 | if (flslvl==0) {p=dodef(p); continue;} | |
731 | } else if (np==incloc) {/* include */ | |
732 | if (flslvl==0) {p=doincl(p); continue;} | |
733 | } else if (np==ifnloc) {/* ifndef */ | |
734 | ++flslvl; p=skipbl(p); np=slookup(inp,p,0); --flslvl; | |
735 | if (flslvl==0 && np->value==0) ++trulvl; | |
736 | else ++flslvl; | |
737 | } else if (np==ifdloc) {/* ifdef */ | |
738 | ++flslvl; p=skipbl(p); np=slookup(inp,p,0); --flslvl; | |
739 | if (flslvl==0 && np->value!=0) ++trulvl; | |
740 | else ++flslvl; | |
741 | } else if (np==eifloc) {/* endif */ | |
61a8d43d | 742 | if (flslvl) {if (--flslvl==0) sayline(CONT);} |
66cbbe7c RH |
743 | else if (trulvl) --trulvl; |
744 | else pperror("If-less endif",0); | |
745 | } else if (np==elsloc) {/* else */ | |
746 | if (flslvl) { | |
747 | if (--flslvl!=0) ++flslvl; | |
61a8d43d | 748 | else {++trulvl; sayline(CONT);} |
66cbbe7c RH |
749 | } |
750 | else if (trulvl) {++flslvl; --trulvl;} | |
751 | else pperror("If-less else",0); | |
752 | } else if (np==udfloc) {/* undefine */ | |
753 | if (flslvl==0) { | |
754 | ++flslvl; p=skipbl(p); slookup(inp,p,DROP); --flslvl; | |
755 | } | |
756 | } else if (np==ifloc) {/* if */ | |
757 | #if tgp | |
758 | pperror(" IF not implemented, true assumed", 0); | |
759 | if (flslvl==0) ++trulvl; else ++flslvl; | |
760 | #else | |
761 | newp=p; | |
762 | if (flslvl==0 && yyparse()) ++trulvl; else ++flslvl; | |
763 | p=newp; | |
764 | #endif | |
765 | } else if (np==lneloc) {/* line */ | |
766 | if (flslvl==0 && pflag==0) { | |
9372792e | 767 | char *cp, *cp2, *savestring(); |
66cbbe7c | 768 | outp=inp=p; *--outp='#'; while (*inp!='\n') p=cotoken(p); |
9372792e RH |
769 | cp = outp + 1; |
770 | while (isspace(*cp) && cp < inp) | |
771 | cp++; | |
772 | while (isdigit(*cp) && cp < inp) | |
773 | cp++; | |
774 | while (*cp != '"' && cp < inp) | |
775 | cp++; | |
776 | if (cp < inp) { | |
777 | cp++; | |
778 | cp2 = cp; | |
779 | while (*cp2 != '"' && cp2 < inp) | |
780 | cp2++; | |
781 | fnames[ifno] = savestring(cp, cp2); | |
782 | } | |
66cbbe7c RH |
783 | continue; |
784 | } | |
785 | } else if (*++inp=='\n') outp=inp; /* allows blank line after # */ | |
786 | else pperror("undefined control",0); | |
787 | /* flush to lf */ | |
788 | ++flslvl; while (*inp!='\n') {outp=inp=p; p=cotoken(p);} --flslvl; | |
789 | } | |
790 | } | |
791 | ||
9372792e RH |
792 | char * |
793 | savestring(start, finish) | |
794 | register char *start, *finish; | |
795 | { | |
796 | char *retbuf; | |
797 | register char *cp; | |
798 | ||
799 | retbuf = (char *) calloc(finish - start + 1, sizeof (char)); | |
800 | cp = retbuf; | |
801 | while (start < finish) | |
802 | *cp++ = *start++; | |
803 | *cp = 0; | |
804 | return(retbuf); | |
805 | } | |
806 | ||
66cbbe7c RH |
807 | struct symtab * |
808 | stsym(s) register char *s; { | |
809 | char buf[BUFSIZ]; register char *p; | |
810 | ||
811 | /* make definition look exactly like end of #define line */ | |
812 | /* copy to avoid running off end of world when param list is at end */ | |
813 | p=buf; while (*p++= *s++); | |
814 | p=buf; while (isid(*p++)); /* skip first identifier */ | |
815 | if (*--p=='=') {*p++=' '; while (*p++);} | |
816 | else {s=" 1"; while (*p++= *s++);} | |
817 | pend=p; *--p='\n'; | |
818 | sloscan(); dodef(buf); return(lastsym); | |
819 | } | |
820 | ||
821 | struct symtab * | |
822 | ppsym(s) char *s; {/* kluge */ | |
823 | register struct symtab *sp; | |
824 | cinit=SALT; *savch++=SALT; sp=stsym(s); --sp->name; cinit=0; return(sp); | |
825 | } | |
826 | ||
827 | /* VARARGS1 */ | |
828 | pperror(s,x,y) char *s; { | |
829 | if (fnames[ifno][0]) fprintf(stderr, | |
830 | # if gcos | |
831 | "*%c* \"%s\", line ", exfail >= 0 ? 'F' : 'W', | |
832 | # else | |
833 | "%s: ", | |
834 | # endif | |
835 | fnames[ifno]); | |
836 | fprintf(stderr, "%d: ",lineno[ifno]); | |
837 | fprintf(stderr, s, x, y); | |
838 | fprintf(stderr,"\n"); | |
839 | ++exfail; | |
840 | } | |
841 | ||
842 | yyerror(s,a,b) char *s; { | |
843 | pperror(s,a,b); | |
844 | } | |
845 | ||
846 | ppwarn(s,x) char *s; { | |
847 | int fail = exfail; | |
848 | exfail = -1; | |
849 | pperror(s,x); | |
850 | exfail = fail; | |
851 | } | |
852 | ||
853 | struct symtab * | |
854 | lookup(namep, enterf) | |
855 | char *namep; | |
856 | { | |
857 | register char *np, *snp; | |
858 | register int c, i; int around; | |
859 | register struct symtab *sp; | |
860 | ||
861 | /* namep had better not be too long (currently, <=NCPS chars) */ | |
862 | np=namep; around=0; i=cinit; | |
863 | while (c= *np++) i += i+c; c=i; /* c=i for register usage on pdp11 */ | |
864 | c %= symsiz; if (c<0) c += symsiz; | |
865 | sp = &stab[c]; | |
866 | while (snp=sp->name) { | |
867 | np = namep; | |
868 | while (*snp++ == *np) if (*np++ == '\0') { | |
869 | if (enterf==DROP) {sp->name[0]= DROP; sp->value=0;} | |
870 | return(lastsym=sp); | |
871 | } | |
872 | if (--sp < &stab[0]) | |
873 | if (around) {pperror("too many defines", 0); exit(exfail);} | |
874 | else {++around; sp = &stab[symsiz-1];} | |
875 | } | |
876 | if (enterf==1) sp->name=namep; | |
877 | return(lastsym=sp); | |
878 | } | |
879 | ||
880 | struct symtab * | |
881 | slookup(p1,p2,enterf) register char *p1,*p2; int enterf;{ | |
882 | register char *p3; char c2,c3; struct symtab *np; | |
883 | c2= *p2; *p2='\0'; /* mark end of token */ | |
884 | if ((p2-p1)>NCPS) p3=p1+NCPS; else p3=p2; | |
885 | c3= *p3; *p3='\0'; /* truncate to NCPS chars or less */ | |
886 | if (enterf==1) p1=copy(p1); | |
887 | np=lookup(p1,enterf); *p3=c3; *p2=c2; | |
888 | if (np->value!=0 && flslvl==0) newp=subst(p2,np); | |
889 | else newp=0; | |
890 | return(np); | |
891 | } | |
892 | ||
893 | char * | |
894 | subst(p,sp) register char *p; struct symtab *sp; { | |
895 | static char match[]="%s: argument mismatch"; | |
896 | register char *ca,*vp; int params; | |
8c7b88c5 SL |
897 | char *actual[MAXFRM]; /* actual[n] is text of nth actual */ |
898 | char actused[MAXFRM]; /* for newline processing in actuals */ | |
899 | char acttxt[BUFSIZ]; /* space for actuals */ | |
900 | int nlines = 0; | |
66cbbe7c RH |
901 | |
902 | if (0==(vp=sp->value)) return(p); | |
903 | if ((p-macforw)<=macdam) { | |
904 | if (++maclvl>symsiz && !rflag) { | |
905 | pperror("%s: macro recursion",sp->name); return(p); | |
906 | } | |
907 | } else maclvl=0; /* level decreased */ | |
908 | macforw=p; macdam=0; /* new target for decrease in level */ | |
909 | macnam=sp->name; | |
910 | dump(); | |
911 | if (sp==ulnloc) { | |
912 | vp=acttxt; *vp++='\0'; | |
913 | sprintf(vp,"%d",lineno[ifno]); while (*vp++); | |
914 | } else if (sp==uflloc) { | |
915 | vp=acttxt; *vp++='\0'; | |
916 | sprintf(vp,"\"%s\"",fnames[ifno]); while (*vp++); | |
917 | } | |
918 | if (0!=(params= *--vp&0xFF)) {/* definition calls for params */ | |
919 | register char **pa; | |
920 | ca=acttxt; pa=actual; | |
921 | if (params==0xFF) params=1; /* #define foo() ... */ | |
922 | sloscan(); ++flslvl; /* no expansion during search for actuals */ | |
923 | plvl= -1; | |
924 | do p=skipbl(p); while (*inp=='\n'); /* skip \n too */ | |
925 | if (*inp=='(') { | |
926 | maclin=lineno[ifno]; macfil=fnames[ifno]; | |
927 | for (plvl=1; plvl!=0; ) { | |
928 | *ca++='\0'; | |
929 | for (;;) { | |
930 | outp=inp=p; p=cotoken(p); | |
931 | if (*inp=='(') ++plvl; | |
932 | if (*inp==')' && --plvl==0) {--params; break;} | |
933 | if (plvl==1 && *inp==',') {--params; break;} | |
934 | while (inp<p) *ca++= *inp++; | |
935 | if (ca> &acttxt[BUFSIZ]) | |
936 | pperror("%s: actuals too long",sp->name); | |
937 | } | |
938 | if (pa>= &actual[MAXFRM]) ppwarn(match,sp->name); | |
8c7b88c5 | 939 | else { actused[pa-actual]=0; *pa++=ca; } |
66cbbe7c | 940 | } |
8c7b88c5 SL |
941 | nlines = lineno[ifno] - maclin; |
942 | lineno[ifno] = maclin; /* don't count newlines here */ | |
66cbbe7c RH |
943 | } |
944 | if (params!=0) ppwarn(match,sp->name); | |
945 | while (--params>=0) *pa++=""+1; /* null string for missing actuals */ | |
946 | --flslvl; fasscan(); | |
947 | } | |
948 | for (;;) {/* push definition onto front of input stack */ | |
949 | while (!iswarn(*--vp)) { | |
950 | if (bob(p)) {outp=inp=p; p=unfill(p);} | |
951 | *--p= *vp; | |
952 | } | |
953 | if (*vp==warnc) {/* insert actual param */ | |
954 | ca=actual[*--vp-1]; | |
955 | while (*--ca) { | |
956 | if (bob(p)) {outp=inp=p; p=unfill(p);} | |
8c7b88c5 SL |
957 | /* Actuals with newlines confuse line numbering */ |
958 | if (*ca == '\n' && actused[*vp-1]) | |
959 | if (*(ca-1) == '\\') ca--; | |
960 | else *--p = ' '; | |
961 | else { *--p= *ca; if (*ca == '\n') nlines--; } | |
66cbbe7c | 962 | } |
8c7b88c5 SL |
963 | actused[*vp-1] = 1; |
964 | } else { | |
965 | if (nlines > 0 ) | |
966 | while (nlines-- > 0) | |
967 | *--p = '\n'; | |
968 | break; | |
969 | } | |
66cbbe7c RH |
970 | } |
971 | outp=inp=p; | |
972 | return(p); | |
973 | } | |
974 | ||
975 | ||
976 | ||
977 | ||
978 | char * | |
979 | trmdir(s) register char *s; { | |
980 | register char *p = s; | |
981 | while (*p++); --p; while (p>s && *--p!='/'); | |
982 | # if unix | |
983 | if (p==s) *p++='.'; | |
984 | # endif | |
985 | *p='\0'; | |
986 | return(s); | |
987 | } | |
988 | ||
989 | STATIC char * | |
990 | copy(s) register char *s; { | |
991 | register char *old; | |
992 | ||
993 | old = savch; while (*savch++ = *s++); | |
994 | return(old); | |
995 | } | |
996 | ||
997 | char * | |
998 | strdex(s,c) char *s,c; { | |
999 | while (*s) if (*s++==c) return(--s); | |
1000 | return(0); | |
1001 | } | |
1002 | ||
1003 | yywrap(){ return(1); } | |
1004 | ||
1005 | main(argc,argv) | |
1006 | char *argv[]; | |
1007 | { | |
1008 | register int i,c; | |
1009 | register char *p; | |
1010 | char *tf,**cp2; | |
1011 | ||
1012 | # if gcos | |
1013 | if (setjmp(env)) return (exfail); | |
1014 | # endif | |
1015 | p="_$ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; | |
1016 | i=0; | |
1017 | while (c= *p++) { | |
1018 | (fastab+COFF)[c] |= IB|NB|SB; (toktyp+COFF)[c]=IDENT; | |
1019 | #if scw2 | |
1020 | /* 53 == 63-10; digits rarely appear in identifiers, | |
1021 | /* and can never be the first char of an identifier. | |
1022 | /* 11 == 53*53/sizeof(macbit) . | |
1023 | */ | |
1024 | ++i; (t21+COFF)[c]=(53*i)/11; (t22+COFF)[c]=i%11; | |
1025 | #endif | |
1026 | } | |
1027 | p="0123456789."; | |
1028 | while (c= *p++) {(fastab+COFF)[c] |= NB|SB; (toktyp+COFF)[c]=NUMBR;} | |
1029 | # if gcos | |
1030 | p="\n\"'`/\\"; | |
1031 | # else | |
1032 | p="\n\"'/\\"; | |
1033 | # endif | |
1034 | while (c= *p++) (fastab+COFF)[c] |= SB; | |
1035 | # if gcos | |
1036 | p="\n\"'`\\"; | |
1037 | # else | |
1038 | p="\n\"'\\"; | |
1039 | # endif | |
1040 | while (c= *p++) (fastab+COFF)[c] |= QB; | |
1041 | p="*\n"; while (c= *p++) (fastab+COFF)[c] |= CB; | |
1042 | (fastab+COFF)[warnc] |= WB; | |
1043 | (fastab+COFF)['\0'] |= CB|QB|SB|WB; | |
1044 | for (i=ALFSIZ; --i>=0; ) slotab[i]=fastab[i]|SB; | |
1045 | p=" \t\013\f\r"; /* note no \n; \v not legal for vertical tab? */ | |
1046 | while (c= *p++) (toktyp+COFF)[c]=BLANK; | |
1047 | #if scw2 | |
1048 | for ((t23+COFF)[i=ALFSIZ+7-COFF]=1; --i>=-COFF; ) | |
1049 | if (((t23+COFF)[i]=(t23+COFF+1)[i]<<1)==0) (t23+COFF)[i]=1; | |
1050 | #endif | |
1051 | ||
1052 | # if unix | |
1053 | fnames[ifno=0] = ""; dirnams[0]=dirs[0]="."; | |
1054 | # endif | |
1055 | # if ibm | |
1056 | fnames[ifno=0] = ""; | |
1057 | # endif | |
1058 | # if gcos | |
1059 | if (inquire(stdin, _TTY)) freopen("*src", "rt", stdin); | |
1060 | # endif | |
1061 | # if gimpel || gcos | |
1062 | fnames[ifno=0] = (char *)inquire(stdin, _FILENAME); | |
1063 | dirnams[0] = dirs[0] = trmdir(copy(fnames[0])); | |
1064 | # endif | |
1065 | for(i=1; i<argc; i++) | |
1066 | { | |
1067 | switch(argv[i][0]) | |
1068 | { | |
1069 | case '-': | |
1070 | # if gcos | |
1071 | switch(toupper(argv[i][1])) { /* case-independent on GCOS */ | |
1072 | # else | |
1073 | switch(argv[i][1]) { | |
1074 | # endif | |
61a8d43d | 1075 | case 'M': mflag++; |
66cbbe7c RH |
1076 | case 'P': pflag++; |
1077 | case 'E': continue; | |
1078 | case 'R': ++rflag; continue; | |
1079 | case 'C': passcom++; continue; | |
1080 | case 'D': | |
1081 | if (predef>prespc+NPREDEF) { | |
1082 | pperror("too many -D options, ignoring %s",argv[i]); | |
1083 | continue; | |
1084 | } | |
1085 | /* ignore plain "-D" (no argument) */ | |
1086 | if (*(argv[i]+2)) *predef++ = argv[i]+2; | |
1087 | continue; | |
1088 | case 'U': | |
1089 | if (prund>punspc+NPREDEF) { | |
1090 | pperror("too many -U options, ignoring %s",argv[i]); | |
1091 | continue; | |
1092 | } | |
1093 | *prund++ = argv[i]+2; | |
1094 | continue; | |
1095 | case 'I': | |
1096 | if (nd>8) pperror("excessive -I file (%s) ignored",argv[i]); | |
1097 | else dirs[nd++] = argv[i]+2; | |
1098 | continue; | |
1099 | case '\0': continue; | |
1100 | default: | |
1101 | pperror("unknown flag %s", argv[i]); | |
1102 | continue; | |
1103 | } | |
1104 | default: | |
1105 | if (fin==STDIN) { | |
1106 | if (0>(fin=open(argv[i], READ))) { | |
1107 | pperror("No source file %s",argv[i]); exit(8); | |
1108 | } | |
1109 | fnames[ifno]=copy(argv[i]); | |
61a8d43d | 1110 | infile=copy(argv[i]); |
9372792e | 1111 | dirs[0]=dirnams[ifno]=trmdir(argv[i]); |
66cbbe7c RH |
1112 | # ifndef gcos |
1113 | /* too dangerous to have file name in same syntactic position | |
1114 | be input or output file depending on file redirections, | |
1115 | so force output to stdout, willy-nilly | |
1116 | [i don't see what the problem is. jfr] | |
1117 | */ | |
1118 | } else if (fout==stdout) { | |
66cbbe7c RH |
1119 | if (NULL==(fout=fopen(argv[i], "w"))) { |
1120 | pperror("Can't create %s", argv[i]); exit(8); | |
ba27d052 | 1121 | } else fclose(stdout); |
66cbbe7c RH |
1122 | # endif |
1123 | } else pperror("extraneous name %s", argv[i]); | |
1124 | } | |
1125 | } | |
1126 | ||
61a8d43d KM |
1127 | if (mflag) { |
1128 | if (infile==(char *)0) { | |
1129 | fprintf(stderr, | |
1130 | "no input file specified with -M flag\n"); | |
1131 | exit(8); | |
1132 | } | |
1133 | tf=(char *)rindex(infile, '.'); | |
1134 | if (tf==0) { | |
1135 | fprintf(stderr, "missing component name on %s\n", | |
1136 | infile); | |
1137 | exit(8); | |
1138 | } | |
1139 | tf[1]='o'; | |
1140 | tf=(char *)rindex(infile, '/'); | |
1141 | if (tf!=(char *)0) | |
1142 | infile = tf + 1; | |
1143 | mout=fout; | |
1144 | if (NULL==(fout=fopen("/dev/null", "w"))) { | |
1145 | pperror("Can't open /dev/null"); | |
1146 | exit(8); | |
1147 | } | |
1148 | } | |
66cbbe7c RH |
1149 | fins[ifno]=fin; |
1150 | exfail = 0; | |
1151 | /* after user -I files here are the standard include libraries */ | |
1152 | # if unix | |
1153 | dirs[nd++] = "/usr/include"; | |
1154 | # endif | |
1155 | # if gcos | |
1156 | dirs[nd++] = "cc/include"; | |
1157 | # endif | |
1158 | # if ibm | |
1159 | # ifndef gimpel | |
1160 | dirs[nd++] = "BTL$CLIB"; | |
1161 | # endif | |
1162 | # endif | |
1163 | # ifdef gimpel | |
1164 | dirs[nd++] = intss() ? "SYS3.C." : "" ; | |
1165 | # endif | |
1166 | /* dirs[nd++] = "/compool"; */ | |
1167 | dirs[nd++] = 0; | |
1168 | defloc=ppsym("define"); | |
1169 | udfloc=ppsym("undef"); | |
1170 | incloc=ppsym("include"); | |
1171 | elsloc=ppsym("else"); | |
1172 | eifloc=ppsym("endif"); | |
1173 | ifdloc=ppsym("ifdef"); | |
1174 | ifnloc=ppsym("ifndef"); | |
1175 | ifloc=ppsym("if"); | |
1176 | lneloc=ppsym("line"); | |
1177 | for (i=sizeof(macbit)/sizeof(macbit[0]); --i>=0; ) macbit[i]=0; | |
1178 | # if unix | |
1179 | ysysloc=stsym("unix"); | |
1180 | # endif | |
1181 | # if gcos | |
1182 | ysysloc=stsym ("gcos"); | |
1183 | # endif | |
1184 | # if ibm | |
1185 | ysysloc=stsym ("ibm"); | |
1186 | # endif | |
1187 | # if pdp11 | |
1188 | varloc=stsym("pdp11"); | |
1189 | # endif | |
1190 | # if vax | |
1191 | varloc=stsym("vax"); | |
1192 | # endif | |
1193 | # if interdata | |
1194 | varloc=stsym ("interdata"); | |
1195 | # endif | |
1196 | # if tss | |
1197 | varloc=stsym ("tss"); | |
1198 | # endif | |
1199 | # if os | |
1200 | varloc=stsym ("os"); | |
1201 | # endif | |
1202 | # if mert | |
1203 | varloc=stsym ("mert"); | |
5f18cf8b SL |
1204 | # endif |
1205 | # if mc68000 | |
1206 | varloc=stsym("mc68000"); | |
1207 | # endif | |
1208 | # if sun | |
1209 | varloc=stsym("sun"); | |
66cbbe7c RH |
1210 | # endif |
1211 | ulnloc=stsym ("__LINE__"); | |
1212 | uflloc=stsym ("__FILE__"); | |
1213 | ||
1214 | tf=fnames[ifno]; fnames[ifno]="command line"; lineno[ifno]=1; | |
1215 | cp2=prespc; | |
1216 | while (cp2<predef) stsym(*cp2++); | |
1217 | cp2=punspc; | |
1218 | while (cp2<prund) { | |
1219 | if (p=strdex(*cp2, '=')) *p++='\0'; | |
1220 | lookup(*cp2++, DROP); | |
1221 | } | |
1222 | fnames[ifno]=tf; | |
1223 | pbeg=buffer+NCPS; pbuf=pbeg+BUFSIZ; pend=pbuf+BUFSIZ; | |
1224 | ||
1225 | trulvl = 0; flslvl = 0; | |
61a8d43d | 1226 | lineno[0] = 1; sayline(START); |
66cbbe7c RH |
1227 | outp=inp=pend; |
1228 | control(pend); | |
1229 | return (exfail); | |
1230 | } |