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 ************************************************************************/
37 * Include the rms stuff. (We can't just include rms.h as it uses the
38 * VaxC-specific library include syntax that Decus CPP doesn't support.
39 * By including things by hand, we can CPP ourself.)
48 * Generate (by hand-inspection) a set of unique values for each control
49 * operator. Note that this is not guaranteed to work for non-Ascii
50 * machines. CPP won't compile if there are hash conflicts.
53 #define L_assert ('a' + ('s' << 1))
54 #define L_define ('d' + ('f' << 1))
55 #define L_elif ('e' + ('i' << 1))
56 #define L_else ('e' + ('s' << 1))
57 #define L_endif ('e' + ('d' << 1))
58 #define L_if ('i' + (EOS << 1))
59 #define L_ifdef ('i' + ('d' << 1))
60 #define L_ifndef ('i' + ('n' << 1))
61 #define L_include ('i' + ('c' << 1))
62 #define L_line ('l' + ('n' << 1))
63 #define L_nogood (EOS + (EOS << 1)) /* To catch #i */
64 #define L_pragma ('p' + ('a' << 1))
65 #define L_undef ('u' + ('d' << 1))
66 #define L_error ('e' + ('r' << 1)) /* BP 5.3.92, #error */
67 #define MAXLINE 80 /* BP 5.3.92, #error */
68 #if OSL_DEBUG_LEVEL > 1
69 #define L_debug ('d' + ('b' << 1)) /* #debug */
70 #define L_nodebug ('n' + ('d' << 1)) /* #nodebug */
83 * Process #control lines. Simple commands are processed inline,
84 * while complex commands have their own subroutines.
86 * The counter is used to force out a newline before #line, and
87 * #pragma commands. This prevents these commands from ending up at
88 * the end of the previous line if cpp is invoked with the -C option.
97 if (c
== '\n' || c
== EOF_CHAR
)
100 scanid(c
); /* Get #word to token[] */
102 unget(); /* Hack -- allow #123 as a */
103 strcpy(token
, "line"); /* synonym for #line 123 */
105 hash
= (token
[1] == EOS
) ? L_nogood
: (token
[0] + (token
[2] << 1));
107 case L_assert
: tp
= "assert"; break;
108 case L_define
: tp
= "define"; break;
109 case L_elif
: tp
= "elif"; break;
110 case L_else
: tp
= "else"; break;
111 case L_endif
: tp
= "endif"; break;
112 case L_if
: tp
= "if"; break;
113 case L_ifdef
: tp
= "ifdef"; break;
114 case L_ifndef
: tp
= "ifndef"; break;
115 case L_include
: tp
= "include"; break;
116 case L_line
: tp
= "line"; break;
117 case L_pragma
: tp
= "pragma"; break;
118 case L_undef
: tp
= "undef"; break;
119 case L_error
: tp
= "error"; break;
120 #if OSL_DEBUG_LEVEL > 1
121 case L_debug
: tp
= "debug"; break;
122 case L_nodebug
: tp
= "nodebug"; break;
124 default: hash
= L_nogood
;
125 case L_nogood
: tp
= ""; break;
127 if (!streq(tp
, token
))
130 * hash is set to a unique value corresponding to the
131 * control keyword (or L_nogood if we think it's nonsense).
133 if (infile
->fp
== NULL
)
134 cwarn("Control line \"%s\" within macro expansion", token
);
135 if (!compiling
) { /* Not compiling now */
137 case L_if
: /* These can't turn */
138 case L_ifdef
: /* compilation on, but */
139 case L_ifndef
: /* we must nest #if's */
140 if (++ifptr
>= &ifstack
[BLK_NEST
])
142 *ifptr
= 0; /* !WAS_COMPILING */
143 case L_line
: /* Many */
145 * Are pragma's always processed?
147 case L_pragma
: /* options */
148 case L_include
: /* are uninteresting */
149 case L_define
: /* if we */
150 case L_undef
: /* aren't */
151 case L_assert
: /* compiling. */
152 case L_error
: /* BP 5.3.92, #error */
153 dump_line
: skipnl(); /* Ignore rest of line */
154 return (counter
+ 1);
158 * Make sure that #line and #pragma are output on a fresh line.
160 if (counter
> 0 && (hash
== L_line
|| hash
== L_pragma
)) {
167 * Parse the line to update the line number and "progname"
168 * field and line number for the next input line.
169 * Set wrongline to force it out later.
172 workp
= work
; /* Save name in work */
173 while (c
!= '\n' && c
!= EOF_CHAR
) {
180 * Split #line argument into <line-number> and <name>
181 * We subtract 1 as we want the number of the next line.
183 line
= atoi(work
) - 1; /* Reset line number */
184 for (tp
= work
; isdigit(*tp
) || type
[(int)*tp
] == SPA
; tp
++)
185 ; /* Skip over digits */
186 if (*tp
!= EOS
) { /* Got a filename, so: */
187 if (*tp
== '"' && (ep
= strrchr(tp
+ 1, '"')) != NULL
) {
188 tp
++; /* Skip over left quote */
189 *ep
= EOS
; /* And ignore right one */
191 if (infile
->progname
!= NULL
) /* Give up the old name */
192 free(infile
->progname
); /* if it's allocated. */
193 infile
->progname
= savestring(tp
);
195 wrongline
= TRUE
; /* Force output later */
211 if (ifptr
== &ifstack
[0])
213 else if ((*ifptr
& ELSE_SEEN
) != 0)
216 if ((*ifptr
& WAS_COMPILING
) != 0) {
217 if (compiling
|| (*ifptr
& TRUE_SEEN
) != 0)
226 if (ifptr
== &ifstack
[0])
228 else if ((*ifptr
& ELSE_SEEN
) != 0) {
229 else_seen_err
: cerror("#%s may not follow #else", token
);
232 if ((*ifptr
& (WAS_COMPILING
| TRUE_SEEN
)) != WAS_COMPILING
) {
233 compiling
= FALSE
; /* Done compiling stuff */
234 goto dump_line
; /* Skip this clause */
242 if (++ifptr
>= &ifstack
[BLK_NEST
])
243 if_nest_err
: cfatal("Too many nested #%s statements", token
);
244 *ifptr
= WAS_COMPILING
;
249 if (ifptr
== &ifstack
[0]) {
250 nest_err
: cerror("#%s must be in an #if", token
);
253 if (!compiling
&& (*ifptr
& WAS_COMPILING
) != 0)
255 compiling
= ((*ifptr
& WAS_COMPILING
) != 0);
261 cerror("Preprocessor assertion failure", NULLST
);
266 * #pragma is provided to pass "options" to later
267 * passes of the compiler. cpp doesn't have any yet.
269 fprintf( pCppOut
, "#pragma ");
270 while ((c
= get()) != '\n' && c
!= EOF_CHAR
)
275 #if OSL_DEBUG_LEVEL > 1
278 dumpdef("debug set on");
286 case L_error
: /* BP 5.3.92, #error */
288 fprintf( pCppOut
, "cpp: line %u, Error directive: ", line
);
289 while ((c
= get()) != '\n' && c
!= EOF_CHAR
)
291 fprintf( pCppOut
, "\n" );
297 * Undefined #control keyword.
298 * Note: the correct behavior may be to warn and
299 * pass the line to a subsequent compiler pass.
300 * This would allow #asm or similar extensions.
302 cerror("Illegal # command \"%s\"", token
);
305 if (hash
!= L_include
) {
308 * Ignore the rest of the #control line so you can write
312 goto dump_line
; /* Take common exit */
314 if (skipws() != '\n') {
315 cwarn("Unexpected text in #control line ignored", NULLST
);
320 return (counter
+ 1);
326 * Process an #if, #ifdef, or #ifndef. The latter two are straightforward,
327 * while #if needs a subroutine of its own to evaluate the expression.
329 * doif() is called only if compiling is TRUE. If false, compilation
330 * is always supressed, so we don't need to evaluate anything. This
331 * supresses unnecessary warnings.
337 if ((c
= skipws()) == '\n' || c
== EOF_CHAR
) {
343 found
= (eval() != 0); /* Evaluate expr, != 0 is TRUE */
344 hash
= L_ifdef
; /* #if is now like #ifdef */
347 if (type
[c
] != LET
) /* Next non-blank isn't letter */
348 goto badif
; /* ... is an error */
349 found
= (lookid(c
) != NULL
); /* Look for it in symbol table */
351 if (found
== (hash
== L_ifdef
)) {
360 badif
: cerror("#if, #ifdef, or #ifndef without an argument", NULLST
);
361 #if !OLD_PREPROCESSOR
362 skipnl(); /* Prevent an extra */
363 unget(); /* Error message */
371 * Process the #include control line.
372 * There are three variations:
373 * #include "file" search somewhere relative to the
374 * current source file, if not found,
375 * treat as #include <file>.
376 * #include <file> Search in an implementation-dependent
378 * #include token Expand the token, it must be one of
379 * "file" or <file>, process as such.
381 * Note: the November 12 draft forbids '>' in the #include <file> format.
382 * This restriction is unnecessary and not implemented.
388 char def_filename
[NAM$C_MAXRSS
+ 1];
391 delim
= macroid(skipws());
392 if (delim
!= '<' && delim
!= '"')
397 instring
= TRUE
; /* Accept all characters */
398 #ifdef CONTROL_COMMENTS_NOT_ALLOWED
399 while ((c
= get()) != '\n' && c
!= EOF_CHAR
)
400 save(c
); /* Put it away. */
401 unget(); /* Force nl after includee */
403 * The draft is unclear if the following should be done.
405 while (--workp
>= work
&& *workp
== ' ')
406 ; /* Trim blanks from filename */
410 while ((c
= get()) != delim
&& c
!= EOF_CHAR
)
413 *workp
= EOS
; /* Terminate filename */
417 * Assume the default .h filetype.
419 if (!vmsparse(work
, ".H", def_filename
)) {
420 perror(work
); /* Oops. */
423 else if (openinclude(def_filename
, (delim
== '"')))
426 if (openinclude(work
, (delim
== '"')))
430 * No sense continuing if #include file isn't there.
432 cfatal("Cannot open include file \"%s\"", work
);
434 incerr
: cerror("#include syntax error", NULLST
);
439 openinclude(char* filename
, int searchlocal
)
441 * Actually open an include file. This routine is only called from
442 * doinclude() above, but was written as a separate subroutine for
443 * programmer convenience. It searches the list of directories
444 * and actually opens the file, linking it into the list of
445 * active files. Returns TRUE if the file was opened, FALSE
446 * if openinclude() fails. No error message is printed.
449 register char **incptr
;
451 #if NFWORK < (NAM$C_MAXRSS + 1)
452 << error
, NFWORK is
not greater than NAM$C_MAXRSS
>>
455 char tmpname
[NFWORK
]; /* Filename work area */
459 * Look in local directory first
463 * Try to open filename relative to the directory of the current
464 * source file (as opposed to the current directory). (ARF, SCK).
466 if (filename
[0] != '/'
467 && hasdirectory(infile
->filename
, tmpname
))
468 strcat(tmpname
, filename
);
470 strcpy(tmpname
, filename
);
473 if (!hasdirectory(filename
, tmpname
)
474 && hasdirectory(infile
->filename
, tmpname
))
475 strcat(tmpname
, filename
);
477 strcpy(tmpname
, filename
);
480 if (openfile(tmpname
))
484 * Look in any directories specified by -I command line
485 * arguments, then in the builtin search list.
487 for (incptr
= incdir
; incptr
< incend
; incptr
++) {
488 if (strlen(*incptr
) + strlen(filename
) >= (NFWORK
- 1))
489 cfatal("Filename work buffer overflow", NULLST
);
492 if (filename
[0] == '/')
493 strcpy(tmpname
, filename
);
495 sprintf(tmpname
, "%s/%s", *incptr
, filename
);
497 #elif HOST == SYS_UNKNOWN
498 if (filename
[0] == '\\')
499 strcpy(tmpname
, filename
);
501 sprintf(tmpname
, "%s\\%s", *incptr
, filename
);
504 if (!hasdirectory(filename
, tmpname
))
505 sprintf(tmpname
, "%s%s", *incptr
, filename
);
507 if (openfile(tmpname
))
515 hasdirectory(char* source
, char* result
)
517 * If a device or directory is found in the source filename string, the
518 * node/device/directory part of the string is copied to result and
519 * hasdirectory returns TRUE. Else, nothing is copied and it returns FALSE.
525 if ((tp
= strrchr(source
, '/')) == NULL
)
528 strncpy(result
, source
, tp
- source
+ 1);
529 result
[tp
- source
+ 1] = EOS
;
534 if (vmsparse(source
, NULLST
, result
)
542 * Random DEC operating system (RSX, RT11, RSTS/E)
546 if ((tp
= strrchr(source
, ']')) == NULL
547 && (tp
= strrchr(source
, ':')) == NULL
)
550 strncpy(result
, source
, tp
- source
+ 1);
551 result
[tp
- source
+ 1] = EOS
;
561 * EXP_DEV is set if a device was specified, EXP_DIR if a directory
562 * is specified. (Both set indicate a file-logical, but EXP_DEV
563 * would be set by itself if you are reading, say, SYS$INPUT:)
565 #define DEVDIR (NAM$M_EXP_DEV | NAM$M_EXP_DIR)
568 vmsparse(source
, defstring
, result
)
570 char *defstring
; /* non-NULL -> default string. */
571 char *result
; /* Size is at least NAM$C_MAXRSS + 1 */
573 * Parse the source string, applying the default (properly, using
574 * the system parse routine), storing it in result.
575 * TRUE if it parsed, FALSE on error.
577 * If defstring is NULL, there are no defaults and result gets
578 * (just) the node::[directory] part of the string (possibly "")
581 struct FAB fab
= cc$rms_fab
; /* File access block */
582 struct NAM nam
= cc$rms_nam
; /* File name block */
583 char fullname
[NAM$C_MAXRSS
+ 1];
584 register char *rp
; /* Result pointer */
586 fab
.fab$l_nam
= &nam
; /* fab -> nam */
587 fab
.fab$l_fna
= source
; /* Source filename */
588 fab
.fab$b_fns
= strlen(source
); /* Size of source */
589 fab
.fab$l_dna
= defstring
; /* Default string */
590 if (defstring
!= NULLST
)
591 fab
.fab$b_dns
= strlen(defstring
); /* Size of default */
592 nam
.nam$l_esa
= fullname
; /* Expanded filename */
593 nam
.nam$b_ess
= NAM$C_MAXRSS
; /* Expanded name size */
594 if (sys$
parse(&fab
) == RMS$_NORMAL
) { /* Parse away */
595 fullname
[nam
.nam$b_esl
] = EOS
; /* Terminate string */
596 result
[0] = EOS
; /* Just in case */
599 * Remove stuff added implicitly, accepting node names and
600 * dev:[directory] strings (but not process-permanent files).
602 if ((nam
.nam$l_fnb
& NAM$M_PPF
) == 0) {
603 if ((nam
.nam$l_fnb
& NAM$M_NODE
) != 0) {
604 strncpy(result
, nam
.nam$l_node
, nam
.nam$b_node
);
605 rp
+= nam
.nam$b_node
;
608 if ((nam
.nam$l_fnb
& DEVDIR
) == DEVDIR
) {
609 strncpy(rp
, nam
.nam$l_dev
, nam
.nam$b_dev
+ nam
.nam$b_dir
);
610 rp
+= nam
.nam$b_dev
+ nam
.nam$b_dir
;
614 if (defstring
!= NULLST
) {
615 strncpy(rp
, nam
.nam$l_name
, nam
.nam$b_name
+ nam
.nam$b_type
);
616 rp
+= nam
.nam$b_name
+ nam
.nam$b_type
;
618 if ((nam
.nam$l_fnb
& NAM$M_EXP_VER
) != 0) {
619 strncpy(rp
, nam
.nam$l_ver
, nam
.nam$b_ver
);
620 rp
[nam
.nam$b_ver
] = EOS
;