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