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