xref: /aoo4110/main/rsc/source/rscpp/cpp1.c (revision b1cdbd2c)
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