Print this page
cpp: make it easier to find macro sources
This is a dubiously useful hack, but invaluable when debugging the
preprocessor.
If CPP_DEBUG_DEFINITIONS is in the environment, output to stderr at
every macro definition its name, and the defining file and line number,
such that the operative definition of common macros (such as __P) can be
determined.
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 }
↓ open down ↓ |
813 lines elided |
↑ open up ↑ |
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 + if (getenv("CPP_DEBUG_DEFINITIONS") != NULL)
825 + fprintf(stderr, "*** defining %s at %s:%d\n",
826 + np->name, fnames[ifno], lineno[ifno]);
824 827 if ((oldval=np->value) != NULL)
825 828 savch=oldsavch; /* was previously defined */
826 829 b=1; cf=pin;
827 830 while (cf<p) {/* update macbit */
828 831 c= *cf++; xmac1(c,b,|=); b=(b+b)&0xFF;
829 832 if (cf!=p) {
830 833 xmac2(c,*cf,-1+(cf-pin),|=);
831 834 } else {
832 835 xmac2(c,0,-1+(cf-pin),|=);
833 836 }
834 837 }
835 838 params=0; outp=inp=p; p=cotoken(p); pin=inp;
836 839 formal[0] = ""; /* Prepare for hack at next line... */
837 840 pf = formal; /* Make gcc/lint quiet, pf only used with params!=0 */
838 841 if (*pin=='(') {/* with parameters; identify the formals */
839 842 cf=formtxt; pf=formal;
840 843 for (;;) {
841 844 p=skipbl(p); pin=inp;
842 845 if (*pin=='\n') {
843 846 --lineno[ifno];
844 847 --p;
845 848 pperror("%s: missing )",np->name);
846 849 break;
847 850 }
848 851 if (*pin==')') break;
849 852 if (*pin==',') continue;
850 853 if ((toktyp+COFF)[(int)*pin]!=IDENT) {
851 854 c= *p;
852 855 *p='\0';
853 856 pperror("bad formal: %s",pin);
854 857 *p=c;
855 858 } else if (pf>= &formal[MAXFRM]) {
856 859 c= *p;
857 860 *p='\0';
858 861 pperror("too many formals: %s",pin);
859 862 *p=c;
860 863 } else {
861 864 *pf++=cf;
862 865 while (pin<p)
863 866 *cf++= *pin++;
864 867 *cf++='\0';
865 868 ++params;
866 869 }
867 870 }
868 871 if (params==0)
869 872 --params; /* #define foo() ... */
870 873 } else if (*pin=='\n') {
871 874 --lineno[ifno];
872 875 --p;
873 876 }
874 877 /*
875 878 * remember beginning of macro body, so that we can
876 879 * warn if a redefinition is different from old value.
877 880 */
878 881 oldsavch=psav=savch;
879 882 for (;;) {/* accumulate definition until linefeed */
880 883 outp=inp=p; p=cotoken(p); pin=inp;
881 884 if (*pin=='\\' && pin[1]=='\n')
882 885 continue; /* ignore escaped lf */
883 886 if (*pin=='\n') break;
884 887 if (params) {
885 888 /* mark the appearance of formals in the definiton */
886 889 if ((toktyp+COFF)[(int)*pin]==IDENT) {
887 890 for (qf=pf; --qf>=formal; ) {
888 891 if (equfrm(*qf,pin,p)) {
889 892 *psav++=qf-formal+1;
890 893 *psav++=WARN;
891 894 pin=p;
892 895 break;
893 896 }
894 897 }
895 898 } else if (*pin=='"' || *pin=='\'') {
896 899 /* inside quotation marks, too */
897 900 char quoc= *pin;
898 901 for (*psav++= *pin++; pin<p && *pin!=quoc; ) {
899 902 while (pin<p && !isid(*pin))
900 903 *psav++= *pin++;
901 904 cf=pin;
902 905 while (cf<p && isid(*cf))
903 906 ++cf;
904 907 for (qf=pf; --qf>=formal; ) {
905 908 if (equfrm(*qf,pin,cf)) {
906 909 *psav++=qf-formal+1;
907 910 *psav++=WARN;
908 911 pin=cf;
909 912 break;
910 913 }
911 914 }
912 915 while (pin<cf)
913 916 *psav++= *pin++;
914 917 }
915 918 }
916 919 }
917 920 while (pin<p) *psav++= *pin++;
918 921 }
919 922 *psav++=params; *psav++='\0';
920 923 if ((cf=oldval)!=NULL) {/* redefinition */
921 924 --cf; /* skip no. of params, which may be zero */
922 925 while (*--cf); /* go back to the beginning */
923 926 if (0!=strcmp(++cf,oldsavch)) {
924 927 /* redefinition different from old */
925 928 --lineno[ifno];
926 929 ppwarn("%s redefined",np->name);
927 930 ++lineno[ifno];
928 931 np->value=psav-1;
929 932 } else {
930 933 psav=oldsavch; /* identical redef.; reclaim space */
931 934 }
932 935 } else {
933 936 np->value=psav-1;
934 937 }
935 938 --flslvl; inp=pin; savch=psav; return(p);
936 939 }
937 940
938 941 #define fasscan() ptrtab=fastab+COFF
939 942 #define sloscan() ptrtab=slotab+COFF
940 943
941 944 static char *
942 945 control(p) register char *p; {/* find and handle preprocessor control lines */
943 946 register struct symtab *np;
944 947 for (;;) {
945 948 fasscan(); p=cotoken(p); if (*inp=='\n') ++inp; dump();
946 949 sloscan(); p=skipbl(p);
947 950 *--inp=SALT; outp=inp; ++flslvl; np=slookup(inp,p,0); --flslvl;
948 951 if (np==defloc) {/* define */
949 952 if (flslvl==0) {p=dodef(p); continue;}
950 953 } else if (np==incloc) {/* include */
951 954 if (flslvl==0) {p=doincl(p); continue;}
952 955 } else if (np==ifnloc) {/* ifndef */
953 956 ++flslvl; p=skipbl(p); np=slookup(inp,p,0); --flslvl;
954 957 if (flslvl==0 && np->value==0) ++trulvl;
955 958 else ++flslvl;
956 959 } else if (np==ifdloc) {/* ifdef */
957 960 ++flslvl; p=skipbl(p); np=slookup(inp,p,0); --flslvl;
958 961 if (flslvl==0 && np->value!=0) ++trulvl;
959 962 else ++flslvl;
960 963 } else if (np==eifloc) {/* endif */
961 964 if (flslvl) {if (--flslvl==0) sayline(NOINCLUDE);}
962 965 else if (trulvl) --trulvl;
963 966 else pperror("If-less endif",0);
964 967
965 968 if (flslvl == 0)
966 969 elflvl = 0;
967 970 elslvl = 0;
968 971 } else if (np==elifloc) {/* elif */
969 972 if (flslvl == 0)
970 973 elflvl = trulvl;
971 974 if (flslvl) {
972 975 if (elflvl > trulvl) {
973 976 ;
974 977 } else if (--flslvl != 0) {
975 978 ++flslvl;
976 979 } else {
977 980 newp = p;
978 981 if (yyparse()) {
979 982 ++trulvl;
980 983 sayline(NOINCLUDE);
981 984 } else {
982 985 ++flslvl;
983 986 }
984 987 p = newp;
985 988 }
986 989 } else if (trulvl) {
987 990 ++flslvl;
988 991 --trulvl;
989 992 } else
990 993 pperror("If-less elif");
991 994
992 995 } else if (np==elsloc) {/* else */
993 996 if (flslvl) {
994 997 if (elflvl > trulvl)
995 998 ;
996 999 else if (--flslvl!=0) ++flslvl;
997 1000 else {++trulvl; sayline(NOINCLUDE);}
998 1001 }
999 1002 else if (trulvl) {++flslvl; --trulvl;}
1000 1003 else pperror("If-less else",0);
1001 1004
1002 1005 if (elslvl==trulvl+flslvl)
1003 1006 pperror("Too many #else's");
1004 1007 elslvl=trulvl+flslvl;
1005 1008
1006 1009 } else if (np==udfloc) {/* undefine */
1007 1010 if (flslvl==0) {
1008 1011 ++flslvl; p=skipbl(p); slookup(inp,p,DROP); --flslvl;
1009 1012 }
1010 1013 } else if (np==ifloc) {/* if */
1011 1014 #if tgp
1012 1015 pperror(" IF not implemented, true assumed", 0);
1013 1016 if (flslvl==0) ++trulvl; else ++flslvl;
1014 1017 #else
1015 1018 newp=p;
1016 1019 if (flslvl==0 && yyparse()) ++trulvl; else ++flslvl;
1017 1020 p=newp;
1018 1021 #endif
1019 1022 } else if (np == idtloc) { /* ident */
1020 1023 if (pflag == 0)
1021 1024 while (*inp != '\n') /* pass text */
1022 1025 p = cotoken(p);
1023 1026 } else if (np == pragmaloc) { /* pragma */
1024 1027 while (*inp != '\n') /* pass text */
1025 1028 p = cotoken(p);
1026 1029 } else if (np == errorloc) { /* error */
1027 1030 #ifdef EXIT_ON_ERROR
1028 1031 if (trulvl > 0) {
1029 1032 char ebuf[BUFFERSIZ];
1030 1033
1031 1034 p = ebuf;
1032 1035 while (*inp != '\n') {
1033 1036 if (*inp == '\0')
1034 1037 if (eob(--inp)) {
1035 1038 inp = refill(inp);
1036 1039 continue;
1037 1040 }
1038 1041 *p++ = *inp++;
1039 1042 if (p >= &ebuf[BUFFERSIZ-1])
1040 1043 break;
1041 1044 }
1042 1045 *p = '\0';
1043 1046 pperror(ebuf);
1044 1047 exit(exfail);
1045 1048 }
1046 1049 #else
1047 1050 while (*inp != '\n') /* pass text */
1048 1051 p = cotoken(p);
1049 1052 #endif
1050 1053 } else if (np==lneloc) {/* line */
1051 1054 if (flslvl==0 && pflag==0) {
1052 1055 outp=inp=p;
1053 1056 *--outp='#';
1054 1057 while (*inp!='\n')
1055 1058 p=cotoken(p);
1056 1059 continue;
1057 1060 }
1058 1061 } else if (*++inp=='\n') {
1059 1062 outp=inp; /* allows blank line after # */
1060 1063 } else {
1061 1064 pperror("undefined control",0);
1062 1065 }
1063 1066 /* flush to lf */
1064 1067 ++flslvl;
1065 1068 while (*inp!='\n') {
1066 1069 outp=inp=p;
1067 1070 p=cotoken(p);
1068 1071 }
1069 1072 --flslvl;
1070 1073 }
1071 1074 }
1072 1075
1073 1076 static struct symtab *
1074 1077 stsym(s) register char *s; {
1075 1078 char buf[BUFFERSIZ]; register char *p;
1076 1079
1077 1080 /* make definition look exactly like end of #define line */
1078 1081 /* copy to avoid running off end of world when param list is at end */
1079 1082 p=buf; while ((*p++= *s++) != '\0');
1080 1083 p=buf; while (isid(*p++)); /* skip first identifier */
1081 1084 if (*--p=='=') {*p++=' '; while (*p++);}
1082 1085 else {s=" 1"; while ((*p++= *s++) != '\0');}
1083 1086 pend=p; *--p='\n';
1084 1087 sloscan(); dodef(buf); return(lastsym);
1085 1088 }
1086 1089
1087 1090 static struct symtab *
1088 1091 ppsym(s) char *s; {/* kluge */
1089 1092 register struct symtab *sp;
1090 1093 cinit=SALT; *savch++=SALT; sp=stsym(s); --sp->name; cinit=0; return(sp);
1091 1094 }
1092 1095
1093 1096 void
1094 1097 verror(char *fmt, va_list args)
1095 1098 {
1096 1099 if (fnames[ifno][0])
1097 1100 fprintf(stderr, "%s: ", fnames[ifno]);
1098 1101 fprintf(stderr, "%d: ",lineno[ifno]);
1099 1102
1100 1103 (void)vfprintf(stderr, fmt, args);
1101 1104 fputc('\n', stderr);
1102 1105 }
1103 1106
1104 1107 /* VARARGS1 */
1105 1108 void
1106 1109 pperror(char *fmt, ...)
1107 1110 {
1108 1111 va_list args;
1109 1112
1110 1113 va_start(args, fmt);
1111 1114 verror(fmt, args);
1112 1115 va_end(args);
1113 1116
1114 1117 ++exfail;
1115 1118 }
1116 1119
1117 1120 /* VARARGS1 */
1118 1121 void
1119 1122 yyerror(char *fmt, ...)
1120 1123 {
1121 1124 va_list args;
1122 1125
1123 1126 va_start(args, fmt);
1124 1127 verror(fmt, args);
1125 1128 va_end(args);
1126 1129 }
1127 1130
1128 1131 /* VARARGS1 */
1129 1132 static void
1130 1133 ppwarn(char *fmt, ...)
1131 1134 {
1132 1135 va_list args;
1133 1136 int fail = exfail;
1134 1137 exfail = -1;
1135 1138
1136 1139 va_start(args, fmt);
1137 1140 verror(fmt, args);
1138 1141 va_end(args);
1139 1142
1140 1143 exfail = fail;
1141 1144 }
1142 1145
1143 1146 struct symtab *
1144 1147 lookup(namep, enterf)
1145 1148 char *namep;
1146 1149 int enterf;
1147 1150 {
1148 1151 register char *np, *snp;
1149 1152 register int c, i; int around;
1150 1153 register struct symtab *sp;
1151 1154
1152 1155 /* namep had better not be too long (currently, <=symlen chars) */
1153 1156 np=namep; around=0; i=cinit;
1154 1157 while ((c = *np++) != '\0')
1155 1158 i += i+c;
1156 1159 c=i; /* c=i for register usage on pdp11 */
1157 1160 c %= symsiz;
1158 1161 if (c<0)
1159 1162 c += symsiz;
1160 1163 sp = &stab[c];
1161 1164 while ((snp=sp->name) != NULL) {
1162 1165 np = namep;
1163 1166 while (*snp++ == *np)
1164 1167 if (*np++ == '\0') {
1165 1168 if (enterf==DROP) {
1166 1169 sp->name[0]= DROP;
1167 1170 sp->value=0;
1168 1171 }
1169 1172 return(lastsym=sp);
1170 1173 }
1171 1174 if (--sp < &stab[0]) {
1172 1175 if (around) {
1173 1176 pperror("too many defines", 0);
1174 1177 exit(exfail);
1175 1178 } else {
1176 1179 ++around;
1177 1180 sp = &stab[symsiz-1];
1178 1181 }
1179 1182 }
1180 1183 }
1181 1184 if (enterf>0)
1182 1185 sp->name=namep;
1183 1186 return (lastsym=sp);
1184 1187 }
1185 1188
1186 1189 static struct symtab *
1187 1190 slookup(p1,p2,enterf) register char *p1,*p2; int enterf;{
1188 1191 register char *p3; char c2,c3; struct symtab *np;
1189 1192 c2= *p2; *p2='\0'; /* mark end of token */
1190 1193 if ((p2-p1)>symlen)
1191 1194 p3=p1+symlen;
1192 1195 else
1193 1196 p3=p2;
1194 1197 c3= *p3; *p3='\0'; /* truncate to symlen chars or less */
1195 1198 if (enterf==1)
1196 1199 p1=copy(p1);
1197 1200 np=lookup(p1,enterf); *p3=c3; *p2=c2;
1198 1201 if (np->value!=0 && flslvl==0)
1199 1202 newp=subst(p2,np);
1200 1203 else
1201 1204 newp=0;
1202 1205 return(np);
1203 1206 }
1204 1207
1205 1208 static char *
1206 1209 subst(p,sp) register char *p; struct symtab *sp; {
1207 1210 static char match[]="%s: argument mismatch";
1208 1211 register char *ca,*vp; int params;
1209 1212 char *actual[MAXFRM]; /* actual[n] is text of nth actual */
1210 1213 char acttxt[BUFFERSIZ]; /* space for actuals */
1211 1214
1212 1215 if (0==(vp=sp->value)) return(p);
1213 1216 if ((p-macforw)<=macdam) {
1214 1217 if (++maclvl>symsiz && !rflag) {
1215 1218 pperror("%s: macro recursion",sp->name);
1216 1219 return(p);
1217 1220 }
1218 1221 } else {
1219 1222 maclvl=0; /* level decreased */
1220 1223 }
1221 1224 macforw=p; macdam=0; /* new target for decrease in level */
1222 1225 macnam=sp->name;
1223 1226 dump();
1224 1227 if (sp==ulnloc) {
1225 1228 vp=acttxt; *vp++='\0';
1226 1229 sprintf(vp,"%d",lineno[ifno]); while (*vp++);
1227 1230 } else if (sp==uflloc) {
1228 1231 vp=acttxt; *vp++='\0';
1229 1232 sprintf(vp,"\"%s\"",fnames[ifno]); while (*vp++);
1230 1233 }
1231 1234 if (0!=(params= *--vp&0xFF)) {/* definition calls for params */
1232 1235 register char **pa;
1233 1236 ca=acttxt; pa=actual;
1234 1237 if (params==0xFF)
1235 1238 params=1; /* #define foo() ... */
1236 1239 sloscan();
1237 1240 ++flslvl; /* no expansion during search for actuals */
1238 1241 plvl= -1;
1239 1242 do p=skipbl(p); while (*inp=='\n'); /* skip \n too */
1240 1243 if (*inp=='(') {
1241 1244 maclin=lineno[ifno]; macfil=fnames[ifno];
1242 1245 for (plvl=1; plvl!=0; ) {
1243 1246 *ca++='\0';
1244 1247 for (;;) {
1245 1248 outp=inp=p; p=cotoken(p);
1246 1249 if (*inp=='(') ++plvl;
1247 1250 if (*inp==')' && --plvl==0) {
1248 1251 --params;
1249 1252 break;
1250 1253 }
1251 1254 if (plvl==1 && *inp==',') {
1252 1255 --params;
1253 1256 break;
1254 1257 }
1255 1258 while (inp<p) {
1256 1259 /*
1257 1260 * Sun cpp compatibility.
1258 1261 * Needed for kernel assembler
1259 1262 * preprocessing.
1260 1263 * Replace newlines in actual
1261 1264 * macro parameters by spaces.
1262 1265 * Keep escaped newlines, they
1263 1266 * are assumed to be inside a
1264 1267 * string.
1265 1268 */
1266 1269 if (*inp == '\n' &&
1267 1270 inp[-1] != '\\')
1268 1271 *inp = ' ';
1269 1272 *ca++= *inp++;
1270 1273 }
1271 1274 if (ca> &acttxt[BUFFERSIZ])
1272 1275 pperror("%s: actuals too long",
1273 1276 sp->name);
1274 1277 }
1275 1278 if (pa>= &actual[MAXFRM])
1276 1279 ppwarn(match,sp->name);
1277 1280 else
1278 1281 *pa++=ca;
1279 1282 }
1280 1283 }
1281 1284 if (params!=0)
1282 1285 ppwarn(match,sp->name);
1283 1286 while (--params>=0)
1284 1287 *pa++=""+1; /* null string for missing actuals */
1285 1288 --flslvl; fasscan();
1286 1289 }
1287 1290 for (;;) {/* push definition onto front of input stack */
1288 1291 while (!iswarn(*--vp)) {
1289 1292 if (bob(p)) {outp=inp=p; p=unfill(p);}
1290 1293 *--p= *vp;
1291 1294 }
1292 1295 if (*vp==warnc) {/* insert actual param */
1293 1296 ca=actual[*--vp-1];
1294 1297 while (*--ca) {
1295 1298 if (bob(p)) {outp=inp=p; p=unfill(p);}
1296 1299 *--p= *ca;
1297 1300 }
1298 1301 } else break;
1299 1302 }
1300 1303 outp=inp=p;
1301 1304 return(p);
1302 1305 }
1303 1306
1304 1307 static char *
1305 1308 trmdir(s) register char *s; {
1306 1309 register char *p = s;
1307 1310 while (*p++); --p; while (p>s && *--p!='/');
1308 1311 # if unix
1309 1312 if (p==s) *p++='.';
1310 1313 # endif
1311 1314 *p='\0';
1312 1315 return(s);
1313 1316 }
1314 1317
1315 1318 static char *
1316 1319 copy(s) register char *s; {
1317 1320 register char *old;
1318 1321
1319 1322 old = savch; while ((*savch++ = *s++) != '\0');
1320 1323 return(old);
1321 1324 }
1322 1325
1323 1326 static char *
1324 1327 strdex(s,c) char *s,c; {
1325 1328 while (*s) if (*s++==c) return(--s);
1326 1329 return(0);
1327 1330 }
1328 1331
1329 1332 int
1330 1333 yywrap() {
1331 1334 return(1);
1332 1335 }
1333 1336
1334 1337 int
1335 1338 main(argc,argv)
1336 1339 char *argv[];
1337 1340 int argc;
1338 1341 {
1339 1342 register int i,c;
1340 1343 register char *p;
1341 1344 char *tf,**cp2;
1342 1345 char *sysdir = NULL;
1343 1346
1344 1347 fout = stdout; /* Mac OS X is not POSIX compliant (stdout nonconst.) */
1345 1348
1346 1349 p="_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
1347 1350 i=0;
1348 1351 while ((c= *p++) != '\0') {
1349 1352 (fastab+COFF)[c] |= IB|NB|SB;
1350 1353 (toktyp+COFF)[c]=IDENT;
1351 1354 #if scw2
1352 1355 /*
1353 1356 * 53 == 63-10; digits rarely appear in identifiers,
1354 1357 * and can never be the first char of an identifier.
1355 1358 * 11 == 53*53/sizeof(macbit) .
1356 1359 */
1357 1360 ++i; (t21+COFF)[c]=(53*i)/11; (t22+COFF)[c]=i%11;
1358 1361 #endif
1359 1362 }
1360 1363 p="0123456789.";
1361 1364 while ((c = *p++) != '\0') {
1362 1365 (fastab+COFF)[c] |= NB|SB;
1363 1366 (toktyp+COFF)[c]=NUMBR;
1364 1367 }
1365 1368 p="\n\"'/\\";
1366 1369 while ((c = *p++) != '\0')
1367 1370 (fastab+COFF)[c] |= SB;
1368 1371 p="\n\"'\\";
1369 1372 while ((c = *p++) != '\0')
1370 1373 (fastab+COFF)[c] |= QB;
1371 1374 p="*\n";
1372 1375 while ((c = *p++)!= '\0')
1373 1376 (fastab+COFF)[c] |= CB;
1374 1377 (fastab+COFF)[(int)warnc] |= WB;
1375 1378 (fastab+COFF)['\0'] |= CB|QB|SB|WB;
1376 1379 for (i=ALFSIZ; --i>=0; )
1377 1380 slotab[i]=fastab[i]|SB;
1378 1381 p=" \t\013\f\r"; /* note no \n; \v not legal for vertical tab? */
1379 1382 while ((c = *p++) != '\0')
1380 1383 (toktyp+COFF)[c]=BLANK;
1381 1384 #if scw2
1382 1385 for ((t23+COFF)[i=ALFSIZ+7-COFF]=1; --i>=-COFF; )
1383 1386 if (((t23+COFF)[i]=(t23+COFF+1)[i]<<1)==0)
1384 1387 (t23+COFF)[i]=1;
1385 1388 #endif
1386 1389
1387 1390 # if unix
1388 1391 fnames[ifno=0] = "";
1389 1392 dirs[0]=dirnams[0]= ".";
1390 1393 # endif
1391 1394 # if ibm
1392 1395 fnames[ifno=0] = "";
1393 1396 # endif
1394 1397 # if gimpel
1395 1398 fnames[ifno=0] = (char *)inquire(stdin, _FILENAME);
1396 1399 dirnams[0] = dirs[0] = trmdir(copy(fnames[0]));
1397 1400 # endif
1398 1401 for (i=1; i<argc; i++) {
1399 1402 switch(argv[i][0]) {
1400 1403 case '-':
1401 1404 switch(argv[i][1]) {
1402 1405 case 'P':
1403 1406 pflag++;
1404 1407 continue;
1405 1408 case 'E':
1406 1409 continue;
1407 1410 case 'R':
1408 1411 ++rflag;
1409 1412 continue;
1410 1413 case 'C':
1411 1414 passcom++;
1412 1415 continue;
1413 1416 case 'D':
1414 1417 if (predef>prespc+NPREDEF) {
1415 1418 pperror("too many -D options, "
1416 1419 "ignoring %s", argv[i]);
1417 1420 continue;
1418 1421 }
1419 1422 /* ignore plain "-D" (no argument) */
1420 1423 if (*(argv[i]+2))
1421 1424 *predef++ = argv[i]+2;
1422 1425 continue;
1423 1426 case 'U':
1424 1427 if (prund>punspc+NPREDEF) {
1425 1428 pperror("too many -U options, "
1426 1429 "ignoring %s", argv[i]);
1427 1430 continue;
1428 1431 }
1429 1432 *prund++ = argv[i]+2;
1430 1433 continue;
1431 1434 case 'u':
1432 1435 if (strcmp(argv[i], "-undef") == 0)
1433 1436 nopredef = 1;
1434 1437 else
1435 1438 goto unknown;
1436 1439 continue;
1437 1440 case 'I':
1438 1441 if (nd>=MAXIDIRS)
1439 1442 pperror("excessive -I file "
1440 1443 "(%s) ignored", argv[i]);
1441 1444 else
1442 1445 dirs[nd++] = argv[i]+2;
1443 1446 continue;
1444 1447 case 'T':
1445 1448 symlen = 8;
1446 1449 /* Compatibility with V7 */
1447 1450 continue;
1448 1451 case 'H':
1449 1452 /* Print included filenames */
1450 1453 hflag++;
1451 1454 continue;
1452 1455 case 'Y':
1453 1456 /* Replace system include dir */
1454 1457 sysdir = argv[i]+2;
1455 1458 continue;
1456 1459 case '\0': continue;
1457 1460 default:
1458 1461 unknown:
1459 1462 pperror("unknown flag %s", argv[i]);
1460 1463 continue;
1461 1464 }
1462 1465 default:
1463 1466 if (fin == STDIN_FILENO) {
1464 1467 if (0>(fin=open(argv[i], O_RDONLY))) {
1465 1468 pperror("No source file %s",
1466 1469 argv[i]);
1467 1470 exit(8);
1468 1471 }
1469 1472 fnames[ifno]=copy(argv[i]);
1470 1473 dirs[0]=dirnams[ifno]=trmdir(argv[i]);
1471 1474 /* too dangerous to have file name in same syntactic position
1472 1475 be input or output file depending on file redirections,
1473 1476 so force output to stdout, willy-nilly
1474 1477 [i don't see what the problem is. jfr]
1475 1478 */
1476 1479 } else if (fout==stdout) {
1477 1480 static char _sobuff[BUFSIZ];
1478 1481 if (NULL==(fout=fopen(argv[i], "w"))) {
1479 1482 pperror("Can't create %s",
1480 1483 argv[i]);
1481 1484 exit(8);
1482 1485 } else {
1483 1486 fclose(stdout);
1484 1487 setbuf(fout,_sobuff);
1485 1488 }
1486 1489 } else {
1487 1490 pperror("extraneous name %s", argv[i]);
1488 1491 }
1489 1492 }
1490 1493 }
1491 1494
1492 1495 fins[ifno]=fin;
1493 1496 exfail = 0;
1494 1497 /* after user -I files here are the standard include libraries */
1495 1498 if (sysdir != NULL) {
1496 1499 dirs[nd++] = sysdir;
1497 1500 } else {
1498 1501 # if unix
1499 1502 dirs[nd++] = "/usr/include";
1500 1503 # endif
1501 1504 /* dirs[nd++] = "/compool"; */
1502 1505 }
1503 1506 dirs[nd++] = 0;
1504 1507 defloc=ppsym("define");
1505 1508 udfloc=ppsym("undef");
1506 1509 incloc=ppsym("include");
1507 1510 elsloc=ppsym("else");
1508 1511 eifloc=ppsym("endif");
1509 1512 elifloc=ppsym("elif");
1510 1513 ifdloc=ppsym("ifdef");
1511 1514 ifnloc=ppsym("ifndef");
1512 1515 ifloc=ppsym("if");
1513 1516 lneloc=ppsym("line");
1514 1517 idtloc=ppsym("ident");
1515 1518 pragmaloc=ppsym("pragma");
1516 1519 errorloc=ppsym("error");
1517 1520 for (i=sizeof(macbit)/sizeof(macbit[0]); --i>=0; )
1518 1521 macbit[i]=0;
1519 1522
1520 1523 if (! nopredef) {
1521 1524 # if unix
1522 1525 ysysloc=stsym("unix");
1523 1526 # endif
1524 1527 # if __sparc__
1525 1528 varloc=stsym ("sparc");
1526 1529 # endif
1527 1530 # if __i386__
1528 1531 varloc=stsym ("i386");
1529 1532 # endif
1530 1533 }
1531 1534 ulnloc=stsym ("__LINE__");
1532 1535 uflloc=stsym ("__FILE__");
1533 1536 varloc=stsym ("__BUILTIN_VA_ARG_INCR");
1534 1537
1535 1538 tf=fnames[ifno]; fnames[ifno]="command line"; lineno[ifno]=1;
1536 1539 cp2=prespc;
1537 1540 while (cp2<predef) stsym(*cp2++);
1538 1541 cp2=punspc;
1539 1542 while (cp2<prund) {
1540 1543 if ((p=strdex(*cp2, '=')) != NULL) *p++='\0';
1541 1544 if (strlen(*cp2) > symlen)
1542 1545 (*cp2)[symlen] = '\0';
1543 1546 lookup(*cp2++, DROP);
1544 1547 }
1545 1548 fnames[ifno]=tf;
1546 1549 pbeg=buffer+symlen; pbuf=pbeg+BUFFERSIZ; pend=pbuf+BUFFERSIZ;
1547 1550
1548 1551 trulvl = 0; flslvl = 0;
1549 1552 lineno[0] = 1; sayline(NOINCLUDE);
1550 1553 outp=inp=pend;
1551 1554 control(pend);
1552 1555 return (exfail);
1553 1556 }
↓ open down ↓ |
720 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX