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