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