1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
27 #include "time.h" /* BP */
32 int AddInclude( char *pIncStr
); /* BP, 11.09.91, Forward-Deklaration */
35 #if (OSL_DEBUG_LEVEL > 1) && (HOST == SYS_VMS || HOST == SYS_UNIX)
45 openfile(char* filename
)
47 * Open a file, add it to the linked list of open files.
48 * This is called only from openfile() above.
53 if ((fp
= fopen(filename
, "r")) == NULL
) {
54 #if OSL_DEBUG_LEVEL > 1
55 if ( debug
|| !bDumpDefs
)
60 #if OSL_DEBUG_LEVEL > 1
62 fprintf(stderr
, "Reading from \"%s\"\n", filename
);
64 addfile(fp
, filename
);
68 void addfile(FILE* fp
, char* filename
)
70 * Initialize tables for this open file. This is called from openfile()
71 * above (for #include files), and from the entry to cpp to open the main
72 * input file. It calls a common routine, getfile() to build the FILEINFO
73 * structure which is used to read characters. (getfile() is also called
74 * to setup a macro replacement.)
77 register FILEINFO
*file
;
78 extern FILEINFO
*getfile( int, char * );
79 file
= getfile(NBUFF
, filename
);
80 file
->fp
= fp
; /* Better remember FILE * */
81 file
->buffer
[0] = EOS
; /* Initialize for first read */
82 line
= 1; /* Working on line 1 now */
83 wrongline
= TRUE
; /* Force out initial #line */
88 * Append system-specific directories to the include directory list.
89 * Called only when cpp is started.
94 *incend
++ = CPP_INCLUDE
;
101 *incend
++ = "/usr/include";
102 #define MAXINCLUDE (NINCLUDE - 1 - IS_INCLUDE)
106 extern char *getenv();
108 if (getenv("C$LIBRARY") != NULL
)
109 *incend
++ = "C$LIBRARY:";
110 *incend
++ = "SYS$LIBRARY:";
111 #define MAXINCLUDE (NINCLUDE - 2 - IS_INCLUDE)
115 extern int $$rsts
; /* TRUE on RSTS/E */
116 extern int $$pos
; /* TRUE on PRO-350 P/OS */
117 extern int $$vms
; /* TRUE on VMS compat. */
119 if ($$pos
) { /* P/OS? */
120 *incend
++ = "SY:[ZZDECUSC]"; /* C #includes */
121 *incend
++ = "LB:[1,5]"; /* RSX library */
123 else if ($$rsts
) { /* RSTS/E? */
124 *incend
++ = "SY:@"; /* User-defined account */
125 *incend
++ = "C:"; /* Decus-C library */
126 *incend
++ = "LB:[1,1]"; /* RSX library */
128 else if ($$vms
) { /* VMS compatibility? */
131 else { /* Plain old RSX/IAS */
132 *incend
++ = "LB:[1,1]";
134 #define MAXINCLUDE (NINCLUDE - 3 - IS_INCLUDE)
138 extern int $$rsts
; /* RSTS/E emulation? */
141 *incend
++ = "SY:@"; /* User-defined account */
142 *incend
++ = "C:"; /* Decus-C library disk */
143 *incend
++ = "SY:"; /* System (boot) disk */
144 #define MAXINCLUDE (NINCLUDE - 3 - IS_INCLUDE)
147 #if HOST == SYS_UNKNOWN
150 * Unter DOS wird nun auch die Environment-Variable INCLUDE ausgewetet.
151 * Es kommt erschwerend hinzu, dass alle Eintraege, die mit ';' getrennt
152 * sind, mit in die Liste aufenommen werden muessen.
153 * Dies wird mit der Funktion strtok() realisiert.
154 * Vorsicht bei der Benutzung von malloc !!!
155 * In savestring wird naemlich getmem() verwendet. Vermutlich kommen sich
156 * die beiden Funktion in die Quere. Als ich malloc statt savestring
157 * verwendete knallte es in strcpy() !
160 #if !defined( WNT ) && ! defined UNX
161 extern char *getenv( char *pStr
); /* BP */
163 char *pIncGetEnv
= NULL
; /* Pointer auf INCLUDE */
165 if ( ( pIncGetEnv
= getenv("INCLUDE") ) != NULL
)
166 AddInclude( pIncGetEnv
);
168 #define MAXINCLUDE (NINCLUDE - 3 - IS_INCLUDE)
174 /* Kontext: Erweiterung des INCLUDE-Services
175 * Bislang konnte der cpp keine Include-Angaben in der Kommandozeile
176 * vertragen, bei denen die directries mit ';' getrennt wurden.
177 * Dies ist auch verstaendlich, da dieses cpp fuer UNIX-Systeme
178 * massgeschneidert wurde und in UNI die ';' als Zeichen zum Abschluss
179 * von Kommandos gilt.
182 int AddInclude( char* pIncStr
)
184 char *pIncEnv
= NULL
; /* Kopie des INCLUDE */
185 char *pIncPos
; /* wandert zum naechsten */
187 pIncEnv
= savestring( pIncStr
);
188 pIncPos
= strtok( pIncEnv
, ";" );
190 while( pIncPos
!= NULL
)
192 if (incend
>= &incdir
[MAXINCLUDE
])
193 cfatal("Too many include directories", NULLST
);
195 pIncPos
= strtok( NULL
, ";" );
201 dooptions(int argc
, char** argv
)
203 * dooptions is called to process command line arguments (-Detc).
204 * It is called only at cpp startup.
212 SIZES
*sizp
; /* For -S */
213 int size
; /* For -S */
214 int isdatum
; /* FALSE for -S* */
215 int endtest
; /* For -S */
217 for (i
= j
= 1; i
< argc
; i
++) {
220 if (*ap
++ != '-' || *ap
== EOS
)
225 c
= *ap
++; /* Option byte */
226 if (islower(c
)) /* Normalize case */
228 switch (c
) { /* Command character */
229 case 'C': /* Keep comments */
234 case 'D': /* Define symbol */
236 * If the option is just "-Dfoo", make it -Dfoo=1
238 while (*ap
!= EOS
&& *ap
!= '=')
245 * Now, save the word and its definition.
247 dp
= defendel(argv
[i
] + 2, FALSE
);
248 dp
->repl
= savestring(ap
);
249 dp
->nargs
= DEF_NOARGS
;
252 case 'E': /* Ignore non-fatal */
253 eflag
= TRUE
; /* errors. */
256 case 'I': /* Include directory */
257 AddInclude( ap
); /* BP, 11.09.91 */
260 case 'N': /* No predefineds */
261 nflag
++; /* Repeat to undefine */
262 break; /* __LINE__, etc. */
266 if (0 != (isdatum
= (*ap
!= '*'))) /* If it's just -S, */
267 endtest
= T_FPTR
; /* Stop here */
268 else { /* But if it's -S* */
269 ap
++; /* Step over '*' */
270 endtest
= 0; /* Stop at end marker */
272 while (sizp
->bits
!= endtest
&& *ap
!= EOS
) {
273 if (!isdigit(*ap
)) { /* Skip to next digit */
277 size
= 0; /* Compile the value */
278 while (isdigit(*ap
)) {
280 size
+= (*ap
++ - '0');
283 sizp
->size
= size
; /* Datum size */
285 sizp
->psize
= size
; /* Pointer size */
288 if (sizp
->bits
!= endtest
)
289 cwarn("-S, too few values specified in %s", argv
[i
]);
291 cwarn("-S, too many values, \"%s\" unused", ap
);
294 case 'U': /* Undefine symbol */
295 if (defendel(ap
, TRUE
) == NULL
)
296 cwarn("\"%s\" wasn't defined", ap
);
299 #if OSL_DEBUG_LEVEL > 1
300 case 'X': /* Debug */
301 debug
= (isdigit(*ap
)) ? atoi(ap
) : 1;
302 #if (HOST == SYS_VMS || HOST == SYS_UNIX)
303 signal(SIGINT
, (void (*)(int)) abort
); /* Trap "interrupt" */
305 fprintf(stderr
, "Debug set to %d\n", debug
);
309 #if OSL_DEBUG_LEVEL > 1
310 case 'P': /* #define's dump */
312 fprintf(stderr
, "Dump #define's is on\n");
316 default: /* What is this one? */
317 cwarn("Unknown option \"%s\"", arg
);
318 fprintf(stderr
, "The following options are valid:\n\
319 -C\t\t\tWrite source file comments to output\n\
320 -Dsymbol=value\tDefine a symbol with the given (optional) value\n\
321 -Idirectory\t\tAdd a directory to the #include search list\n\
322 -N\t\t\tDon't predefine target-specific names\n\
323 -Stext\t\tSpecify sizes for #if sizeof\n\
324 -Usymbol\t\tUndefine symbol\n");
325 #if OSL_DEBUG_LEVEL > 1
326 fprintf(stderr
, " -Xvalue\t\tSet internal debug flag\n");
327 fprintf(stderr
, " -P\t\t\tdump #define's\n");
330 } /* Switch on all options */
331 } /* If it's a -option */
332 } /* For all arguments */
333 #if OSL_DEBUG_LEVEL > 1
334 if ( (bDumpDefs
? j
> 4 : j
> 3) ) {
339 "Too many file arguments. Usage: cpp [input [output]]",
342 return (j
); /* Return new argc */
346 readoptions(char* filename
, char*** pfargv
)
351 char optbuff
[1024], *poptbuff
;
353 char *fargv
[PARALIMIT
], **pfa
;
355 pfa
=*pfargv
=malloc(sizeof(fargv
));
357 poptbuff
=&optbuff
[0];
359 if ((fp
= fopen(filename
, "r")) == NULL
) {
360 #if OSL_DEBUG_LEVEL > 1
361 if ( debug
|| !bDumpDefs
)
369 * #i27914# double ticks '"' now have a duplicate function:
370 * 1. they define a string ( e.g. -DFOO="baz" )
371 * 2. a string can contain spaces, so -DFOO="baz zum" defines one
375 if ( c
!= ' ' && c
!= CR
&& c
!= NL
&& c
!= HT
&& c
!= EOF
)
379 bInQuotes
= ~bInQuotes
;
383 if( c
!= EOF
&& bInQuotes
)
388 if (strlen(optbuff
)>0)
390 pfa
[fargc
+1]=malloc(strlen(optbuff
)+1);
391 strcpy(pfa
[fargc
+1],optbuff
);
394 poptbuff
=&optbuff
[0];
402 back
=dooptions(fargc
+1,pfa
);
411 * Dec operating systems mangle upper-lower case in command lines.
412 * This routine forces the -D and -U arguments to uppercase.
413 * It is called only on cpp startup by dooptions().
418 * Don't use islower() here so it works with Multinational
420 if (*ap
>= 'a' && *ap
<= 'z')
421 *ap
= (char)toupper(*ap
);
429 * Initialize the built-in #define's. There are two flavors:
430 * #define decus 1 (static definitions)
431 * #define __FILE__ ?? (dynamic, evaluated by magic)
432 * Called only on cpp startup.
434 * Note: the built-in static definitions are supressed by the -N option.
435 * __LINE__, __FILE__, and __DATE__ are always present.
444 #if !defined( WNT ) && !defined(G3)
445 extern char *ctime();
449 * Predefine the built-in symbols. Allow the
450 * implementor to pre-define a symbol as "" to
454 for (pp
= preset
; *pp
!= NULL
; pp
++) {
456 dp
= defendel(*pp
, FALSE
);
457 dp
->repl
= savestring("1");
458 dp
->nargs
= DEF_NOARGS
;
463 * The magic pre-defines (__FILE__ and __LINE__ are
464 * initialized with negative argument counts. expand()
465 * notices this and calls the appropriate routine.
466 * DEF_NOARGS is one greater than the first "magic" definition.
469 for (pp
= magic
, i
= DEF_NOARGS
; *pp
!= NULL
; pp
++) {
470 dp
= defendel(*pp
, FALSE
);
475 * Define __DATE__ as today's date.
477 dp
= defendel("__DATE__", FALSE
);
478 dp
->repl
= tp
= getmem(27);
479 dp
->nargs
= DEF_NOARGS
;
482 strcpy(tp
, ctime(&tvec
));
483 tp
[24] = '"'; /* Overwrite newline */
490 * getredirection() is intended to aid in porting C programs
491 * to VMS (Vax-11 C) which does not support '>' and '<'
492 * I/O redirection. With suitable modification, it may
493 * useful for other portability problems as well.
497 getredirection(argc
, argv
)
501 * Process vms redirection arg's. Exit if any error is seen.
502 * If getredirection() processes an argument, it is erased
503 * from the vector. getredirection() returns a new argc value.
505 * Warning: do not try to simplify the code for vms. The code
506 * presupposes that getredirection() is called before any data is
507 * read from stdin or written to stdout.
509 * Normal usage is as follows:
515 * argc = getredirection(argc, argv);
519 register char *ap
; /* Argument pointer */
520 int i
; /* argv[] index */
521 int j
; /* Output index */
522 int file
; /* File_descriptor */
523 extern int errno
; /* Last vms i/o error */
525 for (j
= i
= 1; i
< argc
; i
++) { /* Do all arguments */
526 switch (*(ap
= argv
[i
])) {
527 case '<': /* <file */
528 if (freopen(++ap
, "r", stdin
) == NULL
) {
529 perror(ap
); /* Can't find file */
530 exit(errno
); /* Is a fatal error */
534 case '>': /* >file or >>file */
535 if (*++ap
== '>') { /* >>file */
537 * If the file exists, and is writable by us,
538 * call freopen to append to the file (using the
539 * file's current attributes). Otherwise, create
540 * a new file with "vanilla" attributes as if the
541 * argument was given as ">filename".
542 * access(name, 2) returns zero if we can write on
543 * the specified file.
545 if (access(++ap
, 2) == 0) {
546 if (freopen(ap
, "a", stdout
) != NULL
)
547 break; /* Exit case statement */
548 perror(ap
); /* Error, can't append */
549 exit(errno
); /* After access test */
550 } /* If file accessible */
553 * On vms, we want to create the file using "standard"
554 * record attributes. creat(...) creates the file
555 * using the caller's default protection mask and
556 * "variable length, implied carriage return"
557 * attributes. dup2() associates the file with stdout.
559 if ((file
= creat(ap
, 0, "rat=cr", "rfm=var")) == -1
560 || dup2(file
, fileno(stdout
)) == -1) {
561 perror(ap
); /* Can't create file */
562 exit(errno
); /* is a fatal error */
563 } /* If '>' creation */
564 break; /* Exit case test */
567 argv
[j
++] = ap
; /* Not a redirector */
568 break; /* Exit case test */
570 } /* For all arguments */
571 argv
[j
] = NULL
; /* Terminate argv[] */
572 return (j
); /* Return new argc */
576 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */