18e2a856bSAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
38e2a856bSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
48e2a856bSAndrew Rist * or more contributor license agreements. See the NOTICE file
58e2a856bSAndrew Rist * distributed with this work for additional information
68e2a856bSAndrew Rist * regarding copyright ownership. The ASF licenses this file
78e2a856bSAndrew Rist * to you under the Apache License, Version 2.0 (the
88e2a856bSAndrew Rist * "License"); you may not use this file except in compliance
98e2a856bSAndrew Rist * with the License. You may obtain a copy of the License at
108e2a856bSAndrew Rist *
118e2a856bSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
128e2a856bSAndrew Rist *
138e2a856bSAndrew Rist * Unless required by applicable law or agreed to in writing,
148e2a856bSAndrew Rist * software distributed under the License is distributed on an
158e2a856bSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
168e2a856bSAndrew Rist * KIND, either express or implied. See the License for the
178e2a856bSAndrew Rist * specific language governing permissions and limitations
188e2a856bSAndrew Rist * under the License.
198e2a856bSAndrew Rist *
208e2a856bSAndrew Rist *************************************************************/
218e2a856bSAndrew Rist
228e2a856bSAndrew 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
12386e1cf34SPedro Giffuni * commands and when compilation is suppressed 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.
16086e1cf34SPedro Giffuni * The -N option suppresses 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
InitCpp1()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
MAIN(int argc,char ** argv)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 }
332*cf09c872SPedro Giffuni strncpy(work, useargv[1], NWORK+1); /* Remember input filename */
333*cf09c872SPedro Giffuni work[NWORK] = '\0';
334cdf0e10cSrcweir break;
335cdf0e10cSrcweir } /* Else, just get stdin */
336cdf0e10cSrcweir case 0: /* No args? */
337cdf0e10cSrcweir case 1: /* No files, stdin -> stdout */
338cdf0e10cSrcweir #if (HOST == SYS_UNIX) || (HOST == SYS_UNKNOWN)
339cdf0e10cSrcweir work[0] = EOS; /* Unix can't find stdin name */
340cdf0e10cSrcweir #else
341cdf0e10cSrcweir fgetname(stdin, work); /* Vax-11C, Decus C know name */
342cdf0e10cSrcweir #endif
343cdf0e10cSrcweir break;
344cdf0e10cSrcweir
345cdf0e10cSrcweir default:
346cdf0e10cSrcweir exit(IO_ERROR); /* Can't happen */
347cdf0e10cSrcweir }
348cdf0e10cSrcweir /* if ( pfargv )
349cdf0e10cSrcweir {
350cdf0e10cSrcweir for ( j=0;j++;j < PARALIMIT )
351cdf0e10cSrcweir {
352cdf0e10cSrcweir if (pfargv[j]!=0)
353cdf0e10cSrcweir free(pfargv[j]);
354cdf0e10cSrcweir }
355cdf0e10cSrcweir free(pfargv);
356cdf0e10cSrcweir }
357cdf0e10cSrcweir */
358cdf0e10cSrcweir
359cdf0e10cSrcweir setincdirs(); /* Setup -I include directories */
360cdf0e10cSrcweir addfile( pCppIn, work); /* "open" main input file */
361cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
362cdf0e10cSrcweir if (debug > 0 || bDumpDefs)
363cdf0e10cSrcweir dumpdef("preset #define symbols");
364cdf0e10cSrcweir #endif
365cdf0e10cSrcweir if( pCppIn != stdin )
366cdf0e10cSrcweir rewind( pCppIn );
367cdf0e10cSrcweir
368cdf0e10cSrcweir cppmain(); /* Process main file */
369cdf0e10cSrcweir
370cdf0e10cSrcweir if ((i = (ifptr - &ifstack[0])) != 0) {
371cdf0e10cSrcweir #if OLD_PREPROCESSOR
372cdf0e10cSrcweir ciwarn("Inside #ifdef block at end of input, depth = %d", i);
373cdf0e10cSrcweir #else
374cdf0e10cSrcweir cierror("Inside #ifdef block at end of input, depth = %d", i);
375cdf0e10cSrcweir #endif
376cdf0e10cSrcweir }
377cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
378cdf0e10cSrcweir if( pDefOut != stdout && pDefOut != stderr )
379cdf0e10cSrcweir fclose( pDefOut );
380cdf0e10cSrcweir #endif
381cdf0e10cSrcweir if( pCppOut != stdout && pCppOut != stderr )
382cdf0e10cSrcweir fclose( pCppOut );
383cdf0e10cSrcweir
384cdf0e10cSrcweir if (errors > 0) {
385cdf0e10cSrcweir fprintf(stderr, (errors == 1)
386cdf0e10cSrcweir ? "%d error in preprocessor\n"
387cdf0e10cSrcweir : "%d errors in preprocessor\n", errors);
388cdf0e10cSrcweir if (!eflag)
389cdf0e10cSrcweir exit(IO_ERROR);
390cdf0e10cSrcweir }
391cdf0e10cSrcweir #ifdef NOMAIN /* BP */ /* kein exit im der LIB-Version */
392cdf0e10cSrcweir return( IO_NORMAL );
393cdf0e10cSrcweir #else
394cdf0e10cSrcweir exit(IO_NORMAL); /* No errors or -E option set */
395cdf0e10cSrcweir #endif
396cdf0e10cSrcweir
397cdf0e10cSrcweir }
398cdf0e10cSrcweir
399cdf0e10cSrcweir FILE_LOCAL
400cdf0e10cSrcweir void cppmain()
401cdf0e10cSrcweir /*
402cdf0e10cSrcweir * Main process for cpp -- copies tokens from the current input
403cdf0e10cSrcweir * stream (main file, include file, or a macro) to the output
404cdf0e10cSrcweir * file.
405cdf0e10cSrcweir */
406cdf0e10cSrcweir {
407cdf0e10cSrcweir register int c; /* Current character */
408cdf0e10cSrcweir register int counter; /* newlines and spaces */
409cdf0e10cSrcweir
410cdf0e10cSrcweir /*
411cdf0e10cSrcweir * Explicitly output a #line at the start of cpp output so
412cdf0e10cSrcweir * that lint (etc.) knows the name of the original source
413cdf0e10cSrcweir * file. If we don't do this explicitly, we may get
414cdf0e10cSrcweir * the name of the first #include file instead.
415cdf0e10cSrcweir * We also seem to need a blank line following that first #line.
416cdf0e10cSrcweir */
417cdf0e10cSrcweir #ifdef EVALDEFS
418cdf0e10cSrcweir if ( !bIsInEval )
419cdf0e10cSrcweir #endif
420cdf0e10cSrcweir {
421cdf0e10cSrcweir sharp();
422cdf0e10cSrcweir PUTCHAR('\n');
423cdf0e10cSrcweir }
424cdf0e10cSrcweir /*
425cdf0e10cSrcweir * This loop is started "from the top" at the beginning of each line
426cdf0e10cSrcweir * wrongline is set TRUE in many places if it is necessary to write
427cdf0e10cSrcweir * a #line record. (But we don't write them when expanding macros.)
428cdf0e10cSrcweir *
429cdf0e10cSrcweir * The counter variable has two different uses: at
430cdf0e10cSrcweir * the start of a line, it counts the number of blank lines that
431cdf0e10cSrcweir * have been skipped over. These are then either output via
432cdf0e10cSrcweir * #line records or by outputting explicit blank lines.
433cdf0e10cSrcweir * When expanding tokens within a line, the counter remembers
434cdf0e10cSrcweir * whether a blank/tab has been output. These are dropped
435cdf0e10cSrcweir * at the end of the line, and replaced by a single blank
436cdf0e10cSrcweir * within lines.
437cdf0e10cSrcweir */
438cdf0e10cSrcweir for (;;) {
439cdf0e10cSrcweir counter = 0; /* Count empty lines */
440cdf0e10cSrcweir for (;;) { /* For each line, ... */
441cdf0e10cSrcweir while (type[(c = get())] == SPA) /* Skip leading blanks */
442cdf0e10cSrcweir ; /* in this line. */
443cdf0e10cSrcweir if (c == '\n') /* If line's all blank, */
444cdf0e10cSrcweir ++counter; /* Do nothing now */
445cdf0e10cSrcweir else if (c == '#') { /* Is 1st non-space '#' */
446cdf0e10cSrcweir keepcomments = FALSE; /* Don't pass comments */
447cdf0e10cSrcweir counter = control(counter); /* Yes, do a #command */
448cdf0e10cSrcweir keepcomments = (cflag && compiling);
449cdf0e10cSrcweir }
450cdf0e10cSrcweir else if (c == EOF_CHAR) /* At end of file? */
451cdf0e10cSrcweir {
452cdf0e10cSrcweir break;
453cdf0e10cSrcweir }
454cdf0e10cSrcweir else if (!compiling) { /* #ifdef false? */
455cdf0e10cSrcweir skipnl(); /* Skip to newline */
456cdf0e10cSrcweir counter++; /* Count it, too. */
457cdf0e10cSrcweir }
458cdf0e10cSrcweir else {
459cdf0e10cSrcweir break; /* Actual token */
460cdf0e10cSrcweir }
461cdf0e10cSrcweir }
462cdf0e10cSrcweir if (c == EOF_CHAR) /* Exit process at */
463cdf0e10cSrcweir break; /* End of file */
464cdf0e10cSrcweir /*
465cdf0e10cSrcweir * If the loop didn't terminate because of end of file, we
466cdf0e10cSrcweir * know there is a token to compile. First, clean up after
467cdf0e10cSrcweir * absorbing newlines. counter has the number we skipped.
468cdf0e10cSrcweir */
469cdf0e10cSrcweir if ((wrongline && infile->fp != NULL) || counter > 4)
470cdf0e10cSrcweir sharp(); /* Output # line number */
471cdf0e10cSrcweir else { /* If just a few, stuff */
472cdf0e10cSrcweir while (--counter >= 0) /* them out ourselves */
473cdf0e10cSrcweir PUTCHAR('\n');
474cdf0e10cSrcweir }
475cdf0e10cSrcweir /*
476cdf0e10cSrcweir * Process each token on this line.
477cdf0e10cSrcweir */
478cdf0e10cSrcweir unget(); /* Reread the char. */
479cdf0e10cSrcweir for (;;) { /* For the whole line, */
480cdf0e10cSrcweir do { /* Token concat. loop */
481cdf0e10cSrcweir for (counter = 0; (type[(c = get())] == SPA);) {
482cdf0e10cSrcweir #if COMMENT_INVISIBLE
483cdf0e10cSrcweir if (c != COM_SEP)
484cdf0e10cSrcweir counter++;
485cdf0e10cSrcweir #else
486cdf0e10cSrcweir counter++; /* Skip over blanks */
487cdf0e10cSrcweir #endif
488cdf0e10cSrcweir }
489cdf0e10cSrcweir if (c == EOF_CHAR || c == '\n')
490cdf0e10cSrcweir goto end_line; /* Exit line loop */
491cdf0e10cSrcweir else if (counter > 0) /* If we got any spaces */
492cdf0e10cSrcweir PUTCHAR(' '); /* Output one space */
493cdf0e10cSrcweir c = macroid(c); /* Grab the token */
494cdf0e10cSrcweir } while (type[c] == LET && catenate());
495cdf0e10cSrcweir if (c == EOF_CHAR || c == '\n') /* From macro exp error */
496cdf0e10cSrcweir goto end_line; /* Exit line loop */
497cdf0e10cSrcweir switch (type[c]) {
498cdf0e10cSrcweir case LET:
499cdf0e10cSrcweir fputs(token, pCppOut); /* Quite ordinary token */
500cdf0e10cSrcweir #ifdef EVALDEFS
501cdf0e10cSrcweir {
502cdf0e10cSrcweir int len;
503cdf0e10cSrcweir if ( bIsInEval
504cdf0e10cSrcweir && nEvalOff + (len=strlen(token)) < NEVALBUF )
505cdf0e10cSrcweir {
506cdf0e10cSrcweir strcpy( &EvalBuf[nEvalOff], token );
507cdf0e10cSrcweir nEvalOff += len;
508cdf0e10cSrcweir }
509cdf0e10cSrcweir }
510cdf0e10cSrcweir #endif
511cdf0e10cSrcweir break;
512cdf0e10cSrcweir
513cdf0e10cSrcweir
514cdf0e10cSrcweir case DIG: /* Output a number */
515cdf0e10cSrcweir case DOT: /* Dot may begin floats */
516cdf0e10cSrcweir #ifdef EVALDEFS
517cdf0e10cSrcweir if ( bIsInEval )
518cdf0e10cSrcweir scannumber(c, outputEval);
519cdf0e10cSrcweir else
520cdf0e10cSrcweir scannumber(c, output);
521cdf0e10cSrcweir #else
522cdf0e10cSrcweir scannumber(c, output);
523cdf0e10cSrcweir #endif
524cdf0e10cSrcweir break;
525cdf0e10cSrcweir
526cdf0e10cSrcweir case QUO: /* char or string const */
527cdf0e10cSrcweir scanstring(c, output); /* Copy it to output */
528cdf0e10cSrcweir break;
529cdf0e10cSrcweir
530cdf0e10cSrcweir default: /* Some other character */
531cdf0e10cSrcweir cput(c); /* Just output it */
532cdf0e10cSrcweir #ifdef EVALDEFS
533cdf0e10cSrcweir if ( bIsInEval && nEvalOff < NEVALBUF )
534cdf0e10cSrcweir EvalBuf[nEvalOff++] = c;
535cdf0e10cSrcweir #endif
536cdf0e10cSrcweir break;
537cdf0e10cSrcweir } /* Switch ends */
538cdf0e10cSrcweir } /* Line for loop */
539cdf0e10cSrcweir end_line: if (c == '\n') { /* Compiling at EOL? */
540cdf0e10cSrcweir PUTCHAR('\n'); /* Output newline, if */
541cdf0e10cSrcweir if (infile->fp == NULL) /* Expanding a macro, */
542cdf0e10cSrcweir wrongline = TRUE; /* Output # line later */
543cdf0e10cSrcweir }
544cdf0e10cSrcweir } /* Continue until EOF */
545cdf0e10cSrcweir #ifdef EVALDEFS
546cdf0e10cSrcweir if ( bIsInEval )
547cdf0e10cSrcweir EvalBuf[nEvalOff++] = '\0';
548cdf0e10cSrcweir #endif
549cdf0e10cSrcweir }
550cdf0e10cSrcweir
551cdf0e10cSrcweir void output(int c)
552cdf0e10cSrcweir /*
553cdf0e10cSrcweir * Output one character to stdout -- output() is passed as an
554cdf0e10cSrcweir * argument to scanstring()
555cdf0e10cSrcweir */
556cdf0e10cSrcweir {
557cdf0e10cSrcweir #if COMMENT_INVISIBLE
558cdf0e10cSrcweir if (c != TOK_SEP && c != COM_SEP)
559cdf0e10cSrcweir #else
560cdf0e10cSrcweir if (c != TOK_SEP)
561cdf0e10cSrcweir #endif
562cdf0e10cSrcweir /* alt: PUTCHAR(c); */
563cdf0e10cSrcweir PUTCHAR(c);
564cdf0e10cSrcweir }
565cdf0e10cSrcweir
566cdf0e10cSrcweir #ifdef EVALDEFS
567cdf0e10cSrcweir outputEval(c)
568cdf0e10cSrcweir int c;
569cdf0e10cSrcweir /*
570cdf0e10cSrcweir * Output one character to stdout -- output() is passed as an
571cdf0e10cSrcweir * argument to scanstring()
572cdf0e10cSrcweir */
573cdf0e10cSrcweir {
574cdf0e10cSrcweir #if COMMENT_INVISIBLE
575cdf0e10cSrcweir if (c != TOK_SEP && c != COM_SEP)
576cdf0e10cSrcweir #else
577cdf0e10cSrcweir if (c != TOK_SEP)
578cdf0e10cSrcweir #endif
579cdf0e10cSrcweir /* alt: PUTCHAR(c); */
580cdf0e10cSrcweir {
581cdf0e10cSrcweir PUTCHAR(c);
582cdf0e10cSrcweir if ( bIsInEval && nEvalOff < NEVALBUF )
583cdf0e10cSrcweir EvalBuf[nEvalOff++] = c;
584cdf0e10cSrcweir }
585cdf0e10cSrcweir }
586cdf0e10cSrcweir #endif
587cdf0e10cSrcweir
588cdf0e10cSrcweir
589cdf0e10cSrcweir FILE_LOCAL
590cdf0e10cSrcweir void sharp()
591cdf0e10cSrcweir /*
592cdf0e10cSrcweir * Output a line number line.
593cdf0e10cSrcweir */
594cdf0e10cSrcweir {
595cdf0e10cSrcweir register char *name;
596cdf0e10cSrcweir
597cdf0e10cSrcweir if (keepcomments) /* Make sure # comes on */
598cdf0e10cSrcweir PUTCHAR('\n'); /* a fresh, new line. */
599cdf0e10cSrcweir fprintf( pCppOut, "#%s %d", LINE_PREFIX, line);
600cdf0e10cSrcweir if (infile->fp != NULL) {
601cdf0e10cSrcweir name = (infile->progname != NULL)
602cdf0e10cSrcweir ? infile->progname : infile->filename;
603cdf0e10cSrcweir if (sharpfilename == NULL
604cdf0e10cSrcweir || (sharpfilename != NULL && !streq(name, sharpfilename)) ) {
605cdf0e10cSrcweir if (sharpfilename != NULL)
606cdf0e10cSrcweir free(sharpfilename);
607cdf0e10cSrcweir sharpfilename = savestring(name);
608cdf0e10cSrcweir fprintf( pCppOut, " \"%s\"", name);
609cdf0e10cSrcweir }
610cdf0e10cSrcweir }
611cdf0e10cSrcweir PUTCHAR('\n');
612cdf0e10cSrcweir wrongline = FALSE;
613cdf0e10cSrcweir }
614