/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #ifdef UNX #include #endif #include #include "cppdef.h" #include "cpp.h" #include "time.h" /* BP */ #include #if (OSL_DEBUG_LEVEL > 1) && (HOST == SYS_UNIX) #include #endif void InitCpp3() { } /* * Open a file, add it to the linked list of open files. * This is called only from openfile() above. */ int openfile(char* filename) { FILE* fp; if ((fp = fopen(filename, "r")) == NULL) { #if OSL_DEBUG_LEVEL > 1 if ( debug || !bDumpDefs ) perror(filename); #endif return (FALSE); } #if OSL_DEBUG_LEVEL > 1 if (debug) fprintf(stderr, "Reading from \"%s\"\n", filename); #endif addfile(fp, filename); return (TRUE); } /* * Initialize tables for this open file. This is called from openfile() * above (for #include files), and from the entry to cpp to open the main * input file. It calls a common routine, getfile() to build the FILEINFO * structure which is used to read characters. (getfile() is also called * to setup a macro replacement.) */ void addfile(FILE* fp, char* filename) { FILEINFO* file; file = getfile(NBUFF, filename); file->fp = fp; /* Better remember FILE * */ file->buffer[0] = EOS; /* Initialize for first read */ line = 1; /* Working on line 1 now */ wrongline = TRUE; /* Force out initial #line */ } /* * Append system-specific directories to the include directory list. * Called only when cpp is started. */ void setincdirs() { #ifdef CPP_INCLUDE *incend++ = CPP_INCLUDE; #define IS_INCLUDE 1 #else #define IS_INCLUDE 0 #endif #if HOST == SYS_UNIX *incend++ = "/usr/include"; #define MAXINCLUDE (NINCLUDE - 1 - IS_INCLUDE) #endif #if HOST == SYS_UNKNOWN /* * Kontext: GenMake * Unter DOS wird nun auch die Environment-Variable INCLUDE ausgewetet. * Es kommt erschwerend hinzu, dass alle Eintraege, die mit ';' getrennt * sind, mit in die Liste aufenommen werden muessen. * Dies wird mit der Funktion strtok() realisiert. * Vorsicht bei der Benutzung von malloc !!! * In savestring wird naemlich getmem() verwendet. Vermutlich kommen sich * die beiden Funktion in die Quere. Als ich malloc statt savestring * verwendete knallte es in strcpy() ! */ #if !defined( WNT ) && ! defined UNX extern char* getenv( char *pStr ); /* BP */ #endif char* pIncGetEnv = NULL; /* Pointer auf INCLUDE */ if ( ( pIncGetEnv = getenv("INCLUDE") ) != NULL ) AddInclude( pIncGetEnv ); #define MAXINCLUDE (NINCLUDE - 3 - IS_INCLUDE) #endif } /* Kontext: Erweiterung des INCLUDE-Services * Bislang konnte der cpp keine Include-Angaben in der Kommandozeile * vertragen, bei denen die directries mit ';' getrennt wurden. * Dies ist auch verstaendlich, da dieses cpp fuer UNIX-Systeme * massgeschneidert wurde und in UNI die ';' als Zeichen zum Abschluss * von Kommandos gilt. */ int AddInclude( char* pIncStr ) { char* pIncEnv = NULL; /* Kopie des INCLUDE */ char* pIncPos; /* wandert zum naechsten */ pIncEnv = savestring( pIncStr ); pIncPos = strtok( pIncEnv, ";" ); while( pIncPos != NULL ) { if (incend >= &incdir[MAXINCLUDE]) cfatal("Too many include directories", NULLST); *incend++ = pIncPos; pIncPos = strtok( NULL, ";" ); } return( 1 ); } /* * dooptions is called to process command line arguments (-Detc). * It is called only at cpp startup. */ int dooptions(int argc, char** argv) { char* ap; DEFBUF* dp; int c; int i, j; char* arg; SIZES* sizp; /* For -S */ int size; /* For -S */ int isdatum; /* FALSE for -S* */ int endtest; /* For -S */ for (i = j = 1; i < argc; i++) { arg = ap = argv[i]; if (*ap++ != '-' || *ap == EOS) { argv[j++] = argv[i]; } else { c = *ap++; /* Option byte */ if (islower(c)) /* Normalize case */ c = toupper(c); switch (c) /* Command character */ { case 'C': /* Keep comments */ cflag = TRUE; keepcomments = TRUE; break; case 'D': /* Define symbol */ /* * If the option is just "-Dfoo", make it -Dfoo=1 */ while (*ap != EOS && *ap != '=') ap++; if (*ap == EOS) ap = "1"; else *ap++ = EOS; /* * Now, save the word and its definition. */ dp = defendel(argv[i] + 2, FALSE); dp->repl = savestring(ap); dp->nargs = DEF_NOARGS; break; case 'E': /* Ignore non-fatal */ eflag = TRUE; /* errors. */ break; case 'I': /* Include directory */ AddInclude( ap ); /* BP, 11.09.91 */ break; case 'N': /* No predefineds */ nflag++; /* Repeat to undefine */ break; /* __LINE__, etc. */ case 'S': sizp = size_table; if (0 != (isdatum = (*ap != '*'))) /* If it's just -S, */ endtest = T_FPTR; /* Stop here */ else /* But if it's -S* */ { ap++; /* Step over '*' */ endtest = 0; /* Stop at end marker */ } while (sizp->bits != endtest && *ap != EOS) { if (!isdigit(*ap)) /* Skip to next digit */ { ap++; continue; } size = 0; /* Compile the value */ while (isdigit(*ap)) { size *= 10; size += (*ap++ - '0'); } if (isdatum) sizp->size = size; /* Datum size */ else sizp->psize = size; /* Pointer size */ sizp++; } if (sizp->bits != endtest) cwarn("-S, too few values specified in %s", argv[i]); else if (*ap != EOS) cwarn("-S, too many values, \"%s\" unused", ap); break; case 'U': /* Undefine symbol */ if (defendel(ap, TRUE) == NULL) cwarn("\"%s\" wasn't defined", ap); break; #if OSL_DEBUG_LEVEL > 1 case 'X': /* Debug */ debug = (isdigit(*ap)) ? atoi(ap) : 1; #if (HOST == SYS_UNIX) signal(SIGINT, (void (*)(int)) abort); /* Trap "interrupt" */ #endif fprintf(stderr, "Debug set to %d\n", debug); break; #endif #if OSL_DEBUG_LEVEL > 1 case 'P': /* #define's dump */ bDumpDefs = 1; fprintf(stderr, "Dump #define's is on\n"); break; #endif default: /* What is this one? */ cwarn("Unknown option \"%s\"", arg); fprintf(stderr, "The following options are valid:\n\ -C\t\t\tWrite source file comments to output\n\ -Dsymbol=value\tDefine a symbol with the given (optional) value\n\ -Idirectory\t\tAdd a directory to the #include search list\n\ -N\t\t\tDon't predefine target-specific names\n\ -Stext\t\tSpecify sizes for #if sizeof\n\ -Usymbol\t\tUndefine symbol\n"); #if OSL_DEBUG_LEVEL > 1 fprintf(stderr, " -Xvalue\t\tSet internal debug flag\n"); fprintf(stderr, " -P\t\t\tdump #define's\n"); #endif break; } /* Switch on all options */ } /* If it's a -option */ } /* For all arguments */ #if OSL_DEBUG_LEVEL > 1 if ( (bDumpDefs ? j > 4 : j > 3) ) #else if (j > 3) #endif { cerror( "Too many file arguments. Usage: cpp [input [output]]", NULLST); } return (j); /* Return new argc */ } int readoptions(char* filename, char*** pfargv) { FILE* fp; int c; int bInQuotes = 0; char optbuff[1024]; char* poptbuff; int fargc=0; int back; char* fargv[PARALIMIT]; char** pfa; pfa = *pfargv = malloc(sizeof(fargv)); poptbuff = &optbuff[0]; filename++; if ((fp = fopen(filename, "r")) == NULL) { #if OSL_DEBUG_LEVEL > 1 if ( debug || !bDumpDefs ) perror(filename); #endif return (FALSE); } do { /* * #i27914# double ticks '"' now have a duplicate function: * 1. they define a string ( e.g. -DFOO="baz" ) * 2. a string can contain spaces, so -DFOO="baz zum" defines one * argument no two ! */ c = fgetc(fp); if ( c != ' ' && c != CR && c != NL && c != HT && c != EOF) { *poptbuff++ = (char)c; if( c == '"' ) bInQuotes = ~bInQuotes; } else { if( c != EOF && bInQuotes ) *poptbuff++ = (char)c; else { *poptbuff = EOS; if (strlen(optbuff)>0) { pfa[fargc + 1] = strdup(optbuff); fargc++; pfa[fargc + 1] = 0; poptbuff = &optbuff[0]; } } } } while ( c != EOF ); fclose(fp); back=dooptions(fargc+1,pfa); return (back); } #if HOST != SYS_UNIX /* * Dec operating systems mangle upper-lower case in command lines. * This routine forces the -D and -U arguments to uppercase. * It is called only on cpp startup by dooptions(). */ FILE_LOCAL void zap_uc(char* ap) { while (*ap != EOS) { /* * Don't use islower() here so it works with Multinational */ if (*ap >= 'a' && *ap <= 'z') *ap = (char)toupper(*ap); ap++; } } #endif /* * Initialize the built-in #define's. There are two flavors: * #define decus 1 (static definitions) * #define __FILE__ ?? (dynamic, evaluated by magic) * Called only on cpp startup. * * Note: the built-in static definitions are suppressed by the -N option. * __LINE__, __FILE__, and __DATE__ are always present. */ void initdefines() { char** pp; char* tp; DEFBUF* dp; int i; time_t tvec; /* * Predefine the built-in symbols. Allow the * implementor to pre-define a symbol as "" to * eliminate it. */ if (nflag == 0) { for (pp = preset; *pp != NULL; pp++) { if (*pp[0] != EOS) { dp = defendel(*pp, FALSE); dp->repl = savestring("1"); dp->nargs = DEF_NOARGS; } } } /* * The magic pre-defines (__FILE__ and __LINE__ are * initialized with negative argument counts. expand() * notices this and calls the appropriate routine. * DEF_NOARGS is one greater than the first "magic" definition. */ if (nflag < 2) { for (pp = magic, i = DEF_NOARGS; *pp != NULL; pp++) { dp = defendel(*pp, FALSE); dp->nargs = --i; } #if OK_DATE /* * Define __DATE__ as today's date. */ dp = defendel("__DATE__", FALSE); dp->repl = tp = getmem(27); dp->nargs = DEF_NOARGS; time( &tvec); *tp++ = '"'; strcpy(tp, ctime(&tvec)); tp[24] = '"'; /* Overwrite newline */ #endif } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */