1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
30 #if defined(_MSC_VER) && (_MSC_VER > 1310)
31 #define _USE_32BIT_TIME_T
42 #include "time.h" /* BP */
49 int AddInclude( char *pIncStr
); /* BP, 11.09.91, Forward-Deklaration */
52 #if (OSL_DEBUG_LEVEL > 1) && (HOST == SYS_VMS || HOST == SYS_UNIX)
62 openfile(char* filename
)
64 * Open a file, add it to the linked list of open files.
65 * This is called only from openfile() above.
70 if ((fp
= fopen(filename
, "r")) == NULL
) {
71 #if OSL_DEBUG_LEVEL > 1
72 if ( debug
|| !bDumpDefs
)
77 #if OSL_DEBUG_LEVEL > 1
79 fprintf(stderr
, "Reading from \"%s\"\n", filename
);
81 addfile(fp
, filename
);
85 void addfile(FILE* fp
, char* filename
)
87 * Initialize tables for this open file. This is called from openfile()
88 * above (for #include files), and from the entry to cpp to open the main
89 * input file. It calls a common routine, getfile() to build the FILEINFO
90 * structure which is used to read characters. (getfile() is also called
91 * to setup a macro replacement.)
94 register FILEINFO
*file
;
95 /* #ifndef _NO_PROTO */
96 extern FILEINFO
*getfile( int bufsize
, char *filename
); /* BP */
98 file
= getfile(NBUFF
, filename
);
99 file
->fp
= fp
; /* Better remember FILE * */
100 file
->buffer
[0] = EOS
; /* Initialize for first read */
101 line
= 1; /* Working on line 1 now */
102 wrongline
= TRUE
; /* Force out initial #line */
107 * Append system-specific directories to the include directory list.
108 * Called only when cpp is started.
113 *incend
++ = CPP_INCLUDE
;
120 *incend
++ = "/usr/include";
121 #define MAXINCLUDE (NINCLUDE - 1 - IS_INCLUDE)
125 extern char *getenv();
127 if (getenv("C$LIBRARY") != NULL
)
128 *incend
++ = "C$LIBRARY:";
129 *incend
++ = "SYS$LIBRARY:";
130 #define MAXINCLUDE (NINCLUDE - 2 - IS_INCLUDE)
134 extern int $$rsts
; /* TRUE on RSTS/E */
135 extern int $$pos
; /* TRUE on PRO-350 P/OS */
136 extern int $$vms
; /* TRUE on VMS compat. */
138 if ($$pos
) { /* P/OS? */
139 *incend
++ = "SY:[ZZDECUSC]"; /* C #includes */
140 *incend
++ = "LB:[1,5]"; /* RSX library */
142 else if ($$rsts
) { /* RSTS/E? */
143 *incend
++ = "SY:@"; /* User-defined account */
144 *incend
++ = "C:"; /* Decus-C library */
145 *incend
++ = "LB:[1,1]"; /* RSX library */
147 else if ($$vms
) { /* VMS compatibility? */
150 else { /* Plain old RSX/IAS */
151 *incend
++ = "LB:[1,1]";
153 #define MAXINCLUDE (NINCLUDE - 3 - IS_INCLUDE)
157 extern int $$rsts
; /* RSTS/E emulation? */
160 *incend
++ = "SY:@"; /* User-defined account */
161 *incend
++ = "C:"; /* Decus-C library disk */
162 *incend
++ = "SY:"; /* System (boot) disk */
163 #define MAXINCLUDE (NINCLUDE - 3 - IS_INCLUDE)
166 #if HOST == SYS_UNKNOWN
168 * BP: 25.07.91, Kontext: GenMake
169 * Unter DOS wird nun auch die Environment-Variable INCLUDE ausgewetet.
170 * Es kommt erschwerend hinzu, dass alle Eintraege, die mit ';' getrennt
171 * sind, mit in die Liste aufenommen werden muessen.
172 * Dies wird mit der Funktion strtok() realisiert.
173 * Vorsicht bei der Benutzung von malloc !!!
174 * In savestring wird naemlich getmem() verwendet. Vermutlich kommen sich
175 * die beiden Funktion in die Quere. Als ich malloc statt savestring
176 * verwendete knallte es in strcpy() !
179 #if !defined( ZTC ) && !defined( WNT ) && !defined(BLC) && ! defined UNX && ! defined OS2
180 extern char *getenv( char *pStr
); /* BP */
182 char *pIncGetEnv
= NULL
; /* Pointer auf INCLUDE */
184 if ( ( pIncGetEnv
= getenv("INCLUDE") ) != NULL
)
185 AddInclude( pIncGetEnv
);
187 #define MAXINCLUDE (NINCLUDE - 3 - IS_INCLUDE)
193 /* BP: 11.09.91, Kontext: Erweiterung des INCLUDE-Services
194 * Bislang konnte der cpp keine Include-Angaben in der Kommandozeile
195 * vertragen, bei denen die directries mit ';' getrennt wurden.
196 * Dies ist auch verstaendlich, da dieses cpp fuer UNIX-Systeme
197 * massgeschneidert wurde und in UNI die ';' als Zeichen zum Abschluss
198 * von Kommandos gilt.
201 int AddInclude( char* pIncStr
)
203 char *pIncEnv
= NULL
; /* Kopie des INCLUDE */
204 char *pIncPos
; /* wandert zum naechsten */
206 pIncEnv
= savestring( pIncStr
);
207 pIncPos
= strtok( pIncEnv
, ";" );
209 while( pIncPos
!= NULL
)
211 if (incend
>= &incdir
[MAXINCLUDE
])
212 cfatal("Too many include directories", NULLST
);
214 pIncPos
= strtok( NULL
, ";" );
223 dooptions(int argc
, char** argv
)
225 * dooptions is called to process command line arguments (-Detc).
226 * It is called only at cpp startup.
234 SIZES
*sizp
; /* For -S */
235 int size
; /* For -S */
236 int isdatum
; /* FALSE for -S* */
237 int endtest
; /* For -S */
239 for (i
= j
= 1; i
< argc
; i
++) {
242 if (*ap
++ != '-' || *ap
== EOS
)
247 c
= *ap
++; /* Option byte */
248 if (islower(c
)) /* Normalize case */
250 switch (c
) { /* Command character */
251 case 'C': /* Keep comments */
256 case 'D': /* Define symbol */
258 /* zap_uc(ap); */ /* Force define to U.C. */
261 * If the option is just "-Dfoo", make it -Dfoo=1
263 while (*ap
!= EOS
&& *ap
!= '=')
270 * Now, save the word and its definition.
272 dp
= defendel(argv
[i
] + 2, FALSE
);
273 dp
->repl
= savestring(ap
);
274 dp
->nargs
= DEF_NOARGS
;
277 case 'E': /* Ignore non-fatal */
278 eflag
= TRUE
; /* errors. */
281 case 'I': /* Include directory */
282 AddInclude( ap
); /* BP, 11.09.91 */
285 case 'N': /* No predefineds */
286 nflag
++; /* Repeat to undefine */
287 break; /* __LINE__, etc. */
291 if (0 != (isdatum
= (*ap
!= '*'))) /* If it's just -S, */
292 endtest
= T_FPTR
; /* Stop here */
293 else { /* But if it's -S* */
294 ap
++; /* Step over '*' */
295 endtest
= 0; /* Stop at end marker */
297 while (sizp
->bits
!= endtest
&& *ap
!= EOS
) {
298 if (!isdigit(*ap
)) { /* Skip to next digit */
302 size
= 0; /* Compile the value */
303 while (isdigit(*ap
)) {
305 size
+= (*ap
++ - '0');
308 sizp
->size
= size
; /* Datum size */
310 sizp
->psize
= size
; /* Pointer size */
313 if (sizp
->bits
!= endtest
)
314 cwarn("-S, too few values specified in %s", argv
[i
]);
316 cwarn("-S, too many values, \"%s\" unused", ap
);
319 case 'U': /* Undefine symbol */
323 if (defendel(ap
, TRUE
) == NULL
)
324 cwarn("\"%s\" wasn't defined", ap
);
327 #if OSL_DEBUG_LEVEL > 1
328 case 'X': /* Debug */
329 debug
= (isdigit(*ap
)) ? atoi(ap
) : 1;
330 #if (HOST == SYS_VMS || HOST == SYS_UNIX)
331 signal(SIGINT
, (void (*)(int)) abort
); /* Trap "interrupt" */
333 fprintf(stderr
, "Debug set to %d\n", debug
);
337 #if OSL_DEBUG_LEVEL > 1
338 case 'P': /* #define's dump */
340 fprintf(stderr
, "Dump #define's is on\n");
344 default: /* What is this one? */
345 cwarn("Unknown option \"%s\"", arg
);
346 fprintf(stderr
, "The following options are valid:\n\
347 -C\t\t\tWrite source file comments to output\n\
348 -Dsymbol=value\tDefine a symbol with the given (optional) value\n\
349 -Idirectory\t\tAdd a directory to the #include search list\n\
350 -N\t\t\tDon't predefine target-specific names\n\
351 -Stext\t\tSpecify sizes for #if sizeof\n\
352 -Usymbol\t\tUndefine symbol\n");
353 #if OSL_DEBUG_LEVEL > 1
354 fprintf(stderr
, " -Xvalue\t\tSet internal debug flag\n");
355 fprintf(stderr
, " -P\t\t\tdump #define's\n");
358 } /* Switch on all options */
359 } /* If it's a -option */
360 } /* For all arguments */
361 #if OSL_DEBUG_LEVEL > 1
362 if ( (bDumpDefs
? j
> 4 : j
> 3) ) {
367 "Too many file arguments. Usage: cpp [input [output]]",
370 return (j
); /* Return new argc */
374 readoptions(char* filename
, char*** pfargv
)
379 char optbuff
[1024], *poptbuff
;
381 char *fargv
[PARALIMIT
], **pfa
;
383 pfa
=*pfargv
=malloc(sizeof(fargv
));
385 poptbuff
=&optbuff
[0];
387 if ((fp
= fopen(filename
, "r")) == NULL
) {
388 #if OSL_DEBUG_LEVEL > 1
389 if ( debug
|| !bDumpDefs
)
397 * #i27914# double ticks '"' now have a duplicate function:
398 * 1. they define a string ( e.g. -DFOO="baz" )
399 * 2. a string can contain spaces, so -DFOO="baz zum" defines one
403 if ( c
!= ' ' && c
!= CR
&& c
!= NL
&& c
!= HT
&& c
!= EOF
)
407 bInQuotes
= ~bInQuotes
;
411 if( c
!= EOF
&& bInQuotes
)
416 if (strlen(optbuff
)>0)
418 pfa
[fargc
+1]=malloc(strlen(optbuff
)+1);
419 strcpy(pfa
[fargc
+1],optbuff
);
422 poptbuff
=&optbuff
[0];
430 back
=dooptions(fargc
+1,pfa
);
441 * Dec operating systems mangle upper-lower case in command lines.
442 * This routine forces the -D and -U arguments to uppercase.
443 * It is called only on cpp startup by dooptions().
448 * Don't use islower() here so it works with Multinational
450 if (*ap
>= 'a' && *ap
<= 'z')
451 *ap
= (char)toupper(*ap
);
459 * Initialize the built-in #define's. There are two flavors:
460 * #define decus 1 (static definitions)
461 * #define __FILE__ ?? (dynamic, evaluated by magic)
462 * Called only on cpp startup.
464 * Note: the built-in static definitions are supressed by the -N option.
465 * __LINE__, __FILE__, and __DATE__ are always present.
474 #if !defined( ZTC ) && !defined( WNT ) && !defined(BLC) && !defined(G3)
475 extern char *ctime();
479 * Predefine the built-in symbols. Allow the
480 * implementor to pre-define a symbol as "" to
484 for (pp
= preset
; *pp
!= NULL
; pp
++) {
486 dp
= defendel(*pp
, FALSE
);
487 dp
->repl
= savestring("1");
488 dp
->nargs
= DEF_NOARGS
;
493 * The magic pre-defines (__FILE__ and __LINE__ are
494 * initialized with negative argument counts. expand()
495 * notices this and calls the appropriate routine.
496 * DEF_NOARGS is one greater than the first "magic" definition.
499 for (pp
= magic
, i
= DEF_NOARGS
; *pp
!= NULL
; pp
++) {
500 dp
= defendel(*pp
, FALSE
);
505 * Define __DATE__ as today's date.
507 dp
= defendel("__DATE__", FALSE
);
508 dp
->repl
= tp
= getmem(27);
509 dp
->nargs
= DEF_NOARGS
;
510 time( (time_t*)&tvec
);
512 strcpy(tp
, ctime((const time_t*)&tvec
));
513 tp
[24] = '"'; /* Overwrite newline */
520 * getredirection() is intended to aid in porting C programs
521 * to VMS (Vax-11 C) which does not support '>' and '<'
522 * I/O redirection. With suitable modification, it may
523 * useful for other portability problems as well.
527 getredirection(argc
, argv
)
531 * Process vms redirection arg's. Exit if any error is seen.
532 * If getredirection() processes an argument, it is erased
533 * from the vector. getredirection() returns a new argc value.
535 * Warning: do not try to simplify the code for vms. The code
536 * presupposes that getredirection() is called before any data is
537 * read from stdin or written to stdout.
539 * Normal usage is as follows:
545 * argc = getredirection(argc, argv);
549 register char *ap
; /* Argument pointer */
550 int i
; /* argv[] index */
551 int j
; /* Output index */
552 int file
; /* File_descriptor */
553 extern int errno
; /* Last vms i/o error */
555 for (j
= i
= 1; i
< argc
; i
++) { /* Do all arguments */
556 switch (*(ap
= argv
[i
])) {
557 case '<': /* <file */
558 if (freopen(++ap
, "r", stdin
) == NULL
) {
559 perror(ap
); /* Can't find file */
560 exit(errno
); /* Is a fatal error */
564 case '>': /* >file or >>file */
565 if (*++ap
== '>') { /* >>file */
567 * If the file exists, and is writable by us,
568 * call freopen to append to the file (using the
569 * file's current attributes). Otherwise, create
570 * a new file with "vanilla" attributes as if the
571 * argument was given as ">filename".
572 * access(name, 2) returns zero if we can write on
573 * the specified file.
575 if (access(++ap
, 2) == 0) {
576 if (freopen(ap
, "a", stdout
) != NULL
)
577 break; /* Exit case statement */
578 perror(ap
); /* Error, can't append */
579 exit(errno
); /* After access test */
580 } /* If file accessable */
583 * On vms, we want to create the file using "standard"
584 * record attributes. creat(...) creates the file
585 * using the caller's default protection mask and
586 * "variable length, implied carriage return"
587 * attributes. dup2() associates the file with stdout.
589 if ((file
= creat(ap
, 0, "rat=cr", "rfm=var")) == -1
590 || dup2(file
, fileno(stdout
)) == -1) {
591 perror(ap
); /* Can't create file */
592 exit(errno
); /* is a fatal error */
593 } /* If '>' creation */
594 break; /* Exit case test */
597 argv
[j
++] = ap
; /* Not a redirector */
598 break; /* Exit case test */
600 } /* For all arguments */
601 argv
[j
] = NULL
; /* Terminate argv[] */
602 return (j
); /* Return new argc */