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