Commit | Line | Data |
---|---|---|
66cbbe7c | 1 | #ifndef lint |
061309d9 | 2 | static char sccsid[] = "@(#)cpp.c 1.12 %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 | ||
061309d9 | 20 | #define FIRSTOPEN -2 |
66cbbe7c RH |
21 | #define READ 0 |
22 | #define WRITE 1 | |
23 | #define SALT '#' | |
d9f07ef8 KM |
24 | #if !defined BUFSIZ || BUFSIZ < 8192 |
25 | #undef BUFSIZ | |
26 | #define BUFSIZ 8192 | |
66cbbe7c RH |
27 | #endif |
28 | ||
29 | char *pbeg,*pbuf,*pend; | |
30 | char *outp,*inp; | |
31 | char *newp; | |
32 | char cinit; | |
33 | ||
34 | /* some code depends on whether characters are sign or zero extended */ | |
35 | /* #if '\377' < 0 not used here, old cpp doesn't understand */ | |
8c7b88c5 | 36 | #if pdp11 | vax | mc68000 |
66cbbe7c RH |
37 | #define COFF 128 |
38 | #else | |
39 | #define COFF 0 | |
40 | #endif | |
41 | ||
42 | # if gcos | |
43 | #define ALFSIZ 512 /* alphabet size */ | |
44 | # else | |
45 | #define ALFSIZ 256 /* alphabet size */ | |
46 | # endif | |
47 | char macbit[ALFSIZ+11]; | |
48 | char toktyp[ALFSIZ]; | |
49 | #define BLANK 1 | |
50 | #define IDENT 2 | |
51 | #define NUMBR 3 | |
52 | ||
53 | /* a superimposed code is used to reduce the number of calls to the | |
54 | /* symbol table lookup routine. (if the kth character of an identifier | |
55 | /* is 'a' and there are no macro names whose kth character is 'a' | |
56 | /* then the identifier cannot be a macro name, hence there is no need | |
57 | /* to look in the symbol table.) 'scw1' enables the test based on | |
58 | /* single characters and their position in the identifier. 'scw2' | |
59 | /* enables the test based on adjacent pairs of characters and their | |
60 | /* position in the identifier. scw1 typically costs 1 indexed fetch, | |
61 | /* an AND, and a jump per character of identifier, until the identifier | |
62 | /* is known as a non-macro name or until the end of the identifier. | |
63 | /* scw1 is inexpensive. scw2 typically costs 4 indexed fetches, | |
64 | /* an add, an AND, and a jump per character of identifier, but it is also | |
65 | /* slightly more effective at reducing symbol table searches. | |
66 | /* scw2 usually costs too much because the symbol table search is | |
67 | /* usually short; but if symbol table search should become expensive, | |
68 | /* the code is here. | |
69 | /* using both scw1 and scw2 is of dubious value. | |
70 | */ | |
71 | #define scw1 1 | |
72 | #define scw2 0 | |
73 | ||
74 | #if scw2 | |
75 | char t21[ALFSIZ],t22[ALFSIZ],t23[ALFSIZ+NCPS]; | |
76 | #endif | |
77 | ||
78 | #if scw1 | |
79 | #define b0 1 | |
80 | #define b1 2 | |
81 | #define b2 4 | |
82 | #define b3 8 | |
83 | #define b4 16 | |
84 | #define b5 32 | |
85 | #define b6 64 | |
86 | #define b7 128 | |
87 | #endif | |
88 | ||
89 | #define IB 1 | |
90 | #define SB 2 | |
91 | #define NB 4 | |
92 | #define CB 8 | |
93 | #define QB 16 | |
94 | #define WB 32 | |
95 | char fastab[ALFSIZ]; | |
96 | char slotab[ALFSIZ]; | |
97 | char *ptrtab; | |
98 | #define isslo (ptrtab==(slotab+COFF)) | |
99 | #define isid(a) ((fastab+COFF)[a]&IB) | |
100 | #define isspc(a) (ptrtab[a]&SB) | |
101 | #define isnum(a) ((fastab+COFF)[a]&NB) | |
102 | #define iscom(a) ((fastab+COFF)[a]&CB) | |
103 | #define isquo(a) ((fastab+COFF)[a]&QB) | |
104 | #define iswarn(a) ((fastab+COFF)[a]&WB) | |
105 | ||
106 | #define eob(a) ((a)>=pend) | |
107 | #define bob(a) (pbeg>=(a)) | |
108 | ||
8c7b88c5 SL |
109 | # define cputc(a,b) if(!flslvl) putc(a,b) |
110 | ||
66cbbe7c RH |
111 | char buffer[NCPS+BUFSIZ+BUFSIZ+NCPS]; |
112 | ||
7e5ed264 KM |
113 | char *lastcopy; |
114 | ||
115 | char *malloc(), *realloc(); | |
66cbbe7c RH |
116 | |
117 | # define DROP 0xFE /* special character not legal ASCII or EBCDIC */ | |
118 | # define WARN DROP | |
119 | # define SAME 0 | |
120 | # define MAXINC 10 | |
121 | # define MAXFRE 14 /* max buffers of macro pushback */ | |
122 | # define MAXFRM 31 /* max number of formals/actuals to a macro */ | |
123 | ||
124 | static char warnc = WARN; | |
125 | ||
126 | int mactop,fretop; | |
127 | char *instack[MAXFRE],*bufstack[MAXFRE],*endbuf[MAXFRE]; | |
128 | ||
129 | int plvl; /* parenthesis level during scan for macro actuals */ | |
130 | int maclin; /* line number of macro call requiring actuals */ | |
131 | char *macfil; /* file name of macro call requiring actuals */ | |
132 | char *macnam; /* name of macro requiring actuals */ | |
133 | int maclvl; /* # calls since last decrease in nesting level */ | |
134 | char *macforw; /* pointer which must be exceeded to decrease nesting level */ | |
135 | int macdam; /* offset to macforw due to buffer shifting */ | |
136 | ||
137 | #if tgp | |
138 | int tgpscan; /* flag for dump(); */ | |
139 | #endif | |
140 | ||
141 | STATIC int inctop[MAXINC]; | |
142 | STATIC char *fnames[MAXINC]; | |
143 | STATIC char *dirnams[MAXINC]; /* actual directory of #include files */ | |
144 | STATIC int fins[MAXINC]; | |
145 | STATIC int lineno[MAXINC]; | |
146 | ||
147 | STATIC char *dirs[10]; /* -I and <> directories */ | |
148 | char *strdex(), *copy(), *subst(), *trmdir(); | |
149 | struct symtab *stsym(); | |
061309d9 | 150 | STATIC int fin = FIRSTOPEN; |
66cbbe7c RH |
151 | STATIC FILE *fout = stdout; |
152 | STATIC int nd = 1; | |
153 | STATIC int pflag; /* don't put out lines "# 12 foo.c" */ | |
8c7b88c5 | 154 | int passcom; /* don't delete comments */ |
66cbbe7c | 155 | STATIC int rflag; /* allow macro recursion */ |
61a8d43d KM |
156 | STATIC int mflag; /* generate makefile dependencies */ |
157 | STATIC char *infile; /* name of .o file to build dependencies from */ | |
158 | STATIC FILE *mout; /* file to place dependencies on */ | |
159 | #define START 1 | |
160 | #define CONT 2 | |
161 | #define BACK 3 | |
66cbbe7c RH |
162 | STATIC int ifno; |
163 | # define NPREDEF 20 | |
164 | STATIC char *prespc[NPREDEF]; | |
165 | STATIC char **predef = prespc; | |
166 | STATIC char *punspc[NPREDEF]; | |
167 | STATIC char **prund = punspc; | |
168 | STATIC int exfail; | |
169 | struct symtab { | |
170 | char *name; | |
171 | char *value; | |
172 | } *lastsym, *lookup(), *slookup(); | |
173 | ||
174 | # if gcos | |
175 | #include <setjmp.h> | |
176 | static jmp_buf env; | |
177 | # define main mainpp | |
178 | # undef exit | |
179 | # define exit(S) longjmp(env, 1) | |
180 | # define open(S,D) fileno(fopen(S, "r")) | |
181 | # define close(F) fclose(_f[F]) | |
182 | extern FILE *_f[]; | |
183 | # define symsiz 500 | |
184 | # else | |
8c7b88c5 | 185 | # define symsiz 2000 /* std = 500, wnj aug 1979 */ |
66cbbe7c RH |
186 | # endif |
187 | STATIC struct symtab stab[symsiz]; | |
188 | ||
189 | STATIC struct symtab *defloc; | |
190 | STATIC struct symtab *udfloc; | |
191 | STATIC struct symtab *incloc; | |
192 | STATIC struct symtab *ifloc; | |
193 | STATIC struct symtab *elsloc; | |
194 | STATIC struct symtab *eifloc; | |
195 | STATIC struct symtab *ifdloc; | |
196 | STATIC struct symtab *ifnloc; | |
197 | STATIC struct symtab *ysysloc; | |
198 | STATIC struct symtab *varloc; | |
199 | STATIC struct symtab *lneloc; | |
200 | STATIC struct symtab *ulnloc; | |
201 | STATIC struct symtab *uflloc; | |
7e5ed264 | 202 | STATIC struct symtab *identloc; /* Sys 5r3 compatibility */ |
66cbbe7c RH |
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 | /* | |
7e5ed264 | 261 | /* space for side buffers is obtained from 'malloc' and is never returned. |
66cbbe7c RH |
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 { | |
7e5ed264 KM |
537 | np=malloc(BUFSIZ+1); |
538 | if (np==NULL) {pperror("no space"); exit(exfail);} | |
539 | np[BUFSIZ]='\0'; | |
66cbbe7c RH |
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 | } | |
7e5ed264 | 585 | if((nfil=malloc(BUFSIZ))==NULL) {pperror("no space"); exit(exfail);} |
66cbbe7c RH |
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 | } | |
7e5ed264 | 611 | if(filok==0){pperror("Can't find include file %s",filname);free(nfil);} |
66cbbe7c | 612 | else { |
7e5ed264 KM |
613 | nfil=realloc(nfil,strlen(nfil)+1); |
614 | lineno[ifno]=1; fnames[ifno]=nfil; | |
66cbbe7c | 615 | dirnams[ifno]=dirs[0]=trmdir(copy(nfil)); |
61a8d43d | 616 | sayline(START); |
66cbbe7c RH |
617 | /* save current contents of buffer */ |
618 | while (!eob(p)) p=unfill(p); | |
619 | inctop[ifno]=mactop; | |
620 | } | |
621 | return(p); | |
622 | } | |
623 | ||
624 | equfrm(a,p1,p2) register char *a,*p1,*p2; { | |
625 | register char c; int flag; | |
626 | c= *p2; *p2='\0'; | |
627 | flag=strcmp(a,p1); *p2=c; return(flag==SAME); | |
628 | } | |
629 | ||
630 | char * | |
631 | dodef(p) char *p; {/* process '#define' */ | |
632 | register char *pin,*psav,*cf; | |
633 | char **pf,**qf; int b,c,params; struct symtab *np; | |
7e5ed264 KM |
634 | char *oldval; |
635 | char *space, *newspace; | |
66cbbe7c RH |
636 | char *formal[MAXFRM]; /* formal[n] is name of nth formal */ |
637 | char formtxt[BUFSIZ]; /* space for formal names */ | |
638 | ||
66cbbe7c RH |
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); | |
7e5ed264 | 645 | if (oldval=np->value) free(lastcopy); /* was previously defined */ |
66cbbe7c RH |
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 | */ | |
7e5ed264 KM |
675 | space=psav=malloc(BUFSIZ); |
676 | if (space==NULL) {pperror("too much defining"); return(p);} | |
677 | *psav++ = '\0'; | |
66cbbe7c RH |
678 | for (;;) {/* accumulate definition until linefeed */ |
679 | outp=inp=p; p=cotoken(p); pin=inp; | |
680 | if (*pin=='\\' && pin[1]=='\n') {putc('\n',fout); continue;} /* ignore escaped lf */ | |
681 | if (*pin=='\n') break; | |
682 | if (params) {/* mark the appearance of formals in the definiton */ | |
683 | if ((toktyp+COFF)[*pin]==IDENT) { | |
684 | for (qf=pf; --qf>=formal; ) { | |
685 | if (equfrm(*qf,pin,p)) { | |
686 | *psav++=qf-formal+1; *psav++=WARN; pin=p; break; | |
687 | } | |
688 | } | |
689 | } else if (*pin=='"' || *pin=='\'' | |
690 | # if gcos | |
691 | || *pin=='`' | |
692 | # endif | |
693 | ) {/* inside quotation marks, too */ | |
694 | char quoc= *pin; | |
695 | for (*psav++= *pin++; pin<p && *pin!=quoc; ) { | |
696 | while (pin<p && !isid(*pin)) *psav++= *pin++; | |
697 | cf=pin; while (cf<p && isid(*cf)) ++cf; | |
698 | for (qf=pf; --qf>=formal; ) { | |
699 | if (equfrm(*qf,pin,cf)) { | |
700 | *psav++=qf-formal+1; *psav++=WARN; pin=cf; break; | |
701 | } | |
702 | } | |
703 | while (pin<cf) *psav++= *pin++; | |
704 | } | |
705 | } | |
706 | } | |
707 | while (pin<p) *psav++= *pin++; | |
708 | } | |
709 | *psav++=params; *psav++='\0'; | |
710 | if ((cf=oldval)!=NULL) {/* redefinition */ | |
711 | --cf; /* skip no. of params, which may be zero */ | |
712 | while (*--cf); /* go back to the beginning */ | |
7e5ed264 | 713 | if (0!=strcmp(++cf,space+1)) {/* redefinition different from old */ |
66cbbe7c RH |
714 | --lineno[ifno]; ppwarn("%s redefined",np->name); ++lineno[ifno]; |
715 | np->value=psav-1; | |
7e5ed264 | 716 | } else free(space); /* identical redef.; reclaim space */ |
66cbbe7c | 717 | } else np->value=psav-1; |
7e5ed264 KM |
718 | --flslvl; inp=pin; |
719 | if (np->value == psav-1) { | |
720 | newspace = realloc(space, psav-space); | |
721 | if (newspace==NULL) {pperror("no space"); exit(exfail);} | |
722 | /* | |
723 | * Adjust pointer in case this moved. | |
724 | */ | |
725 | np->value += newspace-space; | |
726 | } | |
727 | return(p); | |
66cbbe7c RH |
728 | } |
729 | ||
730 | #define fasscan() ptrtab=fastab+COFF | |
731 | #define sloscan() ptrtab=slotab+COFF | |
732 | ||
733 | char * | |
734 | control(p) register char *p; {/* find and handle preprocessor control lines */ | |
735 | register struct symtab *np; | |
736 | for (;;) { | |
737 | fasscan(); p=cotoken(p); if (*inp=='\n') ++inp; dump(); | |
738 | sloscan(); p=skipbl(p); | |
739 | *--inp=SALT; outp=inp; ++flslvl; np=slookup(inp,p,0); --flslvl; | |
740 | if (np==defloc) {/* define */ | |
741 | if (flslvl==0) {p=dodef(p); continue;} | |
742 | } else if (np==incloc) {/* include */ | |
743 | if (flslvl==0) {p=doincl(p); continue;} | |
744 | } else if (np==ifnloc) {/* ifndef */ | |
745 | ++flslvl; p=skipbl(p); np=slookup(inp,p,0); --flslvl; | |
746 | if (flslvl==0 && np->value==0) ++trulvl; | |
747 | else ++flslvl; | |
748 | } else if (np==ifdloc) {/* ifdef */ | |
749 | ++flslvl; p=skipbl(p); np=slookup(inp,p,0); --flslvl; | |
750 | if (flslvl==0 && np->value!=0) ++trulvl; | |
751 | else ++flslvl; | |
752 | } else if (np==eifloc) {/* endif */ | |
61a8d43d | 753 | if (flslvl) {if (--flslvl==0) sayline(CONT);} |
66cbbe7c RH |
754 | else if (trulvl) --trulvl; |
755 | else pperror("If-less endif",0); | |
756 | } else if (np==elsloc) {/* else */ | |
757 | if (flslvl) { | |
758 | if (--flslvl!=0) ++flslvl; | |
61a8d43d | 759 | else {++trulvl; sayline(CONT);} |
66cbbe7c RH |
760 | } |
761 | else if (trulvl) {++flslvl; --trulvl;} | |
762 | else pperror("If-less else",0); | |
763 | } else if (np==udfloc) {/* undefine */ | |
764 | if (flslvl==0) { | |
765 | ++flslvl; p=skipbl(p); slookup(inp,p,DROP); --flslvl; | |
766 | } | |
767 | } else if (np==ifloc) {/* if */ | |
768 | #if tgp | |
769 | pperror(" IF not implemented, true assumed", 0); | |
770 | if (flslvl==0) ++trulvl; else ++flslvl; | |
771 | #else | |
772 | newp=p; | |
773 | if (flslvl==0 && yyparse()) ++trulvl; else ++flslvl; | |
774 | p=newp; | |
775 | #endif | |
776 | } else if (np==lneloc) {/* line */ | |
777 | if (flslvl==0 && pflag==0) { | |
9372792e | 778 | char *cp, *cp2, *savestring(); |
66cbbe7c | 779 | outp=inp=p; *--outp='#'; while (*inp!='\n') p=cotoken(p); |
9372792e RH |
780 | cp = outp + 1; |
781 | while (isspace(*cp) && cp < inp) | |
782 | cp++; | |
783 | while (isdigit(*cp) && cp < inp) | |
784 | cp++; | |
785 | while (*cp != '"' && cp < inp) | |
786 | cp++; | |
787 | if (cp < inp) { | |
788 | cp++; | |
789 | cp2 = cp; | |
790 | while (*cp2 != '"' && cp2 < inp) | |
791 | cp2++; | |
792 | fnames[ifno] = savestring(cp, cp2); | |
793 | } | |
66cbbe7c RH |
794 | continue; |
795 | } | |
7e5ed264 KM |
796 | } else if (np==identloc) {/* ident (for Sys 5r3 compat) */ |
797 | while(*inp!='\n') p=cotoken(p); | |
66cbbe7c RH |
798 | } else if (*++inp=='\n') outp=inp; /* allows blank line after # */ |
799 | else pperror("undefined control",0); | |
800 | /* flush to lf */ | |
801 | ++flslvl; while (*inp!='\n') {outp=inp=p; p=cotoken(p);} --flslvl; | |
802 | } | |
803 | } | |
804 | ||
9372792e RH |
805 | char * |
806 | savestring(start, finish) | |
807 | register char *start, *finish; | |
808 | { | |
809 | char *retbuf; | |
810 | register char *cp; | |
811 | ||
812 | retbuf = (char *) calloc(finish - start + 1, sizeof (char)); | |
813 | cp = retbuf; | |
814 | while (start < finish) | |
815 | *cp++ = *start++; | |
816 | *cp = 0; | |
817 | return(retbuf); | |
818 | } | |
819 | ||
66cbbe7c RH |
820 | struct symtab * |
821 | stsym(s) register char *s; { | |
822 | char buf[BUFSIZ]; register char *p; | |
823 | ||
824 | /* make definition look exactly like end of #define line */ | |
825 | /* copy to avoid running off end of world when param list is at end */ | |
826 | p=buf; while (*p++= *s++); | |
827 | p=buf; while (isid(*p++)); /* skip first identifier */ | |
828 | if (*--p=='=') {*p++=' '; while (*p++);} | |
829 | else {s=" 1"; while (*p++= *s++);} | |
830 | pend=p; *--p='\n'; | |
831 | sloscan(); dodef(buf); return(lastsym); | |
832 | } | |
833 | ||
834 | struct symtab * | |
835 | ppsym(s) char *s; {/* kluge */ | |
836 | register struct symtab *sp; | |
7e5ed264 KM |
837 | register char *name; |
838 | ||
839 | cinit=SALT; sp=stsym(s); name = malloc(strlen(sp->name)+1+1); | |
840 | name[0] = '#'; strcpy(name+1, sp->name); sp->name = name; | |
841 | cinit=0; return(sp); | |
66cbbe7c RH |
842 | } |
843 | ||
844 | /* VARARGS1 */ | |
845 | pperror(s,x,y) char *s; { | |
846 | if (fnames[ifno][0]) fprintf(stderr, | |
847 | # if gcos | |
848 | "*%c* \"%s\", line ", exfail >= 0 ? 'F' : 'W', | |
849 | # else | |
850 | "%s: ", | |
851 | # endif | |
852 | fnames[ifno]); | |
853 | fprintf(stderr, "%d: ",lineno[ifno]); | |
854 | fprintf(stderr, s, x, y); | |
855 | fprintf(stderr,"\n"); | |
856 | ++exfail; | |
857 | } | |
858 | ||
859 | yyerror(s,a,b) char *s; { | |
860 | pperror(s,a,b); | |
861 | } | |
862 | ||
863 | ppwarn(s,x) char *s; { | |
864 | int fail = exfail; | |
865 | exfail = -1; | |
866 | pperror(s,x); | |
867 | exfail = fail; | |
868 | } | |
869 | ||
870 | struct symtab * | |
871 | lookup(namep, enterf) | |
872 | char *namep; | |
873 | { | |
874 | register char *np, *snp; | |
875 | register int c, i; int around; | |
876 | register struct symtab *sp; | |
877 | ||
878 | /* namep had better not be too long (currently, <=NCPS chars) */ | |
879 | np=namep; around=0; i=cinit; | |
880 | while (c= *np++) i += i+c; c=i; /* c=i for register usage on pdp11 */ | |
881 | c %= symsiz; if (c<0) c += symsiz; | |
882 | sp = &stab[c]; | |
883 | while (snp=sp->name) { | |
884 | np = namep; | |
885 | while (*snp++ == *np) if (*np++ == '\0') { | |
886 | if (enterf==DROP) {sp->name[0]= DROP; sp->value=0;} | |
887 | return(lastsym=sp); | |
888 | } | |
889 | if (--sp < &stab[0]) | |
890 | if (around) {pperror("too many defines", 0); exit(exfail);} | |
891 | else {++around; sp = &stab[symsiz-1];} | |
892 | } | |
893 | if (enterf==1) sp->name=namep; | |
894 | return(lastsym=sp); | |
895 | } | |
896 | ||
897 | struct symtab * | |
898 | slookup(p1,p2,enterf) register char *p1,*p2; int enterf;{ | |
899 | register char *p3; char c2,c3; struct symtab *np; | |
900 | c2= *p2; *p2='\0'; /* mark end of token */ | |
901 | if ((p2-p1)>NCPS) p3=p1+NCPS; else p3=p2; | |
902 | c3= *p3; *p3='\0'; /* truncate to NCPS chars or less */ | |
903 | if (enterf==1) p1=copy(p1); | |
904 | np=lookup(p1,enterf); *p3=c3; *p2=c2; | |
905 | if (np->value!=0 && flslvl==0) newp=subst(p2,np); | |
906 | else newp=0; | |
907 | return(np); | |
908 | } | |
909 | ||
910 | char * | |
911 | subst(p,sp) register char *p; struct symtab *sp; { | |
912 | static char match[]="%s: argument mismatch"; | |
913 | register char *ca,*vp; int params; | |
8c7b88c5 SL |
914 | char *actual[MAXFRM]; /* actual[n] is text of nth actual */ |
915 | char actused[MAXFRM]; /* for newline processing in actuals */ | |
916 | char acttxt[BUFSIZ]; /* space for actuals */ | |
917 | int nlines = 0; | |
66cbbe7c RH |
918 | |
919 | if (0==(vp=sp->value)) return(p); | |
920 | if ((p-macforw)<=macdam) { | |
921 | if (++maclvl>symsiz && !rflag) { | |
922 | pperror("%s: macro recursion",sp->name); return(p); | |
923 | } | |
924 | } else maclvl=0; /* level decreased */ | |
925 | macforw=p; macdam=0; /* new target for decrease in level */ | |
926 | macnam=sp->name; | |
927 | dump(); | |
928 | if (sp==ulnloc) { | |
929 | vp=acttxt; *vp++='\0'; | |
930 | sprintf(vp,"%d",lineno[ifno]); while (*vp++); | |
931 | } else if (sp==uflloc) { | |
932 | vp=acttxt; *vp++='\0'; | |
933 | sprintf(vp,"\"%s\"",fnames[ifno]); while (*vp++); | |
934 | } | |
935 | if (0!=(params= *--vp&0xFF)) {/* definition calls for params */ | |
936 | register char **pa; | |
937 | ca=acttxt; pa=actual; | |
938 | if (params==0xFF) params=1; /* #define foo() ... */ | |
939 | sloscan(); ++flslvl; /* no expansion during search for actuals */ | |
940 | plvl= -1; | |
941 | do p=skipbl(p); while (*inp=='\n'); /* skip \n too */ | |
942 | if (*inp=='(') { | |
943 | maclin=lineno[ifno]; macfil=fnames[ifno]; | |
944 | for (plvl=1; plvl!=0; ) { | |
945 | *ca++='\0'; | |
946 | for (;;) { | |
947 | outp=inp=p; p=cotoken(p); | |
948 | if (*inp=='(') ++plvl; | |
949 | if (*inp==')' && --plvl==0) {--params; break;} | |
950 | if (plvl==1 && *inp==',') {--params; break;} | |
951 | while (inp<p) *ca++= *inp++; | |
952 | if (ca> &acttxt[BUFSIZ]) | |
953 | pperror("%s: actuals too long",sp->name); | |
954 | } | |
955 | if (pa>= &actual[MAXFRM]) ppwarn(match,sp->name); | |
8c7b88c5 | 956 | else { actused[pa-actual]=0; *pa++=ca; } |
66cbbe7c | 957 | } |
8c7b88c5 SL |
958 | nlines = lineno[ifno] - maclin; |
959 | lineno[ifno] = maclin; /* don't count newlines here */ | |
66cbbe7c RH |
960 | } |
961 | if (params!=0) ppwarn(match,sp->name); | |
962 | while (--params>=0) *pa++=""+1; /* null string for missing actuals */ | |
963 | --flslvl; fasscan(); | |
964 | } | |
965 | for (;;) {/* push definition onto front of input stack */ | |
966 | while (!iswarn(*--vp)) { | |
967 | if (bob(p)) {outp=inp=p; p=unfill(p);} | |
968 | *--p= *vp; | |
969 | } | |
970 | if (*vp==warnc) {/* insert actual param */ | |
971 | ca=actual[*--vp-1]; | |
972 | while (*--ca) { | |
973 | if (bob(p)) {outp=inp=p; p=unfill(p);} | |
8c7b88c5 SL |
974 | /* Actuals with newlines confuse line numbering */ |
975 | if (*ca == '\n' && actused[*vp-1]) | |
976 | if (*(ca-1) == '\\') ca--; | |
977 | else *--p = ' '; | |
978 | else { *--p= *ca; if (*ca == '\n') nlines--; } | |
66cbbe7c | 979 | } |
8c7b88c5 SL |
980 | actused[*vp-1] = 1; |
981 | } else { | |
982 | if (nlines > 0 ) | |
983 | while (nlines-- > 0) | |
984 | *--p = '\n'; | |
985 | break; | |
986 | } | |
66cbbe7c RH |
987 | } |
988 | outp=inp=p; | |
989 | return(p); | |
990 | } | |
991 | ||
992 | ||
993 | ||
994 | ||
995 | char * | |
996 | trmdir(s) register char *s; { | |
997 | register char *p = s; | |
998 | while (*p++); --p; while (p>s && *--p!='/'); | |
999 | # if unix | |
1000 | if (p==s) *p++='.'; | |
1001 | # endif | |
1002 | *p='\0'; | |
1003 | return(s); | |
1004 | } | |
1005 | ||
1006 | STATIC char * | |
1007 | copy(s) register char *s; { | |
1008 | register char *old; | |
1009 | ||
7e5ed264 KM |
1010 | old = malloc(strlen(s)+1); |
1011 | if (old==NULL) {pperror("no space"); exit(exfail);} | |
1012 | strcpy(old, s); | |
1013 | return(lastcopy=old); | |
66cbbe7c RH |
1014 | } |
1015 | ||
1016 | char * | |
1017 | strdex(s,c) char *s,c; { | |
1018 | while (*s) if (*s++==c) return(--s); | |
1019 | return(0); | |
1020 | } | |
1021 | ||
1022 | yywrap(){ return(1); } | |
1023 | ||
1024 | main(argc,argv) | |
1025 | char *argv[]; | |
1026 | { | |
1027 | register int i,c; | |
1028 | register char *p; | |
1029 | char *tf,**cp2; | |
1030 | ||
1031 | # if gcos | |
1032 | if (setjmp(env)) return (exfail); | |
1033 | # endif | |
1034 | p="_$ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; | |
1035 | i=0; | |
1036 | while (c= *p++) { | |
1037 | (fastab+COFF)[c] |= IB|NB|SB; (toktyp+COFF)[c]=IDENT; | |
1038 | #if scw2 | |
1039 | /* 53 == 63-10; digits rarely appear in identifiers, | |
1040 | /* and can never be the first char of an identifier. | |
1041 | /* 11 == 53*53/sizeof(macbit) . | |
1042 | */ | |
1043 | ++i; (t21+COFF)[c]=(53*i)/11; (t22+COFF)[c]=i%11; | |
1044 | #endif | |
1045 | } | |
1046 | p="0123456789."; | |
1047 | while (c= *p++) {(fastab+COFF)[c] |= NB|SB; (toktyp+COFF)[c]=NUMBR;} | |
1048 | # if gcos | |
1049 | p="\n\"'`/\\"; | |
1050 | # else | |
1051 | p="\n\"'/\\"; | |
1052 | # endif | |
1053 | while (c= *p++) (fastab+COFF)[c] |= SB; | |
1054 | # if gcos | |
1055 | p="\n\"'`\\"; | |
1056 | # else | |
1057 | p="\n\"'\\"; | |
1058 | # endif | |
1059 | while (c= *p++) (fastab+COFF)[c] |= QB; | |
1060 | p="*\n"; while (c= *p++) (fastab+COFF)[c] |= CB; | |
1061 | (fastab+COFF)[warnc] |= WB; | |
1062 | (fastab+COFF)['\0'] |= CB|QB|SB|WB; | |
1063 | for (i=ALFSIZ; --i>=0; ) slotab[i]=fastab[i]|SB; | |
1064 | p=" \t\013\f\r"; /* note no \n; \v not legal for vertical tab? */ | |
1065 | while (c= *p++) (toktyp+COFF)[c]=BLANK; | |
1066 | #if scw2 | |
1067 | for ((t23+COFF)[i=ALFSIZ+7-COFF]=1; --i>=-COFF; ) | |
1068 | if (((t23+COFF)[i]=(t23+COFF+1)[i]<<1)==0) (t23+COFF)[i]=1; | |
1069 | #endif | |
1070 | ||
1071 | # if unix | |
1072 | fnames[ifno=0] = ""; dirnams[0]=dirs[0]="."; | |
1073 | # endif | |
1074 | # if ibm | |
1075 | fnames[ifno=0] = ""; | |
1076 | # endif | |
1077 | # if gcos | |
1078 | if (inquire(stdin, _TTY)) freopen("*src", "rt", stdin); | |
1079 | # endif | |
1080 | # if gimpel || gcos | |
1081 | fnames[ifno=0] = (char *)inquire(stdin, _FILENAME); | |
1082 | dirnams[0] = dirs[0] = trmdir(copy(fnames[0])); | |
1083 | # endif | |
1084 | for(i=1; i<argc; i++) | |
1085 | { | |
1086 | switch(argv[i][0]) | |
1087 | { | |
1088 | case '-': | |
1089 | # if gcos | |
1090 | switch(toupper(argv[i][1])) { /* case-independent on GCOS */ | |
1091 | # else | |
1092 | switch(argv[i][1]) { | |
1093 | # endif | |
61a8d43d | 1094 | case 'M': mflag++; |
66cbbe7c RH |
1095 | case 'P': pflag++; |
1096 | case 'E': continue; | |
1097 | case 'R': ++rflag; continue; | |
1098 | case 'C': passcom++; continue; | |
1099 | case 'D': | |
1100 | if (predef>prespc+NPREDEF) { | |
1101 | pperror("too many -D options, ignoring %s",argv[i]); | |
1102 | continue; | |
1103 | } | |
1104 | /* ignore plain "-D" (no argument) */ | |
1105 | if (*(argv[i]+2)) *predef++ = argv[i]+2; | |
1106 | continue; | |
1107 | case 'U': | |
1108 | if (prund>punspc+NPREDEF) { | |
1109 | pperror("too many -U options, ignoring %s",argv[i]); | |
1110 | continue; | |
1111 | } | |
1112 | *prund++ = argv[i]+2; | |
1113 | continue; | |
1114 | case 'I': | |
1115 | if (nd>8) pperror("excessive -I file (%s) ignored",argv[i]); | |
1116 | else dirs[nd++] = argv[i]+2; | |
1117 | continue; | |
1118 | case '\0': continue; | |
1119 | default: | |
1120 | pperror("unknown flag %s", argv[i]); | |
1121 | continue; | |
1122 | } | |
1123 | default: | |
061309d9 | 1124 | if (fin==FIRSTOPEN) { |
66cbbe7c RH |
1125 | if (0>(fin=open(argv[i], READ))) { |
1126 | pperror("No source file %s",argv[i]); exit(8); | |
1127 | } | |
1128 | fnames[ifno]=copy(argv[i]); | |
61a8d43d | 1129 | infile=copy(argv[i]); |
9372792e | 1130 | dirs[0]=dirnams[ifno]=trmdir(argv[i]); |
66cbbe7c RH |
1131 | # ifndef gcos |
1132 | /* too dangerous to have file name in same syntactic position | |
1133 | be input or output file depending on file redirections, | |
1134 | so force output to stdout, willy-nilly | |
1135 | [i don't see what the problem is. jfr] | |
1136 | */ | |
1137 | } else if (fout==stdout) { | |
66cbbe7c RH |
1138 | if (NULL==(fout=fopen(argv[i], "w"))) { |
1139 | pperror("Can't create %s", argv[i]); exit(8); | |
ba27d052 | 1140 | } else fclose(stdout); |
66cbbe7c RH |
1141 | # endif |
1142 | } else pperror("extraneous name %s", argv[i]); | |
1143 | } | |
1144 | } | |
1145 | ||
61a8d43d KM |
1146 | if (mflag) { |
1147 | if (infile==(char *)0) { | |
1148 | fprintf(stderr, | |
1149 | "no input file specified with -M flag\n"); | |
1150 | exit(8); | |
1151 | } | |
1152 | tf=(char *)rindex(infile, '.'); | |
1153 | if (tf==0) { | |
1154 | fprintf(stderr, "missing component name on %s\n", | |
1155 | infile); | |
1156 | exit(8); | |
1157 | } | |
1158 | tf[1]='o'; | |
1159 | tf=(char *)rindex(infile, '/'); | |
1160 | if (tf!=(char *)0) | |
1161 | infile = tf + 1; | |
1162 | mout=fout; | |
1163 | if (NULL==(fout=fopen("/dev/null", "w"))) { | |
1164 | pperror("Can't open /dev/null"); | |
1165 | exit(8); | |
1166 | } | |
1167 | } | |
66cbbe7c RH |
1168 | fins[ifno]=fin; |
1169 | exfail = 0; | |
1170 | /* after user -I files here are the standard include libraries */ | |
1171 | # if unix | |
1172 | dirs[nd++] = "/usr/include"; | |
1173 | # endif | |
1174 | # if gcos | |
1175 | dirs[nd++] = "cc/include"; | |
1176 | # endif | |
1177 | # if ibm | |
1178 | # ifndef gimpel | |
1179 | dirs[nd++] = "BTL$CLIB"; | |
1180 | # endif | |
1181 | # endif | |
1182 | # ifdef gimpel | |
1183 | dirs[nd++] = intss() ? "SYS3.C." : "" ; | |
1184 | # endif | |
1185 | /* dirs[nd++] = "/compool"; */ | |
1186 | dirs[nd++] = 0; | |
1187 | defloc=ppsym("define"); | |
1188 | udfloc=ppsym("undef"); | |
1189 | incloc=ppsym("include"); | |
1190 | elsloc=ppsym("else"); | |
1191 | eifloc=ppsym("endif"); | |
1192 | ifdloc=ppsym("ifdef"); | |
1193 | ifnloc=ppsym("ifndef"); | |
1194 | ifloc=ppsym("if"); | |
1195 | lneloc=ppsym("line"); | |
7e5ed264 | 1196 | identloc=ppsym("ident"); /* Sys 5r3 compatibility */ |
66cbbe7c RH |
1197 | for (i=sizeof(macbit)/sizeof(macbit[0]); --i>=0; ) macbit[i]=0; |
1198 | # if unix | |
1199 | ysysloc=stsym("unix"); | |
1200 | # endif | |
1201 | # if gcos | |
1202 | ysysloc=stsym ("gcos"); | |
1203 | # endif | |
1204 | # if ibm | |
1205 | ysysloc=stsym ("ibm"); | |
1206 | # endif | |
1207 | # if pdp11 | |
1208 | varloc=stsym("pdp11"); | |
1209 | # endif | |
1210 | # if vax | |
1211 | varloc=stsym("vax"); | |
1212 | # endif | |
1213 | # if interdata | |
1214 | varloc=stsym ("interdata"); | |
1215 | # endif | |
1216 | # if tss | |
1217 | varloc=stsym ("tss"); | |
1218 | # endif | |
1219 | # if os | |
1220 | varloc=stsym ("os"); | |
1221 | # endif | |
1222 | # if mert | |
1223 | varloc=stsym ("mert"); | |
5f18cf8b SL |
1224 | # endif |
1225 | # if mc68000 | |
1226 | varloc=stsym("mc68000"); | |
1227 | # endif | |
1228 | # if sun | |
1229 | varloc=stsym("sun"); | |
66cbbe7c RH |
1230 | # endif |
1231 | ulnloc=stsym ("__LINE__"); | |
1232 | uflloc=stsym ("__FILE__"); | |
1233 | ||
1234 | tf=fnames[ifno]; fnames[ifno]="command line"; lineno[ifno]=1; | |
1235 | cp2=prespc; | |
1236 | while (cp2<predef) stsym(*cp2++); | |
1237 | cp2=punspc; | |
1238 | while (cp2<prund) { | |
1239 | if (p=strdex(*cp2, '=')) *p++='\0'; | |
1240 | lookup(*cp2++, DROP); | |
1241 | } | |
1242 | fnames[ifno]=tf; | |
1243 | pbeg=buffer+NCPS; pbuf=pbeg+BUFSIZ; pend=pbuf+BUFSIZ; | |
1244 | ||
1245 | trulvl = 0; flslvl = 0; | |
61a8d43d | 1246 | lineno[0] = 1; sayline(START); |
66cbbe7c RH |
1247 | outp=inp=pend; |
1248 | control(pend); | |
1249 | return (exfail); | |
1250 | } |