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 * Evaluate an #if expression.
40 static char *opname
[] = { /* For debug and error messages */
41 "end of expression", "val", "id",
42 "+", "-", "*", "/", "%",
43 "<<", ">>", "&", "|", "^",
44 "==", "!=", "<", "<=", ">=", ">",
45 "&&", "||", "?", ":", ",",
46 "unary +", "unary -", "~", "!", "(", ")", "(none)",
50 * opdope[] has the operator precedence:
52 * 7 Unused (so the value is always positive)
53 * 6-2 Precedence (000x .. 017x)
54 * 1-0 Binary op. flags:
55 * 01 The binop flag should be set/cleared when this op is seen.
56 * 10 The new value of the binop flag.
57 * Note: Expected, New binop
58 * constant 0 1 Binop, end, or ) should follow constants
59 * End of line 1 0 End may not be preceeded by an operator
60 * binary 1 0 Binary op follows a value, value follows.
61 * unary 0 0 Unary op doesn't follow a value, value follows
62 * ( 0 0 Doesn't follow value, value or unop follows
63 * ) 1 1 Follows value. Op follows.
66 static char opdope
[OP_MAX
] = {
67 0001, /* End of expression */
69 0000, /* Letter (identifier) */
70 0141, 0141, 0151, 0151, 0151, /* ADD, SUB, MUL, DIV, MOD */
71 0131, 0131, 0101, 0071, 0071, /* ASL, ASR, AND, OR, XOR */
72 0111, 0111, 0121, 0121, 0121, 0121, /* EQ, NE, LT, LE, GE, GT */
73 0061, 0051, 0041, 0041, 0031, /* ANA, ORO, QUE, COL, CMA */
77 0160, 0160, 0160, 0160, /* NEG, PLU, COM, NOT */
78 0170, 0013, 0023, /* LPA, RPA, END */
81 * OP_QUE and OP_RPA have alternate precedences:
83 #define OP_RPA_PREC 0013
84 #define OP_QUE_PREC 0034
87 * S_ANDOR and S_QUEST signal "short-circuit" boolean evaluation, so that
88 * #if FOO != 0 && 10 / FOO ...
89 * doesn't generate an error message. They are stored in optab.skip.
94 typedef struct optab
{
95 char op
; /* Operator */
96 char prec
; /* Its precedence */
97 char skip
; /* Short-circuit: TRUE to skip */
99 static int evalue
; /* Current value from evallex() */
106 return (op
>= FIRST_BINOP
&& op
<= LAST_BINOP
);
113 return (op
>= FIRST_UNOP
&& op
<= LAST_UNOP
);
116 #define isbinary(op) (op >= FIRST_BINOP && op <= LAST_BINOP)
117 #define isunary(op) (op >= FIRST_UNOP && op <= LAST_UNOP)
121 * The following definitions are used to specify basic variable sizes.
125 #define S_CHAR (sizeof (char))
128 #define S_SINT (sizeof (short int))
131 #define S_INT (sizeof (int))
134 #define S_LINT (sizeof (long int))
137 #define S_FLOAT (sizeof (float))
140 #define S_DOUBLE (sizeof (double))
143 #define S_PCHAR (sizeof (char *))
146 #define S_PSINT (sizeof (short int *))
149 #define S_PINT (sizeof (int *))
152 #define S_PLINT (sizeof (long int *))
155 #define S_PFLOAT (sizeof (float *))
158 #define S_PDOUBLE (sizeof (double *))
161 #define S_PFPTR (sizeof (int (*)()))
164 typedef struct types
{
165 short type
; /* This is the bit if */
166 char *name
; /* this is the token word */
169 static TYPES basic_types
[] = {
172 { T_FLOAT
, "float", },
173 { T_DOUBLE
, "double", },
174 { T_SHORT
, "short", },
176 { T_SIGNED
, "signed", },
177 { T_UNSIGNED
, "unsigned", },
178 { 0, NULL
, }, /* Signal end */
182 * Test_table[] is used to test for illegal combinations.
184 static short test_table
[] = {
185 T_FLOAT
| T_DOUBLE
| T_LONG
| T_SHORT
,
186 T_FLOAT
| T_DOUBLE
| T_CHAR
| T_INT
,
187 T_FLOAT
| T_DOUBLE
| T_SIGNED
| T_UNSIGNED
,
188 T_LONG
| T_SHORT
| T_CHAR
,
193 * The order of this table is important -- it is also referenced by
194 * the command line processor to allow run-time overriding of the
195 * built-in size values. The order must not be changed:
196 * char, short, int, long, float, double (func pointer)
198 SIZES size_table
[] = {
199 { T_CHAR
, S_CHAR
, S_PCHAR
}, /* char */
200 { T_SHORT
, S_SINT
, S_PSINT
}, /* short int */
201 { T_INT
, S_INT
, S_PINT
}, /* int */
202 { T_LONG
, S_LINT
, S_PLINT
}, /* long */
203 { T_FLOAT
, S_FLOAT
, S_PFLOAT
}, /* float */
204 { T_DOUBLE
, S_DOUBLE
, S_PDOUBLE
}, /* double */
205 { T_FPTR
, 0, S_PFPTR
}, /* int (*()) */
206 { 0, 0, 0 }, /* End of table */
220 * Evaluate an expression. Straight-forward operator precedence.
221 * This is called from control() on encountering an #if statement.
222 * It calls the following routines:
223 * evallex Lexical analyser -- returns the type and value of
224 * the next input token.
225 * evaleval Evaluate the current operator, given the values on
226 * the value stack. Returns a pointer to the (new)
228 * For compatiblity with older cpp's, this return returns 1 (TRUE)
229 * if a syntax error is detected.
232 register int op
; /* Current operator */
233 register int *valp
; /* -> value vector */
234 register OPTAB
*opp
; /* Operator stack */
235 int prec
; /* Op precedence */
236 int binop
; /* Set if binary op. needed */
237 int op1
; /* Operand from stack */
238 int skip
; /* For short-circuit testing */
239 int value
[NEXP
]; /* Value stack */
240 OPTAB opstack
[NEXP
]; /* Operand stack */
242 extern int *evaleval(); /* Does actual evaluation */
246 opp
->op
= OP_END
; /* Mark bottom of stack */
247 opp
->prec
= opdope
[OP_END
]; /* And its precedence */
248 opp
->skip
= 0; /* Not skipping now */
252 fprintf( pCppOut
, "In #if at again: skip = %d, binop = %d, line is: %s",
253 opp
->skip
, binop
, infile
->bptr
);
255 if ((op
= evallex(opp
->skip
)) == OP_SUB
&& binop
== 0)
256 op
= OP_NEG
; /* Unary minus */
257 else if (op
== OP_ADD
&& binop
== 0)
258 op
= OP_PLU
; /* Unary plus */
259 else if (op
== OP_FAIL
)
260 return (1); /* Error in evallex */
262 fprintf( pCppOut
, "op = %s, opdope = %03o, binop = %d, skip = %d\n",
263 opname
[op
], opdope
[op
], binop
, opp
->skip
);
265 if (op
== DIG
) { /* Value? */
267 cerror("misplaced constant in #if", NULLST
);
270 else if (valp
>= &value
[NEXP
-1]) {
271 cerror("#if value stack overflow", NULLST
);
276 fprintf( pCppOut
, "pushing %d onto value stack[%d]\n",
277 evalue
, valp
- value
);
284 else if (op
> OP_END
) {
285 cerror("Illegal #if line", NULLST
);
289 if (binop
!= (prec
& 1)) {
290 cerror("Operator %s in incorrect context", opname
[op
]);
293 binop
= (prec
& 2) >> 1;
296 fprintf( pCppOut
, "op %s, prec %d., stacked op %s, prec %d, skip %d\n",
297 opname
[op
], prec
, opname
[opp
->op
], opp
->prec
, opp
->skip
);
299 if (prec
> opp
->prec
) {
302 else if (op
== OP_QUE
)
304 op1
= opp
->skip
; /* Save skip for test */
306 * Push operator onto op. stack.
309 if (opp
>= &opstack
[NEXP
]) {
310 cerror("expression stack overflow at op \"%s\"",
315 opp
->prec
= (char)prec
;
316 skip
= (valp
[-1] != 0); /* Short-circuit tester */
318 * Do the short-circuit stuff here. Short-circuiting
319 * stops automagically when operators are evaluated.
321 if ((op
== OP_ANA
&& !skip
)
322 || (op
== OP_ORO
&& skip
))
323 opp
->skip
= S_ANDOR
; /* And/or skip starts */
324 else if (op
== OP_QUE
) /* Start of ?: operator */
325 opp
->skip
= (char)((op1
& S_ANDOR
) | ((!skip
) ? S_QUEST
: 0));
326 else if (op
== OP_COL
) { /* : inverts S_QUEST */
327 opp
->skip
= (char)((op1
& S_ANDOR
)
328 | (((op1
& S_QUEST
) != 0) ? 0 : S_QUEST
));
330 else { /* Other ops leave */
331 opp
->skip
= (char)op1
; /* skipping unchanged. */
334 fprintf( pCppOut
, "stacking %s, valp[-1] == %d at %s",
335 opname
[op
], valp
[-1], infile
->bptr
);
336 dumpstack(opstack
, opp
, value
, valp
);
341 * Pop operator from op. stack and evaluate it.
342 * End of stack and '(' are specials.
344 skip
= opp
->skip
; /* Remember skip value */
345 switch ((op1
= opp
->op
)) { /* Look at stacked op */
346 case OP_END
: /* Stack end marker */
348 return (valp
[-1]); /* Finished ok. */
349 goto again
; /* Read another op. */
351 case OP_LPA
: /* ( on stack */
352 if (op
!= OP_RPA
) { /* Matches ) on input */
353 cerror("unbalanced paren's, op is \"%s\"", opname
[op
]);
356 opp
--; /* Unstack it */
357 /* goto again; -- Fall through */
360 goto again
; /* Evaluate true expr. */
362 case OP_COL
: /* : on stack. */
363 opp
--; /* Unstack : */
364 if (opp
->op
!= OP_QUE
) { /* Matches ? on stack? */
365 cerror("Misplaced '?' or ':', previous operator is %s",
366 opname
[(int)opp
->op
]);
372 default: /* Others: */
373 opp
--; /* Unstack the operator */
375 fprintf( pCppOut
, "Stack before evaluation of %s\n", opname
[op1
]);
376 dumpstack(opstack
, opp
, value
, valp
);
378 valp
= evaleval(valp
, op1
, skip
);
380 fprintf( pCppOut
, "Stack after evaluation\n");
381 dumpstack(opstack
, opp
, value
, valp
);
383 } /* op1 switch end */
384 } /* Stack unwind loop */
390 * Return next eval operator or value. Called from eval(). It
391 * calls a special-purpose routines for 'char' strings and
393 * evalchar called to evaluate 'x'
394 * evalnum called to evaluate numbers.
397 register int c
, c1
, t
;
399 again
: do { /* Collect the token */
401 if ((c
= macroid(c
)) == EOF_CHAR
|| c
== '\n') {
403 return (OP_EOE
); /* End of expression */
405 } while ((t
= type
[c
]) == LET
&& catenate());
406 if (t
== INV
) { /* Total nonsense */
408 if (isascii(c
) && isprint(c
))
409 cierror("illegal character '%c' in #if", c
);
411 cierror("illegal character (%d decimal) in #if", c
);
415 else if (t
== QUO
) { /* ' or " */
416 if (c
== '\'') { /* Character constant */
417 evalue
= evalchar(skip
); /* Somewhat messy */
419 fprintf( pCppOut
, "evalchar returns %d.\n", evalue
);
421 return (DIG
); /* Return a value */
423 cerror("Can't use a string in an #if", NULLST
);
426 else if (t
== LET
) { /* ID must be a macro */
427 if (streq(token
, "defined")) { /* Or defined name */
429 if (c
== '(') /* Allow defined(name) */
431 if (type
[c
] == LET
) {
432 evalue
= (lookid(c
) != NULL
);
433 if (c1
!= '(' /* Need to balance */
434 || skipws() == ')') /* Did we balance? */
435 return (DIG
); /* Parsed ok */
437 cerror("Bad #if ... defined() syntax", NULLST
);
440 else if (streq(token
, "sizeof")) /* New sizeof hackery */
441 return (dosizeof()); /* Gets own routine */
443 * The Draft ANSI C Standard says that an undefined symbol
444 * in an #if has the value zero. We are a bit pickier,
445 * warning except where the programmer was careful to write
446 * #if defined(foo) ? foo : 0
450 cwarn("undefined symbol \"%s\" in #if, 0 used", token
);
455 else if (t
== DIG
) { /* Numbers are harder */
458 fprintf( pCppOut
, "evalnum returns %d.\n", evalue
);
461 else if (strchr("!=<>&|\\", c
) != NULL
) {
463 * Process a possible multi-byte lexeme.
465 c1
= cget(); /* Peek at next char */
473 if (c1
!= '=') { /* Can't say a=b in #if */
475 cerror("= not allowed in #if", NULLST
);
483 return ((c
== '<') ? OP_ASL
: OP_ASR
);
485 return ((c
== '<') ? OP_LE
: OP_GE
);
491 return ((c
== '|') ? OP_ORO
: OP_ANA
);
495 if (c1
== '\n') /* Multi-line if */
497 cerror("Unexpected \\ in #if", NULLST
);
508 * Process the sizeof (basic type) operation in an #if string.
509 * Sets evalue to the size and returns
511 * OP_FAIL bad parse or something.
516 register SIZES
*sizp
;
517 register short *testp
;
520 if ((c
= skipws()) != '(')
523 * Scan off the tokens.
526 while (0 != (c
= skipws())) {
527 if ((c
= macroid(c
)) == EOF_CHAR
|| c
== '\n')
528 goto nogood
; /* End of line is a bug */
529 else if (c
== '(') { /* thing (*)() func ptr */
531 && skipws() == ')') { /* We found (*) */
532 if (skipws() != '(') /* Let () be optional */
534 else if (skipws() != ')')
536 typecode
|= T_FPTR
; /* Function pointer */
538 else { /* Junk is a bug */
542 else if (type
[c
] != LET
) /* Exit if not a type */
544 else if (!catenate()) { /* Maybe combine tokens */
546 * Look for this unexpandable token in basic_types.
547 * The code accepts "int long" as well as "long int"
548 * which is a minor bug as bugs go (and one shared with
549 * a lot of C compilers).
551 for (tp
= basic_types
; tp
->name
!= NULLST
; tp
++) {
552 if (streq(token
, tp
->name
))
555 if (tp
->name
== NULLST
) {
556 cerror("#if sizeof, unknown type \"%s\"", token
);
559 typecode
|= tp
->type
; /* Or in the type bit */
563 * We are at the end of the type scan. Chew off '*' if necessary.
569 if (c
== ')') { /* Last syntax check */
570 for (testp
= test_table
; *testp
!= 0; testp
++) {
571 if (!bittest(typecode
& *testp
)) {
572 cerror("#if ... sizeof: illegal type combination", NULLST
);
577 * We assume that all function pointers are the same size:
578 * sizeof (int (*)()) == sizeof (float (*)())
579 * We assume that signed and unsigned don't change the size:
580 * sizeof (signed int) == (sizeof unsigned int)
582 if ((typecode
& T_FPTR
) != 0) /* Function pointer */
583 typecode
= T_FPTR
| T_PTR
;
584 else { /* Var or var * datum */
585 typecode
&= ~(T_SIGNED
| T_UNSIGNED
);
586 if ((typecode
& (T_SHORT
| T_LONG
)) != 0)
589 if ((typecode
& ~T_PTR
) == 0) {
590 cerror("#if sizeof() error, no type specified", NULLST
);
594 * Exactly one bit (and possibly T_PTR) may be set.
596 for (sizp
= size_table
; sizp
->bits
!= 0; sizp
++) {
597 if ((typecode
& ~T_PTR
) == sizp
->bits
) {
598 evalue
= ((typecode
& T_PTR
) != 0)
599 ? sizp
->psize
: sizp
->size
;
602 } /* We shouldn't fail */
603 cierror("#if ... sizeof: bug, unknown type code 0x%x", typecode
);
608 cerror("#if ... sizeof() syntax error", NULLST
);
615 * TRUE if value is zero or exactly one bit is set in value.
618 #if (4096 & ~(-4096)) == 0
619 return ((value
& ~(-value
)) == 0);
622 * Do it the hard way (for non 2's complement machines)
624 return (value
== 0 || value
^ (value
- 1) == (value
* 2 - 1));
631 * Expand number for #if lexical analysis. Note: evalnum recognizes
632 * the unsigned suffix, but only returns a signed int value.
641 else if ((c
= cget()) == 'x' || c
== 'X') {
649 if (isascii(c
) && isupper(c1
))
658 if (c1
< 0 || c1
>= base
)
664 if (c
== 'u' || c
== 'U') /* Unsigned nonsense */
673 * Get a character constant
681 if ((c
= cget()) == '\\') {
682 switch ((c
= cget())) {
683 case 'a': /* New in Standard */
684 #if ('a' == '\a' || '\a' == ALERT)
685 value
= ALERT
; /* Use predefined value */
687 value
= '\a'; /* Use compiler's value */
711 case 'v': /* New in Standard */
712 #if ('v' == '\v' || '\v' == VT)
713 value
= VT
; /* Use predefined value */
715 value
= '\v'; /* Use compiler's value */
719 case 'x': /* '\xFF' */
722 while ((((c
= get()) >= '0' && c
<= '9')
723 || (c
>= 'a' && c
<= 'f')
724 || (c
>= 'A' && c
<= 'F'))
728 value
+= (c
<= '9') ? (c
- '0') : ((c
& 0xF) + 9);
730 value
+= (c
>= '0') ? (c
- '0') : ((c
& 0xF) + 9);
737 if (c
>= '0' && c
<= '7') {
740 while (c
>= '0' && c
<= '7' && --count
>= 0) {
755 * We warn on multi-byte constants and try to hack
756 * (big|little)endian machines.
761 while ((c
= get()) != '\'' && c
!= EOF_CHAR
&& c
!= '\n') {
763 ciwarn("multi-byte constant '%c' isn't portable", c
);
766 value
+= (c
<< count
);
777 evaleval(int* valp
, int op
, int skip
)
779 * Apply the argument operator to the data on the value stack.
780 * One or two values are popped from the value stack and the result
781 * is pushed onto the value stack.
783 * OP_COL is a special case.
785 * evaleval() returns the new pointer to the top of the value stack.
788 register int v1
, v2
= 0;
794 fprintf( pCppOut
, "%s op %s", (isbinary(op
)) ? "binary" : "unary",
797 fprintf( pCppOut
, ", v2 = %d.", v2
);
798 fprintf( pCppOut
, ", v1 = %d.\n", v1
);
820 cwarn("%s by zero in #if, zero result assumed",
821 (op
== OP_DIV
) ? "divide" : "mod");
825 else if (op
== OP_DIV
)
885 * v1 has the "true" value, v2 the "false" value.
886 * The top of the value stack has the test.
888 v1
= (*--valp
) ? v1
: v2
;
907 cierror("#if bug, operand = %d.", op
);
915 dumpstack(opstack
, opp
, value
, valp
)
916 OPTAB opstack
[NEXP
]; /* Operand stack */
917 register OPTAB
*opp
; /* Operator stack */
918 int value
[NEXP
]; /* Value stack */
919 register int *valp
; /* -> value vector */
921 fprintf( pCppOut
, "index op prec skip name -- op stack at %s", infile
->bptr
);
922 while (opp
> opstack
) {
923 fprintf( pCppOut
, " [%2d] %2d %03o %d %s\n", opp
- opstack
,
924 opp
->op
, opp
->prec
, opp
->skip
, opname
[opp
->op
]);
927 while (--valp
>= value
) {
928 fprintf( pCppOut
, "value[%d] = %d\n", (valp
- value
), *valp
);