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