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