1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski *
3*b1cdbd2cSJim Jagielski * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski * or more contributor license agreements. See the NOTICE file
5*b1cdbd2cSJim Jagielski * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski * regarding copyright ownership. The ASF licenses this file
7*b1cdbd2cSJim Jagielski * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski * with the License. You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski *
11*b1cdbd2cSJim Jagielski * http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski *
13*b1cdbd2cSJim Jagielski * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski * KIND, either express or implied. See the License for the
17*b1cdbd2cSJim Jagielski * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski * under the License.
19*b1cdbd2cSJim Jagielski *
20*b1cdbd2cSJim Jagielski *************************************************************/
21*b1cdbd2cSJim Jagielski
22*b1cdbd2cSJim Jagielski
23*b1cdbd2cSJim Jagielski
24*b1cdbd2cSJim Jagielski #include <stdio.h>
25*b1cdbd2cSJim Jagielski #include <ctype.h>
26*b1cdbd2cSJim Jagielski #include "cppdef.h"
27*b1cdbd2cSJim Jagielski #include "cpp.h"
28*b1cdbd2cSJim Jagielski
29*b1cdbd2cSJim Jagielski FILE *pCppOut = NULL;
30*b1cdbd2cSJim Jagielski FILE *pCppIn = NULL;
31*b1cdbd2cSJim Jagielski
32*b1cdbd2cSJim Jagielski #if OSL_DEBUG_LEVEL > 1
33*b1cdbd2cSJim Jagielski FILE *pDefOut = NULL; /* ER evtl. #define's dump */
34*b1cdbd2cSJim Jagielski #endif
35*b1cdbd2cSJim Jagielski
36*b1cdbd2cSJim Jagielski #ifdef B200
37*b1cdbd2cSJim Jagielski /* BP, 25.07.91, einzige Moeglichkeit unter BC Stack und Heap festzusetzen */
38*b1cdbd2cSJim Jagielski extern unsigned _stklen = 24000;
39*b1cdbd2cSJim Jagielski extern unsigned _heaplen = 30000;
40*b1cdbd2cSJim Jagielski #endif
41*b1cdbd2cSJim Jagielski
42*b1cdbd2cSJim Jagielski
43*b1cdbd2cSJim Jagielski
44*b1cdbd2cSJim Jagielski /*
45*b1cdbd2cSJim Jagielski * Commonly used global variables:
46*b1cdbd2cSJim Jagielski * line is the current input line number.
47*b1cdbd2cSJim Jagielski * wrongline is set in many places when the actual output
48*b1cdbd2cSJim Jagielski * line is out of sync with the numbering, e.g,
49*b1cdbd2cSJim Jagielski * when expanding a macro with an embedded newline.
50*b1cdbd2cSJim Jagielski *
51*b1cdbd2cSJim Jagielski * token holds the last identifier scanned (which might
52*b1cdbd2cSJim Jagielski * be a candidate for macro expansion).
53*b1cdbd2cSJim Jagielski * errors is the running cpp error counter.
54*b1cdbd2cSJim Jagielski * infile is the head of a linked list of input files (extended by
55*b1cdbd2cSJim Jagielski * #include and macros being expanded). infile always points
56*b1cdbd2cSJim Jagielski * to the current file/macro. infile->parent to the includer,
57*b1cdbd2cSJim Jagielski * etc. infile->fd is NULL if this input stream is a macro.
58*b1cdbd2cSJim Jagielski */
59*b1cdbd2cSJim Jagielski int line; /* Current line number */
60*b1cdbd2cSJim Jagielski int wrongline; /* Force #line to compiler */
61*b1cdbd2cSJim Jagielski char token[IDMAX + 1]; /* Current input token */
62*b1cdbd2cSJim Jagielski int errors; /* cpp error counter */
63*b1cdbd2cSJim Jagielski FILEINFO *infile = NULL; /* Current input file */
64*b1cdbd2cSJim Jagielski #if OSL_DEBUG_LEVEL > 1
65*b1cdbd2cSJim Jagielski int debug; /* TRUE if debugging now */
66*b1cdbd2cSJim Jagielski int bDumpDefs; /* TRUE if #define's dump req. */
67*b1cdbd2cSJim Jagielski #ifdef EVALDEFS
68*b1cdbd2cSJim Jagielski int bIsInEval; /* TRUE if #define eval now */
69*b1cdbd2cSJim Jagielski char EvalBuf[NEVALBUF + 1]; /* evaluation buffer */
70*b1cdbd2cSJim Jagielski int nEvalOff = 0; /* offset to free buffer pos */
71*b1cdbd2cSJim Jagielski #endif
72*b1cdbd2cSJim Jagielski #endif
73*b1cdbd2cSJim Jagielski /*
74*b1cdbd2cSJim Jagielski * This counter is incremented when a macro expansion is initiated.
75*b1cdbd2cSJim Jagielski * If it exceeds a built-in value, the expansion stops -- this tests
76*b1cdbd2cSJim Jagielski * for a runaway condition:
77*b1cdbd2cSJim Jagielski * #define X Y
78*b1cdbd2cSJim Jagielski * #define Y X
79*b1cdbd2cSJim Jagielski * X
80*b1cdbd2cSJim Jagielski * This can be disabled by falsifying rec_recover. (Nothing does this
81*b1cdbd2cSJim Jagielski * currently: it is a hook for an eventual invocation flag.)
82*b1cdbd2cSJim Jagielski */
83*b1cdbd2cSJim Jagielski int recursion; /* Infinite recursion counter */
84*b1cdbd2cSJim Jagielski int rec_recover = TRUE; /* Unwind recursive macros */
85*b1cdbd2cSJim Jagielski
86*b1cdbd2cSJim Jagielski /*
87*b1cdbd2cSJim Jagielski * instring is set TRUE when a string is scanned. It modifies the
88*b1cdbd2cSJim Jagielski * behavior of the "get next character" routine, causing all characters
89*b1cdbd2cSJim Jagielski * to be passed to the caller (except <DEF_MAGIC>). Note especially that
90*b1cdbd2cSJim Jagielski * comments and \<newline> are not removed from the source. (This
91*b1cdbd2cSJim Jagielski * prevents cpp output lines from being arbitrarily long).
92*b1cdbd2cSJim Jagielski *
93*b1cdbd2cSJim Jagielski * inmacro is set by #define -- it absorbs comments and converts
94*b1cdbd2cSJim Jagielski * form-feed and vertical-tab to space, but returns \<newline>
95*b1cdbd2cSJim Jagielski * to the caller. Strictly speaking, this is a bug as \<newline>
96*b1cdbd2cSJim Jagielski * shouldn't delimit tokens, but we'll worry about that some other
97*b1cdbd2cSJim Jagielski * time -- it is more important to prevent infinitly long output lines.
98*b1cdbd2cSJim Jagielski *
99*b1cdbd2cSJim Jagielski * instring and inmarcor are parameters to the get() routine which
100*b1cdbd2cSJim Jagielski * were made global for speed.
101*b1cdbd2cSJim Jagielski */
102*b1cdbd2cSJim Jagielski int instring = FALSE; /* TRUE if scanning string */
103*b1cdbd2cSJim Jagielski int inmacro = FALSE; /* TRUE if #defining a macro */
104*b1cdbd2cSJim Jagielski
105*b1cdbd2cSJim Jagielski /*
106*b1cdbd2cSJim Jagielski * work[] and workp are used to store one piece of text in a temporay
107*b1cdbd2cSJim Jagielski * buffer. To initialize storage, set workp = work. To store one
108*b1cdbd2cSJim Jagielski * character, call save(c); (This will fatally exit if there isn't
109*b1cdbd2cSJim Jagielski * room.) To terminate the string, call save(EOS). Note that
110*b1cdbd2cSJim Jagielski * the work buffer is used by several subroutines -- be sure your
111*b1cdbd2cSJim Jagielski * data won't be overwritten. The extra byte in the allocation is
112*b1cdbd2cSJim Jagielski * needed for string formal replacement.
113*b1cdbd2cSJim Jagielski */
114*b1cdbd2cSJim Jagielski char work[NWORK + 1]; /* Work buffer */
115*b1cdbd2cSJim Jagielski char *workp; /* Work buffer pointer */
116*b1cdbd2cSJim Jagielski
117*b1cdbd2cSJim Jagielski /*
118*b1cdbd2cSJim Jagielski * keepcomments is set TRUE by the -C option. If TRUE, comments
119*b1cdbd2cSJim Jagielski * are written directly to the output stream. This is needed if
120*b1cdbd2cSJim Jagielski * the output from cpp is to be passed to lint (which uses commands
121*b1cdbd2cSJim Jagielski * embedded in comments). cflag contains the permanent state of the
122*b1cdbd2cSJim Jagielski * -C flag. keepcomments is always falsified when processing #control
123*b1cdbd2cSJim Jagielski * commands and when compilation is supressed by a false #if
124*b1cdbd2cSJim Jagielski *
125*b1cdbd2cSJim Jagielski * If eflag is set, CPP returns "success" even if non-fatal errors
126*b1cdbd2cSJim Jagielski * were detected.
127*b1cdbd2cSJim Jagielski *
128*b1cdbd2cSJim Jagielski * If nflag is non-zero, no symbols are predefined except __LINE__.
129*b1cdbd2cSJim Jagielski * __FILE__, and __DATE__. If nflag > 1, absolutely no symbols
130*b1cdbd2cSJim Jagielski * are predefined.
131*b1cdbd2cSJim Jagielski */
132*b1cdbd2cSJim Jagielski int keepcomments = FALSE; /* Write out comments flag */
133*b1cdbd2cSJim Jagielski int cflag = FALSE; /* -C option (keep comments) */
134*b1cdbd2cSJim Jagielski int eflag = FALSE; /* -E option (never fail) */
135*b1cdbd2cSJim Jagielski int nflag = 0; /* -N option (no predefines) */
136*b1cdbd2cSJim Jagielski
137*b1cdbd2cSJim Jagielski /*
138*b1cdbd2cSJim Jagielski * ifstack[] holds information about nested #if's. It is always
139*b1cdbd2cSJim Jagielski * accessed via *ifptr. The information is as follows:
140*b1cdbd2cSJim Jagielski * WAS_COMPILING state of compiling flag at outer level.
141*b1cdbd2cSJim Jagielski * ELSE_SEEN set TRUE when #else seen to prevent 2nd #else.
142*b1cdbd2cSJim Jagielski * TRUE_SEEN set TRUE when #if or #elif succeeds
143*b1cdbd2cSJim Jagielski * ifstack[0] holds the compiling flag. It is TRUE if compilation
144*b1cdbd2cSJim Jagielski * is currently enabled. Note that this must be initialized TRUE.
145*b1cdbd2cSJim Jagielski */
146*b1cdbd2cSJim Jagielski char ifstack[BLK_NEST] = { TRUE }; /* #if information */
147*b1cdbd2cSJim Jagielski char *ifptr = ifstack; /* -> current ifstack[] */
148*b1cdbd2cSJim Jagielski
149*b1cdbd2cSJim Jagielski /*
150*b1cdbd2cSJim Jagielski * incdir[] stores the -i directories (and the system-specific
151*b1cdbd2cSJim Jagielski * #include <...> directories.
152*b1cdbd2cSJim Jagielski */
153*b1cdbd2cSJim Jagielski char *incdir[NINCLUDE]; /* -i directories */
154*b1cdbd2cSJim Jagielski char **incend = incdir; /* -> free space in incdir[] */
155*b1cdbd2cSJim Jagielski
156*b1cdbd2cSJim Jagielski /*
157*b1cdbd2cSJim Jagielski * This is the table used to predefine target machine and operating
158*b1cdbd2cSJim Jagielski * system designators. It may need hacking for specific circumstances.
159*b1cdbd2cSJim Jagielski * Note: it is not clear that this is part of the Ansi Standard.
160*b1cdbd2cSJim Jagielski * The -N option supresses preset definitions.
161*b1cdbd2cSJim Jagielski */
162*b1cdbd2cSJim Jagielski char *preset[] = { /* names defined at cpp start */
163*b1cdbd2cSJim Jagielski #ifdef MACHINE
164*b1cdbd2cSJim Jagielski MACHINE,
165*b1cdbd2cSJim Jagielski #endif
166*b1cdbd2cSJim Jagielski #ifdef SYSTEM
167*b1cdbd2cSJim Jagielski SYSTEM,
168*b1cdbd2cSJim Jagielski #endif
169*b1cdbd2cSJim Jagielski #ifdef COMPILER
170*b1cdbd2cSJim Jagielski COMPILER,
171*b1cdbd2cSJim Jagielski #endif
172*b1cdbd2cSJim Jagielski #if OSL_DEBUG_LEVEL > 1
173*b1cdbd2cSJim Jagielski "decus_cpp", /* Ourselves! */
174*b1cdbd2cSJim Jagielski #endif
175*b1cdbd2cSJim Jagielski NULL /* Must be last */
176*b1cdbd2cSJim Jagielski };
177*b1cdbd2cSJim Jagielski
178*b1cdbd2cSJim Jagielski /*
179*b1cdbd2cSJim Jagielski * The value of these predefined symbols must be recomputed whenever
180*b1cdbd2cSJim Jagielski * they are evaluated. The order must not be changed.
181*b1cdbd2cSJim Jagielski */
182*b1cdbd2cSJim Jagielski char *magic[] = { /* Note: order is important */
183*b1cdbd2cSJim Jagielski "__LINE__",
184*b1cdbd2cSJim Jagielski "__FILE__",
185*b1cdbd2cSJim Jagielski NULL /* Must be last */
186*b1cdbd2cSJim Jagielski };
187*b1cdbd2cSJim Jagielski
188*b1cdbd2cSJim Jagielski static char *sharpfilename = NULL;
189*b1cdbd2cSJim Jagielski
190*b1cdbd2cSJim Jagielski int nRunde = 0;
191*b1cdbd2cSJim Jagielski
InitCpp1()192*b1cdbd2cSJim Jagielski void InitCpp1()
193*b1cdbd2cSJim Jagielski {
194*b1cdbd2cSJim Jagielski int i;
195*b1cdbd2cSJim Jagielski /* BP */
196*b1cdbd2cSJim Jagielski /* in der LIB-Version muessen alle Variablen initialisiert werden */
197*b1cdbd2cSJim Jagielski
198*b1cdbd2cSJim Jagielski line = wrongline = errors = recursion = 0;
199*b1cdbd2cSJim Jagielski for( i = 0; i < IDMAX; i++ )
200*b1cdbd2cSJim Jagielski token[ i ] = 0;
201*b1cdbd2cSJim Jagielski
202*b1cdbd2cSJim Jagielski for( i = 0; i < NWORK; i++ )
203*b1cdbd2cSJim Jagielski work[ i ] = 0;
204*b1cdbd2cSJim Jagielski
205*b1cdbd2cSJim Jagielski for( i = 0; i < NINCLUDE; i++ )
206*b1cdbd2cSJim Jagielski incdir[ i ] = NULL;
207*b1cdbd2cSJim Jagielski
208*b1cdbd2cSJim Jagielski workp = NULL;
209*b1cdbd2cSJim Jagielski for( i = 0; i < BLK_NEST; i++ )
210*b1cdbd2cSJim Jagielski ifstack[ i ] = TRUE;
211*b1cdbd2cSJim Jagielski ifptr = ifstack;
212*b1cdbd2cSJim Jagielski
213*b1cdbd2cSJim Jagielski pCppOut = stdout;
214*b1cdbd2cSJim Jagielski pCppIn = stdin;
215*b1cdbd2cSJim Jagielski #if OSL_DEBUG_LEVEL > 1
216*b1cdbd2cSJim Jagielski debug = 0;
217*b1cdbd2cSJim Jagielski bDumpDefs = 0;
218*b1cdbd2cSJim Jagielski pDefOut = stdout;
219*b1cdbd2cSJim Jagielski #ifdef EVALDEFS
220*b1cdbd2cSJim Jagielski bIsInEval = 0;
221*b1cdbd2cSJim Jagielski for( i = 0; i < NEVALBUF; i++ )
222*b1cdbd2cSJim Jagielski EvalBuf[ i ] = 0;
223*b1cdbd2cSJim Jagielski nEvalOff = 0;
224*b1cdbd2cSJim Jagielski #endif
225*b1cdbd2cSJim Jagielski #endif
226*b1cdbd2cSJim Jagielski rec_recover = TRUE;
227*b1cdbd2cSJim Jagielski infile = NULL;
228*b1cdbd2cSJim Jagielski instring = inmacro = keepcomments = cflag = eflag = FALSE;
229*b1cdbd2cSJim Jagielski nflag = 0;
230*b1cdbd2cSJim Jagielski incend = incdir;
231*b1cdbd2cSJim Jagielski sharpfilename = NULL;
232*b1cdbd2cSJim Jagielski /* BP */
233*b1cdbd2cSJim Jagielski }
234*b1cdbd2cSJim Jagielski
MAIN(int argc,char ** argv)235*b1cdbd2cSJim Jagielski int MAIN(int argc, char** argv)
236*b1cdbd2cSJim Jagielski {
237*b1cdbd2cSJim Jagielski register int i;
238*b1cdbd2cSJim Jagielski char **useargv, **pfargv;
239*b1cdbd2cSJim Jagielski
240*b1cdbd2cSJim Jagielski
241*b1cdbd2cSJim Jagielski if( nRunde == 0 )
242*b1cdbd2cSJim Jagielski {
243*b1cdbd2cSJim Jagielski pCppIn = stdin;
244*b1cdbd2cSJim Jagielski pCppOut = stdout;
245*b1cdbd2cSJim Jagielski }
246*b1cdbd2cSJim Jagielski
247*b1cdbd2cSJim Jagielski nRunde++;
248*b1cdbd2cSJim Jagielski InitCpp1();
249*b1cdbd2cSJim Jagielski InitCpp2();
250*b1cdbd2cSJim Jagielski InitCpp3();
251*b1cdbd2cSJim Jagielski InitCpp4();
252*b1cdbd2cSJim Jagielski InitCpp5();
253*b1cdbd2cSJim Jagielski InitCpp6();
254*b1cdbd2cSJim Jagielski
255*b1cdbd2cSJim Jagielski #if HOST == SYS_VMS
256*b1cdbd2cSJim Jagielski argc = getredirection(argc, argv); /* vms >file and <file */
257*b1cdbd2cSJim Jagielski #endif
258*b1cdbd2cSJim Jagielski initdefines(); /* O.S. specific def's */
259*b1cdbd2cSJim Jagielski if ( argv[argc-1][0] == '@' )
260*b1cdbd2cSJim Jagielski {
261*b1cdbd2cSJim Jagielski i = readoptions( argv[1], &pfargv ); /* Command file */
262*b1cdbd2cSJim Jagielski useargv=pfargv;
263*b1cdbd2cSJim Jagielski }
264*b1cdbd2cSJim Jagielski else
265*b1cdbd2cSJim Jagielski {
266*b1cdbd2cSJim Jagielski i = dooptions(argc, argv); /* Command line -flags */
267*b1cdbd2cSJim Jagielski useargv=argv;
268*b1cdbd2cSJim Jagielski }
269*b1cdbd2cSJim Jagielski switch (i) {
270*b1cdbd2cSJim Jagielski #if OSL_DEBUG_LEVEL > 1
271*b1cdbd2cSJim Jagielski case 4:
272*b1cdbd2cSJim Jagielski if ( bDumpDefs )
273*b1cdbd2cSJim Jagielski {
274*b1cdbd2cSJim Jagielski /*
275*b1cdbd2cSJim Jagielski * Get defBase file, "-" means use stdout.
276*b1cdbd2cSJim Jagielski */
277*b1cdbd2cSJim Jagielski if (!streq(useargv[3], "-")) {
278*b1cdbd2cSJim Jagielski #if HOST == SYS_VMS
279*b1cdbd2cSJim Jagielski /*
280*b1cdbd2cSJim Jagielski * On vms, reopen stdout with "vanilla rms" attributes.
281*b1cdbd2cSJim Jagielski */
282*b1cdbd2cSJim Jagielski if ((i = creat(useargv[3], 0, "rat=cr", "rfm=var")) == -1
283*b1cdbd2cSJim Jagielski || dup2(i, fileno(stdout)) == -1) {
284*b1cdbd2cSJim Jagielski #else
285*b1cdbd2cSJim Jagielski /* alt if (freopen(useargv[3], "w", stdout) == NULL) { */
286*b1cdbd2cSJim Jagielski
287*b1cdbd2cSJim Jagielski pDefOut = fopen( useargv[3], "w" );
288*b1cdbd2cSJim Jagielski if( pDefOut == NULL ) {
289*b1cdbd2cSJim Jagielski #endif
290*b1cdbd2cSJim Jagielski perror(useargv[3]);
291*b1cdbd2cSJim Jagielski cerror("Can't open output file \"%s\"", useargv[3]);
292*b1cdbd2cSJim Jagielski exit(IO_ERROR);
293*b1cdbd2cSJim Jagielski }
294*b1cdbd2cSJim Jagielski } /* Continue by opening output */
295*b1cdbd2cSJim Jagielski }
296*b1cdbd2cSJim Jagielski /* OSL_DEBUG_LEVEL > 1 */
297*b1cdbd2cSJim Jagielski #endif
298*b1cdbd2cSJim Jagielski case 3:
299*b1cdbd2cSJim Jagielski /*
300*b1cdbd2cSJim Jagielski * Get output file, "-" means use stdout.
301*b1cdbd2cSJim Jagielski */
302*b1cdbd2cSJim Jagielski if (!streq(useargv[2], "-")) {
303*b1cdbd2cSJim Jagielski #if HOST == SYS_VMS
304*b1cdbd2cSJim Jagielski /*
305*b1cdbd2cSJim Jagielski * On vms, reopen stdout with "vanilla rms" attributes.
306*b1cdbd2cSJim Jagielski */
307*b1cdbd2cSJim Jagielski if ((i = creat(useargv[2], 0, "rat=cr", "rfm=var")) == -1
308*b1cdbd2cSJim Jagielski || dup2(i, fileno(stdout)) == -1) {
309*b1cdbd2cSJim Jagielski #else
310*b1cdbd2cSJim Jagielski /* alt if (freopen(useargv[2], "w", stdout) == NULL) { */
311*b1cdbd2cSJim Jagielski
312*b1cdbd2cSJim Jagielski pCppOut = fopen( useargv[2], "w" );
313*b1cdbd2cSJim Jagielski if( pCppOut == NULL ) {
314*b1cdbd2cSJim Jagielski #endif
315*b1cdbd2cSJim Jagielski perror(useargv[2]);
316*b1cdbd2cSJim Jagielski cerror("Can't open output file \"%s\"", useargv[2]);
317*b1cdbd2cSJim Jagielski exit(IO_ERROR);
318*b1cdbd2cSJim Jagielski }
319*b1cdbd2cSJim Jagielski } /* Continue by opening input */
320*b1cdbd2cSJim Jagielski case 2: /* One file -> stdin */
321*b1cdbd2cSJim Jagielski /*
322*b1cdbd2cSJim Jagielski * Open input file, "-" means use stdin.
323*b1cdbd2cSJim Jagielski */
324*b1cdbd2cSJim Jagielski if (!streq(useargv[1], "-")) {
325*b1cdbd2cSJim Jagielski /* alt: if (freopen(useargv[1], "r", stdin) == NULL) { */
326*b1cdbd2cSJim Jagielski pCppIn = fopen( useargv[1], "r" );
327*b1cdbd2cSJim Jagielski if( pCppIn == NULL) {
328*b1cdbd2cSJim Jagielski perror(useargv[1]);
329*b1cdbd2cSJim Jagielski cerror("Can't open input file \"%s\"", useargv[1]);
330*b1cdbd2cSJim Jagielski exit(IO_ERROR);
331*b1cdbd2cSJim Jagielski }
332*b1cdbd2cSJim Jagielski strcpy(work, useargv[1]); /* Remember input filename */
333*b1cdbd2cSJim Jagielski break;
334*b1cdbd2cSJim Jagielski } /* Else, just get stdin */
335*b1cdbd2cSJim Jagielski case 0: /* No args? */
336*b1cdbd2cSJim Jagielski case 1: /* No files, stdin -> stdout */
337*b1cdbd2cSJim Jagielski #if (HOST == SYS_UNIX) || (HOST == SYS_UNKNOWN)
338*b1cdbd2cSJim Jagielski work[0] = EOS; /* Unix can't find stdin name */
339*b1cdbd2cSJim Jagielski #else
340*b1cdbd2cSJim Jagielski fgetname(stdin, work); /* Vax-11C, Decus C know name */
341*b1cdbd2cSJim Jagielski #endif
342*b1cdbd2cSJim Jagielski break;
343*b1cdbd2cSJim Jagielski
344*b1cdbd2cSJim Jagielski default:
345*b1cdbd2cSJim Jagielski exit(IO_ERROR); /* Can't happen */
346*b1cdbd2cSJim Jagielski }
347*b1cdbd2cSJim Jagielski /* if ( pfargv )
348*b1cdbd2cSJim Jagielski {
349*b1cdbd2cSJim Jagielski for ( j=0;j++;j < PARALIMIT )
350*b1cdbd2cSJim Jagielski {
351*b1cdbd2cSJim Jagielski if (pfargv[j]!=0)
352*b1cdbd2cSJim Jagielski free(pfargv[j]);
353*b1cdbd2cSJim Jagielski }
354*b1cdbd2cSJim Jagielski free(pfargv);
355*b1cdbd2cSJim Jagielski }
356*b1cdbd2cSJim Jagielski */
357*b1cdbd2cSJim Jagielski
358*b1cdbd2cSJim Jagielski setincdirs(); /* Setup -I include directories */
359*b1cdbd2cSJim Jagielski addfile( pCppIn, work); /* "open" main input file */
360*b1cdbd2cSJim Jagielski #if OSL_DEBUG_LEVEL > 1
361*b1cdbd2cSJim Jagielski if (debug > 0 || bDumpDefs)
362*b1cdbd2cSJim Jagielski dumpdef("preset #define symbols");
363*b1cdbd2cSJim Jagielski #endif
364*b1cdbd2cSJim Jagielski if( pCppIn != stdin )
365*b1cdbd2cSJim Jagielski rewind( pCppIn );
366*b1cdbd2cSJim Jagielski
367*b1cdbd2cSJim Jagielski cppmain(); /* Process main file */
368*b1cdbd2cSJim Jagielski
369*b1cdbd2cSJim Jagielski if ((i = (ifptr - &ifstack[0])) != 0) {
370*b1cdbd2cSJim Jagielski #if OLD_PREPROCESSOR
371*b1cdbd2cSJim Jagielski ciwarn("Inside #ifdef block at end of input, depth = %d", i);
372*b1cdbd2cSJim Jagielski #else
373*b1cdbd2cSJim Jagielski cierror("Inside #ifdef block at end of input, depth = %d", i);
374*b1cdbd2cSJim Jagielski #endif
375*b1cdbd2cSJim Jagielski }
376*b1cdbd2cSJim Jagielski #if OSL_DEBUG_LEVEL > 1
377*b1cdbd2cSJim Jagielski if( pDefOut != stdout && pDefOut != stderr )
378*b1cdbd2cSJim Jagielski fclose( pDefOut );
379*b1cdbd2cSJim Jagielski #endif
380*b1cdbd2cSJim Jagielski if( pCppOut != stdout && pCppOut != stderr )
381*b1cdbd2cSJim Jagielski fclose( pCppOut );
382*b1cdbd2cSJim Jagielski
383*b1cdbd2cSJim Jagielski if (errors > 0) {
384*b1cdbd2cSJim Jagielski fprintf(stderr, (errors == 1)
385*b1cdbd2cSJim Jagielski ? "%d error in preprocessor\n"
386*b1cdbd2cSJim Jagielski : "%d errors in preprocessor\n", errors);
387*b1cdbd2cSJim Jagielski if (!eflag)
388*b1cdbd2cSJim Jagielski exit(IO_ERROR);
389*b1cdbd2cSJim Jagielski }
390*b1cdbd2cSJim Jagielski #ifdef NOMAIN /* BP */ /* kein exit im der LIB-Version */
391*b1cdbd2cSJim Jagielski return( IO_NORMAL );
392*b1cdbd2cSJim Jagielski #else
393*b1cdbd2cSJim Jagielski exit(IO_NORMAL); /* No errors or -E option set */
394*b1cdbd2cSJim Jagielski #endif
395*b1cdbd2cSJim Jagielski
396*b1cdbd2cSJim Jagielski }
397*b1cdbd2cSJim Jagielski
398*b1cdbd2cSJim Jagielski FILE_LOCAL
399*b1cdbd2cSJim Jagielski void cppmain()
400*b1cdbd2cSJim Jagielski /*
401*b1cdbd2cSJim Jagielski * Main process for cpp -- copies tokens from the current input
402*b1cdbd2cSJim Jagielski * stream (main file, include file, or a macro) to the output
403*b1cdbd2cSJim Jagielski * file.
404*b1cdbd2cSJim Jagielski */
405*b1cdbd2cSJim Jagielski {
406*b1cdbd2cSJim Jagielski register int c; /* Current character */
407*b1cdbd2cSJim Jagielski register int counter; /* newlines and spaces */
408*b1cdbd2cSJim Jagielski
409*b1cdbd2cSJim Jagielski /*
410*b1cdbd2cSJim Jagielski * Explicitly output a #line at the start of cpp output so
411*b1cdbd2cSJim Jagielski * that lint (etc.) knows the name of the original source
412*b1cdbd2cSJim Jagielski * file. If we don't do this explicitly, we may get
413*b1cdbd2cSJim Jagielski * the name of the first #include file instead.
414*b1cdbd2cSJim Jagielski * We also seem to need a blank line following that first #line.
415*b1cdbd2cSJim Jagielski */
416*b1cdbd2cSJim Jagielski #ifdef EVALDEFS
417*b1cdbd2cSJim Jagielski if ( !bIsInEval )
418*b1cdbd2cSJim Jagielski #endif
419*b1cdbd2cSJim Jagielski {
420*b1cdbd2cSJim Jagielski sharp();
421*b1cdbd2cSJim Jagielski PUTCHAR('\n');
422*b1cdbd2cSJim Jagielski }
423*b1cdbd2cSJim Jagielski /*
424*b1cdbd2cSJim Jagielski * This loop is started "from the top" at the beginning of each line
425*b1cdbd2cSJim Jagielski * wrongline is set TRUE in many places if it is necessary to write
426*b1cdbd2cSJim Jagielski * a #line record. (But we don't write them when expanding macros.)
427*b1cdbd2cSJim Jagielski *
428*b1cdbd2cSJim Jagielski * The counter variable has two different uses: at
429*b1cdbd2cSJim Jagielski * the start of a line, it counts the number of blank lines that
430*b1cdbd2cSJim Jagielski * have been skipped over. These are then either output via
431*b1cdbd2cSJim Jagielski * #line records or by outputting explicit blank lines.
432*b1cdbd2cSJim Jagielski * When expanding tokens within a line, the counter remembers
433*b1cdbd2cSJim Jagielski * whether a blank/tab has been output. These are dropped
434*b1cdbd2cSJim Jagielski * at the end of the line, and replaced by a single blank
435*b1cdbd2cSJim Jagielski * within lines.
436*b1cdbd2cSJim Jagielski */
437*b1cdbd2cSJim Jagielski for (;;) {
438*b1cdbd2cSJim Jagielski counter = 0; /* Count empty lines */
439*b1cdbd2cSJim Jagielski for (;;) { /* For each line, ... */
440*b1cdbd2cSJim Jagielski while (type[(c = get())] == SPA) /* Skip leading blanks */
441*b1cdbd2cSJim Jagielski ; /* in this line. */
442*b1cdbd2cSJim Jagielski if (c == '\n') /* If line's all blank, */
443*b1cdbd2cSJim Jagielski ++counter; /* Do nothing now */
444*b1cdbd2cSJim Jagielski else if (c == '#') { /* Is 1st non-space '#' */
445*b1cdbd2cSJim Jagielski keepcomments = FALSE; /* Don't pass comments */
446*b1cdbd2cSJim Jagielski counter = control(counter); /* Yes, do a #command */
447*b1cdbd2cSJim Jagielski keepcomments = (cflag && compiling);
448*b1cdbd2cSJim Jagielski }
449*b1cdbd2cSJim Jagielski else if (c == EOF_CHAR) /* At end of file? */
450*b1cdbd2cSJim Jagielski {
451*b1cdbd2cSJim Jagielski break;
452*b1cdbd2cSJim Jagielski }
453*b1cdbd2cSJim Jagielski else if (!compiling) { /* #ifdef false? */
454*b1cdbd2cSJim Jagielski skipnl(); /* Skip to newline */
455*b1cdbd2cSJim Jagielski counter++; /* Count it, too. */
456*b1cdbd2cSJim Jagielski }
457*b1cdbd2cSJim Jagielski else {
458*b1cdbd2cSJim Jagielski break; /* Actual token */
459*b1cdbd2cSJim Jagielski }
460*b1cdbd2cSJim Jagielski }
461*b1cdbd2cSJim Jagielski if (c == EOF_CHAR) /* Exit process at */
462*b1cdbd2cSJim Jagielski break; /* End of file */
463*b1cdbd2cSJim Jagielski /*
464*b1cdbd2cSJim Jagielski * If the loop didn't terminate because of end of file, we
465*b1cdbd2cSJim Jagielski * know there is a token to compile. First, clean up after
466*b1cdbd2cSJim Jagielski * absorbing newlines. counter has the number we skipped.
467*b1cdbd2cSJim Jagielski */
468*b1cdbd2cSJim Jagielski if ((wrongline && infile->fp != NULL) || counter > 4)
469*b1cdbd2cSJim Jagielski sharp(); /* Output # line number */
470*b1cdbd2cSJim Jagielski else { /* If just a few, stuff */
471*b1cdbd2cSJim Jagielski while (--counter >= 0) /* them out ourselves */
472*b1cdbd2cSJim Jagielski PUTCHAR('\n');
473*b1cdbd2cSJim Jagielski }
474*b1cdbd2cSJim Jagielski /*
475*b1cdbd2cSJim Jagielski * Process each token on this line.
476*b1cdbd2cSJim Jagielski */
477*b1cdbd2cSJim Jagielski unget(); /* Reread the char. */
478*b1cdbd2cSJim Jagielski for (;;) { /* For the whole line, */
479*b1cdbd2cSJim Jagielski do { /* Token concat. loop */
480*b1cdbd2cSJim Jagielski for (counter = 0; (type[(c = get())] == SPA);) {
481*b1cdbd2cSJim Jagielski #if COMMENT_INVISIBLE
482*b1cdbd2cSJim Jagielski if (c != COM_SEP)
483*b1cdbd2cSJim Jagielski counter++;
484*b1cdbd2cSJim Jagielski #else
485*b1cdbd2cSJim Jagielski counter++; /* Skip over blanks */
486*b1cdbd2cSJim Jagielski #endif
487*b1cdbd2cSJim Jagielski }
488*b1cdbd2cSJim Jagielski if (c == EOF_CHAR || c == '\n')
489*b1cdbd2cSJim Jagielski goto end_line; /* Exit line loop */
490*b1cdbd2cSJim Jagielski else if (counter > 0) /* If we got any spaces */
491*b1cdbd2cSJim Jagielski PUTCHAR(' '); /* Output one space */
492*b1cdbd2cSJim Jagielski c = macroid(c); /* Grab the token */
493*b1cdbd2cSJim Jagielski } while (type[c] == LET && catenate());
494*b1cdbd2cSJim Jagielski if (c == EOF_CHAR || c == '\n') /* From macro exp error */
495*b1cdbd2cSJim Jagielski goto end_line; /* Exit line loop */
496*b1cdbd2cSJim Jagielski switch (type[c]) {
497*b1cdbd2cSJim Jagielski case LET:
498*b1cdbd2cSJim Jagielski fputs(token, pCppOut); /* Quite ordinary token */
499*b1cdbd2cSJim Jagielski #ifdef EVALDEFS
500*b1cdbd2cSJim Jagielski {
501*b1cdbd2cSJim Jagielski int len;
502*b1cdbd2cSJim Jagielski if ( bIsInEval
503*b1cdbd2cSJim Jagielski && nEvalOff + (len=strlen(token)) < NEVALBUF )
504*b1cdbd2cSJim Jagielski {
505*b1cdbd2cSJim Jagielski strcpy( &EvalBuf[nEvalOff], token );
506*b1cdbd2cSJim Jagielski nEvalOff += len;
507*b1cdbd2cSJim Jagielski }
508*b1cdbd2cSJim Jagielski }
509*b1cdbd2cSJim Jagielski #endif
510*b1cdbd2cSJim Jagielski break;
511*b1cdbd2cSJim Jagielski
512*b1cdbd2cSJim Jagielski
513*b1cdbd2cSJim Jagielski case DIG: /* Output a number */
514*b1cdbd2cSJim Jagielski case DOT: /* Dot may begin floats */
515*b1cdbd2cSJim Jagielski #ifdef EVALDEFS
516*b1cdbd2cSJim Jagielski if ( bIsInEval )
517*b1cdbd2cSJim Jagielski scannumber(c, outputEval);
518*b1cdbd2cSJim Jagielski else
519*b1cdbd2cSJim Jagielski scannumber(c, output);
520*b1cdbd2cSJim Jagielski #else
521*b1cdbd2cSJim Jagielski scannumber(c, output);
522*b1cdbd2cSJim Jagielski #endif
523*b1cdbd2cSJim Jagielski break;
524*b1cdbd2cSJim Jagielski
525*b1cdbd2cSJim Jagielski case QUO: /* char or string const */
526*b1cdbd2cSJim Jagielski scanstring(c, output); /* Copy it to output */
527*b1cdbd2cSJim Jagielski break;
528*b1cdbd2cSJim Jagielski
529*b1cdbd2cSJim Jagielski default: /* Some other character */
530*b1cdbd2cSJim Jagielski cput(c); /* Just output it */
531*b1cdbd2cSJim Jagielski #ifdef EVALDEFS
532*b1cdbd2cSJim Jagielski if ( bIsInEval && nEvalOff < NEVALBUF )
533*b1cdbd2cSJim Jagielski EvalBuf[nEvalOff++] = c;
534*b1cdbd2cSJim Jagielski #endif
535*b1cdbd2cSJim Jagielski break;
536*b1cdbd2cSJim Jagielski } /* Switch ends */
537*b1cdbd2cSJim Jagielski } /* Line for loop */
538*b1cdbd2cSJim Jagielski end_line: if (c == '\n') { /* Compiling at EOL? */
539*b1cdbd2cSJim Jagielski PUTCHAR('\n'); /* Output newline, if */
540*b1cdbd2cSJim Jagielski if (infile->fp == NULL) /* Expanding a macro, */
541*b1cdbd2cSJim Jagielski wrongline = TRUE; /* Output # line later */
542*b1cdbd2cSJim Jagielski }
543*b1cdbd2cSJim Jagielski } /* Continue until EOF */
544*b1cdbd2cSJim Jagielski #ifdef EVALDEFS
545*b1cdbd2cSJim Jagielski if ( bIsInEval )
546*b1cdbd2cSJim Jagielski EvalBuf[nEvalOff++] = '\0';
547*b1cdbd2cSJim Jagielski #endif
548*b1cdbd2cSJim Jagielski }
549*b1cdbd2cSJim Jagielski
550*b1cdbd2cSJim Jagielski void output(int c)
551*b1cdbd2cSJim Jagielski /*
552*b1cdbd2cSJim Jagielski * Output one character to stdout -- output() is passed as an
553*b1cdbd2cSJim Jagielski * argument to scanstring()
554*b1cdbd2cSJim Jagielski */
555*b1cdbd2cSJim Jagielski {
556*b1cdbd2cSJim Jagielski #if COMMENT_INVISIBLE
557*b1cdbd2cSJim Jagielski if (c != TOK_SEP && c != COM_SEP)
558*b1cdbd2cSJim Jagielski #else
559*b1cdbd2cSJim Jagielski if (c != TOK_SEP)
560*b1cdbd2cSJim Jagielski #endif
561*b1cdbd2cSJim Jagielski /* alt: PUTCHAR(c); */
562*b1cdbd2cSJim Jagielski PUTCHAR(c);
563*b1cdbd2cSJim Jagielski }
564*b1cdbd2cSJim Jagielski
565*b1cdbd2cSJim Jagielski #ifdef EVALDEFS
566*b1cdbd2cSJim Jagielski outputEval(c)
567*b1cdbd2cSJim Jagielski int c;
568*b1cdbd2cSJim Jagielski /*
569*b1cdbd2cSJim Jagielski * Output one character to stdout -- output() is passed as an
570*b1cdbd2cSJim Jagielski * argument to scanstring()
571*b1cdbd2cSJim Jagielski */
572*b1cdbd2cSJim Jagielski {
573*b1cdbd2cSJim Jagielski #if COMMENT_INVISIBLE
574*b1cdbd2cSJim Jagielski if (c != TOK_SEP && c != COM_SEP)
575*b1cdbd2cSJim Jagielski #else
576*b1cdbd2cSJim Jagielski if (c != TOK_SEP)
577*b1cdbd2cSJim Jagielski #endif
578*b1cdbd2cSJim Jagielski /* alt: PUTCHAR(c); */
579*b1cdbd2cSJim Jagielski {
580*b1cdbd2cSJim Jagielski PUTCHAR(c);
581*b1cdbd2cSJim Jagielski if ( bIsInEval && nEvalOff < NEVALBUF )
582*b1cdbd2cSJim Jagielski EvalBuf[nEvalOff++] = c;
583*b1cdbd2cSJim Jagielski }
584*b1cdbd2cSJim Jagielski }
585*b1cdbd2cSJim Jagielski #endif
586*b1cdbd2cSJim Jagielski
587*b1cdbd2cSJim Jagielski
588*b1cdbd2cSJim Jagielski FILE_LOCAL
589*b1cdbd2cSJim Jagielski void sharp()
590*b1cdbd2cSJim Jagielski /*
591*b1cdbd2cSJim Jagielski * Output a line number line.
592*b1cdbd2cSJim Jagielski */
593*b1cdbd2cSJim Jagielski {
594*b1cdbd2cSJim Jagielski register char *name;
595*b1cdbd2cSJim Jagielski
596*b1cdbd2cSJim Jagielski if (keepcomments) /* Make sure # comes on */
597*b1cdbd2cSJim Jagielski PUTCHAR('\n'); /* a fresh, new line. */
598*b1cdbd2cSJim Jagielski fprintf( pCppOut, "#%s %d", LINE_PREFIX, line);
599*b1cdbd2cSJim Jagielski if (infile->fp != NULL) {
600*b1cdbd2cSJim Jagielski name = (infile->progname != NULL)
601*b1cdbd2cSJim Jagielski ? infile->progname : infile->filename;
602*b1cdbd2cSJim Jagielski if (sharpfilename == NULL
603*b1cdbd2cSJim Jagielski || (sharpfilename != NULL && !streq(name, sharpfilename)) ) {
604*b1cdbd2cSJim Jagielski if (sharpfilename != NULL)
605*b1cdbd2cSJim Jagielski free(sharpfilename);
606*b1cdbd2cSJim Jagielski sharpfilename = savestring(name);
607*b1cdbd2cSJim Jagielski fprintf( pCppOut, " \"%s\"", name);
608*b1cdbd2cSJim Jagielski }
609*b1cdbd2cSJim Jagielski }
610*b1cdbd2cSJim Jagielski PUTCHAR('\n');
611*b1cdbd2cSJim Jagielski wrongline = FALSE;
612*b1cdbd2cSJim Jagielski }
613