Print this page
cpp: do not pass #error into output stream, warn about it and exit non-0
Split |
Close |
Expand all |
Collapse all |
--- old/cpp/cpp.c
+++ new/cpp/cpp.c
1 1 /*
2 2 * C command
3 3 * written by John F. Reiser
4 4 * July/August 1978
5 5 */
6 6 /* Copyright (c) 2012 Joyent, Inc. All rights reserved. */
7 7 /*
8 8 * This implementation is based on the UNIX 32V release from 1978
9 9 * with permission from Caldera Inc.
10 10 *
11 11 * Copyright (c) 2010 J. Schilling
12 12 * All rights reserved.
13 13 *
14 14 * Redistribution and use in source and binary forms, with or without
15 15 * modification, are permitted provided that the following conditions
16 16 * are met:
17 17 * 1. Redistributions of source code must retain the above copyright
18 18 * notice, this list of conditions and the following disclaimer.
19 19 * 2. Redistributions in binary form must reproduce the above copyright
20 20 * notice, this list of conditions and the following disclaimer in the
21 21 * documentation and/or other materials provided with the distribution.
22 22 * 3. Neither the name of the copyright holder nor the names of contributors
23 23 * may be used to endorse or promote products derived from this software
24 24 * without specific prior written permission.
25 25 *
26 26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND
27 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE
30 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 36 * SUCH DAMAGE.
37 37 */
38 38 /*
39 39 * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
40 40 *
41 41 * Redistribution and use in source and binary forms, with or without
42 42 * modification, are permitted provided that the following conditions are
43 43 * met:
44 44 * 1. Redistributions of source code and documentation must retain the above
45 45 * copyright notice, this list of conditions and the following
46 46 * disclaimer.
47 47 *
48 48 * 2. Redistributions in binary form must reproduce the above copyright
49 49 * notice, this list of conditions and the following disclaimer in the
50 50 * documentation and/or other materials provided with the distribution.
51 51 *
52 52 * 3. All advertising materials mentioning features or use of this software
53 53 * must display the following acknowledgement: This product includes
54 54 * software developed or owned by Caldera International, Inc.
55 55 *
56 56 * 4. Neither the name of Caldera International, Inc. nor the names of other
57 57 * contributors may be used to endorse or promote products derived from
58 58 * this software without specific prior written permission.
59 59 *
60 60 * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
61 61 * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
62 62 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
63 63 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
64 64 * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE FOR
65 65 * ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
66 66 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
67 67 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
68 68 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
69 69 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
70 70 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
71 71 * POSSIBILITY OF SUCH DAMAGE.
72 72 */
73 73 #include <stdio.h>
74 74 #include <unistd.h>
75 75 #include <stdlib.h>
76 76 #include <fcntl.h>
77 77 #include <string.h>
78 78 #include <stdarg.h>
79 79
80 80 #include "cpp.h"
81 81
82 82 #define SYMLEN 128
83 83 static int symlen = SYMLEN;
84 84
85 85
86 86 #define SALT '#'
87 87 #ifndef BUFSIZ
88 88 #define BUFSIZ 512
89 89 #endif
90 90
91 91 static char *pbeg;
92 92 static char *pbuf;
93 93 static char *pend;
94 94 char *outp,*inp;
95 95 char *newp;
96 96 static char cinit;
97 97
98 98 /* some code depends on whether characters are sign or zero extended */
99 99 /* #if '\377' < 0 not used here, old cpp doesn't understand */
100 100 #if pdp11 | vax | '\377' < 0
101 101 #define COFF 128
102 102 #else
103 103 #define COFF 0
104 104 #endif
105 105
106 106 #define ALFSIZ 256 /* alphabet size */
107 107 static char macbit[ALFSIZ+11];
108 108 static char toktyp[ALFSIZ];
109 109 #define BLANK 1 /* white space (" \t\v\f\r") */
110 110 #define IDENT 2 /* valid char for identifier names */
111 111 #define NUMBR 3 /* chars is of "0123456789." */
112 112
113 113 /*
114 114 * a superimposed code is used to reduce the number of calls to the
115 115 * symbol table lookup routine. (if the kth character of an identifier
116 116 * is 'a' and there are no macro names whose kth character is 'a'
117 117 * then the identifier cannot be a macro name, hence there is no need
118 118 * to look in the symbol table.) 'scw1' enables the test based on
119 119 * single characters and their position in the identifier. 'scw2'
120 120 * enables the test based on adjacent pairs of characters and their
121 121 * position in the identifier. scw1 typically costs 1 indexed fetch,
122 122 * an AND, and a jump per character of identifier, until the identifier
123 123 * is known as a non-macro name or until the end of the identifier.
124 124 * scw1 is inexpensive. scw2 typically costs 4 indexed fetches,
125 125 * an add, an AND, and a jump per character of identifier, but it is also
126 126 * slightly more effective at reducing symbol table searches.
127 127 * scw2 usually costs too much because the symbol table search is
128 128 * usually short; but if symbol table search should become expensive,
129 129 * the code is here.
130 130 * using both scw1 and scw2 is of dubious value.
131 131 */
132 132 #define scw1 1
133 133 #define scw2 0
134 134
135 135 #if scw2
136 136 char t21[ALFSIZ],t22[ALFSIZ],t23[ALFSIZ+SYMLEN];
137 137 #endif
138 138
139 139 #if scw1
140 140 #define b0 1
141 141 #define b1 2
142 142 #define b2 4
143 143 #define b3 8
144 144 #define b4 16
145 145 #define b5 32
146 146 #define b6 64
147 147 #define b7 128
148 148 #endif
149 149
150 150 #define IB 1
151 151 #define SB 2
152 152 #define NB 4
153 153 #define CB 8
154 154 #define QB 16
155 155 #define WB 32
156 156 char fastab[ALFSIZ];
157 157 static char slotab[ALFSIZ];
158 158 static char *ptrtab;
159 159
160 160 /*
161 161 * Cast the array index to int in order to avoid GCCs warnings:
162 162 * warning: subscript has type `char'
163 163 */
164 164 #define isslo (ptrtab==(slotab+COFF))
165 165 #define isid(a) ((fastab+COFF)[(int)a]&IB)
166 166 #define isspc(a) (ptrtab[(int)a]&SB)
167 167 #define isnum(a) ((fastab+COFF)[(int)a]&NB)
168 168 #define iscom(a) ((fastab+COFF)[(int)a]&CB)
169 169 #define isquo(a) ((fastab+COFF)[(int)a]&QB)
170 170 #define iswarn(a) ((fastab+COFF)[(int)a]&WB)
171 171
172 172 #define eob(a) ((a)>=pend)
173 173 #define bob(a) (pbeg>=(a))
174 174
175 175 #define BUFFERSIZ 8192
176 176 static char buffer[SYMLEN+BUFFERSIZ+BUFFERSIZ+SYMLEN];
177 177
178 178 /*
179 179 * SBSIZE was 12000 in 1978, we need to have a way to
180 180 * malloc more space.
181 181 */
182 182 #define SBSIZE 512000
183 183 static char sbf[SBSIZE];
184 184 static char *savch = sbf;
185 185
186 186 # define DROP 0xFE /* special character not legal ASCII or EBCDIC */
187 187 # define WARN DROP
188 188 # define SAME 0
189 189 # define MAXINC 16 /* max include nesting depth */
190 190 # define MAXIDIRS 20 /* max # of -I directories */
191 191 # define MAXFRE 14 /* max buffers of macro pushback */
192 192 # define MAXFRM 31 /* max number of formals/actuals to a macro */
193 193
194 194 static char warnc = (char)WARN;
195 195
196 196 static int mactop;
197 197 static int fretop;
198 198 static char *instack[MAXFRE];
199 199 static char *bufstack[MAXFRE];
200 200 static char *endbuf[MAXFRE];
201 201
202 202 static int plvl; /* parenthesis level during scan for macro actuals */
203 203 static int maclin; /* line number of macro call requiring actuals */
204 204 static char *macfil; /* file name of macro call requiring actuals */
205 205 static char *macnam; /* name of macro requiring actuals */
206 206 static int maclvl; /* # calls since last decrease in nesting level */
207 207 static char *macforw; /* ptr which must be exceeded to decrease nesting lvl */
208 208 static int macdam; /* offset to macforw due to buffer shifting */
209 209
210 210 #if tgp
211 211 int tgpscan; /* flag for dump(); */
212 212 #endif
213 213
214 214 static int inctop[MAXINC];
215 215 static char *fnames[MAXINC];
216 216 static char *dirnams[MAXINC]; /* actual directory of #include files */
217 217 static int fins[MAXINC];
218 218 static int lineno[MAXINC];
219 219
220 220 /*
221 221 * We need:
222 222 * "" include dir as dirs[0] +
223 223 * MAXIDIRS +
224 224 * system default include dir +
225 225 * a NULL pointer at the end
226 226 */
227 227 static char *dirs[MAXIDIRS+3]; /* -I and <> directories */
228 228 static int fin = STDIN_FILENO;
229 229 static FILE *fout; /* Init in main(), Mac OS is nonPOSIX */
230 230 static int nd = 1;
231 231 static int pflag; /* don't put out lines "# 12 foo.c" */
232 232 static int passcom; /* don't delete comments */
233 233 static int rflag; /* allow macro recursion */
234 234 static int hflag; /* Print included filenames */
235 235 static int nopredef; /* -undef all */
236 236 static int ifno;
237 237 # define NPREDEF 64
238 238 static char *prespc[NPREDEF];
239 239 static char **predef = prespc;
240 240 static char *punspc[NPREDEF];
241 241 static char **prund = punspc;
242 242 static int exfail;
243 243 static struct symtab *lastsym;
244 244
245 245
246 246 static void sayline(char *);
247 247 static void dump(void);
248 248 static char *refill(char *);
249 249 static char *cotoken(char *);
250 250 char *skipbl(char *);
251 251 static char *unfill(char *);
252 252 static char *doincl(char *);
253 253 static int equfrm(char *, char *, char *);
254 254 static char *dodef(char *);
255 255 static char *control(char *);
256 256 static struct symtab *stsym(char *);
257 257 static struct symtab *ppsym(char *);
258 258 void pperror(char *fmt, ...);
259 259 void yyerror(char *fmt, ...);
260 260 static void ppwarn(char *fmt, ...);
261 261 struct symtab *lookup(char *, int);
262 262 static struct symtab *slookup(char *, char *, int);
263 263 static char *subst(char *, struct symtab *);
264 264 static char *trmdir(char *);
265 265 static char *copy(char *);
266 266 static char *strdex(char *, int);
267 267 int yywrap(void);
268 268 int main(int argc, char **argav);
269 269
270 270
271 271 #define symsiz 4000
272 272 static struct symtab stab[symsiz];
273 273
274 274 static struct symtab *defloc;
275 275 static struct symtab *udfloc;
276 276 static struct symtab *incloc;
277 277 static struct symtab *ifloc;
278 278 static struct symtab *elsloc;
279 279 static struct symtab *eifloc;
280 280 static struct symtab *elifloc;
281 281 static struct symtab *ifdloc;
282 282 static struct symtab *ifnloc;
283 283 static struct symtab *ysysloc;
284 284 static struct symtab *varloc;
285 285 static struct symtab *lneloc;
286 286 static struct symtab *ulnloc;
287 287 static struct symtab *uflloc;
288 288 static struct symtab *idtloc;
289 289 static struct symtab *pragmaloc;
290 290 static struct symtab *errorloc;
291 291 static int trulvl;
292 292 int flslvl;
293 293 static int elflvl;
294 294 static int elslvl;
295 295
296 296 /*
297 297 * The sun cpp prints a classification token past the
298 298 * "# linenumber filename" lines:
299 299 */
300 300 #define NOINCLUDE "" /* Not related to enter/leave incl. file */
301 301 #define ENTERINCLUDE "1" /* We are just entering an include file */
302 302 #define LEAVEINCLUDE "2" /* We are just leaving an include file */
303 303
304 304 /* ARGSUSED */
305 305 static void
306 306 sayline(what)
307 307 char *what;
308 308 {
309 309 if (pflag==0)
310 310 fprintf(fout,"# %d \"%s\" %s\n", lineno[ifno], fnames[ifno], what);
311 311 }
312 312
313 313 /*
314 314 * data structure guide
315 315 *
316 316 * most of the scanning takes place in the buffer:
317 317 *
318 318 * (low address) (high address)
319 319 * pbeg pbuf pend
320 320 * | <-- BUFFERSIZ chars --> | <-- BUFFERSIZ chars --> |
321 321 * _______________________________________________________________________
322 322 * |_______________________________________________________________________|
323 323 * | | |
324 324 * |<-- waiting -->| |<-- waiting -->
325 325 * | to be |<-- current -->| to be
326 326 * | written | token | scanned
327 327 * | | |
328 328 * outp inp p
329 329 *
330 330 * *outp first char not yet written to output file
331 331 * *inp first char of current token
332 332 * *p first char not yet scanned
333 333 *
334 334 * macro expansion: write from *outp to *inp (chars waiting to be written),
335 335 * ignore from *inp to *p (chars of the macro call), place generated
336 336 * characters in front of *p (in reverse order), update pointers,
337 337 * resume scanning.
338 338 *
339 339 * symbol table pointers point to just beyond the end of macro definitions;
340 340 * the first preceding character is the number of formal parameters.
341 341 * the appearance of a formal in the body of a definition is marked by
342 342 * 2 chars: the char WARN, and a char containing the parameter number.
343 343 * the first char of a definition is preceded by a zero character.
344 344 *
345 345 * when macro expansion attempts to back up over the beginning of the
346 346 * buffer, some characters preceding *pend are saved in a side buffer,
347 347 * the address of the side buffer is put on 'instack', and the rest
348 348 * of the main buffer is moved to the right. the end of the saved buffer
349 349 * is kept in 'endbuf' since there may be nulls in the saved buffer.
350 350 *
351 351 * similar action is taken when an 'include' statement is processed,
352 352 * except that the main buffer must be completely emptied. the array
353 353 * element 'inctop[ifno]' records the last side buffer saved when
354 354 * file 'ifno' was included. these buffers remain dormant while
355 355 * the file is being read, and are reactivated at end-of-file.
356 356 *
357 357 * instack[0 : mactop] holds the addresses of all pending side buffers.
358 358 * instack[inctop[ifno]+1 : mactop-1] holds the addresses of the side
359 359 * buffers which are "live"; the side buffers instack[0 : inctop[ifno]]
360 360 * are dormant, waiting for end-of-file on the current file.
361 361 *
362 362 * space for side buffers is obtained from 'savch' and is never returned.
363 363 * bufstack[0:fretop-1] holds addresses of side buffers which
364 364 * are available for use.
365 365 */
366 366
367 367 static void
368 368 dump() {
369 369 /*
370 370 * write part of buffer which lies between outp and inp .
371 371 * this should be a direct call to 'write', but the system slows to a crawl
372 372 * if it has to do an unaligned copy. thus we buffer. this silly loop
373 373 * is 15% of the total time, thus even the 'putc' macro is too slow.
374 374 */
375 375 register char *p1;
376 376 #if tgp
377 377 register char *p2;
378 378 #endif
379 379 register FILE *f;
380 380 if ((p1=outp)==inp || flslvl!=0) return;
381 381 #if tgp
382 382 #define MAXOUT 80
383 383 if (!tgpscan) {
384 384 /* scan again to insure <= MAXOUT chars between linefeeds */
385 385 register char c,*pblank; char savc,stopc,brk;
386 386 tgpscan=1; brk=stopc=pblank=0; p2=inp; savc= *p2; *p2='\0';
387 387 while (c= *p1++) {
388 388 if (c=='\\') c= *p1++;
389 389 if (stopc==c) stopc=0;
390 390 else if (c=='"' || c=='\'') stopc=c;
391 391 if (p1-outp>MAXOUT && pblank!=0) {
392 392 *pblank++='\n';
393 393 inp=pblank;
394 394 dump();
395 395 brk=1;
396 396 pblank=0;
397 397 }
398 398 if (c==' ' && stopc==0) pblank=p1-1;
399 399 }
400 400 if (brk) sayline(NOINCLUDE);
401 401 *p2=savc; inp=p2; p1=outp; tgpscan=0;
402 402 }
403 403 #endif
404 404 f=fout;
405 405 while (p1<inp)
406 406 putc(*p1++,f);
407 407 outp=p1;
408 408 }
409 409
410 410 static char *
411 411 refill(p) register char *p; {
412 412 /*
413 413 * dump buffer. save chars from inp to p. read into buffer at pbuf,
414 414 * contiguous with p. update pointers, return new p.
415 415 */
416 416 register char *np,*op; register int ninbuf;
417 417 dump(); np=pbuf-(p-inp); op=inp;
418 418 if (bob(np+1)) {pperror("token too long"); np=pbeg; p=inp+BUFFERSIZ;}
419 419 macdam += np-inp; outp=inp=np;
420 420 while (op<p) *np++= *op++;
421 421 p=np;
422 422 for (;;) {
423 423 if (mactop>inctop[ifno]) {
424 424 /* retrieve hunk of pushed-back macro text */
425 425 op=instack[--mactop]; np=pbuf;
426 426 do {
427 427 while ((*np++= *op++) != '\0');
428 428 } while (op<endbuf[mactop]); pend=np-1;
429 429 /* make buffer space avail for 'include' processing */
430 430 if (fretop<MAXFRE) bufstack[fretop++]=instack[mactop];
431 431 return(p);
432 432 } else {/* get more text from file(s) */
433 433 maclvl=0;
434 434 if (0<(ninbuf=read(fin,pbuf,BUFFERSIZ))) {
435 435 pend=pbuf+ninbuf; *pend='\0';
436 436 return(p);
437 437 }
438 438 /* end of #include file */
439 439 if (ifno==0) {/* end of input */
440 440 if (plvl!=0) {
441 441 int n=plvl,tlin=lineno[ifno];
442 442 char *tfil=fnames[ifno];
443 443 lineno[ifno]=maclin;
444 444 fnames[ifno]=macfil;
445 445 pperror("%s: unterminated macro call",
446 446 macnam);
447 447 lineno[ifno]=tlin; fnames[ifno]=tfil;
448 448 np=p;
449 449 /*
450 450 * shut off unterminated quoted string
451 451 */
452 452 *np++='\n';
453 453 /* supply missing parens */
454 454 while (--n>=0) *np++=')';
455 455 pend=np; *np='\0';
456 456 if (plvl<0) plvl=0;
457 457 return(p);
458 458 }
459 459 inp=p; dump(); exit(exfail);
460 460 }
461 461 close(fin);
462 462 fin=fins[--ifno];
463 463 dirs[0]=dirnams[ifno];
464 464 sayline(LEAVEINCLUDE);
465 465 }
466 466 }
467 467 }
468 468
469 469 #define BEG 0
470 470 #define LF 1
471 471
472 472 static char *
473 473 cotoken(p) register char *p; {
474 474 register int c,i; char quoc;
475 475 static int state = BEG;
476 476
477 477 if (state!=BEG) goto prevlf;
478 478 for (;;) {
479 479 again:
480 480 while (!isspc(*p++));
481 481 switch (*(inp=p-1)) {
482 482 case 0: {
483 483 if (eob(--p)) {p=refill(p); goto again;}
484 484 else ++p; /* ignore null byte */
485 485 } break;
486 486 case '|': case '&': for (;;) {/* sloscan only */
487 487 if (*p++== *inp) break;
488 488 if (eob(--p)) p=refill(p);
489 489 else break;
490 490 } break;
491 491 case '=': case '!': for (;;) {/* sloscan only */
492 492 if (*p++=='=') break;
493 493 if (eob(--p)) p=refill(p);
494 494 else break;
495 495 } break;
496 496 case '<': case '>': for (;;) {/* sloscan only */
497 497 if (*p++=='=' || p[-2]==p[-1]) break;
498 498 if (eob(--p)) p=refill(p);
499 499 else break;
500 500 } break;
501 501 case '\\': for (;;) {
502 502 if (*p++=='\n') {++lineno[ifno]; break;}
503 503 if (eob(--p)) p=refill(p);
504 504 else {++p; break;}
505 505 } break;
506 506 case '/': for (;;) {
507 507 if (*p++=='*') {/* comment */
508 508 if (!passcom) {inp=p-2; dump(); ++flslvl;}
509 509 for (;;) {
510 510 while (!iscom(*p++));
511 511 if (p[-1]=='*') for (;;) {
512 512 if (*p++=='/') goto endcom;
513 513 if (eob(--p)) {
514 514 if (!passcom) {
515 515 inp=p;
516 516 p=refill(p);
517 517 } else if ((p-inp)>=BUFFERSIZ) {
518 518 /* split long comment */
519 519 inp=p;
520 520 /*
521 521 * last char written
522 522 * is '*'
523 523 */
524 524 p=refill(p);
525 525 /*
526 526 * terminate first part
527 527 */
528 528 putc('/',fout);
529 529 /*
530 530 * and fake start of 2nd
531 531 */
532 532 outp=inp=p-=3;
533 533 *p++='/';
534 534 *p++='*';
535 535 *p++='*';
536 536 } else {
537 537 p=refill(p);
538 538 }
539 539 } else {
540 540 break;
541 541 }
542 542 } else if (p[-1]=='\n') {
543 543 ++lineno[ifno];
544 544 if (!passcom)
545 545 putc('\n',fout);
546 546 } else if (eob(--p)) {
547 547 if (!passcom) {
548 548 inp=p; p=refill(p);
549 549 } else if ((p-inp)>=BUFFERSIZ) {
550 550 /* split long comment */
551 551 inp=p; p=refill(p);
552 552 putc('*',fout); putc('/',fout);
553 553 outp=inp=p-=2;
554 554 *p++='/';
555 555 *p++='*';
556 556 } else {
557 557 p=refill(p);
558 558 }
559 559 } else {
560 560 ++p; /* ignore null byte */
561 561 }
562 562 }
563 563 endcom:
564 564 if (!passcom) {outp=inp=p; --flslvl; goto again;}
565 565 break;
566 566 }
567 567 if (eob(--p)) p=refill(p);
568 568 else break;
569 569 } break;
570 570 case '"': case '\'': {
571 571 quoc=p[-1];
572 572 for (;;) {
573 573 while (!isquo(*p++));
574 574 if (p[-1]==quoc)
575 575 break;
576 576 if (p[-1]=='\n') {
577 577 --p;
578 578 break;
579 579 } /* bare \n terminates quotation */
580 580 if (p[-1]=='\\') {
581 581 for (;;) {
582 582 if (*p++=='\n') {
583 583 ++lineno[ifno];
584 584 break;
585 585 } /* escaped \n ignored */
586 586 if (eob(--p)) {
587 587 p=refill(p);
588 588 } else {
589 589 ++p;
590 590 break;
591 591 }
592 592 }
593 593 } else if (eob(--p)) {
594 594 p=refill(p);
595 595 } else {
596 596 ++p; /* it was a different quote character */
597 597 }
598 598 }
599 599 } break;
600 600 case '\n': {
601 601 ++lineno[ifno]; if (isslo) {state=LF; return(p);}
602 602 prevlf:
603 603 state=BEG;
604 604 for (;;) {
605 605 if (*p++=='#') return(p);
606 606 if (eob(inp= --p)) p=refill(p);
607 607 else goto again;
608 608 }
609 609 }
610 610 /* NOTREACHED */
611 611 case '0': case '1': case '2': case '3': case '4':
612 612 case '5': case '6': case '7': case '8': case '9':
613 613 for (;;) {
614 614 while (isnum(*p++));
615 615 if (eob(--p)) p=refill(p);
616 616 else break;
617 617 } break;
618 618 case 'A': case 'B': case 'C': case 'D': case 'E':
619 619 case 'F': case 'G': case 'H': case 'I': case 'J':
620 620 case 'K': case 'L': case 'M': case 'N': case 'O':
621 621 case 'P': case 'Q': case 'R': case 'S': case 'T':
622 622 case 'U': case 'V': case 'W': case 'X': case 'Y':
623 623 case 'Z': case '_':
624 624 case 'a': case 'b': case 'c': case 'd': case 'e':
625 625 case 'f': case 'g': case 'h': case 'i': case 'j':
626 626 case 'k': case 'l': case 'm': case 'n': case 'o':
627 627 case 'p': case 'q': case 'r': case 's': case 't':
628 628 case 'u': case 'v': case 'w': case 'x': case 'y':
629 629 case 'z':
630 630 #if scw1
631 631 #define tmac1(c,bit) if (!xmac1(c,bit,&)) goto nomac
632 632 #define xmac1(c,bit,op) ((macbit+COFF)[c] op (bit))
633 633 #else
634 634 #define tmac1(c,bit)
635 635 #define xmac1(c,bit,op)
636 636 #endif
637 637
638 638 #if scw2
639 639 #define tmac2(c0,c1,cpos) if (!xmac2(c0,c1,cpos,&)) goto nomac
640 640 #define xmac2(c0,c1,cpos,op)\
641 641 ((macbit+COFF)[(t21+COFF)[c0]+(t22+COFF)[c1]] op (t23+COFF+cpos)[c0])
642 642 #else
643 643 #define tmac2(c0,c1,cpos)
644 644 #define xmac2(c0,c1,cpos,op)
645 645 #endif
646 646
647 647 if (flslvl) goto nomac;
648 648 for (;;) {
649 649 c= p[-1]; tmac1(c,b0);
650 650 i= *p++; if (!isid(i)) goto endid; tmac1(i,b1); tmac2(c,i,0);
651 651 c= *p++; if (!isid(c)) goto endid; tmac1(c,b2); tmac2(i,c,1);
652 652 i= *p++; if (!isid(i)) goto endid; tmac1(i,b3); tmac2(c,i,2);
653 653 c= *p++; if (!isid(c)) goto endid; tmac1(c,b4); tmac2(i,c,3);
654 654 i= *p++; if (!isid(i)) goto endid; tmac1(i,b5); tmac2(c,i,4);
655 655 c= *p++; if (!isid(c)) goto endid; tmac1(c,b6); tmac2(i,c,5);
656 656 i= *p++; if (!isid(i)) goto endid; tmac1(i,b7); tmac2(c,i,6);
657 657 tmac2(i,0,7);
658 658 while (isid(*p++));
659 659 if (eob(--p)) {refill(p); p=inp+1; continue;}
660 660 goto lokid;
661 661 endid:
662 662 if (eob(--p)) {refill(p); p=inp+1; continue;}
663 663 tmac2(p[-1],0,-1+(p-inp));
664 664 lokid:
665 665 slookup(inp,p,0); if (newp) {p=newp; goto again;}
666 666 else break;
667 667 nomac:
668 668 while (isid(*p++));
669 669 if (eob(--p)) {p=refill(p); goto nomac;}
670 670 else break;
671 671 } break;
672 672 } /* end of switch */
673 673
674 674 if (isslo) return(p);
675 675 } /* end of infinite loop */
676 676 }
677 677
678 678 char *
679 679 skipbl(p) register char *p; {/* get next non-blank token */
680 680 do {
681 681 outp=inp=p;
682 682 p=cotoken(p);
683 683 } while ((toktyp+COFF)[(int)*inp]==BLANK);
684 684 return(p);
685 685 }
686 686
687 687 static char *
688 688 unfill(p) register char *p; {
689 689 /*
690 690 * take <= BUFFERSIZ chars from right end of buffer and put them on instack .
691 691 * slide rest of buffer to the right, update pointers, return new p.
692 692 */
693 693 register char *np,*op; register int d;
694 694 if (mactop>=MAXFRE) {
695 695 pperror("%s: too much pushback",macnam);
696 696 p=inp=pend; dump(); /* begin flushing pushback */
697 697 while (mactop>inctop[ifno]) {p=refill(p); p=inp=pend; dump();}
698 698 }
699 699 if (fretop>0)
700 700 np=bufstack[--fretop];
701 701 else {
702 702 np=savch; savch+=BUFFERSIZ;
703 703 if (savch>=sbf+SBSIZE) {pperror("no space"); exit(exfail);}
704 704 *savch++='\0';
705 705 }
706 706 instack[mactop]=np; op=pend-BUFFERSIZ; if (op<p) op=p;
707 707 for (;;) {
708 708 while ((*np++= *op++) != '\0');
709 709 if (eob(op))
710 710 break;
711 711 } /* out with old */
712 712 endbuf[mactop++]=np; /* mark end of saved text */
713 713 np=pbuf+BUFFERSIZ;
714 714 op=pend-BUFFERSIZ;
715 715 pend=np;
716 716 if (op<p)
717 717 op=p;
718 718 while (outp<op) *--np= *--op; /* slide over new */
719 719 if (bob(np))
720 720 pperror("token too long");
721 721 d=np-outp; outp+=d; inp+=d; macdam+=d;
722 722 return(p+d);
723 723 }
724 724
725 725 static char *
726 726 doincl(p) register char *p; {
727 727 int filok,inctype;
728 728 register char *cp; char **dirp,*nfil; char filname[BUFFERSIZ];
729 729
730 730 filname[0] = '\0'; /* Make lint quiet */
731 731 p=skipbl(p); cp=filname;
732 732 if (*inp++=='<') {/* special <> syntax */
733 733 inctype=1;
734 734 for (;;) {
735 735 outp=inp=p; p=cotoken(p);
736 736 if (*inp=='\n') {--p; *cp='\0'; break;}
737 737 if (*inp=='>') { *cp='\0'; break;}
738 738 # ifdef gimpel
739 739 if (*inp=='.' && !intss()) *inp='#';
740 740 # endif
741 741 while (inp<p) *cp++= *inp++;
742 742 }
743 743 } else if (inp[-1]=='"') {/* regular "" syntax */
744 744 inctype=0;
745 745 # ifdef gimpel
746 746 while (inp<p) {if (*inp=='.' && !intss()) *inp='#'; *cp++= *inp++;}
747 747 # else
748 748 while (inp<p) *cp++= *inp++;
749 749 # endif
750 750 if (*--cp=='"') *cp='\0';
751 751 } else {pperror("bad include syntax",0); inctype=2;}
752 752 /* flush current file to \n , then write \n */
753 753 ++flslvl; do {outp=inp=p; p=cotoken(p);} while (*inp!='\n'); --flslvl;
754 754 inp=p; dump(); if (inctype==2) return(p);
755 755 /* look for included file */
756 756 if (ifno+1 >=MAXINC) {
757 757 pperror("Unreasonable include nesting",0); return(p);
758 758 }
759 759 if ((nfil=savch)>sbf+SBSIZE-BUFFERSIZ) {
760 760 pperror("no space");
761 761 exit(exfail);
762 762 }
763 763 filok=0;
764 764 for (dirp=dirs+inctype; *dirp; ++dirp) {
765 765 if (filname[0]=='/' || **dirp=='\0') {
766 766 strcpy(nfil,filname);
767 767 } else {
768 768 strcpy(nfil,*dirp);
769 769 # if unix
770 770 strcat(nfil,"/");
771 771 # endif
772 772 strcat(nfil,filname);
773 773 }
774 774 if (0<(fins[ifno+1]=open(nfil, O_RDONLY))) {
775 775 filok=1; fin=fins[++ifno]; break;
776 776 }
777 777 }
778 778 if (filok==0) {
779 779 pperror("Can't find include file %s",filname);
780 780 } else {
781 781 lineno[ifno]=1; fnames[ifno]=cp=nfil; while (*cp++); savch=cp;
782 782 dirnams[ifno]=dirs[0]=trmdir(copy(nfil));
783 783 sayline(ENTERINCLUDE);
784 784 if (hflag)
785 785 fprintf(stderr, "%s\n", nfil);
786 786 /* save current contents of buffer */
787 787 while (!eob(p)) p=unfill(p);
788 788 inctop[ifno]=mactop;
789 789 }
790 790 return(p);
791 791 }
792 792
793 793 static int
794 794 equfrm(a,p1,p2) register char *a,*p1,*p2; {
795 795 register char c; int flag;
796 796 c= *p2; *p2='\0';
797 797 flag=strcmp(a,p1); *p2=c; return(flag==SAME);
798 798 }
799 799
800 800 static char *
801 801 dodef(p) char *p; {/* process '#define' */
802 802 register char *pin,*psav,*cf;
803 803 char **pf,**qf; int b,c,params; struct symtab *np;
804 804 char *oldval,*oldsavch;
805 805 char *formal[MAXFRM]; /* formal[n] is name of nth formal */
806 806 char formtxt[BUFFERSIZ]; /* space for formal names */
807 807
808 808 formtxt[0] = '\0'; /* Make lint quiet */
809 809
810 810 if (savch>sbf+SBSIZE-BUFFERSIZ) {
811 811 pperror("too much defining");
812 812 return(p);
813 813 }
814 814 oldsavch=savch; /* to reclaim space if redefinition */
815 815 ++flslvl; /* prevent macro expansion during 'define' */
816 816 p=skipbl(p); pin=inp;
817 817 if ((toktyp+COFF)[(int)*pin]!=IDENT) {
818 818 ppwarn("illegal macro name");
819 819 while (*inp!='\n')
820 820 p=skipbl(p);
821 821 return(p);
822 822 }
823 823 np=slookup(pin,p,1);
824 824 if (getenv("CPP_DEBUG_DEFINITIONS") != NULL)
825 825 fprintf(stderr, "*** defining %s at %s:%d\n",
826 826 np->name, fnames[ifno], lineno[ifno]);
827 827 if ((oldval=np->value) != NULL)
828 828 savch=oldsavch; /* was previously defined */
829 829 b=1; cf=pin;
830 830 while (cf<p) {/* update macbit */
831 831 c= *cf++; xmac1(c,b,|=); b=(b+b)&0xFF;
832 832 if (cf!=p) {
833 833 xmac2(c,*cf,-1+(cf-pin),|=);
834 834 } else {
835 835 xmac2(c,0,-1+(cf-pin),|=);
836 836 }
837 837 }
838 838 params=0; outp=inp=p; p=cotoken(p); pin=inp;
839 839 formal[0] = ""; /* Prepare for hack at next line... */
840 840 pf = formal; /* Make gcc/lint quiet, pf only used with params!=0 */
841 841 if (*pin=='(') {/* with parameters; identify the formals */
842 842 cf=formtxt; pf=formal;
843 843 for (;;) {
844 844 p=skipbl(p); pin=inp;
845 845 if (*pin=='\n') {
846 846 --lineno[ifno];
847 847 --p;
848 848 pperror("%s: missing )",np->name);
849 849 break;
850 850 }
851 851 if (*pin==')') break;
852 852 if (*pin==',') continue;
853 853 if ((toktyp+COFF)[(int)*pin]!=IDENT) {
854 854 c= *p;
855 855 *p='\0';
856 856 pperror("bad formal: %s",pin);
857 857 *p=c;
858 858 } else if (pf>= &formal[MAXFRM]) {
859 859 c= *p;
860 860 *p='\0';
861 861 pperror("too many formals: %s",pin);
862 862 *p=c;
863 863 } else {
864 864 *pf++=cf;
865 865 while (pin<p)
866 866 *cf++= *pin++;
867 867 *cf++='\0';
868 868 ++params;
869 869 }
870 870 }
871 871 if (params==0)
872 872 --params; /* #define foo() ... */
873 873 } else if (*pin=='\n') {
874 874 --lineno[ifno];
875 875 --p;
876 876 }
877 877 /*
878 878 * remember beginning of macro body, so that we can
879 879 * warn if a redefinition is different from old value.
880 880 */
881 881 oldsavch=psav=savch;
882 882 for (;;) {/* accumulate definition until linefeed */
883 883 outp=inp=p; p=cotoken(p); pin=inp;
884 884 if (*pin=='\\' && pin[1]=='\n')
885 885 continue; /* ignore escaped lf */
886 886 if (*pin=='\n') break;
887 887 if (params) {
888 888 /* mark the appearance of formals in the definiton */
889 889 if ((toktyp+COFF)[(int)*pin]==IDENT) {
890 890 for (qf=pf; --qf>=formal; ) {
891 891 if (equfrm(*qf,pin,p)) {
892 892 *psav++=qf-formal+1;
893 893 *psav++=WARN;
894 894 pin=p;
895 895 break;
896 896 }
897 897 }
898 898 } else if (*pin=='"' || *pin=='\'') {
899 899 /* inside quotation marks, too */
900 900 char quoc= *pin;
901 901 for (*psav++= *pin++; pin<p && *pin!=quoc; ) {
902 902 while (pin<p && !isid(*pin))
903 903 *psav++= *pin++;
904 904 cf=pin;
905 905 while (cf<p && isid(*cf))
906 906 ++cf;
907 907 for (qf=pf; --qf>=formal; ) {
908 908 if (equfrm(*qf,pin,cf)) {
909 909 *psav++=qf-formal+1;
910 910 *psav++=WARN;
911 911 pin=cf;
912 912 break;
913 913 }
914 914 }
915 915 while (pin<cf)
916 916 *psav++= *pin++;
917 917 }
918 918 }
919 919 }
920 920 while (pin<p) *psav++= *pin++;
921 921 }
922 922 *psav++=params; *psav++='\0';
923 923 if ((cf=oldval)!=NULL) {/* redefinition */
924 924 --cf; /* skip no. of params, which may be zero */
925 925 while (*--cf); /* go back to the beginning */
926 926 if (0!=strcmp(++cf,oldsavch)) {
927 927 /* redefinition different from old */
928 928 --lineno[ifno];
929 929 ppwarn("%s redefined",np->name);
930 930 ++lineno[ifno];
931 931 np->value=psav-1;
932 932 } else {
933 933 psav=oldsavch; /* identical redef.; reclaim space */
934 934 }
935 935 } else {
936 936 np->value=psav-1;
937 937 }
938 938 --flslvl; inp=pin; savch=psav; return(p);
939 939 }
940 940
941 941 #define fasscan() ptrtab=fastab+COFF
942 942 #define sloscan() ptrtab=slotab+COFF
943 943
944 944 static char *
945 945 control(p) register char *p; {/* find and handle preprocessor control lines */
946 946 register struct symtab *np;
947 947 for (;;) {
948 948 fasscan(); p=cotoken(p); if (*inp=='\n') ++inp; dump();
949 949 sloscan(); p=skipbl(p);
950 950 *--inp=SALT; outp=inp; ++flslvl; np=slookup(inp,p,0); --flslvl;
951 951 if (np==defloc) {/* define */
952 952 if (flslvl==0) {p=dodef(p); continue;}
953 953 } else if (np==incloc) {/* include */
954 954 if (flslvl==0) {p=doincl(p); continue;}
955 955 } else if (np==ifnloc) {/* ifndef */
956 956 ++flslvl; p=skipbl(p); np=slookup(inp,p,0); --flslvl;
957 957 if (flslvl==0 && np->value==0) ++trulvl;
958 958 else ++flslvl;
959 959 } else if (np==ifdloc) {/* ifdef */
960 960 ++flslvl; p=skipbl(p); np=slookup(inp,p,0); --flslvl;
961 961 if (flslvl==0 && np->value!=0) ++trulvl;
962 962 else ++flslvl;
963 963 } else if (np==eifloc) {/* endif */
964 964 if (flslvl) {if (--flslvl==0) sayline(NOINCLUDE);}
965 965 else if (trulvl) --trulvl;
966 966 else pperror("If-less endif",0);
967 967
968 968 if (flslvl == 0)
969 969 elflvl = 0;
970 970 elslvl = 0;
971 971 } else if (np==elifloc) {/* elif */
972 972 if (flslvl == 0)
973 973 elflvl = trulvl;
974 974 if (flslvl) {
975 975 if (elflvl > trulvl) {
976 976 ;
977 977 } else if (--flslvl != 0) {
978 978 ++flslvl;
979 979 } else {
980 980 newp = p;
981 981 if (yyparse()) {
982 982 ++trulvl;
983 983 sayline(NOINCLUDE);
984 984 } else {
985 985 ++flslvl;
986 986 }
987 987 p = newp;
988 988 }
989 989 } else if (trulvl) {
990 990 ++flslvl;
991 991 --trulvl;
992 992 } else
993 993 pperror("If-less elif");
994 994
995 995 } else if (np==elsloc) {/* else */
996 996 if (flslvl) {
997 997 if (elflvl > trulvl)
998 998 ;
999 999 else if (--flslvl!=0) ++flslvl;
1000 1000 else {++trulvl; sayline(NOINCLUDE);}
1001 1001 }
1002 1002 else if (trulvl) {++flslvl; --trulvl;}
1003 1003 else pperror("If-less else",0);
1004 1004
1005 1005 if (elslvl==trulvl+flslvl)
1006 1006 pperror("Too many #else's");
1007 1007 elslvl=trulvl+flslvl;
1008 1008
1009 1009 } else if (np==udfloc) {/* undefine */
1010 1010 if (flslvl==0) {
1011 1011 ++flslvl; p=skipbl(p); slookup(inp,p,DROP); --flslvl;
1012 1012 }
1013 1013 } else if (np==ifloc) {/* if */
1014 1014 #if tgp
1015 1015 pperror(" IF not implemented, true assumed", 0);
1016 1016 if (flslvl==0) ++trulvl; else ++flslvl;
1017 1017 #else
1018 1018 newp=p;
↓ open down ↓ |
1018 lines elided |
↑ open up ↑ |
1019 1019 if (flslvl==0 && yyparse()) ++trulvl; else ++flslvl;
1020 1020 p=newp;
1021 1021 #endif
1022 1022 } else if (np == idtloc) { /* ident */
1023 1023 if (pflag == 0)
1024 1024 while (*inp != '\n') /* pass text */
1025 1025 p = cotoken(p);
1026 1026 } else if (np == pragmaloc) { /* pragma */
1027 1027 while (*inp != '\n') /* pass text */
1028 1028 p = cotoken(p);
1029 +#ifdef EXIT_ON_ERROR
1029 1030 } else if (np == errorloc) { /* error */
1030 -#ifdef EXIT_ON_ERROR
1031 1031 if (trulvl > 0) {
1032 1032 char ebuf[BUFFERSIZ];
1033 1033
1034 1034 p = ebuf;
1035 1035 while (*inp != '\n') {
1036 1036 if (*inp == '\0')
1037 1037 if (eob(--inp)) {
1038 1038 inp = refill(inp);
1039 1039 continue;
1040 1040 }
1041 1041 *p++ = *inp++;
1042 1042 if (p >= &ebuf[BUFFERSIZ-1])
1043 1043 break;
1044 1044 }
1045 1045 *p = '\0';
1046 1046 pperror(ebuf);
1047 1047 exit(exfail);
1048 1048 }
1049 -#else
1050 - while (*inp != '\n') /* pass text */
1051 - p = cotoken(p);
1052 1049 #endif
1053 1050 } else if (np==lneloc) {/* line */
1054 1051 if (flslvl==0 && pflag==0) {
1055 1052 outp=inp=p;
1056 1053 *--outp='#';
1057 1054 while (*inp!='\n')
1058 1055 p=cotoken(p);
1059 1056 continue;
1060 1057 }
1061 1058 } else if (*++inp=='\n') {
1062 1059 outp=inp; /* allows blank line after # */
1063 1060 } else {
1064 1061 pperror("undefined control",0);
1065 1062 }
1066 1063 /* flush to lf */
1067 1064 ++flslvl;
1068 1065 while (*inp!='\n') {
1069 1066 outp=inp=p;
1070 1067 p=cotoken(p);
1071 1068 }
1072 1069 --flslvl;
1073 1070 }
1074 1071 }
1075 1072
1076 1073 static struct symtab *
1077 1074 stsym(s) register char *s; {
1078 1075 char buf[BUFFERSIZ]; register char *p;
1079 1076
1080 1077 /* make definition look exactly like end of #define line */
1081 1078 /* copy to avoid running off end of world when param list is at end */
1082 1079 p=buf; while ((*p++= *s++) != '\0');
1083 1080 p=buf; while (isid(*p++)); /* skip first identifier */
1084 1081 if (*--p=='=') {*p++=' '; while (*p++);}
1085 1082 else {s=" 1"; while ((*p++= *s++) != '\0');}
1086 1083 pend=p; *--p='\n';
1087 1084 sloscan(); dodef(buf); return(lastsym);
1088 1085 }
1089 1086
1090 1087 static struct symtab *
1091 1088 ppsym(s) char *s; {/* kluge */
1092 1089 register struct symtab *sp;
1093 1090 cinit=SALT; *savch++=SALT; sp=stsym(s); --sp->name; cinit=0; return(sp);
1094 1091 }
1095 1092
1096 1093 void
1097 1094 verror(char *fmt, va_list args)
1098 1095 {
1099 1096 if (fnames[ifno][0])
1100 1097 fprintf(stderr, "%s: ", fnames[ifno]);
1101 1098 fprintf(stderr, "%d: ",lineno[ifno]);
1102 1099
1103 1100 (void)vfprintf(stderr, fmt, args);
1104 1101 fputc('\n', stderr);
1105 1102 }
1106 1103
1107 1104 /* VARARGS1 */
1108 1105 void
1109 1106 pperror(char *fmt, ...)
1110 1107 {
1111 1108 va_list args;
1112 1109
1113 1110 va_start(args, fmt);
1114 1111 verror(fmt, args);
1115 1112 va_end(args);
1116 1113
1117 1114 ++exfail;
1118 1115 }
1119 1116
1120 1117 /* VARARGS1 */
1121 1118 void
1122 1119 yyerror(char *fmt, ...)
1123 1120 {
1124 1121 va_list args;
1125 1122
1126 1123 va_start(args, fmt);
1127 1124 verror(fmt, args);
1128 1125 va_end(args);
1129 1126 }
1130 1127
1131 1128 /* VARARGS1 */
1132 1129 static void
1133 1130 ppwarn(char *fmt, ...)
1134 1131 {
1135 1132 va_list args;
1136 1133 int fail = exfail;
1137 1134 exfail = -1;
1138 1135
1139 1136 va_start(args, fmt);
1140 1137 verror(fmt, args);
1141 1138 va_end(args);
1142 1139
1143 1140 exfail = fail;
1144 1141 }
1145 1142
1146 1143 struct symtab *
1147 1144 lookup(namep, enterf)
1148 1145 char *namep;
1149 1146 int enterf;
1150 1147 {
1151 1148 register char *np, *snp;
1152 1149 register int c, i; int around;
1153 1150 register struct symtab *sp;
1154 1151
1155 1152 /* namep had better not be too long (currently, <=symlen chars) */
1156 1153 np=namep; around=0; i=cinit;
1157 1154 while ((c = *np++) != '\0')
1158 1155 i += i+c;
1159 1156 c=i; /* c=i for register usage on pdp11 */
1160 1157 c %= symsiz;
1161 1158 if (c<0)
1162 1159 c += symsiz;
1163 1160 sp = &stab[c];
1164 1161 while ((snp=sp->name) != NULL) {
1165 1162 np = namep;
1166 1163 while (*snp++ == *np)
1167 1164 if (*np++ == '\0') {
1168 1165 if (enterf==DROP) {
1169 1166 sp->name[0]= DROP;
1170 1167 sp->value=0;
1171 1168 }
1172 1169 return(lastsym=sp);
1173 1170 }
1174 1171 if (--sp < &stab[0]) {
1175 1172 if (around) {
1176 1173 pperror("too many defines", 0);
1177 1174 exit(exfail);
1178 1175 } else {
1179 1176 ++around;
1180 1177 sp = &stab[symsiz-1];
1181 1178 }
1182 1179 }
1183 1180 }
1184 1181 if (enterf>0)
1185 1182 sp->name=namep;
1186 1183 return (lastsym=sp);
1187 1184 }
1188 1185
1189 1186 static struct symtab *
1190 1187 slookup(p1,p2,enterf) register char *p1,*p2; int enterf;{
1191 1188 register char *p3; char c2,c3; struct symtab *np;
1192 1189 c2= *p2; *p2='\0'; /* mark end of token */
1193 1190 if ((p2-p1)>symlen)
1194 1191 p3=p1+symlen;
1195 1192 else
1196 1193 p3=p2;
1197 1194 c3= *p3; *p3='\0'; /* truncate to symlen chars or less */
1198 1195 if (enterf==1)
1199 1196 p1=copy(p1);
1200 1197 np=lookup(p1,enterf); *p3=c3; *p2=c2;
1201 1198 if (np->value!=0 && flslvl==0)
1202 1199 newp=subst(p2,np);
1203 1200 else
1204 1201 newp=0;
1205 1202 return(np);
1206 1203 }
1207 1204
1208 1205 static char *
1209 1206 subst(p,sp) register char *p; struct symtab *sp; {
1210 1207 static char match[]="%s: argument mismatch";
1211 1208 register char *ca,*vp; int params;
1212 1209 char *actual[MAXFRM]; /* actual[n] is text of nth actual */
1213 1210 char acttxt[BUFFERSIZ]; /* space for actuals */
1214 1211
1215 1212 if (0==(vp=sp->value)) return(p);
1216 1213 if ((p-macforw)<=macdam) {
1217 1214 if (++maclvl>symsiz && !rflag) {
1218 1215 pperror("%s: macro recursion",sp->name);
1219 1216 return(p);
1220 1217 }
1221 1218 } else {
1222 1219 maclvl=0; /* level decreased */
1223 1220 }
1224 1221 macforw=p; macdam=0; /* new target for decrease in level */
1225 1222 macnam=sp->name;
1226 1223 dump();
1227 1224 if (sp==ulnloc) {
1228 1225 vp=acttxt; *vp++='\0';
1229 1226 sprintf(vp,"%d",lineno[ifno]); while (*vp++);
1230 1227 } else if (sp==uflloc) {
1231 1228 vp=acttxt; *vp++='\0';
1232 1229 sprintf(vp,"\"%s\"",fnames[ifno]); while (*vp++);
1233 1230 }
1234 1231 if (0!=(params= *--vp&0xFF)) {/* definition calls for params */
1235 1232 register char **pa;
1236 1233 ca=acttxt; pa=actual;
1237 1234 if (params==0xFF)
1238 1235 params=1; /* #define foo() ... */
1239 1236 sloscan();
1240 1237 ++flslvl; /* no expansion during search for actuals */
1241 1238 plvl= -1;
1242 1239 do p=skipbl(p); while (*inp=='\n'); /* skip \n too */
1243 1240 if (*inp=='(') {
1244 1241 maclin=lineno[ifno]; macfil=fnames[ifno];
1245 1242 for (plvl=1; plvl!=0; ) {
1246 1243 *ca++='\0';
1247 1244 for (;;) {
1248 1245 outp=inp=p; p=cotoken(p);
1249 1246 if (*inp=='(') ++plvl;
1250 1247 if (*inp==')' && --plvl==0) {
1251 1248 --params;
1252 1249 break;
1253 1250 }
1254 1251 if (plvl==1 && *inp==',') {
1255 1252 --params;
1256 1253 break;
1257 1254 }
1258 1255 while (inp<p) {
1259 1256 /*
1260 1257 * Sun cpp compatibility.
1261 1258 * Needed for kernel assembler
1262 1259 * preprocessing.
1263 1260 * Replace newlines in actual
1264 1261 * macro parameters by spaces.
1265 1262 * Keep escaped newlines, they
1266 1263 * are assumed to be inside a
1267 1264 * string.
1268 1265 */
1269 1266 if (*inp == '\n' &&
1270 1267 inp[-1] != '\\')
1271 1268 *inp = ' ';
1272 1269 *ca++= *inp++;
1273 1270 }
1274 1271 if (ca> &acttxt[BUFFERSIZ])
1275 1272 pperror("%s: actuals too long",
1276 1273 sp->name);
1277 1274 }
1278 1275 if (pa>= &actual[MAXFRM])
1279 1276 ppwarn(match,sp->name);
1280 1277 else
1281 1278 *pa++=ca;
1282 1279 }
1283 1280 }
1284 1281 if (params!=0)
1285 1282 ppwarn(match,sp->name);
1286 1283 while (--params>=0)
1287 1284 *pa++=""+1; /* null string for missing actuals */
1288 1285 --flslvl; fasscan();
1289 1286 }
1290 1287 for (;;) {/* push definition onto front of input stack */
1291 1288 while (!iswarn(*--vp)) {
1292 1289 if (bob(p)) {outp=inp=p; p=unfill(p);}
1293 1290 *--p= *vp;
1294 1291 }
1295 1292 if (*vp==warnc) {/* insert actual param */
1296 1293 ca=actual[*--vp-1];
1297 1294 while (*--ca) {
1298 1295 if (bob(p)) {outp=inp=p; p=unfill(p);}
1299 1296 *--p= *ca;
1300 1297 }
1301 1298 } else break;
1302 1299 }
1303 1300 outp=inp=p;
1304 1301 return(p);
1305 1302 }
1306 1303
1307 1304 static char *
1308 1305 trmdir(s) register char *s; {
1309 1306 register char *p = s;
1310 1307 while (*p++); --p; while (p>s && *--p!='/');
1311 1308 # if unix
1312 1309 if (p==s) *p++='.';
1313 1310 # endif
1314 1311 *p='\0';
1315 1312 return(s);
1316 1313 }
1317 1314
1318 1315 static char *
1319 1316 copy(s) register char *s; {
1320 1317 register char *old;
1321 1318
1322 1319 old = savch; while ((*savch++ = *s++) != '\0');
1323 1320 return(old);
1324 1321 }
1325 1322
1326 1323 static char *
1327 1324 strdex(s,c) char *s,c; {
1328 1325 while (*s) if (*s++==c) return(--s);
1329 1326 return(0);
1330 1327 }
1331 1328
1332 1329 int
1333 1330 yywrap() {
1334 1331 return(1);
1335 1332 }
1336 1333
1337 1334 int
1338 1335 main(argc,argv)
1339 1336 char *argv[];
1340 1337 int argc;
1341 1338 {
1342 1339 register int i,c;
1343 1340 register char *p;
1344 1341 char *tf,**cp2;
1345 1342 char *sysdir = NULL;
1346 1343
1347 1344 fout = stdout; /* Mac OS X is not POSIX compliant (stdout nonconst.) */
1348 1345
1349 1346 p="_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
1350 1347 i=0;
1351 1348 while ((c= *p++) != '\0') {
1352 1349 (fastab+COFF)[c] |= IB|NB|SB;
1353 1350 (toktyp+COFF)[c]=IDENT;
1354 1351 #if scw2
1355 1352 /*
1356 1353 * 53 == 63-10; digits rarely appear in identifiers,
1357 1354 * and can never be the first char of an identifier.
1358 1355 * 11 == 53*53/sizeof(macbit) .
1359 1356 */
1360 1357 ++i; (t21+COFF)[c]=(53*i)/11; (t22+COFF)[c]=i%11;
1361 1358 #endif
1362 1359 }
1363 1360 p="0123456789.";
1364 1361 while ((c = *p++) != '\0') {
1365 1362 (fastab+COFF)[c] |= NB|SB;
1366 1363 (toktyp+COFF)[c]=NUMBR;
1367 1364 }
1368 1365 p="\n\"'/\\";
1369 1366 while ((c = *p++) != '\0')
1370 1367 (fastab+COFF)[c] |= SB;
1371 1368 p="\n\"'\\";
1372 1369 while ((c = *p++) != '\0')
1373 1370 (fastab+COFF)[c] |= QB;
1374 1371 p="*\n";
1375 1372 while ((c = *p++)!= '\0')
1376 1373 (fastab+COFF)[c] |= CB;
1377 1374 (fastab+COFF)[(int)warnc] |= WB;
1378 1375 (fastab+COFF)['\0'] |= CB|QB|SB|WB;
1379 1376 for (i=ALFSIZ; --i>=0; )
1380 1377 slotab[i]=fastab[i]|SB;
1381 1378 p=" \t\013\f\r"; /* note no \n; \v not legal for vertical tab? */
1382 1379 while ((c = *p++) != '\0')
1383 1380 (toktyp+COFF)[c]=BLANK;
1384 1381 #if scw2
1385 1382 for ((t23+COFF)[i=ALFSIZ+7-COFF]=1; --i>=-COFF; )
1386 1383 if (((t23+COFF)[i]=(t23+COFF+1)[i]<<1)==0)
1387 1384 (t23+COFF)[i]=1;
1388 1385 #endif
1389 1386
1390 1387 # if unix
1391 1388 fnames[ifno=0] = "";
1392 1389 dirs[0]=dirnams[0]= ".";
1393 1390 # endif
1394 1391 # if ibm
1395 1392 fnames[ifno=0] = "";
1396 1393 # endif
1397 1394 # if gimpel
1398 1395 fnames[ifno=0] = (char *)inquire(stdin, _FILENAME);
1399 1396 dirnams[0] = dirs[0] = trmdir(copy(fnames[0]));
1400 1397 # endif
1401 1398 for (i=1; i<argc; i++) {
1402 1399 switch(argv[i][0]) {
1403 1400 case '-':
1404 1401 switch(argv[i][1]) {
1405 1402 case 'P':
1406 1403 pflag++;
1407 1404 continue;
1408 1405 case 'E':
1409 1406 continue;
1410 1407 case 'R':
1411 1408 ++rflag;
1412 1409 continue;
1413 1410 case 'C':
1414 1411 passcom++;
1415 1412 continue;
1416 1413 case 'D':
1417 1414 if (predef>prespc+NPREDEF) {
1418 1415 pperror("too many -D options, "
1419 1416 "ignoring %s", argv[i]);
1420 1417 continue;
1421 1418 }
1422 1419 /* ignore plain "-D" (no argument) */
1423 1420 if (*(argv[i]+2))
1424 1421 *predef++ = argv[i]+2;
1425 1422 continue;
1426 1423 case 'U':
1427 1424 if (prund>punspc+NPREDEF) {
1428 1425 pperror("too many -U options, "
1429 1426 "ignoring %s", argv[i]);
1430 1427 continue;
1431 1428 }
1432 1429 *prund++ = argv[i]+2;
1433 1430 continue;
1434 1431 case 'u':
1435 1432 if (strcmp(argv[i], "-undef") == 0)
1436 1433 nopredef = 1;
1437 1434 else
1438 1435 goto unknown;
1439 1436 continue;
1440 1437 case 'I':
1441 1438 if (nd>=MAXIDIRS)
1442 1439 pperror("excessive -I file "
1443 1440 "(%s) ignored", argv[i]);
1444 1441 else
1445 1442 dirs[nd++] = argv[i]+2;
1446 1443 continue;
1447 1444 case 'T':
1448 1445 symlen = 8;
1449 1446 /* Compatibility with V7 */
1450 1447 continue;
1451 1448 case 'H':
1452 1449 /* Print included filenames */
1453 1450 hflag++;
1454 1451 continue;
1455 1452 case 'Y':
1456 1453 /* Replace system include dir */
1457 1454 sysdir = argv[i]+2;
1458 1455 continue;
1459 1456 case '\0': continue;
1460 1457 default:
1461 1458 unknown:
1462 1459 pperror("unknown flag %s", argv[i]);
1463 1460 continue;
1464 1461 }
1465 1462 default:
1466 1463 if (fin == STDIN_FILENO) {
1467 1464 if (0>(fin=open(argv[i], O_RDONLY))) {
1468 1465 pperror("No source file %s",
1469 1466 argv[i]);
1470 1467 exit(8);
1471 1468 }
1472 1469 fnames[ifno]=copy(argv[i]);
1473 1470 dirs[0]=dirnams[ifno]=trmdir(argv[i]);
1474 1471 /* too dangerous to have file name in same syntactic position
1475 1472 be input or output file depending on file redirections,
1476 1473 so force output to stdout, willy-nilly
1477 1474 [i don't see what the problem is. jfr]
1478 1475 */
1479 1476 } else if (fout==stdout) {
1480 1477 static char _sobuff[BUFSIZ];
1481 1478 if (NULL==(fout=fopen(argv[i], "w"))) {
1482 1479 pperror("Can't create %s",
1483 1480 argv[i]);
1484 1481 exit(8);
1485 1482 } else {
1486 1483 fclose(stdout);
1487 1484 setbuf(fout,_sobuff);
1488 1485 }
1489 1486 } else {
1490 1487 pperror("extraneous name %s", argv[i]);
1491 1488 }
1492 1489 }
1493 1490 }
1494 1491
1495 1492 fins[ifno]=fin;
1496 1493 exfail = 0;
1497 1494 /* after user -I files here are the standard include libraries */
1498 1495 if (sysdir != NULL) {
1499 1496 dirs[nd++] = sysdir;
1500 1497 } else {
1501 1498 # if unix
1502 1499 dirs[nd++] = "/usr/include";
1503 1500 # endif
1504 1501 /* dirs[nd++] = "/compool"; */
1505 1502 }
1506 1503 dirs[nd++] = 0;
1507 1504 defloc=ppsym("define");
1508 1505 udfloc=ppsym("undef");
1509 1506 incloc=ppsym("include");
1510 1507 elsloc=ppsym("else");
1511 1508 eifloc=ppsym("endif");
1512 1509 elifloc=ppsym("elif");
1513 1510 ifdloc=ppsym("ifdef");
1514 1511 ifnloc=ppsym("ifndef");
1515 1512 ifloc=ppsym("if");
1516 1513 lneloc=ppsym("line");
1517 1514 idtloc=ppsym("ident");
1518 1515 pragmaloc=ppsym("pragma");
1519 1516 errorloc=ppsym("error");
1520 1517 for (i=sizeof(macbit)/sizeof(macbit[0]); --i>=0; )
1521 1518 macbit[i]=0;
1522 1519
1523 1520 if (! nopredef) {
1524 1521 # if unix
1525 1522 ysysloc=stsym("unix");
1526 1523 # endif
1527 1524 # if __sparc__
1528 1525 varloc=stsym ("sparc");
1529 1526 # endif
1530 1527 # if __i386__
1531 1528 varloc=stsym ("i386");
1532 1529 # endif
1533 1530 }
1534 1531 ulnloc=stsym ("__LINE__");
1535 1532 uflloc=stsym ("__FILE__");
1536 1533 varloc=stsym ("__BUILTIN_VA_ARG_INCR");
1537 1534
1538 1535 tf=fnames[ifno]; fnames[ifno]="command line"; lineno[ifno]=1;
1539 1536 cp2=prespc;
1540 1537 while (cp2<predef) stsym(*cp2++);
1541 1538 cp2=punspc;
1542 1539 while (cp2<prund) {
1543 1540 if ((p=strdex(*cp2, '=')) != NULL) *p++='\0';
1544 1541 if (strlen(*cp2) > symlen)
1545 1542 (*cp2)[symlen] = '\0';
1546 1543 lookup(*cp2++, DROP);
1547 1544 }
1548 1545 fnames[ifno]=tf;
1549 1546 pbeg=buffer+symlen; pbuf=pbeg+BUFFERSIZ; pend=pbuf+BUFFERSIZ;
1550 1547
1551 1548 trulvl = 0; flslvl = 0;
1552 1549 lineno[0] = 1; sayline(NOINCLUDE);
1553 1550 outp=inp=pend;
1554 1551 control(pend);
1555 1552 return (exfail);
1556 1553 }
↓ open down ↓ |
495 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX