1 /* @(#)cpp.c 1.54 21/05/30 2010-2021 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)cpp.c 1.54 21/05/30 2010-2021 J. Schilling";
6 #endif
7 /*
8 * C command
9 * written by John F. Reiser
10 * July/August 1978
11 */
12 /*
13 * This implementation is based on the UNIX 32V release from 1978
14 * with permission from Caldera Inc.
15 *
16 * Copyright (c) 2010-2021 J. Schilling
17 * All rights reserved.
18 *
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions
21 * are met:
22 * 1. Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 * 2. Redistributions in binary form must reproduce the above copyright
25 * notice, this list of conditions and the following disclaimer in the
26 * documentation and/or other materials provided with the distribution.
27 * 3. Neither the name of the copyright holder nor the names of contributors
28 * may be used to endorse or promote products derived from this software
29 * without specific prior written permission.
30 *
31 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND
32 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE
35 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
40 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41 * SUCH DAMAGE.
42 */
43 /*
44 * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
45 *
46 * Redistribution and use in source and binary forms, with or without
47 * modification, are permitted provided that the following conditions are
48 * met:
49 * 1. Redistributions of source code and documentation must retain the above
50 * copyright notice, this list of conditions and the following
51 * disclaimer.
52 *
53 * 2. Redistributions in binary form must reproduce the above copyright
54 * notice, this list of conditions and the following disclaimer in the
55 * documentation and/or other materials provided with the distribution.
56 *
57 * 3. All advertising materials mentioning features or use of this software
58 * must display the following acknowledgement: This product includes
59 * software developed or owned by Caldera International, Inc.
60 *
61 * 4. Neither the name of Caldera International, Inc. nor the names of other
62 * contributors may be used to endorse or promote products derived from
63 * this software without specific prior written permission.
64 *
65 * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
66 * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
67 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
68 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
69 * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE FOR
70 * ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
71 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
72 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
73 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
74 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
75 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
76 * POSSIBILITY OF SUCH DAMAGE.
77 */
78 #include <schily/stdio.h>
79 #include <schily/types.h>
80 #include <schily/inttypes.h>
81 #include <schily/unistd.h>
82 #include <schily/stdlib.h>
83 #include <schily/fcntl.h>
84 #include <schily/string.h>
85 #include <schily/ctype.h>
86 #include <schily/standard.h>
87 #include <schily/schily.h>
88 #include <schily/varargs.h>
89
90 #include "cpp.h"
91 #include "version.h"
92
93 #define STATIC static
94
95 #ifdef FLEXNAMES
96 #define SYMLEN 128
97 #else
98 #define SYMLEN 8
99 #endif
100 STATIC int symlen = SYMLEN;
101
102
103 #define SALT '#'
104 #ifndef BUFSIZ
105 #define BUFSIZ 512
106 #endif
107
108 STATIC char *pbeg;
109 STATIC char *pbuf;
110 STATIC char *pend;
111 char *outptr,*inptr;
112 char *newp;
113 STATIC char cinit;
114
115 /* some code depends on whether characters are sign or zero extended */
116 /* #if '\377' < 0 not used here, old cpp doesn't understand */
117 #if pdp11 | vax | '\377' < 0
118 #define COFF 128
119 #else
120 #define COFF 0
121 #endif
122
123 # if gcos
124 #define ALFSIZ 512 /* alphabet size */
125 # else
126 #define ALFSIZ 256 /* alphabet size */
127 # endif
128 STATIC char macbit[ALFSIZ+11];
129 STATIC char toktyp[ALFSIZ];
130 #define BLANK 1 /* white space (" \t\v\f\r") */
131 #define IDENT 2 /* valid char for identifier names */
132 #define NUMBR 3 /* chars is of "0123456789." */
133
134 /*
135 * a superimposed code is used to reduce the number of calls to the
136 * symbol table lookup routine. (if the kth character of an identifier
137 * is 'a' and there are no macro names whose kth character is 'a'
138 * then the identifier cannot be a macro name, hence there is no need
139 * to look in the symbol table.) 'scw1' enables the test based on
140 * single characters and their position in the identifier. 'scw2'
141 * enables the test based on adjacent pairs of characters and their
142 * position in the identifier. scw1 typically costs 1 indexed fetch,
143 * an AND, and a jump per character of identifier, until the identifier
144 * is known as a non-macro name or until the end of the identifier.
145 * scw1 is inexpensive. scw2 typically costs 4 indexed fetches,
146 * an add, an AND, and a jump per character of identifier, but it is also
147 * slightly more effective at reducing symbol table searches.
148 * scw2 usually costs too much because the symbol table search is
149 * usually short; but if symbol table search should become expensive,
150 * the code is here.
151 * using both scw1 and scw2 is of dubious value.
152 */
153 #define scw1 1
154 #define scw2 0
155
156 #if scw2
157 char t21[ALFSIZ],t22[ALFSIZ],t23[ALFSIZ+SYMLEN];
158 #endif
159
160 #if scw1
161 #define b0 1
162 #define b1 2
163 #define b2 4
164 #define b3 8
165 #define b4 16
166 #define b5 32
167 #define b6 64
168 #define b7 128
169 #endif
170
171 #define IB 1
172 #define SB 2
173 #define NB 4
174 #define CB 8
175 #define QB 16
176 #define WB 32
177 char fastab[ALFSIZ];
178 STATIC char slotab[ALFSIZ];
179 STATIC char *ptrtab;
180
181 /*
182 * Cast the array index to int in order to avoid GCCs warnings:
183 * warning: subscript has type `char'
184 */
185 #define isslo (ptrtab==(slotab+COFF))
186 #define isid(a) ((fastab+COFF)[(int)a]&IB)
187 #define isspc(a) (ptrtab[(int)a]&SB)
188 #define isnum(a) ((fastab+COFF)[(int)a]&NB)
189 #define iscom(a) ((fastab+COFF)[(int)a]&CB)
190 #define isquo(a) ((fastab+COFF)[(int)a]&QB)
191 #define iswarn(a) ((fastab+COFF)[(int)a]&WB)
192
193 #define eob(a) ((a)>=pend)
194 #define bob(a) (pbeg>=(a))
195
196 #define BUFFERSIZ 8192
197 STATIC char buffer[SYMLEN+BUFFERSIZ+BUFFERSIZ+SYMLEN];
198
199 /*
200 * SBSIZE was static 12000 chars in 1978, we now have a method to
201 * malloc more space.
202 */
203 # define SBSIZE 65536
204 STATIC char *sbf;
205 STATIC char *savch;
206
207 # define DROP 0xFE /* special character not legal ASCII or EBCDIC */
208 # define WARN DROP
209 # define SAME 0
210 # define MAXINC 16 /* max include nesting depth */
211 # define MAXIDIRS 20 /* max # of -I directories */
212 # define MAXFRE 14 /* max buffers of macro pushback */
213 # define MAXFRM 31 /* max number of formals/actuals to a macro */
214
215 #define MAXMULT (TYPE_MAXVAL(int)/10)
216 #define MAXVAL (TYPE_MAXVAL(int))
217
218 static char warnc = (char)WARN;
219
220 STATIC int mactop;
221 STATIC int fretop;
222 STATIC char *instack[MAXFRE];
223 STATIC char *bufstack[MAXFRE];
224 STATIC char *endbuf[MAXFRE];
225
226 STATIC int plvl; /* parenthesis level during scan for macro actuals */
227 STATIC int maclin; /* line number of macro call requiring actuals */
228 STATIC char *macfil; /* file name of macro call requiring actuals */
229 STATIC char *macnam; /* name of macro requiring actuals */
230 STATIC int maclvl; /* # calls since last decrease in nesting level */
231 STATIC char *macforw; /* pointer which must be exceeded to decrease nesting level */
232 STATIC int macdam; /* offset to macforw due to buffer shifting */
233
234 #if tgp
235 int tgpscan; /* flag for dump(); */
236 #endif
237
238 STATIC int inctop[MAXINC];
239 STATIC char *fnames[MAXINC];
240 STATIC char *dirnams[MAXINC]; /* actual directory of #include files */
241 STATIC int fins[MAXINC];
242 STATIC int lineno[MAXINC];
243 STATIC char *input;
244 STATIC char *target;
245
246 /*
247 * We need:
248 * "" include dir as dirs[0] +
249 * MAXIDIRS +
250 * system default include dir +
251 * a NULL pointer at the end
252 */
253 STATIC char *dirs[MAXIDIRS+3]; /* -I and <> directories */
254 STATIC int fin = STDIN_FILENO;
255 STATIC FILE *fout; /* Init in main(), Mac OS is nonPOSIX */
256 STATIC FILE *mout; /* Output for -M */
257 STATIC FILE *dout; /* Output for "SUNPRO_DEPENDENCIES" */
258 STATIC int nd = 1;
259 STATIC int extrawarn; /* warn on extra tokens */
260 STATIC int pflag; /* don't put out lines "# 12 foo.c" */
261 STATIC int cppflag; /* Support C++ comment */
262 STATIC int passcom; /* don't delete comments */
263 STATIC int rflag; /* allow macro recursion */
264 STATIC int hflag; /* Print included filenames */
265 STATIC int mflag; /* Generate make dependencies */
266 STATIC int noinclude; /* -noinclude /usr/include */
267 STATIC int nopredef; /* -undef all */
268 int char_is_signed = -1; /* for -xuc -xsc */
269 STATIC int ifno;
270 # define NPREDEF 64
271 STATIC char *prespc[NPREDEF];
272 STATIC char **predef = prespc;
273 STATIC char *punspc[NPREDEF];
274 STATIC char **prund = punspc;
275 STATIC int exfail;
276 STATIC struct symtab *lastsym;
277
278
279 LOCAL void sayline __PR((char *));
280 LOCAL void dump __PR((void));
281 LOCAL char *refill __PR((char *));
282 LOCAL char *cotoken __PR((char *));
283 EXPORT char *skipbl __PR((char *));
284 LOCAL char *unfill __PR((char *));
285 LOCAL char *doincl __PR((char *));
286 LOCAL int equfrm __PR((char *, char *, char *));
287 LOCAL char *dodef __PR((char *));
288 LOCAL void control __PR((char *));
289 LOCAL int iscomment __PR((char *));
290 LOCAL struct symtab *stsym __PR((char *));
291 LOCAL struct symtab *ppsym __PR((char *));
292 EXPORT void pperror __PR((char *fmt, ...));
293 EXPORT void yyerror __PR((char *fmt, ...));
294 LOCAL void ppwarn __PR((char *fmt, ...));
295 EXPORT struct symtab *lookup __PR((char *, int));
296 LOCAL struct symtab *slookup __PR((char *, char *, int));
297 LOCAL char *subst __PR((char *, struct symtab *));
298 LOCAL char *trmdir __PR((char *));
299 LOCAL char *copy __PR((char *));
300 LOCAL char *strdex __PR((char *, int));
301 EXPORT int yywrap __PR((void));
302 EXPORT int main __PR((int argc, char **argav));
303 LOCAL void newsbf __PR((void));
304 LOCAL struct symtab *newsym __PR((void));
305 LOCAL void usage __PR((void));
306
307
308 # if gcos
309 #include <schily/setjmp.h>
310 static jmp_buf env;
311 # define main mainpp
312 # undef exit
313 # define exit(S) longjmp(env, 1)
314 # define open(S,D) fileno(fopen(S, "r"))
315 # define close(F) fclose(_f[F])
316 extern FILE *_f[];
317 # define symsiz 500
318 # else
319 # define symsiz 500
320 # endif
321 #define SYMINCR 340 /* Number of symtab entries to allocate as a block */
322 STATIC struct symtab *stab[symsiz];
323
324 STATIC struct symtab *defloc;
325 STATIC struct symtab *udfloc;
326 STATIC struct symtab *incloc;
327 STATIC struct symtab *ifloc;
328 STATIC struct symtab *elsloc;
329 STATIC struct symtab *eifloc;
330 STATIC struct symtab *elifloc;
331 STATIC struct symtab *ifdloc;
332 STATIC struct symtab *ifnloc;
333 STATIC struct symtab *ysysloc;
334 STATIC struct symtab *varloc;
335 STATIC struct symtab *lneloc;
336 STATIC struct symtab *ulnloc;
337 STATIC struct symtab *uflloc;
338 STATIC struct symtab *idtloc;
339 STATIC struct symtab *pragmaloc;
340 STATIC struct symtab *errorloc;
341 STATIC int trulvl;
342 int flslvl;
343 STATIC int elflvl;
344 STATIC int elslvl;
345
346 /*
347 * The sun cpp prints a classification token past the
348 * "# linenumber filename" lines:
349 */
350 #define NOINCLUDE "" /* Not related to enter/leave incl. file */
351 #define ENTERINCLUDE "1" /* We are just entering an include file */
352 #define LEAVEINCLUDE "2" /* We are just leaving an include file */
353
354 /* ARGSUSED */
355 STATIC void
sayline(what)356 sayline(what)
357 char *what;
358 {
359 #ifdef SUN_SAYLINE
360 if (pflag==0) fprintf(fout,"# %d \"%s\" %s\n", lineno[ifno], fnames[ifno], what);
361 #else
362 if (pflag==0) fprintf(fout,"# %d \"%s\"\n", lineno[ifno], fnames[ifno]);
363 #endif
364 }
365
366 /*
367 * data structure guide
368 *
369 * most of the scanning takes place in the buffer:
370 *
371 * (low address) (high address)
372 * pbeg pbuf pend
373 * | <-- BUFFERSIZ chars --> | <-- BUFFERSIZ chars --> |
374 * _______________________________________________________________________
375 * |_______________________________________________________________________|
376 * | | |
377 * |<-- waiting -->| |<-- waiting -->
378 * | to be |<-- current -->| to be
379 * | written | token | scanned
380 * | | |
381 * outptr inptr p
382 *
383 * *outptr first char not yet written to outptrut file
384 * *inptr first char of current token
385 * *p first char not yet scanned
386 *
387 * macro expansion: write from *outptr to *inptr (chars waiting to be written),
388 * ignore from *inptr to *p (chars of the macro call), place generated
389 * characters in front of *p (in reverse order), update pointers,
390 * resume scanning.
391 *
392 * symbol table pointers point to just beyond the end of macro definitions;
393 * the first preceding character is the number of formal parameters.
394 * the appearance of a formal in the body of a definition is marked by
395 * 2 chars: the char WARN, and a char containing the parameter number.
396 * the first char of a definition is preceded by a zero character.
397 *
398 * when macro expansion attempts to back up over the beginning of the
399 * buffer, some characters preceding *pend are saved in a side buffer,
400 * the address of the side buffer is put on 'instack', and the rest
401 * of the main buffer is moved to the right. the end of the saved buffer
402 * is kept in 'endbuf' since there may be nulls in the saved buffer.
403 *
404 * similar action is taken when an 'include' statement is processed,
405 * except that the main buffer must be completely emptied. the array
406 * element 'inctop[ifno]' records the last side buffer saved when
407 * file 'ifno' was included. these buffers remain dormant while
408 * the file is being read, and are reactivated at end-of-file.
409 *
410 * instack[0 : mactop] holds the addresses of all pending side buffers.
411 * instack[inctop[ifno]+1 : mactop-1] holds the addresses of the side
412 * buffers which are "live"; the side buffers instack[0 : inctop[ifno]]
413 * are dormant, waiting for end-of-file on the current file.
414 *
415 * space for side buffers is obtained from 'savch' and is never returned.
416 * bufstack[0:fretop-1] holds addresses of side buffers which
417 * are available for use.
418 */
419
420 STATIC void
dump()421 dump() {
422 /*
423 * write part of buffer which lies between outptr and inptr .
424 * this should be a direct call to 'write', but the system slows to a crawl
425 * if it has to do an unaligned copy. thus we buffer. this silly loop
426 * is 15% of the total time, thus even the 'putc' macro is too slow.
427 */
428 register char *p1;
429 #if tgp
430 register char *p2;
431 #endif
432 register FILE *f;
433 if ((p1=outptr)==inptr || flslvl!=0) return;
434 #if tgp
435 #define MAXOUT 80
436 if (!tgpscan) {/* scan again to insure <= MAXOUT chars between linefeeds */
437 register char c,*pblank; char savc,stopc,brk;
438 tgpscan=1; brk=stopc=pblank=0; p2=inptr; savc= *p2; *p2='\0';
439 while (c= *p1++) {
440 if (c=='\\') c= *p1++;
441 if (stopc==c) stopc=0;
442 else if (c=='"' || c=='\'') stopc=c;
443 if (p1-outptr>MAXOUT && pblank!=0) {
444 *pblank++='\n'; inptr=pblank; dump(); brk=1; pblank=0;
445 }
446 if (c==' ' && stopc==0) pblank=p1-1;
447 }
448 if (brk) sayline(NOINCLUDE);
449 *p2=savc; inptr=p2; p1=outptr; tgpscan=0;
450 }
451 #endif
452 f=fout;
453 # if gcos
454 /* filter out "$ program c" card if first line of input */
455 /* gmatch is a simple pattern matcher in the GCOS Standard Library */
456 { static int gmfirst = 0;
457 if (!gmfirst) {
458 ++gmfirst;
459 if (gmatch(p1, "^$*program[ \t]*c*"))
460 p1 = strdex(p1, '\n');
461 }
462 }
463 # endif
464 while (p1<inptr) putc(*p1++,f);
465 outptr=p1;
466 }
467
468 STATIC char *
refill(p)469 refill(p) register char *p; {
470 /*
471 * dump buffer. save chars from inptr to p. read into buffer at pbuf,
472 * contiguous with p. update pointers, return new p.
473 */
474 register char *np,*op; register int ninbuf;
475 dump(); np=pbuf-(p-inptr); op=inptr;
476 if (bob(np+1)) {pperror("token too long"); np=pbeg; p=inptr+BUFFERSIZ;}
477 macdam += np-inptr; outptr=inptr=np;
478 while (op<p) *np++= *op++;
479 p=np;
480 for (;;) {
481 if (mactop>inctop[ifno]) {/* retrieve hunk of pushed-back macro text */
482 op=instack[--mactop]; np=pbuf;
483 do {while ((*np++= *op++) != '\0');} while (op<endbuf[mactop]); pend=np-1;
484 /* make buffer space avail for 'include' processing */
485 if (fretop<MAXFRE) bufstack[fretop++]=instack[mactop];
486 return(p);
487 } else {/* get more text from file(s) */
488 maclvl=0;
489 if (0<(ninbuf=read(fin,pbuf,BUFFERSIZ))) {
490 pend=pbuf+ninbuf; *pend='\0';
491 return(p);
492 }
493 /* end of #include file */
494 if (ifno==0) {/* end of input */
495 if (plvl!=0) {
496 int n=plvl,tlin=lineno[ifno]; char *tfil=fnames[ifno];
497 lineno[ifno]=maclin; fnames[ifno]=macfil;
498 pperror("%s: unterminated macro call",macnam);
499 lineno[ifno]=tlin; fnames[ifno]=tfil;
500 np=p; *np++='\n'; /* shut off unterminated quoted string */
501 while (--n>=0) *np++=')'; /* supply missing parens */
502 pend=np; *np='\0'; if (plvl<0) plvl=0;
503 return(p);
504 }
505 inptr=p; dump(); exit(exfail);
506 }
507 close(fin); fin=fins[--ifno]; dirs[0]=dirnams[ifno]; sayline(LEAVEINCLUDE);
508 }
509 }
510 }
511
512 #define BEG 0
513 #define LF 1
514
515 STATIC char *
cotoken(p)516 cotoken(p) register char *p; {
517 register int c,i; char quoc;
518 int cppcom = 0;
519 static int state = BEG;
520
521 if (state!=BEG) goto prevlf;
522 for (;;) {
523 again:
524 while (!isspc(*p++));
525 switch (*(inptr=p-1)) {
526 case 0: {
527 if (eob(--p)) {p=refill(p); goto again;}
528 else ++p; /* ignore null byte */
529 } break;
530 case '|': case '&': for (;;) {/* sloscan only */
531 if (*p++== *inptr) break;
532 if (eob(--p)) p=refill(p);
533 else break;
534 } break;
535 case '=': case '!': for (;;) {/* sloscan only */
536 if (*p++=='=') break;
537 if (eob(--p)) p=refill(p);
538 else break;
539 } break;
540 case '<': case '>': for (;;) {/* sloscan only */
541 if (*p++=='=' || p[-2]==p[-1]) break;
542 if (eob(--p)) p=refill(p);
543 else break;
544 } break;
545 case '\\': for (;;) {
546 if (*p++=='\n') {++lineno[ifno]; break;}
547 if (eob(--p)) p=refill(p);
548 else {++p; break;}
549 } break;
550 case '/': for (;;) {
551 if (*p == '*' || (cppflag && *p == '/')) { /* comment */
552 if (*p++ == '/') /* A C++ comment */
553 cppcom++;
554 if (!passcom) {inptr=p-2; dump(); ++flslvl;}
555 for (;;) {
556 while (!iscom(*p++));
557 if (cppcom && p[-1] == '\n') {
558 p--;
559 goto endcom;
560 }
561 if (p[-1]=='*') for (;;) {
562 if (*p++=='/') goto endcom;
563 if (eob(--p)) {
564 if (!passcom) {inptr=p; p=refill(p);}
565 else if ((p-inptr)>=BUFFERSIZ) {/* split long comment */
566 inptr=p; p=refill(p); /* last char written is '*' */
567 putc('/',fout); /* terminate first part */
568 /* and fake start of 2nd */
569 outptr=inptr=p-=3; *p++='/'; *p++='*'; *p++='*';
570 } else p=refill(p);
571 } else break;
572 } else if (p[-1]=='\n') {
573 ++lineno[ifno]; if (!passcom) putc('\n',fout);
574 } else if (eob(--p)) {
575 if (!passcom) {inptr=p; p=refill(p);}
576 else if ((p-inptr)>=BUFFERSIZ) {/* split long comment */
577 inptr=p; p=refill(p);
578 putc('*',fout); putc('/',fout);
579 outptr=inptr=p-=2; *p++='/'; *p++='*';
580 } else p=refill(p);
581 } else ++p; /* ignore null byte */
582 }
583 endcom:
584 cppcom = 0;
585 if (!passcom) {outptr=inptr=p; --flslvl; goto again;}
586 break;
587 } else { /* no comment, skip */
588 p++;
589 }
590 if (eob(--p)) p=refill(p);
591 else break;
592 } break;
593 # if gcos
594 case '`':
595 # endif
596 case '"': case '\'': {
597 quoc=p[-1];
598 for (;;) {
599 while (!isquo(*p++));
600 if (p[-1]==quoc) break;
601 if (p[-1]=='\n') {--p; break;} /* bare \n terminates quotation */
602 if (p[-1]=='\\') for (;;) {
603 if (*p++=='\n') {++lineno[ifno]; break;} /* escaped \n ignored */
604 if (eob(--p)) p=refill(p);
605 else {++p; break;}
606 } else if (eob(--p)) p=refill(p);
607 else ++p; /* it was a different quote character */
608 }
609 } break;
610 case '\n': {
611 ++lineno[ifno]; if (isslo) {state=LF; return(p);}
612 prevlf:
613 state=BEG;
614 for (;;) {
615 if (*p++=='#') return(p);
616 if (eob(inptr= --p)) p=refill(p);
617 else goto again;
618 }
619 }
620 /* NOTREACHED */
621 case '0': case '1': case '2': case '3': case '4':
622 case '5': case '6': case '7': case '8': case '9':
623 for (;;) {
624 while (isnum(*p++));
625 if (eob(--p)) p=refill(p);
626 else break;
627 } break;
628 case 'A': case 'B': case 'C': case 'D': case 'E':
629 case 'F': case 'G': case 'H': case 'I': case 'J':
630 case 'K': case 'L': case 'M': case 'N': case 'O':
631 case 'P': case 'Q': case 'R': case 'S': case 'T':
632 case 'U': case 'V': case 'W': case 'X': case 'Y':
633 case 'Z': case '_':
634 case 'a': case 'b': case 'c': case 'd': case 'e':
635 case 'f': case 'g': case 'h': case 'i': case 'j':
636 case 'k': case 'l': case 'm': case 'n': case 'o':
637 case 'p': case 'q': case 'r': case 's': case 't':
638 case 'u': case 'v': case 'w': case 'x': case 'y':
639 case 'z':
640 #if scw1
641 #define tmac1(c,bit) if (!xmac1(c,bit,&)) goto nomac
642 #define xmac1(c,bit,op) ((macbit+COFF)[c] op (bit))
643 #else
644 #define tmac1(c,bit)
645 #define xmac1(c,bit,op)
646 #endif
647
648 #if scw2
649 #define tmac2(c0,c1,cpos) if (!xmac2(c0,c1,cpos,&)) goto nomac
650 #define xmac2(c0,c1,cpos,op)\
651 ((macbit+COFF)[(t21+COFF)[c0]+(t22+COFF)[c1]] op (t23+COFF+cpos)[c0])
652 #else
653 #define tmac2(c0,c1,cpos)
654 #define xmac2(c0,c1,cpos,op)
655 #endif
656
657 if (flslvl) goto nomac;
658 for (;;) {
659 c= p[-1]; tmac1(c,b0);
660 i= *p++; if (!isid(i)) goto endid; tmac1(i,b1); tmac2(c,i,0);
661 c= *p++; if (!isid(c)) goto endid; tmac1(c,b2); tmac2(i,c,1);
662 i= *p++; if (!isid(i)) goto endid; tmac1(i,b3); tmac2(c,i,2);
663 c= *p++; if (!isid(c)) goto endid; tmac1(c,b4); tmac2(i,c,3);
664 i= *p++; if (!isid(i)) goto endid; tmac1(i,b5); tmac2(c,i,4);
665 c= *p++; if (!isid(c)) goto endid; tmac1(c,b6); tmac2(i,c,5);
666 i= *p++; if (!isid(i)) goto endid; tmac1(i,b7); tmac2(c,i,6);
667 tmac2(i,0,7);
668 while (isid(*p++));
669 if (eob(--p)) {refill(p); p=inptr+1; continue;}
670 goto lokid;
671 endid:
672 if (eob(--p)) {refill(p); p=inptr+1; continue;}
673 tmac2(p[-1],0,-1+(p-inptr));
674 lokid:
675 slookup(inptr,p,0); if (newp) {p=newp; goto again;}
676 else break;
677 nomac:
678 while (isid(*p++));
679 if (eob(--p)) {p=refill(p); goto nomac;}
680 else break;
681 } break;
682 } /* end of switch */
683
684 if (isslo) return(p);
685 } /* end of infinite loop */
686 }
687
688 char *
skipbl(p)689 skipbl(p) register char *p; {/* get next non-blank token */
690 do {outptr=inptr=p; p=cotoken(p);} while ((toktyp+COFF)[(int)*inptr]==BLANK);
691 return(p);
692 }
693
694 STATIC char *
unfill(p)695 unfill(p) register char *p; {
696 /*
697 * take <= BUFFERSIZ chars from right end of buffer and put them on instack .
698 * slide rest of buffer to the right, update pointers, return new p.
699 */
700 register char *np,*op; register int d;
701 if (mactop>=MAXFRE) {
702 pperror("%s: too much pushback",macnam);
703 p=inptr=pend; dump(); /* begin flushing pushback */
704 while (mactop>inctop[ifno]) {p=refill(p); p=inptr=pend; dump();}
705 }
706 if (fretop>0) np=bufstack[--fretop];
707 else {
708 np = savch;
709 savch += BUFFERSIZ;
710 if (savch >= sbf+SBSIZE) {
711 newsbf();
712 np = savch;
713 savch += BUFFERSIZ;
714 }
715 *savch++='\0';
716 }
717 instack[mactop]=np; op=pend-BUFFERSIZ; if (op<p) op=p;
718 for (;;) { /* out with old */
719 while ((*np++= *op++) != '\0')
720 ;
721 if (eob(op))
722 break;
723 }
724 endbuf[mactop++]=np; /* mark end of saved text */
725 np=pbuf+BUFFERSIZ; op=pend-BUFFERSIZ; pend=np; if (op<p) op=p;
726 while (outptr<op) *--np= *--op; /* slide over new */
727 if (bob(np)) pperror("token too long");
728 d=np-outptr; outptr+=d; inptr+=d; macdam+=d; return(p+d);
729 }
730
731 STATIC char *
doincl(p)732 doincl(p) register char *p; {
733 int filok,inctype;
734 register char *cp; char **dirp,*nfil; char filname[BUFFERSIZ];
735
736 filname[0] = '\0'; /* Make lint quiet */
737 p=skipbl(p); cp=filname;
738 if (*inptr++=='<') {/* special <> syntax */
739 inctype=1;
740 for (;;) {
741 outptr=inptr=p; p=cotoken(p);
742 if (*inptr=='\n') {--p; *cp='\0'; break;}
743 if (*inptr=='>') { *cp='\0'; break;}
744 # ifdef gimpel
745 if (*inptr=='.' && !intss()) *inptr='#';
746 # endif
747 while (inptr<p) *cp++= *inptr++;
748 }
749 } else if (inptr[-1]=='"') {/* regular "" syntax */
750 inctype=0;
751 # ifdef gimpel
752 while (inptr<p) {if (*inptr=='.' && !intss()) *inptr='#'; *cp++= *inptr++;}
753 # else
754 while (inptr<p) *cp++= *inptr++;
755 # endif
756 if (*--cp=='"') *cp='\0';
757 } else {pperror("bad include syntax",0); inctype=2;}
758 /* flush current file to \n , then write \n */
759 ++flslvl; do {outptr=inptr=p; p=cotoken(p);} while (*inptr!='\n'); --flslvl;
760 inptr=p; dump(); if (inctype==2) return(p);
761 /* look for included file */
762 if (ifno+1 >=MAXINC) {
763 pperror("Unreasonable include nesting",0); return(p);
764 }
765 if ((nfil = savch) > sbf+SBSIZE-BUFFERSIZ) {
766 newsbf();
767 nfil = savch;
768 }
769 filok=0;
770 for (dirp=dirs+inctype; *dirp; ++dirp) {
771 if (
772 # if gcos
773 strdex(filname, '/')
774 # else
775 filname[0]=='/'
776 # endif
777 || **dirp=='\0') strcpy(nfil,filname);
778 else {
779 strcpy(nfil,*dirp);
780 # if unix || gcos
781 strcat(nfil,"/");
782 # endif
783 #ifdef ibm
784 #ifndef gimpel
785 strcat(nfil,".");
786 #endif
787 #endif
788 strcat(nfil,filname);
789 }
790 if (0<(fins[ifno+1]=open(nfil, O_RDONLY))) {
791 filok=1; fin=fins[++ifno]; break;
792 }
793 }
794 if (filok==0) {
795 pperror("Can't find include file %s",filname);
796 } else {
797 lineno[ifno]=1;
798 fnames[ifno]=cp=nfil;
799 while (*cp++)
800 ;
801 savch=cp;
802 dirnams[ifno]=dirs[0]=trmdir(copy(nfil));
803 sayline(ENTERINCLUDE);
804 if (hflag)
805 fprintf(stderr, "%s\n", nfil);
806 if (mflag)
807 fprintf(mout, "%s: %s\n", input, fnames[ifno]);
808 if (dout)
809 fprintf(dout, "%s: %s\n", target, fnames[ifno]);
810 /* save current contents of buffer */
811 while (!eob(p)) p=unfill(p);
812 inctop[ifno]=mactop;
813 }
814 return(p);
815 }
816
817 STATIC int
equfrm(a,p1,p2)818 equfrm(a,p1,p2) register char *a,*p1,*p2; {
819 register char c; int flag;
820 c= *p2; *p2='\0';
821 flag=strcmp(a,p1); *p2=c; return(flag==SAME);
822 }
823
824 STATIC char *
dodef(p)825 dodef(p) char *p; {/* process '#define' */
826 register char *pin,*psav,*cf;
827 char **pf,**qf; int b,c,params; struct symtab *np;
828 char *oldval,*oldsavch;
829 char *formal[MAXFRM]; /* formal[n] is name of nth formal */
830 char formtxt[BUFFERSIZ]; /* space for formal names */
831
832 formtxt[0] = '\0'; /* Make lint quiet */
833
834 if (savch > sbf+SBSIZE-BUFFERSIZ) {
835 newsbf();
836 }
837 oldsavch=savch; /* to reclaim space if redefinition */
838 ++flslvl; /* prevent macro expansion during 'define' */
839 p=skipbl(p); pin=inptr;
840 if ((toktyp+COFF)[(int)*pin]!=IDENT) {
841 ppwarn("illegal macro name"); while (*inptr!='\n') p=skipbl(p); return(p);
842 }
843 np=slookup(pin,p,1);
844 if ((oldval=np->value) != NULL) savch=oldsavch; /* was previously defined */
845 b=1; cf=pin;
846 while (cf<p) {/* update macbit */
847 c= *cf++; xmac1(c,b,|=); b=(b+b)&0xFF;
848 if (cf!=p) {
849 xmac2(c,*cf,-1+(cf-pin),|=);
850 } else {
851 xmac2(c,0,-1+(cf-pin),|=);
852 }
853 }
854 params=0; outptr=inptr=p; p=cotoken(p); pin=inptr;
855 formal[0] = ""; /* Prepare for hack at next line... */
856 pf = formal; /* Make gcc/lint quiet, pf only used with params!=0 */
857 if (*pin=='(') {/* with parameters; identify the formals */
858 cf=formtxt; pf=formal;
859 for (;;) {
860 p=skipbl(p); pin=inptr;
861 if (*pin=='\n') {
862 --lineno[ifno]; --p; pperror("%s: missing )",np->name); break;
863 }
864 if (*pin==')') break;
865 if (*pin==',') continue;
866 if ((toktyp+COFF)[(int)*pin]!=IDENT) {
867 c= *p; *p='\0'; pperror("bad formal: %s",pin); *p=c;
868 } else if (pf>= &formal[MAXFRM]) {
869 c= *p; *p='\0'; pperror("too many formals: %s",pin); *p=c;
870 } else {
871 *pf++=cf; while (pin<p) *cf++= *pin++; *cf++='\0'; ++params;
872 }
873 }
874 if (params==0) --params; /* #define foo() ... */
875 } else if (*pin=='\n') {--lineno[ifno]; --p;}
876 /*
877 * remember beginning of macro body, so that we can
878 * warn if a redefinition is different from old value.
879 */
880 oldsavch=psav=savch;
881 for (;;) {/* accumulate definition until linefeed */
882 outptr=inptr=p; p=cotoken(p); pin=inptr;
883 if (*pin=='\\' && pin[1]=='\n') continue; /* ignore escaped lf */
884 if (*pin=='\n') break;
885 if (params) {/* mark the appearance of formals in the definiton */
886 if ((toktyp+COFF)[(int)*pin]==IDENT) {
887 for (qf=pf; --qf>=formal; ) {
888 if (equfrm(*qf,pin,p)) {
889 *psav++=qf-formal+1; *psav++=WARN; pin=p; break;
890 }
891 }
892 } else if (*pin=='"' || *pin=='\''
893 # if gcos
894 || *pin=='`'
895 # endif
896 ) {/* inside quotation marks, too */
897 char quoc= *pin;
898 for (*psav++= *pin++; pin<p && *pin!=quoc; ) {
899 while (pin<p && !isid(*pin)) *psav++= *pin++;
900 cf=pin; while (cf<p && isid(*cf)) ++cf;
901 for (qf=pf; --qf>=formal; ) {
902 if (equfrm(*qf,pin,cf)) {
903 *psav++=qf-formal+1; *psav++=WARN; pin=cf; break;
904 }
905 }
906 while (pin<cf) *psav++= *pin++;
907 }
908 }
909 }
910 while (pin < p) {
911 if (*pin == warnc) {
912 *psav++= WARN;
913 }
914 *psav++= *pin++;
915 }
916 }
917 *psav++=params; *psav++='\0';
918 if ((cf=oldval)!=NULL) {/* redefinition */
919 --cf; /* skip no. of params, which may be zero */
920 while (*--cf); /* go back to the beginning */
921 if (0!=strcmp(++cf,oldsavch)) {/* redefinition different from old */
922 --lineno[ifno]; ppwarn("%s redefined",np->name); ++lineno[ifno];
923 np->value=psav-1;
924 } else psav=oldsavch; /* identical redef.; reclaim space */
925 } else np->value=psav-1;
926 --flslvl; inptr=pin; savch=psav; return(p);
927 }
928
929 #define fasscan() ptrtab=fastab+COFF
930 #define sloscan() ptrtab=slotab+COFF
931
932 STATIC void
control(p)933 control(p) register char *p; {/* find and handle preprocessor control lines */
934 register struct symtab *np;
935 int didwarn;
936 for (;;) {
937 fasscan(); p=cotoken(p); if (*inptr=='\n') ++inptr; dump();
938 sloscan(); p=skipbl(p);
939 *--inptr=SALT; outptr=inptr; ++flslvl; np=slookup(inptr,p,0); --flslvl;
940 if (np==defloc) {/* define */
941 if (flslvl==0) {p=dodef(p); continue;}
942 } else if (np==incloc) {/* include */
943 if (flslvl==0) {p=doincl(p); continue;}
944 } else if (np==ifnloc) {/* ifndef */
945 ++flslvl; p=skipbl(p); np=slookup(inptr,p,0); --flslvl;
946 if (flslvl==0 && np->value==0) ++trulvl;
947 else ++flslvl;
948 } else if (np==ifdloc) {/* ifdef */
949 ++flslvl; p=skipbl(p); np=slookup(inptr,p,0); --flslvl;
950 if (flslvl==0 && np->value!=0) ++trulvl;
951 else ++flslvl;
952 } else if (np==eifloc) {/* endif */
953 if (flslvl) {if (--flslvl==0) sayline(NOINCLUDE);}
954 else if (trulvl) --trulvl;
955 else pperror("If-less endif",0);
956
957 if (flslvl == 0)
958 elflvl = 0;
959 elslvl = 0;
960 } else if (np==elifloc) {/* elif */
961 if (flslvl == 0)
962 elflvl = trulvl;
963 if (flslvl) {
964 if (elflvl > trulvl) {
965 ;
966 } else if (--flslvl != 0) {
967 ++flslvl;
968 } else {
969 newp = p;
970 if (yyparse()) {
971 ++trulvl;
972 sayline(NOINCLUDE);
973 } else {
974 ++flslvl;
975 }
976 p = newp;
977 }
978 } else if (trulvl) {
979 ++flslvl;
980 --trulvl;
981 } else
982 pperror("If-less elif");
983
984 } else if (np==elsloc) {/* else */
985 if (flslvl) {
986 if (elflvl > trulvl)
987 ;
988 else if (--flslvl!=0) ++flslvl;
989 else {++trulvl; sayline(NOINCLUDE);}
990 }
991 else if (trulvl) {++flslvl; --trulvl;}
992 else pperror("If-less else",0);
993
994 if (elslvl==trulvl+flslvl)
995 pperror("Too many #else's");
996 elslvl=trulvl+flslvl;
997
998 } else if (np==udfloc) {/* undefine */
999 if (flslvl==0) {
1000 ++flslvl; p=skipbl(p); slookup(inptr,p,DROP); --flslvl;
1001 }
1002 } else if (np==ifloc) {/* if */
1003 #if tgp
1004 pperror(" IF not implemented, true assumed", 0);
1005 if (flslvl==0) ++trulvl; else ++flslvl;
1006 #else
1007 newp=p;
1008 if (flslvl==0 && yyparse()) ++trulvl; else ++flslvl;
1009 p=newp;
1010 #endif
1011 } else if (np == idtloc) { /* ident */
1012 if (pflag == 0)
1013 while (*inptr != '\n') /* pass text */
1014 p = cotoken(p);
1015 } else if (np == pragmaloc) { /* pragma */
1016 while (*inptr != '\n') /* pass text */
1017 p = cotoken(p);
1018 } else if (np == errorloc) { /* error */
1019 #ifdef EXIT_ON_ERROR
1020 /*
1021 * Write a message to stderr and exit immediately, but only
1022 * if #error was in a conditional "active" part of the code.
1023 */
1024 if (flslvl == 0) {
1025 char ebuf[BUFFERSIZ];
1026
1027 p = ebuf;
1028 while (*inptr != '\n') {
1029 if (*inptr == '\0')
1030 if (eob(--inptr)) {
1031 inptr = refill(inptr);
1032 continue;
1033 }
1034 *p++ = *inptr++;
1035 if (p >= &ebuf[BUFFERSIZ-1])
1036 break;
1037 }
1038 *p = '\0';
1039 pperror(ebuf);
1040 exit(exfail);
1041 }
1042 #endif
1043 while (*inptr != '\n') /* pass text */
1044 p = cotoken(p);
1045 } else if (np == lneloc) { /* line */
1046 if (flslvl == 0 && pflag == 0) {
1047 register char *s;
1048 register int n;
1049
1050 outptr = inptr = p;
1051
1052 was_line:
1053 /*
1054 * Enforce the rest of the line to be in the buffer
1055 */
1056 s = p;
1057 while (*s && *s != '\n')
1058 s++;
1059 if (eob(s))
1060 p = refill(s);
1061
1062 s = inptr;
1063 while ((toktyp+COFF)[(int)*s] == BLANK)
1064 s++;
1065 /*
1066 * Now read the new line number...
1067 */
1068 n = 0;
1069 while (isdigit(*s)) {
1070 register int c;
1071
1072 if (n > MAXMULT) {
1073 pperror("bad number for #line");
1074 n = MAXVAL;
1075 break;
1076 }
1077 n *= 10;
1078 c = *s++ - '0';
1079 if ((MAXVAL - n) < c) {
1080 pperror("bad number for #line");
1081 n = MAXVAL;
1082 break;
1083 }
1084 n += c;
1085 }
1086 if (n == 0)
1087 pperror("bad number for #line");
1088 else
1089 lineno[ifno] = n - 1;
1090
1091 while ((toktyp+COFF)[(int)*s] == BLANK)
1092 s++;
1093
1094 /*
1095 * In case there is an optional file name...
1096 */
1097 if (*s != '\n') {
1098 register char *f;
1099
1100 f = s;
1101 while (*f && *f != '\n')
1102 f++;
1103
1104 if (savch >= sbf+SBSIZE-(f-s)) {
1105 newsbf();
1106 }
1107 f = savch;
1108 if (*s != '"')
1109 *f++ = *s;
1110 s++;
1111 while (*s) {
1112 if (*s == '"' || *s == '\n')
1113 break;
1114 *f++ = *s++;
1115 }
1116 *f++ = '\0';
1117 if (strcmp(savch, fnames[ifno])) {
1118 fnames[ifno] = savch;
1119 savch = f;
1120 }
1121 }
1122
1123 /*
1124 * Finally outout the rest of the directive.
1125 */
1126 *--outptr='#';
1127 while (*inptr != '\n')
1128 p = cotoken(p);
1129 continue;
1130 }
1131 } else if (*++inptr=='\n') outptr=inptr; /* allows blank line after # */
1132 else if (isdigit(*inptr)) { /* allow cpp output "#4711" */
1133 /*
1134 * Step back before this token in case it was a number.
1135 */
1136 outptr = p = inptr;
1137 goto was_line;
1138 } else pperror("undefined control",0);
1139 /* flush to lf */
1140 didwarn = 0;
1141 ++flslvl;
1142 while (*inptr != '\n') {
1143 outptr = inptr = p;
1144 p = cotoken(p);
1145 if (extrawarn && !didwarn &&
1146 *inptr != '\n' && *p != '\n' &&
1147 (toktyp+COFF)[(int)*p] != BLANK &&
1148 !iscomment(p)) {
1149 ppwarn("extra tokens (ignored) after directive");
1150 didwarn++;
1151 }
1152 }
1153 --flslvl;
1154 }
1155 }
1156
1157 STATIC int
iscomment(s)1158 iscomment(s)
1159 register char *s;
1160 {
1161 if (*s++ == '/') {
1162 if (*s == '*' || (cppflag && *s == '/'))
1163 return (1);
1164 }
1165 return (0);
1166 }
1167
1168 STATIC struct symtab *
stsym(s)1169 stsym(s) register char *s; {
1170 char buf[BUFFERSIZ]; register char *p;
1171
1172 /* make definition look exactly like end of #define line */
1173 /* copy to avoid running off end of world when param list is at end */
1174 p=buf; while ((*p++= *s++) != '\0');
1175 p=buf; while (isid(*p++)); /* skip first identifier */
1176 if (*--p=='=') {*p++=' '; while (*p++);}
1177 else {s=" 1"; while ((*p++= *s++) != '\0');}
1178 pend=p; *--p='\n';
1179 sloscan(); dodef(buf); return(lastsym);
1180 }
1181
1182 STATIC struct symtab *
ppsym(s)1183 ppsym(s) char *s; {/* kluge */
1184 register struct symtab *sp;
1185 cinit=SALT; *savch++=SALT; sp=stsym(s); --sp->name; cinit=0; return(sp);
1186 }
1187
1188 /* VARARGS1 */
1189 #ifdef PROTOTYPES
1190 EXPORT void
pperror(char * fmt,...)1191 pperror(char *fmt, ...)
1192 #else
1193 EXPORT void
1194 pperror(fmt, va_alist)
1195 char *fmt;
1196 va_dcl
1197 #endif
1198 {
1199 va_list args;
1200
1201 if (fnames[ifno] && fnames[ifno][0]) fprintf(stderr,
1202 # if gcos
1203 "*%c* \"%s\", line ", exfail >= 0 ? 'F' : 'W',
1204 # else
1205 "%s: line ",
1206 # endif
1207 fnames[ifno]);
1208 fprintf(stderr, "%d: ",lineno[ifno]);
1209
1210 #ifdef PROTOTYPES
1211 va_start(args, fmt);
1212 #else
1213 va_start(args);
1214 #endif
1215 (void)js_fprintf(stderr, "%r\n", fmt, args);
1216 va_end(args);
1217 #ifdef INCR_EXCODE
1218 /*
1219 * The historical behavior could cause the impression of exit(0)
1220 * since the historical wait() makes only the low 8 bits of the
1221 * exit code visible.
1222 */
1223 ++exfail;
1224 #else
1225 exfail = 1;
1226 #endif
1227 }
1228
1229 #ifdef PROTOTYPES
1230 EXPORT void
yyerror(char * fmt,...)1231 yyerror(char *fmt, ...)
1232 #else
1233 EXPORT void
1234 yyerror(fmt, va_alist)
1235 char *fmt;
1236 va_dcl
1237 #endif
1238 {
1239 va_list args;
1240
1241 #ifdef PROTOTYPES
1242 va_start(args, fmt);
1243 #else
1244 va_start(args);
1245 #endif
1246 pperror("%r", fmt, args);
1247 va_end(args);
1248 }
1249
1250 #ifdef PROTOTYPES
1251 STATIC void
ppwarn(char * fmt,...)1252 ppwarn(char *fmt, ...)
1253 #else
1254 STATIC void
1255 ppwarn(fmt, va_alist)
1256 char *fmt;
1257 va_dcl
1258 #endif
1259 {
1260 va_list args;
1261 int fail = exfail;
1262 exfail = -1;
1263
1264 #ifdef PROTOTYPES
1265 va_start(args, fmt);
1266 #else
1267 va_start(args);
1268 #endif
1269 pperror("%r", fmt, args);
1270 va_end(args);
1271
1272 exfail = fail;
1273 }
1274
1275 struct symtab *
lookup(namep,enterf)1276 lookup(namep, enterf)
1277 char *namep;
1278 int enterf;
1279 {
1280 register char *np, *snp;
1281 #ifdef SIGNED_HASH
1282 register int c, i;
1283 #else
1284 register unsigned int c, i;
1285 #endif
1286 register struct symtab *sp;
1287 struct symtab *prev;
1288 static struct symtab nsym; /* Hack: Dummy nulled symtab */
1289
1290 /* namep had better not be too long (currently, <=symlen chars) */
1291 np = namep;
1292 i = cinit;
1293 #ifdef SIGNED_HASH
1294 while ((c = *np++) != '\0')
1295 i += i+c;
1296 #else
1297 while ((c = *np++ & 0xFF) != '\0')
1298 i += i+c;
1299 #endif
1300 c = i; /* c = i for register usage on pdp11 */
1301 c %= symsiz;
1302 #ifdef SIGNED_HASH
1303 if (c < 0)
1304 c += symsiz;
1305 #endif
1306 sp = stab[c];
1307 prev = sp;
1308 while (sp != NULL) {
1309 snp = sp->name;
1310 np = namep;
1311 while (*snp++ == *np) {
1312 if (*np++ == '\0') {
1313 if (enterf == DROP) {
1314 sp->name[0] = DROP;
1315 sp->value = 0;
1316 }
1317 return (lastsym = sp);
1318 }
1319 }
1320 prev = sp;
1321 sp = sp->next;
1322 }
1323 if (enterf > 0) {
1324 sp = newsym();
1325 sp->name = namep;
1326 sp->value = NULL;
1327 sp->next = NULL;
1328 if (prev)
1329 prev->next = sp;
1330 else
1331 stab[c] = sp;
1332 }
1333 /*
1334 * Hack: emulate the behavior of the old code with static stab[], where
1335 * a non-matching request returns a zeroed (because previously empty)
1336 * struct symtab.
1337 */
1338 if (sp == NULL)
1339 sp = &nsym;
1340 return (lastsym = sp);
1341 }
1342
1343 STATIC struct symtab *
slookup(p1,p2,enterf)1344 slookup(p1,p2,enterf) register char *p1,*p2; int enterf;{
1345 register char *p3; char c2,c3; struct symtab *np;
1346 c2= *p2; *p2='\0'; /* mark end of token */
1347 if ((p2-p1)>symlen) p3=p1+symlen; else p3=p2;
1348 c3= *p3; *p3='\0'; /* truncate to symlen chars or less */
1349 if (enterf==1) p1=copy(p1);
1350 np=lookup(p1,enterf); *p3=c3; *p2=c2;
1351 if (np->value!=0 && flslvl==0) newp=subst(p2,np);
1352 else newp=0;
1353 return(np);
1354 }
1355
1356 STATIC char *
subst(p,sp)1357 subst(p,sp) register char *p; struct symtab *sp; {
1358 static char match[]="%s: argument mismatch";
1359 register char *ca,*vp; int params;
1360 char *actual[MAXFRM]; /* actual[n] is text of nth actual */
1361 char acttxt[BUFFERSIZ]; /* space for actuals */
1362
1363 if (0==(vp=sp->value)) return(p);
1364 if ((p-macforw)<=macdam) {
1365 if (++maclvl>symsiz && !rflag) {
1366 pperror("%s: macro recursion",sp->name); return(p);
1367 }
1368 } else maclvl=0; /* level decreased */
1369 macforw=p; macdam=0; /* new target for decrease in level */
1370 macnam=sp->name;
1371 dump();
1372 if (sp==ulnloc) {
1373 vp=acttxt; *vp++='\0';
1374 sprintf(vp,"%d",lineno[ifno]); while (*vp++);
1375 } else if (sp==uflloc) {
1376 vp=acttxt; *vp++='\0';
1377 ca = fnames[ifno];
1378 *vp++ = '"';
1379 while (*ca) {
1380 if (*ca == '\\')
1381 *vp++ = '\\';
1382 *vp++ = *ca++;
1383
1384 }
1385 *vp++ = '"';
1386 *vp++ = '\0';
1387 }
1388 if (0!=(params= *--vp&0xFF)) {/* definition calls for params */
1389 register char **pa;
1390 ca=acttxt; pa=actual;
1391 if (params==0xFF) params=1; /* #define foo() ... */
1392 sloscan(); ++flslvl; /* no expansion during search for actuals */
1393 plvl= -1;
1394 do p=skipbl(p); while (*inptr=='\n'); /* skip \n too */
1395 if (*inptr=='(') {
1396 maclin=lineno[ifno]; macfil=fnames[ifno];
1397 for (plvl=1; plvl!=0; ) {
1398 *ca++='\0';
1399 for (;;) {
1400 outptr=inptr=p; p=cotoken(p);
1401 if (*inptr=='(') ++plvl;
1402 if (*inptr==')' && --plvl==0) {--params; break;}
1403 if (plvl==1 && *inptr==',') {--params; break;}
1404 while (inptr<p) {
1405 /*
1406 * Sun cpp compatibility.
1407 * Needed for kernel assembler
1408 * preprocessing.
1409 * Replace newlines in actual
1410 * macro parameters by spaces.
1411 * Keep escaped newlines, they
1412 * are assumed to be inside a
1413 * string.
1414 */
1415 if (*inptr == '\n' &&
1416 inptr[-1] != '\\')
1417 *inptr = ' ';
1418 *ca++= *inptr++;
1419 }
1420 if (ca> &acttxt[BUFFERSIZ])
1421 pperror("%s: actuals too long",sp->name);
1422 }
1423 if (pa>= &actual[MAXFRM]) ppwarn(match,sp->name);
1424 else *pa++=ca;
1425 }
1426 }
1427 if (params!=0) ppwarn(match,sp->name);
1428 while (--params>=0) *pa++=""+1; /* null string for missing actuals */
1429 --flslvl; fasscan();
1430 }
1431 for (;;) {/* push definition onto front of input stack */
1432 while (!iswarn(*--vp)) { /* Terminates with '\0' also */
1433 if (bob(p)) {outptr=inptr=p; p=unfill(p);}
1434 *--p= *vp;
1435 }
1436 if (*vp==warnc) {/* insert actual param */
1437 if (vp[-1] == warnc) {
1438 *--p = *--vp;
1439 continue;
1440 }
1441 ca=actual[*--vp-1];
1442 while (*--ca) {
1443 if (bob(p)) {outptr=inptr=p; p=unfill(p);}
1444 *--p= *ca;
1445 }
1446 } else break;
1447 }
1448 outptr=inptr=p;
1449 return(p);
1450 }
1451
1452
1453
1454
1455 STATIC char *
trmdir(s)1456 trmdir(s) register char *s; {
1457 register char *p = s;
1458
1459 while (*p++)
1460 ;
1461 --p;
1462 while (p>s && *--p!='/')
1463 ;
1464 # if unix
1465 if (p==s)
1466 *p++='.';
1467 # endif
1468 *p='\0';
1469 return(s);
1470 }
1471
1472 STATIC char *
copy(s)1473 copy(s) register char *s; {
1474 register char *old;
1475
1476 old = savch; while ((*savch++ = *s++) != '\0');
1477 return(old);
1478 }
1479
1480 STATIC char *
strdex(s,c)1481 strdex(s,c) char *s,c; {
1482 while (*s) if (*s++==c) return(--s);
1483 return(0);
1484 }
1485
1486 int
yywrap()1487 yywrap(){ return(1); }
1488
1489 int
main(argc,argv)1490 main(argc,argv)
1491 char *argv[];
1492 int argc;
1493 {
1494 register int i,c;
1495 register char *p;
1496 char *tf,**cp2;
1497 char *sysdir = NULL;
1498
1499 fout = stdout; /* Mac OS X is not POSIX compliant (stdout nonconst.) */
1500
1501 # if gcos
1502 if (setjmp(env)) return (exfail);
1503 # endif
1504 p="_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
1505 i=0;
1506 while ((c= *p++) != '\0') {
1507 (fastab+COFF)[c] |= IB|NB|SB; (toktyp+COFF)[c]=IDENT;
1508 #if scw2
1509 /*
1510 * 53 == 63-10; digits rarely appear in identifiers,
1511 * and can never be the first char of an identifier.
1512 * 11 == 53*53/sizeof(macbit) .
1513 */
1514 ++i; (t21+COFF)[c]=(53*i)/11; (t22+COFF)[c]=i%11;
1515 #endif
1516 }
1517 p="0123456789.";
1518 while ((c = *p++) != '\0') {(fastab+COFF)[c] |= NB|SB; (toktyp+COFF)[c]=NUMBR;}
1519 # if gcos
1520 p="\n\"'`/\\";
1521 # else
1522 p="\n\"'/\\";
1523 # endif
1524 while ((c = *p++) != '\0') (fastab+COFF)[c] |= SB;
1525 # if gcos
1526 p="\n\"'`\\";
1527 # else
1528 p="\n\"'\\";
1529 # endif
1530 while ((c = *p++) != '\0') (fastab+COFF)[c] |= QB;
1531 p="*\n"; while ((c = *p++)!= '\0') (fastab+COFF)[c] |= CB;
1532 (fastab+COFF)[(int)warnc] |= WB;
1533 (fastab+COFF)['\0'] |= CB|QB|SB|WB;
1534 for (i=ALFSIZ; --i>=0; ) slotab[i]=fastab[i]|SB;
1535 p=" \t\013\f\r"; /* note no \n; \v not legal for vertical tab? */
1536 while ((c = *p++) != '\0') (toktyp+COFF)[c]=BLANK;
1537 #if scw2
1538 for ((t23+COFF)[i=ALFSIZ+7-COFF]=1; --i>=-COFF; )
1539 if (((t23+COFF)[i]=(t23+COFF+1)[i]<<1)==0) (t23+COFF)[i]=1;
1540 #endif
1541
1542 fnames[ifno=0] = ""; /* Allow pperror() to work correctly */
1543 newsbf(); /* Must be called before copy() / ppsym() */
1544
1545 # if unix
1546 fnames[ifno=0] = "";
1547 dirs[0]=dirnams[0]= ".";
1548 # endif
1549 # if ibm
1550 fnames[ifno=0] = "";
1551 # endif
1552 # if gcos
1553 if (inquire(stdin, _TTY)) freopen("*src", "rt", stdin);
1554 # endif
1555 # if gimpel || gcos
1556 fnames[ifno=0] = (char *)inquire(stdin, _FILENAME);
1557 dirnams[0] = dirs[0] = trmdir(copy(fnames[0]));
1558 # endif
1559 for(i=1; i<argc; i++)
1560 {
1561 switch(argv[i][0])
1562 {
1563 case '-':
1564 # if gcos
1565 switch(toupper(argv[i][1])) { /* case-independent on GCOS */
1566 # else
1567 switch(argv[i][1]) {
1568 # endif
1569 case 'P': pflag++;
1570 case 'E': continue;
1571 case 'R': ++rflag; continue;
1572 case 'B': cppflag++; continue;
1573 case 'C': passcom++; continue;
1574 case 'D':
1575 if (predef>prespc+NPREDEF) {
1576 pperror("too many -D options, ignoring %s",argv[i]);
1577 continue;
1578 }
1579 /* ignore plain "-D" (no argument) */
1580 if (*(argv[i]+2)) *predef++ = argv[i]+2;
1581 continue;
1582 case 'U':
1583 if (prund>punspc+NPREDEF) {
1584 pperror("too many -U options, ignoring %s",argv[i]);
1585 continue;
1586 }
1587 *prund++ = argv[i]+2;
1588 continue;
1589 case 'n':
1590 if (strcmp(argv[i], "-noinclude") == 0)
1591 noinclude = 1;
1592 else
1593 goto unknown;
1594 continue;
1595 case 'u':
1596 if (strcmp(argv[i], "-undef") == 0)
1597 nopredef = 1;
1598 else
1599 goto unknown;
1600 continue;
1601 case 'v':
1602 if (strcmp(argv[i], "-version") == 0) {
1603 printf("cpp version %s %s (%s-%s-%s)\n",
1604 VERSION,
1605 VERSION_DATE,
1606 HOST_CPU, HOST_VENDOR, HOST_OS);
1607 printf("\n");
1608 printf("Copyright (C) 1978 AT&T (John F. Reiser)\n");
1609 printf("Copyright (C) 2010-2021 Joerg Schilling\n");
1610 exit(0);
1611 }
1612 goto unknown;
1613 case 'x':
1614 if (strcmp(argv[i], "-xsc") == 0)
1615 char_is_signed = 1;
1616 else if (strcmp(argv[i], "-xuc") == 0)
1617 char_is_signed = 0;
1618 else
1619 goto unknown;
1620 continue;
1621 case 'I':
1622 if (nd>=MAXIDIRS) pperror("excessive -I file (%s) ignored",argv[i]);
1623 else dirs[nd++] = argv[i]+2;
1624 continue;
1625 case 'p': /* -T + extra tokens warn */
1626 extrawarn++;
1627 case 'T':
1628 symlen = 8; /* Compatibility with V7 */
1629 continue;
1630 case 'H': /* Print included filenames */
1631 hflag++;
1632 continue;
1633 case 'M': /* Generate make dependencies */
1634 mflag++;
1635 continue;
1636 case 'Y': /* Replace system include dir */
1637 sysdir = argv[i]+2;
1638 continue;
1639 case '\0': continue;
1640 case '-':
1641 if (strcmp(argv[i], "--help") == 0)
1642 usage();
1643 else
1644 goto unknown;
1645 case 'h':
1646 if (strcmp(argv[i], "-help") == 0)
1647 usage();
1648 /* FALLTHRU */
1649 default:
1650 unknown:
1651 pperror("unknown flag %s", argv[i]);
1652 continue;
1653 }
1654 default:
1655 if (fin == STDIN_FILENO) {
1656 if (0>(fin=open(argv[i], O_RDONLY))) {
1657 pperror("No source file %s",argv[i]); exit(8);
1658 }
1659 fnames[ifno] = copy(argv[i]);
1660 input = copy(argv[i]);
1661 dirs[0] = dirnams[ifno] = trmdir(argv[i]);
1662 # ifndef gcos
1663 /* too dangerous to have file name in same syntactic position
1664 be input or outptrut file depending on file redirections,
1665 so force outptrut to stdout, willy-nilly
1666 [i don't see what the problem is. jfr]
1667 */
1668 } else if (fout==stdout) {
1669 static char _sobuff[BUFSIZ];
1670 if (NULL==(fout=fopen(argv[i], "w"))) {
1671 pperror("Can't create %s", argv[i]); exit(8);
1672 } else {fclose(stdout); setbuf(fout,_sobuff);}
1673 # endif
1674 } else pperror("extraneous name %s", argv[i]);
1675 }
1676 }
1677
1678 if (mflag) {
1679 if (input == NULL) {
1680 pperror("cpp: no input file specified with -M flag");
1681 exit(8);
1682 }
1683 p = strrchr(input, '.');
1684 if (p == NULL || p[1] == '\0') {
1685 pperror("cpp: no filename suffix");
1686 exit(8);
1687 }
1688 p[1] = 'o';
1689 p = strrchr(input, '/');
1690 if (p != NULL)
1691 input = &p[1];
1692 mout = fout;
1693 if (NULL == (fout = fopen("/dev/null", "w"))) {
1694 pperror("Can't create /dev/null");
1695 exit(8);
1696 }
1697 }
1698 if ((p = getenv("SUNPRO_DEPENDENCIES")) != NULL) {
1699 if ((target = strchr(p, ' ')) != NULL) {
1700 *target++ = '\0';
1701 if (NULL == (dout = fopen(p, "a"))) {
1702 pperror("Can't create %s", p); exit(8);
1703 }
1704 }
1705 }
1706 fins[ifno]=fin;
1707 exfail = 0;
1708 /* after user -I files here are the standard include libraries */
1709 if (sysdir != NULL) {
1710 dirs[nd++] = sysdir;
1711 } else if (!noinclude) {
1712 # if unix
1713 dirs[nd++] = "/usr/include";
1714 # endif
1715 # if gcos
1716 dirs[nd++] = "cc/include";
1717 # endif
1718 # if ibm
1719 # ifndef gimpel
1720 dirs[nd++] = "BTL$CLIB";
1721 # endif
1722 # endif
1723 # ifdef gimpel
1724 dirs[nd++] = intss() ? "SYS3.C." : "" ;
1725 # endif
1726 /* dirs[nd++] = "/compool"; */
1727 }
1728 dirs[nd++] = 0;
1729 defloc=ppsym("define");
1730 udfloc=ppsym("undef");
1731 incloc=ppsym("include");
1732 elsloc=ppsym("else");
1733 eifloc=ppsym("endif");
1734 elifloc=ppsym("elif");
1735 ifdloc=ppsym("ifdef");
1736 ifnloc=ppsym("ifndef");
1737 ifloc=ppsym("if");
1738 lneloc=ppsym("line");
1739 idtloc=ppsym("ident");
1740 pragmaloc=ppsym("pragma");
1741 errorloc=ppsym("error");
1742 for (i=sizeof(macbit)/sizeof(macbit[0]); --i>=0; ) macbit[i]=0;
1743
1744 if (! nopredef) {
1745 varloc = 0;
1746 # if unix
1747 ysysloc=stsym("unix");
1748 # endif
1749 # if gcos
1750 ysysloc=stsym ("gcos");
1751 # endif
1752 # if ibm
1753 ysysloc=stsym ("ibm");
1754 # endif
1755 # if pdp11
1756 varloc=stsym("pdp11");
1757 # endif
1758 # if vax
1759 varloc=stsym("vax");
1760 # endif
1761 # if interdata
1762 varloc=stsym ("interdata");
1763 # endif
1764 # if tss
1765 varloc=stsym ("tss");
1766 # endif
1767 # if os
1768 varloc=stsym ("os");
1769 # endif
1770 # if mert
1771 varloc=stsym ("mert");
1772 # endif
1773 # if sun
1774 varloc=stsym ("sun");
1775 # endif
1776 # if linux
1777 varloc=stsym ("linux");
1778 # endif
1779 # if __NeXT__
1780 varloc=stsym ("__NeXT__");
1781 # endif
1782 # if __APPLE__
1783 varloc=stsym ("__APPLE__");
1784 # endif
1785 # if __MACH__
1786 varloc=stsym ("__MACH__");
1787 # endif
1788 # if sparc
1789 varloc=stsym ("sparc");
1790 # endif
1791 # if i386
1792 varloc=stsym ("i386");
1793 # endif
1794 # if __i386__
1795 varloc=stsym ("__i386__");
1796 # endif
1797 # if __amd64
1798 varloc=stsym ("__amd64");
1799 # endif
1800 # if __amd64__
1801 varloc=stsym ("__amd64__");
1802 # endif
1803 # if __x86_64
1804 varloc=stsym ("__x86_64");
1805 # endif
1806 # if __x86_64__
1807 varloc=stsym ("__x86_64__");
1808 # endif
1809 # if mc68000
1810 varloc=stsym ("mc68000");
1811 # endif
1812 # if mc68010
1813 varloc=stsym ("mc68010");
1814 # endif
1815 # if mc68020
1816 varloc=stsym ("mc68020");
1817 # endif
1818 # if __ppc__
1819 varloc=stsym ("__ppc__");
1820 # endif
1821 # if __ppc64__
1822 varloc=stsym ("__ppc64__");
1823 # endif
1824 # if __arm__
1825 varloc=stsym ("__arm__");
1826 # endif
1827 #ifdef __aarch64__
1828 varloc=stsym ("__aarch64__");
1829 #endif
1830
1831 #ifdef __hp9000s200
1832 varloc=stsym ("__hp9000s200");
1833 #endif
1834 #ifdef __hp9000s300
1835 varloc=stsym ("__hp9000s300");
1836 #endif
1837 #ifdef __hp9000s400
1838 varloc=stsym ("__hp9000s400");
1839 #endif
1840 #ifdef __hp9000s500
1841 varloc=stsym ("__hp9000s500");
1842 #endif
1843 #ifdef __hp9000s600
1844 varloc=stsym ("__hp9000s600");
1845 #endif
1846 #ifdef __hp9000s700
1847 varloc=stsym ("__hp9000s700");
1848 #endif
1849 #ifdef __hp9000s800
1850 varloc=stsym ("__hp9000s800");
1851 #endif
1852 #ifdef hppa
1853 varloc=stsym ("hppa");
1854 #endif
1855 #ifdef __hppa
1856 varloc=stsym ("__hppa");
1857 #endif
1858 #ifdef hpux
1859 varloc=stsym ("hpux");
1860 #endif
1861 #ifdef __hpux
1862 varloc=stsym ("__hpux");
1863 #endif
1864 #ifdef HFS
1865 varloc=stsym ("HFS"); /* HP-UX only? */
1866 #endif
1867 #ifdef PWB
1868 varloc=stsym ("PWB"); /* HP-UX only? */
1869 #endif
1870 #ifdef _PWB
1871 varloc=stsym ("_PWB"); /* HP-UX only? */
1872 #endif
1873
1874
1875 /*
1876 * This is defined on Sun systems starting with SunOS-4.0.
1877 * As GCC does not define __BUILTIN_VA_ARG_INCR, we need
1878 * to define it by our own. To make things simple, asume that
1879 * nobody still likes to compile this on SunOS-3.5 or older.
1880 */
1881 # ifdef sun
1882 # ifndef __BUILTIN_VA_ARG_INCR
1883 # define __BUILTIN_VA_ARG_INCR 1
1884 # endif
1885 # endif
1886 # ifdef __BUILTIN_VA_ARG_INCR
1887 varloc=stsym ("__BUILTIN_VA_ARG_INCR");
1888 # endif
1889 }
1890 ulnloc=stsym ("__LINE__");
1891 uflloc=stsym ("__FILE__");
1892
1893 tf=fnames[ifno]; fnames[ifno]="command line"; lineno[ifno]=1;
1894 cp2=prespc;
1895 while (cp2<predef) stsym(*cp2++);
1896 cp2=punspc;
1897 while (cp2<prund) {
1898 if ((p=strdex(*cp2, '=')) != NULL) *p++='\0';
1899 if (strlen(*cp2) > symlen)
1900 (*cp2)[symlen] = '\0';
1901 lookup(*cp2++, DROP);
1902 }
1903 fnames[ifno]=tf;
1904 pbeg=buffer+symlen; pbuf=pbeg+BUFFERSIZ; pend=pbuf+BUFFERSIZ;
1905
1906 trulvl = 0; flslvl = 0;
1907 lineno[0] = 1; sayline(NOINCLUDE);
1908 outptr=inptr=pend;
1909 if (mflag)
1910 fprintf(mout, "%s: %s\n", input, fnames[ifno]);
1911 control(pend);
1912 return (exfail);
1913 }
1914
1915 STATIC void
newsbf()1916 newsbf()
1917 {
1918 /*
1919 * All name space in symbols is obtained from sbf[] via copy(), so we
1920 * cannot use realloc() here as this might relocate sbf[]. We instead
1921 * throw away the last part of the current sbf[] and allocate new space
1922 * for new symbols.
1923 */
1924 if ((sbf = malloc(SBSIZE)) == NULL) {
1925 pperror("no buffer space");
1926 exit(exfail);
1927 }
1928 savch = sbf; /* Start at new buffer space */
1929 }
1930
1931 STATIC struct symtab *
newsym()1932 newsym()
1933 {
1934 static int nelem = 0;
1935 static struct symtab *syms = NULL;
1936
1937 if (nelem <= 0) {
1938 syms = malloc(SYMINCR * sizeof (struct symtab));
1939 if (syms == NULL) {
1940 pperror("too many defines");
1941 exit(exfail);
1942 }
1943 nelem = SYMINCR;
1944 }
1945 nelem--;
1946 return (syms++);
1947 }
1948
1949 STATIC void
usage()1950 usage()
1951 {
1952 fprintf(stderr, "Usage: cpp [options] [input-file [output-file]]\n");
1953 fprintf(stderr, "Options:\n");
1954 fprintf(stderr, " -B Support the C++ comment indicator '//'.\n");
1955 fprintf(stderr, " -C Pass all comments.\n");
1956 fprintf(stderr, " -H Print the path names of include files on standard error.\n");
1957 fprintf(stderr, " -M Generate a list of dependencies and write them to the output.\n");
1958 fprintf(stderr, " -p Only check for the first eight characters in macro names.\n");
1959 fprintf(stderr, " -P Do not include line control information in the preprocessor output.\n");
1960 fprintf(stderr, " -R Allow recursive macros.\n");
1961 fprintf(stderr, " -T Only check for the first eight characters in macro names, ignore rest.\n");
1962 fprintf(stderr, " -noinclude Ignore standard system include path.\n");
1963 fprintf(stderr, " -undef Remove all initially predefined macros.\n");
1964 fprintf(stderr, " -xsc Character constants are treated as signed char.\n");
1965 fprintf(stderr, " -xuc Character constants are treated as unsigned char.\n");
1966 fprintf(stderr, " -Dname Defines name as 1.\n");
1967 fprintf(stderr, " -Dname=var Defines name as val.\n");
1968 fprintf(stderr, " -Idirectory Adds directory to the search path.\n");
1969 fprintf(stderr, " -Uname Remove an initial definition of name.\n");
1970 fprintf(stderr, " -Ydirectory Uses directory instead of the standard system include directory.\n");
1971
1972 exit(0);
1973 }
1974