diff options
author | David Walter Seikel | 2012-01-04 18:41:13 +1000 |
---|---|---|
committer | David Walter Seikel | 2012-01-04 18:41:13 +1000 |
commit | dd7595a3475407a7fa96a97393bae8c5220e8762 (patch) | |
tree | e341e911d7eb911a51684a7412ef7f7c7605d28e /libraries/edje/src/bin/epp/cppexp.c | |
parent | Add the skeleton. (diff) | |
download | SledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.zip SledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.tar.gz SledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.tar.bz2 SledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.tar.xz |
Add the base Enlightenment Foundation Libraries - eina, eet, evas, ecore, embryo, and edje.
Note that embryo wont be used, but I'm not sure yet if you can build edje without it.
Diffstat (limited to '')
-rw-r--r-- | libraries/edje/src/bin/epp/cppexp.c | 1090 |
1 files changed, 1090 insertions, 0 deletions
diff --git a/libraries/edje/src/bin/epp/cppexp.c b/libraries/edje/src/bin/epp/cppexp.c new file mode 100644 index 0000000..5fcb33f --- /dev/null +++ b/libraries/edje/src/bin/epp/cppexp.c | |||
@@ -0,0 +1,1090 @@ | |||
1 | /* Parse C expressions for CCCP. | ||
2 | * Copyright (C) 1987, 1992, 1994, 1995 Free Software Foundation. | ||
3 | * Copyright (C) 2003-2011 Kim Woelders | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the | ||
7 | * Free Software Foundation; either version 2, or (at your option) any | ||
8 | * later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | * | ||
19 | * In other words, you are welcome to use, share and improve this program. | ||
20 | * You are forbidden to forbid anyone else to use, share and improve | ||
21 | * what you give them. Help stamp out software-hoarding! | ||
22 | * | ||
23 | * Written by Per Bothner 1994. */ | ||
24 | |||
25 | /* Parse a C expression from text in a string */ | ||
26 | |||
27 | #ifdef HAVE_CONFIG_H | ||
28 | # include <config.h> | ||
29 | #endif | ||
30 | |||
31 | #ifdef __EMX__ | ||
32 | # include <strings.h> | ||
33 | #endif | ||
34 | |||
35 | #ifdef MULTIBYTE_CHARS | ||
36 | # include <locale.h> | ||
37 | #endif | ||
38 | |||
39 | #include <stdlib.h> | ||
40 | #include <stdio.h> | ||
41 | #include <string.h> | ||
42 | |||
43 | #include "cpplib.h" | ||
44 | #include "cpphash.h" | ||
45 | |||
46 | /* This is used for communicating lists of keywords with cccp.c. */ | ||
47 | struct arglist { | ||
48 | struct arglist *next; | ||
49 | unsigned char *name; | ||
50 | int length; | ||
51 | int argno; | ||
52 | }; | ||
53 | |||
54 | /* Define a generic NULL if one hasn't already been defined. */ | ||
55 | |||
56 | #ifndef NULL | ||
57 | #define NULL 0 | ||
58 | #endif | ||
59 | |||
60 | #ifndef GENERIC_PTR | ||
61 | #if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__) | ||
62 | #define GENERIC_PTR void * | ||
63 | #else | ||
64 | #define GENERIC_PTR char * | ||
65 | #endif | ||
66 | #endif | ||
67 | |||
68 | #ifndef NULL_PTR | ||
69 | #define NULL_PTR ((GENERIC_PTR)0) | ||
70 | #endif | ||
71 | |||
72 | #ifndef CHAR_TYPE_SIZE | ||
73 | #define CHAR_TYPE_SIZE BITS_PER_UNIT | ||
74 | #endif | ||
75 | |||
76 | #ifndef INT_TYPE_SIZE | ||
77 | #define INT_TYPE_SIZE BITS_PER_WORD | ||
78 | #endif | ||
79 | |||
80 | #ifndef LONG_TYPE_SIZE | ||
81 | #define LONG_TYPE_SIZE BITS_PER_WORD | ||
82 | #endif | ||
83 | |||
84 | #ifndef WCHAR_TYPE_SIZE | ||
85 | #define WCHAR_TYPE_SIZE INT_TYPE_SIZE | ||
86 | #endif | ||
87 | |||
88 | #ifndef MAX_CHAR_TYPE_SIZE | ||
89 | #define MAX_CHAR_TYPE_SIZE CHAR_TYPE_SIZE | ||
90 | #endif | ||
91 | |||
92 | #ifndef MAX_INT_TYPE_SIZE | ||
93 | #define MAX_INT_TYPE_SIZE INT_TYPE_SIZE | ||
94 | #endif | ||
95 | |||
96 | #ifndef MAX_LONG_TYPE_SIZE | ||
97 | #define MAX_LONG_TYPE_SIZE LONG_TYPE_SIZE | ||
98 | #endif | ||
99 | |||
100 | #ifndef MAX_WCHAR_TYPE_SIZE | ||
101 | #define MAX_WCHAR_TYPE_SIZE WCHAR_TYPE_SIZE | ||
102 | #endif | ||
103 | |||
104 | /* Yield nonzero if adding two numbers with A's and B's signs can yield a | ||
105 | * number with SUM's sign, where A, B, and SUM are all C integers. */ | ||
106 | #define possible_sum_sign(a, b, sum) ((((a) ^ (b)) | ~ ((a) ^ (sum))) < 0) | ||
107 | |||
108 | #define ERROR 299 | ||
109 | #define OROR 300 | ||
110 | #define ANDAND 301 | ||
111 | #define EQUAL 302 | ||
112 | #define NOTEQUAL 303 | ||
113 | #define LEQ 304 | ||
114 | #define GEQ 305 | ||
115 | #define LSH 306 | ||
116 | #define RSH 307 | ||
117 | #define NAME 308 | ||
118 | #define INT 309 | ||
119 | #define CHAR 310 | ||
120 | |||
121 | #define LEFT_OPERAND_REQUIRED 1 | ||
122 | #define RIGHT_OPERAND_REQUIRED 2 | ||
123 | #define HAVE_VALUE 4 | ||
124 | /* SKIP_OPERAND is set for '&&' '||' '?' and ':' when the | ||
125 | * following operand should be short-circuited instead of evaluated. */ | ||
126 | #define SKIP_OPERAND 8 | ||
127 | /*#define UNSIGNEDP 16 */ | ||
128 | |||
129 | struct operation { | ||
130 | short op; | ||
131 | char rprio; /* Priority of op (relative to it right operand). */ | ||
132 | char flags; | ||
133 | char unsignedp; /* true if value should be treated as unsigned */ | ||
134 | HOST_WIDE_INT value; /* The value logically "right" of op. */ | ||
135 | }; | ||
136 | |||
137 | /* Take care of parsing a number (anything that starts with a digit). | ||
138 | * LEN is the number of characters in it. */ | ||
139 | |||
140 | /* maybe needs to actually deal with floating point numbers */ | ||
141 | |||
142 | static void | ||
143 | parse_number(struct operation *op, cpp_reader * pfile, const char *start, | ||
144 | int olen) | ||
145 | { | ||
146 | const char *p = start; | ||
147 | int c; | ||
148 | unsigned long n = 0, nd, ULONG_MAX_over_base; | ||
149 | int base = 10; | ||
150 | int len = olen; | ||
151 | int overflow = 0; | ||
152 | int digit, largest_digit = 0; | ||
153 | int spec_long = 0; | ||
154 | |||
155 | op->unsignedp = 0; | ||
156 | |||
157 | for (c = 0; c < len; c++) | ||
158 | if (p[c] == '.') | ||
159 | { | ||
160 | /* It's a float since it contains a point. */ | ||
161 | cpp_error(pfile, | ||
162 | "floating point numbers not allowed in #if expressions"); | ||
163 | op->op = ERROR; | ||
164 | return; | ||
165 | } | ||
166 | if (len >= 3 && (!strncmp(p, "0x", 2) || !strncmp(p, "0X", 2))) | ||
167 | { | ||
168 | p += 2; | ||
169 | base = 16; | ||
170 | len -= 2; | ||
171 | } | ||
172 | else if (*p == '0') | ||
173 | base = 8; | ||
174 | |||
175 | /* Some buggy compilers (e.g. MPW C) seem to need both casts. */ | ||
176 | ULONG_MAX_over_base = ((unsigned long)-1) / ((unsigned long)base); | ||
177 | |||
178 | for (; len > 0; len--) | ||
179 | { | ||
180 | c = *p++; | ||
181 | |||
182 | if (c >= '0' && c <= '9') | ||
183 | digit = c - '0'; | ||
184 | else if (base == 16 && c >= 'a' && c <= 'f') | ||
185 | digit = c - 'a' + 10; | ||
186 | else if (base == 16 && c >= 'A' && c <= 'F') | ||
187 | digit = c - 'A' + 10; | ||
188 | else | ||
189 | { | ||
190 | /* `l' means long, and `u' means unsigned. */ | ||
191 | while (1) | ||
192 | { | ||
193 | if (c == 'l' || c == 'L') | ||
194 | { | ||
195 | if (spec_long) | ||
196 | cpp_error(pfile, "two `l's in integer constant"); | ||
197 | spec_long = 1; | ||
198 | } | ||
199 | else if (c == 'u' || c == 'U') | ||
200 | { | ||
201 | if (op->unsignedp) | ||
202 | cpp_error(pfile, "two `u's in integer constant"); | ||
203 | op->unsignedp = 1; | ||
204 | } | ||
205 | else | ||
206 | break; | ||
207 | |||
208 | if (--len == 0) | ||
209 | break; | ||
210 | c = *p++; | ||
211 | } | ||
212 | /* Don't look for any more digits after the suffixes. */ | ||
213 | break; | ||
214 | } | ||
215 | if (largest_digit < digit) | ||
216 | largest_digit = digit; | ||
217 | nd = n * base + digit; | ||
218 | overflow |= (ULONG_MAX_over_base < n) | (nd < n); | ||
219 | n = nd; | ||
220 | } | ||
221 | |||
222 | if (len != 0) | ||
223 | { | ||
224 | cpp_error(pfile, "Invalid number in #if expression"); | ||
225 | op->op = ERROR; | ||
226 | return; | ||
227 | } | ||
228 | if (base <= largest_digit) | ||
229 | cpp_warning(pfile, "integer constant contains digits beyond the radix"); | ||
230 | |||
231 | if (overflow) | ||
232 | cpp_warning(pfile, "integer constant out of range"); | ||
233 | |||
234 | /* If too big to be signed, consider it unsigned. */ | ||
235 | if ((long)n < 0 && !op->unsignedp) | ||
236 | { | ||
237 | if (base == 10) | ||
238 | cpp_warning(pfile, | ||
239 | "integer constant is so large that it is unsigned"); | ||
240 | op->unsignedp = 1; | ||
241 | } | ||
242 | op->value = n; | ||
243 | op->op = INT; | ||
244 | } | ||
245 | |||
246 | struct token { | ||
247 | const char *oper; | ||
248 | int token; | ||
249 | }; | ||
250 | |||
251 | static struct token tokentab2[] = { | ||
252 | {"&&", ANDAND}, | ||
253 | {"||", OROR}, | ||
254 | {"<<", LSH}, | ||
255 | {">>", RSH}, | ||
256 | {"==", EQUAL}, | ||
257 | {"!=", NOTEQUAL}, | ||
258 | {"<=", LEQ}, | ||
259 | {">=", GEQ}, | ||
260 | {"++", ERROR}, | ||
261 | {"--", ERROR}, | ||
262 | {NULL, ERROR} | ||
263 | }; | ||
264 | |||
265 | /* Read one token. */ | ||
266 | |||
267 | static void | ||
268 | cpp_lex(struct operation *op, cpp_reader * pfile) | ||
269 | { | ||
270 | int c; | ||
271 | struct token *toktab; | ||
272 | enum cpp_token token; | ||
273 | unsigned char *tok_start, *tok_end; | ||
274 | int old_written; | ||
275 | |||
276 | op->value = 0; | ||
277 | op->unsignedp = 0; | ||
278 | |||
279 | retry: | ||
280 | |||
281 | old_written = CPP_WRITTEN(pfile); | ||
282 | cpp_skip_hspace(pfile); | ||
283 | c = CPP_BUF_PEEK(CPP_BUFFER(pfile)); | ||
284 | if (c == '#') | ||
285 | { | ||
286 | parse_number(op, pfile, cpp_read_check_assertion(pfile) ? "1" : "0", 1); | ||
287 | return; | ||
288 | } | ||
289 | |||
290 | if (c == '\n') | ||
291 | { | ||
292 | op->op = 0; | ||
293 | return; | ||
294 | } | ||
295 | token = cpp_get_token(pfile); | ||
296 | tok_start = pfile->token_buffer + old_written; | ||
297 | tok_end = CPP_PWRITTEN(pfile); | ||
298 | pfile->limit = tok_start; | ||
299 | switch (token) | ||
300 | { | ||
301 | case CPP_EOF: /* Should not happen ... */ | ||
302 | op->op = 0; | ||
303 | break; | ||
304 | |||
305 | case CPP_VSPACE: | ||
306 | case CPP_POP: | ||
307 | if (CPP_BUFFER(pfile)->fname) | ||
308 | { | ||
309 | op->op = 0; | ||
310 | break; | ||
311 | } | ||
312 | goto retry; | ||
313 | |||
314 | case CPP_HSPACE: | ||
315 | case CPP_COMMENT: | ||
316 | goto retry; | ||
317 | |||
318 | case CPP_NUMBER: | ||
319 | parse_number(op, pfile, (char *)tok_start, tok_end - tok_start); | ||
320 | break; | ||
321 | |||
322 | case CPP_STRING: | ||
323 | cpp_error(pfile, "string constants not allowed in #if expressions"); | ||
324 | op->op = ERROR; | ||
325 | break; | ||
326 | |||
327 | case CPP_CHAR: | ||
328 | /* This code for reading a character constant | ||
329 | * handles multicharacter constants and wide characters. | ||
330 | * It is mostly copied from c-lex.c. */ | ||
331 | { | ||
332 | int result = 0; | ||
333 | int num_chars = 0; | ||
334 | unsigned width = MAX_CHAR_TYPE_SIZE; | ||
335 | int wide_flag = 0; | ||
336 | int max_chars; | ||
337 | char *ptr = (char *)tok_start; | ||
338 | |||
339 | #ifdef MULTIBYTE_CHARS | ||
340 | char token_buffer[MAX_LONG_TYPE_SIZE / | ||
341 | MAX_CHAR_TYPE_SIZE + MB_CUR_MAX]; | ||
342 | #endif | ||
343 | |||
344 | if (*ptr == 'L') | ||
345 | { | ||
346 | ptr++; | ||
347 | wide_flag = 1; | ||
348 | width = MAX_WCHAR_TYPE_SIZE; | ||
349 | #ifdef MULTIBYTE_CHARS | ||
350 | max_chars = MB_CUR_MAX; | ||
351 | #else | ||
352 | max_chars = 1; | ||
353 | #endif | ||
354 | } | ||
355 | else | ||
356 | max_chars = MAX_LONG_TYPE_SIZE / width; | ||
357 | |||
358 | while (1) | ||
359 | { | ||
360 | if (ptr >= (char *)CPP_PWRITTEN(pfile) || (c = *ptr++) == '\'') | ||
361 | break; | ||
362 | |||
363 | if (c == '\\') | ||
364 | { | ||
365 | c = cpp_parse_escape(pfile, &ptr); | ||
366 | if (width < HOST_BITS_PER_INT | ||
367 | && (unsigned)c >= (unsigned)(1 << width)) | ||
368 | cpp_pedwarn(pfile, | ||
369 | "escape sequence out of range for character"); | ||
370 | } | ||
371 | num_chars++; | ||
372 | |||
373 | /* Merge character into result; ignore excess chars. */ | ||
374 | if (num_chars < max_chars + 1) | ||
375 | { | ||
376 | if (width < HOST_BITS_PER_INT) | ||
377 | result = (result << width) | (c & ((1 << width) - 1)); | ||
378 | else | ||
379 | result = c; | ||
380 | #ifdef MULTIBYTE_CHARS | ||
381 | token_buffer[num_chars - 1] = c; | ||
382 | #endif | ||
383 | } | ||
384 | } | ||
385 | |||
386 | #ifdef MULTIBYTE_CHARS | ||
387 | token_buffer[num_chars] = 0; | ||
388 | #endif | ||
389 | |||
390 | if (c != '\'') | ||
391 | cpp_error(pfile, "malformatted character constant"); | ||
392 | else if (num_chars == 0) | ||
393 | cpp_error(pfile, "empty character constant"); | ||
394 | else if (num_chars > max_chars) | ||
395 | { | ||
396 | num_chars = max_chars; | ||
397 | cpp_error(pfile, "character constant too long"); | ||
398 | } | ||
399 | else if (num_chars != 1 && !CPP_TRADITIONAL(pfile)) | ||
400 | cpp_warning(pfile, "multi-character character constant"); | ||
401 | |||
402 | /* If char type is signed, sign-extend the constant. */ | ||
403 | if (!wide_flag) | ||
404 | { | ||
405 | int num_bits = num_chars * width; | ||
406 | |||
407 | if (cpp_lookup("__CHAR_UNSIGNED__", | ||
408 | sizeof("__CHAR_UNSIGNED__") - 1, -1) | ||
409 | || ((result >> (num_bits - 1)) & 1) == 0) | ||
410 | op->value = | ||
411 | result & ((unsigned long)~0 >> | ||
412 | (HOST_BITS_PER_LONG - num_bits)); | ||
413 | else | ||
414 | op->value = | ||
415 | result | ~((unsigned long)~0 >> | ||
416 | (HOST_BITS_PER_LONG - num_bits)); | ||
417 | } | ||
418 | else | ||
419 | { | ||
420 | #ifdef MULTIBYTE_CHARS | ||
421 | /* Set the initial shift state and convert the next sequence. */ | ||
422 | result = 0; | ||
423 | /* In all locales L'\0' is zero and mbtowc will return zero, | ||
424 | * so don't use it. */ | ||
425 | if (num_chars > 1 | ||
426 | || (num_chars == 1 && token_buffer[0] != '\0')) | ||
427 | { | ||
428 | wchar_t wc; | ||
429 | |||
430 | (void)mbtowc(NULL_PTR, NULL_PTR, 0); | ||
431 | if (mbtowc(&wc, token_buffer, num_chars) == num_chars) | ||
432 | result = wc; | ||
433 | else | ||
434 | cpp_warning(pfile, | ||
435 | "Ignoring invalid multibyte character"); | ||
436 | } | ||
437 | #endif | ||
438 | op->value = result; | ||
439 | } | ||
440 | } | ||
441 | |||
442 | /* This is always a signed type. */ | ||
443 | op->unsignedp = 0; | ||
444 | op->op = CHAR; | ||
445 | break; | ||
446 | |||
447 | case CPP_NAME: | ||
448 | parse_number(op, pfile, "0", 0); | ||
449 | break; | ||
450 | |||
451 | case CPP_OTHER: | ||
452 | /* See if it is a special token of length 2. */ | ||
453 | if (tok_start + 2 == tok_end) | ||
454 | { | ||
455 | for (toktab = tokentab2; toktab->oper; toktab++) | ||
456 | if (tok_start[0] == toktab->oper[0] | ||
457 | && tok_start[1] == toktab->oper[1]) | ||
458 | break; | ||
459 | if (toktab->token == ERROR) | ||
460 | { | ||
461 | char *buf = (char *)malloc(40); | ||
462 | |||
463 | memset(buf, 0, 40); | ||
464 | |||
465 | sprintf(buf, "`%s' not allowed in operand of `#if'", | ||
466 | tok_start); | ||
467 | cpp_error(pfile, buf); | ||
468 | free(buf); | ||
469 | } | ||
470 | op->op = toktab->token; | ||
471 | break; | ||
472 | } | ||
473 | /* fall through */ | ||
474 | default: | ||
475 | op->op = *tok_start; | ||
476 | break; | ||
477 | } | ||
478 | } | ||
479 | |||
480 | /* Parse a C escape sequence. STRING_PTR points to a variable | ||
481 | * containing a pointer to the string to parse. That pointer | ||
482 | * is updated past the characters we use. The value of the | ||
483 | * escape sequence is returned. | ||
484 | * | ||
485 | * A negative value means the sequence \ newline was seen, | ||
486 | * which is supposed to be equivalent to nothing at all. | ||
487 | * | ||
488 | * If \ is followed by a null character, we return a negative | ||
489 | * value and leave the string pointer pointing at the null character. | ||
490 | * | ||
491 | * If \ is followed by 000, we return 0 and leave the string pointer | ||
492 | * after the zeros. A value of 0 does not mean end of string. */ | ||
493 | |||
494 | int | ||
495 | cpp_parse_escape(cpp_reader * pfile, char **string_ptr) | ||
496 | { | ||
497 | int c = *(*string_ptr)++; | ||
498 | |||
499 | switch (c) | ||
500 | { | ||
501 | case 'a': | ||
502 | return TARGET_BELL; | ||
503 | case 'b': | ||
504 | return TARGET_BS; | ||
505 | case 'e': | ||
506 | case 'E': | ||
507 | if (CPP_PEDANTIC(pfile)) | ||
508 | cpp_pedwarn(pfile, "non-ANSI-standard escape sequence, `\\%c'", c); | ||
509 | return 033; | ||
510 | case 'f': | ||
511 | return TARGET_FF; | ||
512 | case 'n': | ||
513 | return TARGET_NEWLINE; | ||
514 | case 'r': | ||
515 | return TARGET_CR; | ||
516 | case 't': | ||
517 | return TARGET_TAB; | ||
518 | case 'v': | ||
519 | return TARGET_VT; | ||
520 | case '\n': | ||
521 | return -2; | ||
522 | case 0: | ||
523 | (*string_ptr)--; | ||
524 | return 0; | ||
525 | |||
526 | case '0': | ||
527 | case '1': | ||
528 | case '2': | ||
529 | case '3': | ||
530 | case '4': | ||
531 | case '5': | ||
532 | case '6': | ||
533 | case '7': | ||
534 | { | ||
535 | int i = c - '0'; | ||
536 | int count = 0; | ||
537 | |||
538 | while (++count < 3) | ||
539 | { | ||
540 | c = *(*string_ptr)++; | ||
541 | if (c >= '0' && c <= '7') | ||
542 | i = (i << 3) + c - '0'; | ||
543 | else | ||
544 | { | ||
545 | (*string_ptr)--; | ||
546 | break; | ||
547 | } | ||
548 | } | ||
549 | if ((i & ~((1 << MAX_CHAR_TYPE_SIZE) - 1)) != 0) | ||
550 | { | ||
551 | i &= (1 << MAX_CHAR_TYPE_SIZE) - 1; | ||
552 | cpp_warning(pfile, | ||
553 | "octal character constant does not fit in a byte"); | ||
554 | } | ||
555 | return i; | ||
556 | } | ||
557 | case 'x': | ||
558 | { | ||
559 | unsigned i = 0, overflow = 0, digits_found = 0, digit; | ||
560 | |||
561 | for (;;) | ||
562 | { | ||
563 | c = *(*string_ptr)++; | ||
564 | if (c >= '0' && c <= '9') | ||
565 | digit = c - '0'; | ||
566 | else if (c >= 'a' && c <= 'f') | ||
567 | digit = c - 'a' + 10; | ||
568 | else if (c >= 'A' && c <= 'F') | ||
569 | digit = c - 'A' + 10; | ||
570 | else | ||
571 | { | ||
572 | (*string_ptr)--; | ||
573 | break; | ||
574 | } | ||
575 | overflow |= i ^ (i << 4 >> 4); | ||
576 | i = (i << 4) + digit; | ||
577 | digits_found = 1; | ||
578 | } | ||
579 | if (!digits_found) | ||
580 | cpp_error(pfile, "\\x used with no following hex digits"); | ||
581 | if (overflow | (i & ~((1 << BITS_PER_UNIT) - 1))) | ||
582 | { | ||
583 | i &= (1 << BITS_PER_UNIT) - 1; | ||
584 | cpp_warning(pfile, | ||
585 | "hex character constant does not fit in a byte"); | ||
586 | } | ||
587 | return i; | ||
588 | } | ||
589 | default: | ||
590 | return c; | ||
591 | } | ||
592 | } | ||
593 | |||
594 | static void | ||
595 | integer_overflow(cpp_reader * pfile) | ||
596 | { | ||
597 | if (CPP_PEDANTIC(pfile)) | ||
598 | cpp_pedwarn(pfile, "integer overflow in preprocessor expression"); | ||
599 | } | ||
600 | |||
601 | static long | ||
602 | left_shift(cpp_reader * pfile, long a, int unsignedp, unsigned long b) | ||
603 | { | ||
604 | if (b >= HOST_BITS_PER_LONG) | ||
605 | { | ||
606 | if (!unsignedp && a != 0) | ||
607 | integer_overflow(pfile); | ||
608 | return 0; | ||
609 | } | ||
610 | else if (unsignedp) | ||
611 | return (unsigned long)a << b; | ||
612 | else | ||
613 | { | ||
614 | long l = a << b; | ||
615 | |||
616 | if (l >> b != a) | ||
617 | integer_overflow(pfile); | ||
618 | return l; | ||
619 | } | ||
620 | } | ||
621 | |||
622 | static long | ||
623 | right_shift(cpp_reader * pfile __UNUSED__, long a, int unsignedp, | ||
624 | unsigned long b) | ||
625 | { | ||
626 | if (b >= HOST_BITS_PER_LONG) | ||
627 | { | ||
628 | return unsignedp ? 0 : a >> (HOST_BITS_PER_LONG - 1); | ||
629 | } | ||
630 | else if (unsignedp) | ||
631 | { | ||
632 | return (unsigned long)a >> b; | ||
633 | } | ||
634 | else | ||
635 | { | ||
636 | return a >> b; | ||
637 | } | ||
638 | } | ||
639 | |||
640 | /* These priorities are all even, so we can handle associatively. */ | ||
641 | #define PAREN_INNER_PRIO 0 | ||
642 | #define COMMA_PRIO 4 | ||
643 | #define COND_PRIO (COMMA_PRIO+2) | ||
644 | #define OROR_PRIO (COND_PRIO+2) | ||
645 | #define ANDAND_PRIO (OROR_PRIO+2) | ||
646 | #define OR_PRIO (ANDAND_PRIO+2) | ||
647 | #define XOR_PRIO (OR_PRIO+2) | ||
648 | #define AND_PRIO (XOR_PRIO+2) | ||
649 | #define EQUAL_PRIO (AND_PRIO+2) | ||
650 | #define LESS_PRIO (EQUAL_PRIO+2) | ||
651 | #define SHIFT_PRIO (LESS_PRIO+2) | ||
652 | #define PLUS_PRIO (SHIFT_PRIO+2) | ||
653 | #define MUL_PRIO (PLUS_PRIO+2) | ||
654 | #define UNARY_PRIO (MUL_PRIO+2) | ||
655 | #define PAREN_OUTER_PRIO (UNARY_PRIO+2) | ||
656 | |||
657 | #define COMPARE(OP) \ | ||
658 | top->unsignedp = 0;\ | ||
659 | top->value = (unsigned1 || unsigned2) ? (unsigned long) v1 OP (unsigned long) v2 : (v1 OP v2) | ||
660 | |||
661 | /* Parse and evaluate a C expression, reading from PFILE. | ||
662 | * Returns the value of the expression. */ | ||
663 | |||
664 | HOST_WIDE_INT | ||
665 | cpp_parse_expr(cpp_reader * pfile) | ||
666 | { | ||
667 | /* The implementation is an operator precedence parser, | ||
668 | * i.e. a bottom-up parser, using a stack for not-yet-reduced tokens. | ||
669 | * | ||
670 | * The stack base is 'stack', and the current stack pointer is 'top'. | ||
671 | * There is a stack element for each operator (only), | ||
672 | * and the most recently pushed operator is 'top->op'. | ||
673 | * An operand (value) is stored in the 'value' field of the stack | ||
674 | * element of the operator that precedes it. | ||
675 | * In that case the 'flags' field has the HAVE_VALUE flag set. */ | ||
676 | |||
677 | #define INIT_STACK_SIZE 20 | ||
678 | struct operation init_stack[INIT_STACK_SIZE]; | ||
679 | struct operation *stack = init_stack; | ||
680 | struct operation *limit = stack + INIT_STACK_SIZE; | ||
681 | struct operation *top = stack; | ||
682 | int lprio = 0, rprio = 0; | ||
683 | int skip_evaluation = 0; | ||
684 | |||
685 | top->rprio = 0; | ||
686 | top->flags = 0; | ||
687 | for (;;) | ||
688 | { | ||
689 | struct operation op; | ||
690 | char flags = 0; | ||
691 | |||
692 | /* Read a token */ | ||
693 | cpp_lex(&op, pfile); | ||
694 | |||
695 | /* See if the token is an operand, in which case go to set_value. | ||
696 | * If the token is an operator, figure out its left and right | ||
697 | * priorities, and then goto maybe_reduce. */ | ||
698 | |||
699 | switch (op.op) | ||
700 | { | ||
701 | case NAME: | ||
702 | top->value = 0, top->unsignedp = 0; | ||
703 | goto set_value; | ||
704 | case INT: | ||
705 | case CHAR: | ||
706 | top->value = op.value; | ||
707 | top->unsignedp = op.unsignedp; | ||
708 | goto set_value; | ||
709 | case 0: | ||
710 | lprio = 0; | ||
711 | goto maybe_reduce; | ||
712 | case '+': | ||
713 | case '-': | ||
714 | /* Is this correct if unary ? FIXME */ | ||
715 | flags = RIGHT_OPERAND_REQUIRED; | ||
716 | lprio = PLUS_PRIO; | ||
717 | rprio = lprio + 1; | ||
718 | goto maybe_reduce; | ||
719 | case '!': | ||
720 | case '~': | ||
721 | flags = RIGHT_OPERAND_REQUIRED; | ||
722 | rprio = UNARY_PRIO; | ||
723 | lprio = rprio + 1; | ||
724 | goto maybe_reduce; | ||
725 | case '*': | ||
726 | case '/': | ||
727 | case '%': | ||
728 | lprio = MUL_PRIO; | ||
729 | goto binop; | ||
730 | case '<': | ||
731 | case '>': | ||
732 | case LEQ: | ||
733 | case GEQ: | ||
734 | lprio = LESS_PRIO; | ||
735 | goto binop; | ||
736 | case EQUAL: | ||
737 | case NOTEQUAL: | ||
738 | lprio = EQUAL_PRIO; | ||
739 | goto binop; | ||
740 | case LSH: | ||
741 | case RSH: | ||
742 | lprio = SHIFT_PRIO; | ||
743 | goto binop; | ||
744 | case '&': | ||
745 | lprio = AND_PRIO; | ||
746 | goto binop; | ||
747 | case '^': | ||
748 | lprio = XOR_PRIO; | ||
749 | goto binop; | ||
750 | case '|': | ||
751 | lprio = OR_PRIO; | ||
752 | goto binop; | ||
753 | case ANDAND: | ||
754 | lprio = ANDAND_PRIO; | ||
755 | goto binop; | ||
756 | case OROR: | ||
757 | lprio = OROR_PRIO; | ||
758 | goto binop; | ||
759 | case ',': | ||
760 | lprio = COMMA_PRIO; | ||
761 | goto binop; | ||
762 | case '(': | ||
763 | lprio = PAREN_OUTER_PRIO; | ||
764 | rprio = PAREN_INNER_PRIO; | ||
765 | goto maybe_reduce; | ||
766 | case ')': | ||
767 | lprio = PAREN_INNER_PRIO; | ||
768 | rprio = PAREN_OUTER_PRIO; | ||
769 | goto maybe_reduce; | ||
770 | case ':': | ||
771 | lprio = COND_PRIO; | ||
772 | rprio = COND_PRIO; | ||
773 | goto maybe_reduce; | ||
774 | case '?': | ||
775 | lprio = COND_PRIO + 1; | ||
776 | rprio = COND_PRIO; | ||
777 | goto maybe_reduce; | ||
778 | binop: | ||
779 | flags = LEFT_OPERAND_REQUIRED | RIGHT_OPERAND_REQUIRED; | ||
780 | rprio = lprio + 1; | ||
781 | goto maybe_reduce; | ||
782 | default: | ||
783 | cpp_error(pfile, "invalid character in #if"); | ||
784 | goto syntax_error; | ||
785 | } | ||
786 | |||
787 | set_value: | ||
788 | /* Push a value onto the stack. */ | ||
789 | if (top->flags & HAVE_VALUE) | ||
790 | { | ||
791 | cpp_error(pfile, "syntax error in #if"); | ||
792 | goto syntax_error; | ||
793 | } | ||
794 | top->flags |= HAVE_VALUE; | ||
795 | continue; | ||
796 | |||
797 | maybe_reduce: | ||
798 | /* Push an operator, and check if we can reduce now. */ | ||
799 | while (top->rprio > lprio) | ||
800 | { | ||
801 | long v1 = top[-1].value, v2 = top[0].value; | ||
802 | int unsigned1 = top[-1].unsignedp, unsigned2 = | ||
803 | top[0].unsignedp; | ||
804 | |||
805 | top--; | ||
806 | if ((top[1].flags & LEFT_OPERAND_REQUIRED) | ||
807 | && !(top[0].flags & HAVE_VALUE)) | ||
808 | { | ||
809 | cpp_error(pfile, "syntax error - missing left operand"); | ||
810 | goto syntax_error; | ||
811 | } | ||
812 | if ((top[1].flags & RIGHT_OPERAND_REQUIRED) | ||
813 | && !(top[1].flags & HAVE_VALUE)) | ||
814 | { | ||
815 | cpp_error(pfile, "syntax error - missing right operand"); | ||
816 | goto syntax_error; | ||
817 | } | ||
818 | /* top[0].value = (top[1].op)(v1, v2); */ | ||
819 | switch (top[1].op) | ||
820 | { | ||
821 | case '+': | ||
822 | if (!(top->flags & HAVE_VALUE)) | ||
823 | { /* Unary '+' */ | ||
824 | top->value = v2; | ||
825 | top->unsignedp = unsigned2; | ||
826 | top->flags |= HAVE_VALUE; | ||
827 | } | ||
828 | else | ||
829 | { | ||
830 | top->value = v1 + v2; | ||
831 | top->unsignedp = unsigned1 || unsigned2; | ||
832 | if (!top->unsignedp && !skip_evaluation | ||
833 | && !possible_sum_sign(v1, v2, top->value)) | ||
834 | integer_overflow(pfile); | ||
835 | } | ||
836 | break; | ||
837 | case '-': | ||
838 | if (skip_evaluation); /* do nothing */ | ||
839 | else if (!(top->flags & HAVE_VALUE)) | ||
840 | { /* Unary '-' */ | ||
841 | top->value = -v2; | ||
842 | if ((top->value & v2) < 0 && !unsigned2) | ||
843 | integer_overflow(pfile); | ||
844 | top->unsignedp = unsigned2; | ||
845 | top->flags |= HAVE_VALUE; | ||
846 | } | ||
847 | else | ||
848 | { /* Binary '-' */ | ||
849 | top->value = v1 - v2; | ||
850 | top->unsignedp = unsigned1 || unsigned2; | ||
851 | if (!top->unsignedp | ||
852 | && !possible_sum_sign(top->value, v2, v1)) | ||
853 | integer_overflow(pfile); | ||
854 | } | ||
855 | break; | ||
856 | case '*': | ||
857 | top->unsignedp = unsigned1 || unsigned2; | ||
858 | if (top->unsignedp) | ||
859 | top->value = (unsigned long)v1 *v2; | ||
860 | |||
861 | else if (!skip_evaluation) | ||
862 | { | ||
863 | top->value = v1 * v2; | ||
864 | if (v1 | ||
865 | && (top->value / v1 != v2 | ||
866 | || (top->value & v1 & v2) < 0)) | ||
867 | integer_overflow(pfile); | ||
868 | } | ||
869 | break; | ||
870 | case '/': | ||
871 | if (skip_evaluation) | ||
872 | break; | ||
873 | if (v2 == 0) | ||
874 | { | ||
875 | cpp_error(pfile, "division by zero in #if"); | ||
876 | v2 = 1; | ||
877 | } | ||
878 | top->unsignedp = unsigned1 || unsigned2; | ||
879 | if (top->unsignedp) | ||
880 | top->value = (unsigned long)v1 / v2; | ||
881 | else | ||
882 | { | ||
883 | top->value = v1 / v2; | ||
884 | if ((top->value & v1 & v2) < 0) | ||
885 | integer_overflow(pfile); | ||
886 | } | ||
887 | break; | ||
888 | case '%': | ||
889 | if (skip_evaluation) | ||
890 | break; | ||
891 | if (v2 == 0) | ||
892 | { | ||
893 | cpp_error(pfile, "division by zero in #if"); | ||
894 | v2 = 1; | ||
895 | } | ||
896 | top->unsignedp = unsigned1 || unsigned2; | ||
897 | if (top->unsignedp) | ||
898 | top->value = (unsigned long)v1 % v2; | ||
899 | else | ||
900 | top->value = v1 % v2; | ||
901 | break; | ||
902 | case '!': | ||
903 | if (top->flags & HAVE_VALUE) | ||
904 | { | ||
905 | cpp_error(pfile, "syntax error"); | ||
906 | goto syntax_error; | ||
907 | } | ||
908 | top->value = !v2; | ||
909 | top->unsignedp = 0; | ||
910 | top->flags |= HAVE_VALUE; | ||
911 | break; | ||
912 | case '~': | ||
913 | if (top->flags & HAVE_VALUE) | ||
914 | { | ||
915 | cpp_error(pfile, "syntax error"); | ||
916 | goto syntax_error; | ||
917 | } | ||
918 | top->value = ~v2; | ||
919 | top->unsignedp = unsigned2; | ||
920 | top->flags |= HAVE_VALUE; | ||
921 | break; | ||
922 | case '<': | ||
923 | COMPARE(<); | ||
924 | break; | ||
925 | case '>': | ||
926 | COMPARE(>); | ||
927 | break; | ||
928 | case LEQ: | ||
929 | COMPARE(<=); | ||
930 | break; | ||
931 | case GEQ: | ||
932 | COMPARE(>=); | ||
933 | break; | ||
934 | case EQUAL: | ||
935 | top->value = (v1 == v2); | ||
936 | top->unsignedp = 0; | ||
937 | break; | ||
938 | case NOTEQUAL: | ||
939 | top->value = (v1 != v2); | ||
940 | top->unsignedp = 0; | ||
941 | break; | ||
942 | case LSH: | ||
943 | if (skip_evaluation) | ||
944 | break; | ||
945 | top->unsignedp = unsigned1; | ||
946 | if (v2 < 0 && !unsigned2) | ||
947 | top->value = right_shift(pfile, v1, unsigned1, -v2); | ||
948 | else | ||
949 | top->value = left_shift(pfile, v1, unsigned1, v2); | ||
950 | break; | ||
951 | case RSH: | ||
952 | if (skip_evaluation) | ||
953 | break; | ||
954 | top->unsignedp = unsigned1; | ||
955 | if (v2 < 0 && !unsigned2) | ||
956 | top->value = left_shift(pfile, v1, unsigned1, -v2); | ||
957 | else | ||
958 | top->value = right_shift(pfile, v1, unsigned1, v2); | ||
959 | break; | ||
960 | #define LOGICAL(OP) \ | ||
961 | top->value = v1 OP v2;\ | ||
962 | top->unsignedp = unsigned1 || unsigned2; | ||
963 | case '&': | ||
964 | LOGICAL(&); | ||
965 | break; | ||
966 | case '^': | ||
967 | LOGICAL(^); | ||
968 | break; | ||
969 | case '|': | ||
970 | LOGICAL(|); | ||
971 | break; | ||
972 | case ANDAND: | ||
973 | top->value = v1 && v2; | ||
974 | top->unsignedp = 0; | ||
975 | if (!v1) | ||
976 | skip_evaluation--; | ||
977 | break; | ||
978 | case OROR: | ||
979 | top->value = v1 || v2; | ||
980 | top->unsignedp = 0; | ||
981 | if (v1) | ||
982 | skip_evaluation--; | ||
983 | break; | ||
984 | case ',': | ||
985 | if (CPP_PEDANTIC(pfile)) | ||
986 | cpp_pedwarn(pfile, "comma operator in operand of `#if'"); | ||
987 | top->value = v2; | ||
988 | top->unsignedp = unsigned2; | ||
989 | break; | ||
990 | case '(': | ||
991 | case '?': | ||
992 | cpp_error(pfile, "syntax error in #if"); | ||
993 | goto syntax_error; | ||
994 | case ':': | ||
995 | if (top[0].op != '?') | ||
996 | { | ||
997 | cpp_error(pfile, | ||
998 | "syntax error ':' without preceding '?'"); | ||
999 | goto syntax_error; | ||
1000 | } | ||
1001 | else if (!(top[1].flags & HAVE_VALUE) | ||
1002 | || !(top[-1].flags & HAVE_VALUE) | ||
1003 | || !(top[0].flags & HAVE_VALUE)) | ||
1004 | { | ||
1005 | cpp_error(pfile, "bad syntax for ?: operator"); | ||
1006 | goto syntax_error; | ||
1007 | } | ||
1008 | else | ||
1009 | { | ||
1010 | top--; | ||
1011 | if (top->value) | ||
1012 | skip_evaluation--; | ||
1013 | top->value = top->value ? v1 : v2; | ||
1014 | top->unsignedp = unsigned1 || unsigned2; | ||
1015 | } | ||
1016 | break; | ||
1017 | case ')': | ||
1018 | if ((top[1].flags & HAVE_VALUE) | ||
1019 | || !(top[0].flags & HAVE_VALUE) | ||
1020 | || top[0].op != '(' || (top[-1].flags & HAVE_VALUE)) | ||
1021 | { | ||
1022 | cpp_error(pfile, "mismatched parentheses in #if"); | ||
1023 | goto syntax_error; | ||
1024 | } | ||
1025 | else | ||
1026 | { | ||
1027 | top--; | ||
1028 | top->value = v1; | ||
1029 | top->unsignedp = unsigned1; | ||
1030 | top->flags |= HAVE_VALUE; | ||
1031 | } | ||
1032 | break; | ||
1033 | default: | ||
1034 | fprintf(stderr, | ||
1035 | top[1].op >= ' ' && top[1].op <= '~' | ||
1036 | ? "unimplemented operator '%c'\n" | ||
1037 | : "unimplemented operator '\\%03o'\n", top[1].op); | ||
1038 | } | ||
1039 | } | ||
1040 | if (op.op == 0) | ||
1041 | { | ||
1042 | if (top != stack) | ||
1043 | cpp_error(pfile, "internal error in #if expression"); | ||
1044 | if (stack != init_stack) | ||
1045 | free(stack); | ||
1046 | return top->value; | ||
1047 | } | ||
1048 | top++; | ||
1049 | |||
1050 | /* Check for and handle stack overflow. */ | ||
1051 | if (top == limit) | ||
1052 | { | ||
1053 | struct operation *new_stack; | ||
1054 | int old_size = (char *)limit - (char *)stack; | ||
1055 | int new_size = 2 * old_size; | ||
1056 | |||
1057 | if (stack != init_stack) | ||
1058 | new_stack = (struct operation *)xrealloc(stack, new_size); | ||
1059 | else | ||
1060 | { | ||
1061 | new_stack = (struct operation *)xmalloc(new_size); | ||
1062 | memcpy((char *)new_stack, (char *)stack, old_size); | ||
1063 | } | ||
1064 | stack = new_stack; | ||
1065 | top = (struct operation *)((char *)new_stack + old_size); | ||
1066 | limit = (struct operation *)((char *)new_stack + new_size); | ||
1067 | } | ||
1068 | top->flags = flags; | ||
1069 | top->rprio = rprio; | ||
1070 | top->op = op.op; | ||
1071 | if ((op.op == OROR && top[-1].value) | ||
1072 | || (op.op == ANDAND && !top[-1].value) | ||
1073 | || (op.op == '?' && !top[-1].value)) | ||
1074 | { | ||
1075 | skip_evaluation++; | ||
1076 | } | ||
1077 | else if (op.op == ':') | ||
1078 | { | ||
1079 | if (top[-2].value) /* Was condition true? */ | ||
1080 | skip_evaluation++; | ||
1081 | else | ||
1082 | skip_evaluation--; | ||
1083 | } | ||
1084 | } | ||
1085 | syntax_error: | ||
1086 | if (stack != init_stack) | ||
1087 | free(stack); | ||
1088 | skip_rest_of_line(pfile); | ||
1089 | return 0; | ||
1090 | } | ||