summaryrefslogtreecommitdiff
path: root/rsc/source/rscpp/cpp3.c
diff options
context:
space:
mode:
Diffstat (limited to 'rsc/source/rscpp/cpp3.c')
-rw-r--r--rsc/source/rscpp/cpp3.c639
1 files changed, 639 insertions, 0 deletions
diff --git a/rsc/source/rscpp/cpp3.c b/rsc/source/rscpp/cpp3.c
new file mode 100644
index 000000000000..a831daf5e3ea
--- /dev/null
+++ b/rsc/source/rscpp/cpp3.c
@@ -0,0 +1,639 @@
+/*************************************************************************
+ *
+ * $RCSfile: cpp3.c,v $
+ *
+ * $Revision: 1.1 $
+ *
+ * last change: $Author: nf $ $Date: 2001-04-18 10:31:56 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (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.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <stdio.h>
+#ifdef UNX
+#include <stdlib.h>
+#endif
+#include <ctype.h>
+#include "cppdef.h"
+#include "cpp.h"
+
+#include "time.h" /* BP */
+
+#ifndef _STRING_H
+#include <string.h>
+#endif
+
+#ifndef _NO_PROTO
+int AddInclude( char *pIncStr ); /* BP, 11.09.91, Forward-Deklaration */
+#endif
+
+#if defined(DEBUG) && (HOST == SYS_VMS || HOST == SYS_UNIX)
+#include <signal.h>
+extern int abort(); /* For debugging */
+#endif
+
+void InitCpp3()
+{
+}
+
+
+int
+openfile(filename)
+char *filename;
+/*
+ * Open a file, add it to the linked list of open files.
+ * This is called only from openfile() above.
+ */
+{
+ register FILE *fp;
+
+ if ((fp = fopen(filename, "r")) == NULL) {
+#ifdef DEBUG
+ if ( debug || !bDumpDefs )
+ perror(filename);
+#endif
+ return (FALSE);
+ }
+#ifdef DEBUG
+ if (debug)
+ fprintf(stderr, "Reading from \"%s\"\n", filename);
+#endif
+ addfile(fp, filename);
+ return (TRUE);
+}
+
+addfile(fp, filename)
+FILE *fp; /* Open file pointer */
+char *filename; /* Name of the file */
+/*
+ * 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.)
+ */
+{
+ register FILEINFO *file;
+/* #ifndef _NO_PROTO */
+ extern FILEINFO *getfile( int bufsize, char *filename ); /* BP */
+/* #endif */
+ 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 */
+}
+
+setincdirs()
+/*
+ * Append system-specific directories to the include directory list.
+ * Called only when cpp is started.
+ */
+{
+
+#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_VMS
+ extern char *getenv();
+
+ if (getenv("C$LIBRARY") != NULL)
+ *incend++ = "C$LIBRARY:";
+ *incend++ = "SYS$LIBRARY:";
+#define MAXINCLUDE (NINCLUDE - 2 - IS_INCLUDE)
+#endif
+
+#if HOST == SYS_RSX
+ extern int $$rsts; /* TRUE on RSTS/E */
+ extern int $$pos; /* TRUE on PRO-350 P/OS */
+ extern int $$vms; /* TRUE on VMS compat. */
+
+ if ($$pos) { /* P/OS? */
+ *incend++ = "SY:[ZZDECUSC]"; /* C #includes */
+ *incend++ = "LB:[1,5]"; /* RSX library */
+ }
+ else if ($$rsts) { /* RSTS/E? */
+ *incend++ = "SY:@"; /* User-defined account */
+ *incend++ = "C:"; /* Decus-C library */
+ *incend++ = "LB:[1,1]"; /* RSX library */
+ }
+ else if ($$vms) { /* VMS compatibility? */
+ *incend++ = "C:";
+ }
+ else { /* Plain old RSX/IAS */
+ *incend++ = "LB:[1,1]";
+ }
+#define MAXINCLUDE (NINCLUDE - 3 - IS_INCLUDE)
+#endif
+
+#if HOST == SYS_RT11
+ extern int $$rsts; /* RSTS/E emulation? */
+
+ if ($$rsts)
+ *incend++ = "SY:@"; /* User-defined account */
+ *incend++ = "C:"; /* Decus-C library disk */
+ *incend++ = "SY:"; /* System (boot) disk */
+#define MAXINCLUDE (NINCLUDE - 3 - IS_INCLUDE)
+#endif
+
+#if HOST == SYS_UNKNOWN
+/*
+ * BP: 25.07.91, 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( ZTC ) && !defined( WNT ) && !defined(BLC) && ! 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
+
+
+}
+
+/* BP: 11.09.91, 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( pIncStr )
+ 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 );
+}
+
+
+
+
+int
+dooptions(argc, argv)
+int argc;
+char *argv[];
+/*
+ * dooptions is called to process command line arguments (-Detc).
+ * It is called only at cpp startup.
+ */
+{
+ register char *ap;
+ register DEFBUF *dp;
+ register 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 HOST != SYS_UNIX
+ zap_uc(ap); /* Force define to U.C. */
+#endif
+ /*
+ * 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 (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 HOST != SYS_UNIX
+ zap_uc(ap);
+#endif
+ if (defendel(ap, TRUE) == NULL)
+ cwarn("\"%s\" wasn't defined", ap);
+ break;
+
+#ifdef DEBUG
+ case 'X': /* Debug */
+ debug = (isdigit(*ap)) ? atoi(ap) : 1;
+#if (HOST == SYS_VMS || HOST == SYS_UNIX)
+ signal(SIGINT, abort); /* Trap "interrupt" */
+#endif
+ fprintf(stderr, "Debug set to %d\n", debug);
+ break;
+#endif
+
+#ifdef DEBUG
+ 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");
+#ifdef DEBUG
+ 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 */
+#ifdef DEBUG
+ 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;
+ char optbuff[1024], *poptbuff;
+ int fargc=0, endit=FALSE, i, back;
+ char *fargv[PARALIMIT], **pfa;
+
+ pfa=*pfargv=malloc(sizeof(fargv));
+
+ poptbuff=&optbuff[0];
+ filename++;
+ if ((fp = fopen(filename, "r")) == NULL) {
+#ifdef DEBUG
+ if ( debug || !bDumpDefs )
+ perror(filename);
+#endif
+ return (FALSE);
+ }
+ do
+ {
+ c=fgetc(fp);
+ if ( c != ' ' && c != CR && c != NL && c != HT && c != EOF)
+ {
+ *poptbuff++=c;
+ }
+ else
+ {
+/*
+ if ( c == EOF )
+ {
+ endit=TRUE;
+ }
+*/
+ *poptbuff=EOS;
+ if (strlen(optbuff)>0)
+ {
+ pfa[fargc+1]=malloc(strlen(optbuff)+1);
+ strcpy(pfa[fargc+1],optbuff);
+ fargc++;
+ pfa[fargc+1]=0;
+ poptbuff=&optbuff[0];
+ }
+ }
+ }
+/* while ( !endit );
+ */
+ while ( c != EOF );
+
+ fclose(fp);
+ back=dooptions(fargc+1,pfa);
+
+ return (back);
+}
+
+
+
+#if HOST != SYS_UNIX
+FILE_LOCAL
+zap_uc(ap)
+register char *ap;
+/*
+ * 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().
+ */
+{
+ while (*ap != EOS) {
+ /*
+ * Don't use islower() here so it works with Multinational
+ */
+ if (*ap >= 'a' && *ap <= 'z')
+ *ap = toupper(*ap);
+ ap++;
+ }
+}
+#endif
+
+initdefines()
+/*
+ * 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 supressed by the -N option.
+ * __LINE__, __FILE__, and __DATE__ are always present.
+ */
+{
+ register char **pp;
+ register char *tp;
+ register DEFBUF *dp;
+ int i;
+ long tvec;
+
+#if !defined( ZTC ) && !defined( WNT ) && !defined(BLC) && !defined(G3)
+ extern char *ctime();
+#endif
+
+ /*
+ * 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;
+#ifdef MAC /* MA */
+ time( (time_t*)&tvec);
+#else
+ time(&tvec);
+#endif
+ *tp++ = '"';
+ strcpy(tp, ctime(&tvec));
+ tp[24] = '"'; /* Overwrite newline */
+#endif
+ }
+}
+
+#if HOST == SYS_VMS
+/*
+ * getredirection() is intended to aid in porting C programs
+ * to VMS (Vax-11 C) which does not support '>' and '<'
+ * I/O redirection. With suitable modification, it may
+ * useful for other portability problems as well.
+ */
+
+int
+getredirection(argc, argv)
+int argc;
+char **argv;
+/*
+ * Process vms redirection arg's. Exit if any error is seen.
+ * If getredirection() processes an argument, it is erased
+ * from the vector. getredirection() returns a new argc value.
+ *
+ * Warning: do not try to simplify the code for vms. The code
+ * presupposes that getredirection() is called before any data is
+ * read from stdin or written to stdout.
+ *
+ * Normal usage is as follows:
+ *
+ * main(argc, argv)
+ * int argc;
+ * char *argv[];
+ * {
+ * argc = getredirection(argc, argv);
+ * }
+ */
+{
+ register char *ap; /* Argument pointer */
+ int i; /* argv[] index */
+ int j; /* Output index */
+ int file; /* File_descriptor */
+ extern int errno; /* Last vms i/o error */
+
+ for (j = i = 1; i < argc; i++) { /* Do all arguments */
+ switch (*(ap = argv[i])) {
+ case '<': /* <file */
+ if (freopen(++ap, "r", stdin) == NULL) {
+ perror(ap); /* Can't find file */
+ exit(errno); /* Is a fatal error */
+ }
+ break;
+
+ case '>': /* >file or >>file */
+ if (*++ap == '>') { /* >>file */
+ /*
+ * If the file exists, and is writable by us,
+ * call freopen to append to the file (using the
+ * file's current attributes). Otherwise, create
+ * a new file with "vanilla" attributes as if the
+ * argument was given as ">filename".
+ * access(name, 2) returns zero if we can write on
+ * the specified file.
+ */
+ if (access(++ap, 2) == 0) {
+ if (freopen(ap, "a", stdout) != NULL)
+ break; /* Exit case statement */
+ perror(ap); /* Error, can't append */
+ exit(errno); /* After access test */
+ } /* If file accessable */
+ }
+ /*
+ * On vms, we want to create the file using "standard"
+ * record attributes. creat(...) creates the file
+ * using the caller's default protection mask and
+ * "variable length, implied carriage return"
+ * attributes. dup2() associates the file with stdout.
+ */
+ if ((file = creat(ap, 0, "rat=cr", "rfm=var")) == -1
+ || dup2(file, fileno(stdout)) == -1) {
+ perror(ap); /* Can't create file */
+ exit(errno); /* is a fatal error */
+ } /* If '>' creation */
+ break; /* Exit case test */
+
+ default:
+ argv[j++] = ap; /* Not a redirector */
+ break; /* Exit case test */
+ }
+ } /* For all arguments */
+ argv[j] = NULL; /* Terminate argv[] */
+ return (j); /* Return new argc */
+}
+#endif
+