cexp.y 28.9 KB
Newer Older
Charles Hannum committed
1
/* Parse C expressions for CCCP.
2
   Copyright (C) 1987, 1992, 94 - 97, 1998 Free Software Foundation.
Charles Hannum committed
3 4 5 6 7 8 9 10 11 12 13 14 15

This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Richard Kenner committed
16 17
Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
Charles Hannum committed
18 19 20 21 22

 In other words, you are welcome to use, share and improve this program.
 You are forbidden to forbid anyone else to use, share and improve
 what you give them.   Help stamp out software-hoarding!

Richard Stallman committed
23
 Adapted from expread.y of GDB by Paul Rubin, July 1986.  */
Charles Hannum committed
24 25 26 27 28

/* Parse a C expression from text in a string  */
   
%{
#include "config.h"
29

30 31
#define PRINTF_PROTO(ARGS, m, n) PVPROTO (ARGS) ATTRIBUTE_PRINTF(m, n)

32
#define PRINTF_PROTO_1(ARGS) PRINTF_PROTO(ARGS, 1, 2)
33

34 35 36
#include "system.h"
#include <setjmp.h>
/* #define YYDEBUG 1 */
Jeff Law committed
37

Charles Hannum committed
38
#ifdef MULTIBYTE_CHARS
39
#include "mbchar.h"
Charles Hannum committed
40
#include <locale.h>
41
#endif /* MULTIBYTE_CHARS */
42

Charles Hannum committed
43 44 45 46 47 48 49 50 51 52
typedef unsigned char U_CHAR;

/* This is used for communicating lists of keywords with cccp.c.  */
struct arglist {
  struct arglist *next;
  U_CHAR *name;
  int length;
  int argno;
};

53
/* Find the largest host integer type and set its size and type.
Jeff Law committed
54
   Watch out: on some crazy hosts `long' is shorter than `int'.  */
55

Jeff Law committed
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
#ifndef HOST_WIDE_INT
# if HAVE_INTTYPES_H
#  include <inttypes.h>
#  define HOST_WIDE_INT intmax_t
#  define unsigned_HOST_WIDE_INT uintmax_t
# else
#  if (HOST_BITS_PER_LONG <= HOST_BITS_PER_INT && HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_INT)
#   define HOST_WIDE_INT int
#  else
#  if (HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_LONG || ! (defined LONG_LONG_MAX || defined LLONG_MAX))
#   define HOST_WIDE_INT long
#  else
#   define HOST_WIDE_INT long long
#  endif
#  endif
# endif
#endif
73

Jeff Law committed
74 75
#ifndef unsigned_HOST_WIDE_INT
#define unsigned_HOST_WIDE_INT unsigned HOST_WIDE_INT
76 77
#endif

Jeff Law committed
78 79 80 81 82 83
#ifndef CHAR_BIT
#define CHAR_BIT 8
#endif

#ifndef HOST_BITS_PER_WIDE_INT
#define HOST_BITS_PER_WIDE_INT (CHAR_BIT * sizeof (HOST_WIDE_INT))
84 85
#endif

Jeff Law committed
86
HOST_WIDE_INT parse_c_expression PROTO((char *, int));
87 88 89

static int yylex PROTO((void));
static void yyerror PROTO((char *)) __attribute__ ((noreturn));
90
static HOST_WIDE_INT expression_value;
Jeff Law committed
91 92 93
#ifdef TEST_EXP_READER
static int expression_signedp;
#endif
Charles Hannum committed
94 95 96 97 98 99

static jmp_buf parse_return_error;

/* Nonzero means count most punctuation as part of a name.  */
static int keyword_parsing = 0;

100 101 102 103
/* Nonzero means do not evaluate this expression.
   This is a count, since unevaluated expressions can nest.  */
static int skip_evaluation;

Jeff Law committed
104 105 106
/* Nonzero means warn if undefined identifiers are evaluated.  */
static int warn_undef;

Charles Hannum committed
107
/* some external tables of character types */
108
extern unsigned char is_idstart[], is_idchar[], is_space[];
Charles Hannum committed
109 110 111 112 113 114 115

/* Flag for -pedantic.  */
extern int pedantic;

/* Flag for -traditional.  */
extern int traditional;

116 117 118
/* Flag for -lang-c89.  */
extern int c89;

Charles Hannum committed
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
#ifndef CHAR_TYPE_SIZE
#define CHAR_TYPE_SIZE BITS_PER_UNIT
#endif

#ifndef INT_TYPE_SIZE
#define INT_TYPE_SIZE BITS_PER_WORD
#endif

#ifndef LONG_TYPE_SIZE
#define LONG_TYPE_SIZE BITS_PER_WORD
#endif

#ifndef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE INT_TYPE_SIZE
#endif
134

135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
#ifndef MAX_CHAR_TYPE_SIZE
#define MAX_CHAR_TYPE_SIZE CHAR_TYPE_SIZE
#endif

#ifndef MAX_INT_TYPE_SIZE
#define MAX_INT_TYPE_SIZE INT_TYPE_SIZE
#endif

#ifndef MAX_LONG_TYPE_SIZE
#define MAX_LONG_TYPE_SIZE LONG_TYPE_SIZE
#endif

#ifndef MAX_WCHAR_TYPE_SIZE
#define MAX_WCHAR_TYPE_SIZE WCHAR_TYPE_SIZE
#endif

Jeff Law committed
151 152 153
#define MAX_CHAR_TYPE_MASK (MAX_CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT \
			    ? (~ (~ (HOST_WIDE_INT) 0 << MAX_CHAR_TYPE_SIZE)) \
			    : ~ (HOST_WIDE_INT) 0)
154

Jeff Law committed
155 156 157
#define MAX_WCHAR_TYPE_MASK (MAX_WCHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT \
			     ? ~ (~ (HOST_WIDE_INT) 0 << MAX_WCHAR_TYPE_SIZE) \
			     : ~ (HOST_WIDE_INT) 0)
158

159 160 161 162 163 164 165 166 167 168 169 170 171
/* Suppose A1 + B1 = SUM1, using 2's complement arithmetic ignoring overflow.
   Suppose A, B and SUM have the same respective signs as A1, B1, and SUM1.
   Suppose SIGNEDP is negative if the result is signed, zero if unsigned.
   Then this yields nonzero if overflow occurred during the addition.
   Overflow occurs if A and B have the same sign, but A and SUM differ in sign,
   and SIGNEDP is negative.
   Use `^' to test whether signs differ, and `< 0' to isolate the sign.  */
#define overflow_sum_sign(a, b, sum, signedp) \
	((~((a) ^ (b)) & ((a) ^ (sum)) & (signedp)) < 0)

struct constant;

GENERIC_PTR xmalloc PROTO((size_t));
172
HOST_WIDE_INT parse_escape PROTO((char **, HOST_WIDE_INT));
173 174 175 176 177 178 179
int check_assertion PROTO((U_CHAR *, int, int, struct arglist *));
struct hashnode *lookup PROTO((U_CHAR *, int, int));
void error PRINTF_PROTO_1((char *, ...));
void pedwarn PRINTF_PROTO_1((char *, ...));
void warning PRINTF_PROTO_1((char *, ...));

static int parse_number PROTO((int));
Jeff Law committed
180 181
static HOST_WIDE_INT left_shift PROTO((struct constant *, unsigned_HOST_WIDE_INT));
static HOST_WIDE_INT right_shift PROTO((struct constant *, unsigned_HOST_WIDE_INT));
182 183 184 185 186
static void integer_overflow PROTO((void));

/* `signedp' values */
#define SIGNED (~0)
#define UNSIGNED 0
Charles Hannum committed
187 188 189
%}

%union {
190
  struct constant {HOST_WIDE_INT value; int signedp;} integer;
Charles Hannum committed
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
  struct name {U_CHAR *address; int length;} name;
  struct arglist *keywords;
}

%type <integer> exp exp1 start
%type <keywords> keywords
%token <integer> INT CHAR
%token <name> NAME
%token <integer> ERROR

%right '?' ':'
%left ','
%left OR
%left AND
%left '|'
%left '^'
%left '&'
%left EQUAL NOTEQUAL
%left '<' '>' LEQ GEQ
%left LSH RSH
%left '+' '-'
%left '*' '/' '%'
%right UNARY

/* %expect 40 */

%%

start   :	exp1
Jeff Law committed
220 221 222 223 224 225
		{
		  expression_value = $1.value;
#ifdef TEST_EXP_READER
		  expression_signedp = $1.signedp;
#endif
		}
Charles Hannum committed
226 227 228 229 230 231 232 233 234 235 236 237 238
	;

/* Expressions, including the comma operator.  */
exp1	:	exp
	|	exp1 ',' exp
			{ if (pedantic)
			    pedwarn ("comma operator in operand of `#if'");
			  $$ = $3; }
	;

/* Expressions, not including the comma operator.  */
exp	:	'-' exp    %prec UNARY
			{ $$.value = - $2.value;
239 240 241
			  $$.signedp = $2.signedp;
			  if (($$.value & $2.value & $$.signedp) < 0)
			    integer_overflow (); }
Charles Hannum committed
242 243
	|	'!' exp    %prec UNARY
			{ $$.value = ! $2.value;
244
			  $$.signedp = SIGNED; }
Charles Hannum committed
245 246 247 248
	|	'+' exp    %prec UNARY
			{ $$ = $2; }
	|	'~' exp    %prec UNARY
			{ $$.value = ~ $2.value;
249
			  $$.signedp = $2.signedp; }
Charles Hannum committed
250 251 252
	|	'#' NAME
  			{ $$.value = check_assertion ($2.address, $2.length,
						      0, NULL_PTR);
253
			  $$.signedp = SIGNED; }
Charles Hannum committed
254 255 256 257 258 259
	|	'#' NAME
			{ keyword_parsing = 1; }
		'(' keywords ')'
  			{ $$.value = check_assertion ($2.address, $2.length,
						      1, $5);
			  keyword_parsing = 0;
260
			  $$.signedp = SIGNED; }
Charles Hannum committed
261 262 263 264 265 266
	|	'(' exp1 ')'
			{ $$ = $2; }
	;

/* Binary operators in order of decreasing precedence.  */
exp	:	exp '*' exp
267 268
			{ $$.signedp = $1.signedp & $3.signedp;
			  if ($$.signedp)
269 270 271 272 273 274
			    {
			      $$.value = $1.value * $3.value;
			      if ($1.value
				  && ($$.value / $1.value != $3.value
				      || ($$.value & $1.value & $3.value) < 0))
				integer_overflow ();
275 276
			    }
			  else
Jeff Law committed
277
			    $$.value = ((unsigned_HOST_WIDE_INT) $1.value
278
					* $3.value); }
Charles Hannum committed
279 280 281
	|	exp '/' exp
			{ if ($3.value == 0)
			    {
282 283
			      if (!skip_evaluation)
				error ("division by zero in #if");
Charles Hannum committed
284 285
			      $3.value = 1;
			    }
286 287
			  $$.signedp = $1.signedp & $3.signedp;
			  if ($$.signedp)
288 289 290 291
			    {
			      $$.value = $1.value / $3.value;
			      if (($$.value & $1.value & $3.value) < 0)
				integer_overflow ();
292 293
			    }
			  else
Jeff Law committed
294
			    $$.value = ((unsigned_HOST_WIDE_INT) $1.value
295
					/ $3.value); }
Charles Hannum committed
296 297 298
	|	exp '%' exp
			{ if ($3.value == 0)
			    {
299 300
			      if (!skip_evaluation)
				error ("division by zero in #if");
Charles Hannum committed
301 302
			      $3.value = 1;
			    }
303 304 305
			  $$.signedp = $1.signedp & $3.signedp;
			  if ($$.signedp)
			    $$.value = $1.value % $3.value;
Charles Hannum committed
306
			  else
Jeff Law committed
307
			    $$.value = ((unsigned_HOST_WIDE_INT) $1.value
308
					% $3.value); }
Charles Hannum committed
309 310
	|	exp '+' exp
			{ $$.value = $1.value + $3.value;
311 312 313
			  $$.signedp = $1.signedp & $3.signedp;
			  if (overflow_sum_sign ($1.value, $3.value,
						 $$.value, $$.signedp))
314
			    integer_overflow (); }
Charles Hannum committed
315 316
	|	exp '-' exp
			{ $$.value = $1.value - $3.value;
317 318 319
			  $$.signedp = $1.signedp & $3.signedp;
			  if (overflow_sum_sign ($$.value, $3.value,
						 $1.value, $$.signedp))
320
			    integer_overflow (); }
Charles Hannum committed
321
	|	exp LSH exp
322 323
			{ $$.signedp = $1.signedp;
			  if (($3.value & $3.signedp) < 0)
324
			    $$.value = right_shift (&$1, -$3.value);
Charles Hannum committed
325
			  else
326
			    $$.value = left_shift (&$1, $3.value); }
Charles Hannum committed
327
	|	exp RSH exp
328 329
			{ $$.signedp = $1.signedp;
			  if (($3.value & $3.signedp) < 0)
330
			    $$.value = left_shift (&$1, -$3.value);
Charles Hannum committed
331
			  else
332
			    $$.value = right_shift (&$1, $3.value); }
Charles Hannum committed
333 334
	|	exp EQUAL exp
			{ $$.value = ($1.value == $3.value);
335
			  $$.signedp = SIGNED; }
Charles Hannum committed
336 337
	|	exp NOTEQUAL exp
			{ $$.value = ($1.value != $3.value);
338
			  $$.signedp = SIGNED; }
Charles Hannum committed
339
	|	exp LEQ exp
340 341 342
			{ $$.signedp = SIGNED;
			  if ($1.signedp & $3.signedp)
			    $$.value = $1.value <= $3.value;
Charles Hannum committed
343
			  else
Jeff Law committed
344
			    $$.value = ((unsigned_HOST_WIDE_INT) $1.value
345
					<= $3.value); }
Charles Hannum committed
346
	|	exp GEQ exp
347 348 349
			{ $$.signedp = SIGNED;
			  if ($1.signedp & $3.signedp)
			    $$.value = $1.value >= $3.value;
Charles Hannum committed
350
			  else
Jeff Law committed
351
			    $$.value = ((unsigned_HOST_WIDE_INT) $1.value
352
					>= $3.value); }
Charles Hannum committed
353
	|	exp '<' exp
354 355 356
			{ $$.signedp = SIGNED;
			  if ($1.signedp & $3.signedp)
			    $$.value = $1.value < $3.value;
Charles Hannum committed
357
			  else
Jeff Law committed
358
			    $$.value = ((unsigned_HOST_WIDE_INT) $1.value
359
					< $3.value); }
Charles Hannum committed
360
	|	exp '>' exp
361 362 363
			{ $$.signedp = SIGNED;
			  if ($1.signedp & $3.signedp)
			    $$.value = $1.value > $3.value;
Charles Hannum committed
364
			  else
Jeff Law committed
365
			    $$.value = ((unsigned_HOST_WIDE_INT) $1.value
366
					> $3.value); }
Charles Hannum committed
367 368
	|	exp '&' exp
			{ $$.value = $1.value & $3.value;
369
			  $$.signedp = $1.signedp & $3.signedp; }
Charles Hannum committed
370 371
	|	exp '^' exp
			{ $$.value = $1.value ^ $3.value;
372
			  $$.signedp = $1.signedp & $3.signedp; }
Charles Hannum committed
373 374
	|	exp '|' exp
			{ $$.value = $1.value | $3.value;
375
			  $$.signedp = $1.signedp & $3.signedp; }
376 377 378 379 380
	|	exp AND
			{ skip_evaluation += !$1.value; }
		exp
			{ skip_evaluation -= !$1.value;
			  $$.value = ($1.value && $4.value);
381
			  $$.signedp = SIGNED; }
382 383 384 385 386
	|	exp OR
			{ skip_evaluation += !!$1.value; }
		exp
			{ skip_evaluation -= !!$1.value;
			  $$.value = ($1.value || $4.value);
387
			  $$.signedp = SIGNED; }
388 389 390 391 392 393 394
	|	exp '?'
			{ skip_evaluation += !$1.value; }
	        exp ':'
			{ skip_evaluation += !!$1.value - !$1.value; }
		exp
			{ skip_evaluation -= !!$1.value;
			  $$.value = $1.value ? $4.value : $7.value;
395
			  $$.signedp = $4.signedp & $7.signedp; }
Charles Hannum committed
396 397 398 399 400
	|	INT
			{ $$ = yylval.integer; }
	|	CHAR
			{ $$ = yylval.integer; }
	|	NAME
401 402 403 404
			{ if (warn_undef && !skip_evaluation)
			    warning ("`%.*s' is not defined",
				     $1.length, $1.address);
			  $$.value = 0;
405
			  $$.signedp = SIGNED; }
Charles Hannum committed
406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
	;

keywords :
			{ $$ = 0; } 
	|	'(' keywords ')' keywords
			{ struct arglist *temp;
			  $$ = (struct arglist *) xmalloc (sizeof (struct arglist));
			  $$->next = $2;
			  $$->name = (U_CHAR *) "(";
			  $$->length = 1;
			  temp = $$;
			  while (temp != 0 && temp->next != 0)
			    temp = temp->next;
			  temp->next = (struct arglist *) xmalloc (sizeof (struct arglist));
			  temp->next->next = $4;
			  temp->next->name = (U_CHAR *) ")";
			  temp->next->length = 1; }
	|	NAME keywords
			{ $$ = (struct arglist *) xmalloc (sizeof (struct arglist));
			  $$->name = $1.address;
			  $$->length = $1.length;
			  $$->next = $2; } 
	;
%%

/* During parsing of a C expression, the pointer to the next character
   is in this variable.  */

static char *lexptr;

/* Take care of parsing a number (anything that starts with a digit).
   Set yylval and return the token type; update lexptr.
   LEN is the number of characters in it.  */

/* maybe needs to actually deal with floating point numbers */

442
static int
Charles Hannum committed
443 444 445 446 447
parse_number (olen)
     int olen;
{
  register char *p = lexptr;
  register int c;
Jeff Law committed
448
  register unsigned_HOST_WIDE_INT n = 0, nd, max_over_base;
Charles Hannum committed
449 450
  register int base = 10;
  register int len = olen;
451
  register int overflow = 0;
452
  register int digit, largest_digit = 0;
453
  int spec_long = 0;
Charles Hannum committed
454

455
  yylval.integer.signedp = SIGNED;
Charles Hannum committed
456

457
  if (*p == '0') {
Charles Hannum committed
458
    base = 8;
459 460 461 462 463 464
    if (len >= 3 && (p[1] == 'x' || p[1] == 'X')) {
      p += 2;
      base = 16;
      len -= 2;
    }
  }
Charles Hannum committed
465

Jeff Law committed
466
  max_over_base = (unsigned_HOST_WIDE_INT) -1 / base;
467 468

  for (; len > 0; len--) {
Charles Hannum committed
469
    c = *p++;
470 471 472 473 474 475 476 477

    if (c >= '0' && c <= '9')
      digit = c - '0';
    else if (base == 16 && c >= 'a' && c <= 'f')
      digit = c - 'a' + 10;
    else if (base == 16 && c >= 'A' && c <= 'F')
      digit = c - 'A' + 10;
    else {
Charles Hannum committed
478 479 480
      /* `l' means long, and `u' means unsigned.  */
      while (1) {
	if (c == 'l' || c == 'L')
481
	  {
482 483 484
	    if (!pedantic < spec_long)
	      yyerror ("too many `l's in integer constant");
	    spec_long++;
485
	  }
Charles Hannum committed
486
	else if (c == 'u' || c == 'U')
487
	  {
488
	    if (! yylval.integer.signedp)
489
	      yyerror ("two `u's in integer constant");
490
	    yylval.integer.signedp = UNSIGNED;
491
	  }
492
	else {
493
	  if (c == '.' || c == 'e' || c == 'E' || c == 'p' || c == 'P')
494 495 496 497 498 499 500 501
	    yyerror ("Floating point numbers not allowed in #if expressions");
	  else {
	    char *buf = (char *) alloca (p - lexptr + 40);
	    sprintf (buf, "missing white space after number `%.*s'",
		     (int) (p - lexptr - 1), lexptr);
	    yyerror (buf);
	  }
	}
Charles Hannum committed
502

503
	if (--len == 0)
Charles Hannum committed
504 505 506 507 508 509
	  break;
	c = *p++;
      }
      /* Don't look for any more digits after the suffixes.  */
      break;
    }
510 511 512
    if (largest_digit < digit)
      largest_digit = digit;
    nd = n * base + digit;
513
    overflow |= (max_over_base < n) | (nd < n);
514
    n = nd;
Charles Hannum committed
515 516
  }

517
  if (base <= largest_digit)
518
    pedwarn ("integer constant contains digits beyond the radix");
519

520
  if (overflow)
521
    pedwarn ("integer constant out of range");
522

Charles Hannum committed
523
  /* If too big to be signed, consider it unsigned.  */
524
  if (((HOST_WIDE_INT) n & yylval.integer.signedp) < 0)
525 526 527
    {
      if (base == 10)
	warning ("integer constant is so large that it is unsigned");
528
      yylval.integer.signedp = UNSIGNED;
529
    }
Charles Hannum committed
530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556

  lexptr = p;
  yylval.integer.value = n;
  return INT;
}

struct token {
  char *operator;
  int token;
};

static struct token tokentab2[] = {
  {"&&", AND},
  {"||", OR},
  {"<<", LSH},
  {">>", RSH},
  {"==", EQUAL},
  {"!=", NOTEQUAL},
  {"<=", LEQ},
  {">=", GEQ},
  {"++", ERROR},
  {"--", ERROR},
  {NULL, ERROR}
};

/* Read one token, getting characters through lexptr.  */

557
static int
Charles Hannum committed
558 559 560 561
yylex ()
{
  register int c;
  register int namelen;
562
  register unsigned char *tokstart;
Charles Hannum committed
563 564
  register struct token *toktab;
  int wide_flag;
565
  HOST_WIDE_INT mask;
Charles Hannum committed
566 567 568

 retry:

569
  tokstart = (unsigned char *) lexptr;
Charles Hannum committed
570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585
  c = *tokstart;
  /* See if it is a special token of length 2.  */
  if (! keyword_parsing)
    for (toktab = tokentab2; toktab->operator != NULL; toktab++)
      if (c == *toktab->operator && tokstart[1] == toktab->operator[1]) {
	lexptr += 2;
	if (toktab->token == ERROR)
	  {
	    char *buf = (char *) alloca (40);
	    sprintf (buf, "`%s' not allowed in operand of `#if'", toktab->operator);
	    yyerror (buf);
	  }
	return toktab->token;
      }

  switch (c) {
586
  case '\n':
Charles Hannum committed
587 588 589 590 591 592 593 594 595 596 597 598 599 600
    return 0;
    
  case ' ':
  case '\t':
  case '\r':
    lexptr++;
    goto retry;
    
  case 'L':
    /* Capital L may start a wide-string or wide-character constant.  */
    if (lexptr[1] == '\'')
      {
	lexptr++;
	wide_flag = 1;
601
	mask = MAX_WCHAR_TYPE_MASK;
Charles Hannum committed
602 603 604 605 606 607
	goto char_constant;
      }
    if (lexptr[1] == '"')
      {
	lexptr++;
	wide_flag = 1;
608
	mask = MAX_WCHAR_TYPE_MASK;
Charles Hannum committed
609 610 611 612 613 614
	goto string_constant;
      }
    break;

  case '\'':
    wide_flag = 0;
615
    mask = MAX_CHAR_TYPE_MASK;
Charles Hannum committed
616 617 618 619 620 621 622
  char_constant:
    lexptr++;
    if (keyword_parsing) {
      char *start_ptr = lexptr - 1;
      while (1) {
	c = *lexptr++;
	if (c == '\\')
623
	  c = parse_escape (&lexptr, mask);
Charles Hannum committed
624 625 626
	else if (c == '\'')
	  break;
      }
627
      yylval.name.address = tokstart;
Charles Hannum committed
628 629 630 631 632 633 634 635
      yylval.name.length = lexptr - start_ptr;
      return NAME;
    }

    /* This code for reading a character constant
       handles multicharacter constants and wide characters.
       It is mostly copied from c-lex.c.  */
    {
636
      register HOST_WIDE_INT result = 0;
Jeff Law committed
637
      register int num_chars = 0;
638
      int chars_seen = 0;
639
      unsigned width = MAX_CHAR_TYPE_SIZE;
Charles Hannum committed
640 641
      int max_chars;
#ifdef MULTIBYTE_CHARS
642 643 644
      int longest_char = local_mb_cur_max ();
      char *token_buffer = (char *) alloca (longest_char);
      (void) local_mbtowc (NULL_PTR, NULL_PTR, 0);
Charles Hannum committed
645 646
#endif

647 648 649
      max_chars = MAX_LONG_TYPE_SIZE / width;
      if (wide_flag)
	width = MAX_WCHAR_TYPE_SIZE;
Charles Hannum committed
650 651 652 653 654 655 656 657

      while (1)
	{
	  c = *lexptr++;

	  if (c == '\'' || c == EOF)
	    break;

658
	  ++chars_seen;
Charles Hannum committed
659 660
	  if (c == '\\')
	    {
661
	      c = parse_escape (&lexptr, mask);
Charles Hannum committed
662
	    }
663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708
	  else
	    {
#ifdef MULTIBYTE_CHARS
	      wchar_t wc;
	      int i;
	      int char_len = -1;
	      for (i = 1; i <= longest_char; ++i)
		{
		  token_buffer[i - 1] = c;
		  char_len = local_mbtowc (& wc, token_buffer, i);
		  if (char_len != -1)
		    break;
		  c = *lexptr++;
		}
	      if (char_len > 1)
		{
		  /* mbtowc sometimes needs an extra char before accepting */
		  if (char_len < i)
		    lexptr--;
		  if (! wide_flag)
		    {
		      /* Merge character into result; ignore excess chars.  */
		      for (i = 1; i <= char_len; ++i)
			{
			  if (i > max_chars)
			    break;
			  if (width < HOST_BITS_PER_INT)
			    result = (result << width)
			      | (token_buffer[i - 1]
				 & ((1 << width) - 1));
			  else
			    result = token_buffer[i - 1];
			}
		      num_chars += char_len;
		      continue;
		    }
		}
	      else
		{
		  if (char_len == -1)
		    warning ("Ignoring invalid multibyte character");
		}
	      if (wide_flag)
		c = wc;
#endif /* ! MULTIBYTE_CHARS */
	    }
Charles Hannum committed
709

710 711 712 713 714 715
	  if (wide_flag)
	    {
	      if (chars_seen == 1) /* only keep the first one */
		result = c;
	      continue;
	    }
Charles Hannum committed
716 717

	  /* Merge character into result; ignore excess chars.  */
718
	  num_chars++;
719
	  if (num_chars <= max_chars)
Charles Hannum committed
720
	    {
721 722
	      if (width < HOST_BITS_PER_INT)
		result = (result << width) | (c & ((1 << width) - 1));
Charles Hannum committed
723 724 725 726 727 728 729
	      else
		result = c;
	    }
	}

      if (c != '\'')
	error ("malformatted character constant");
730
      else if (chars_seen == 0)
Charles Hannum committed
731 732 733 734 735 736
	error ("empty character constant");
      else if (num_chars > max_chars)
	{
	  num_chars = max_chars;
	  error ("character constant too long");
	}
737
      else if (chars_seen != 1 && ! traditional)
Charles Hannum committed
738 739 740 741 742 743
	warning ("multi-character character constant");

      /* If char type is signed, sign-extend the constant.  */
      if (! wide_flag)
	{
	  int num_bits = num_chars * width;
744 745 746 747
	  if (num_bits == 0)
	    /* We already got an error; avoid invalid shift.  */
	    yylval.integer.value = 0;
	  else if (lookup ((U_CHAR *) "__CHAR_UNSIGNED__",
748
		      sizeof ("__CHAR_UNSIGNED__") - 1, -1)
Charles Hannum committed
749 750
	      || ((result >> (num_bits - 1)) & 1) == 0)
	    yylval.integer.value
Jeff Law committed
751
	      = result & (~ (unsigned_HOST_WIDE_INT) 0
752
			  >> (HOST_BITS_PER_WIDE_INT - num_bits));
Charles Hannum committed
753 754
	  else
	    yylval.integer.value
Jeff Law committed
755
	      = result | ~(~ (unsigned_HOST_WIDE_INT) 0
756
			   >> (HOST_BITS_PER_WIDE_INT - num_bits));
Charles Hannum committed
757 758 759 760 761 762 763 764
	}
      else
	{
	  yylval.integer.value = result;
	}
    }

    /* This is always a signed type.  */
765
    yylval.integer.signedp = SIGNED;
Charles Hannum committed
766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801
    
    return CHAR;

    /* some of these chars are invalid in constant expressions;
       maybe do something about them later */
  case '/':
  case '+':
  case '-':
  case '*':
  case '%':
  case '|':
  case '&':
  case '^':
  case '~':
  case '!':
  case '@':
  case '<':
  case '>':
  case '[':
  case ']':
  case '.':
  case '?':
  case ':':
  case '=':
  case '{':
  case '}':
  case ',':
  case '#':
    if (keyword_parsing)
      break;
  case '(':
  case ')':
    lexptr++;
    return c;

  case '"':
802
    mask = MAX_CHAR_TYPE_MASK;
Charles Hannum committed
803 804 805 806 807 808 809
  string_constant:
    if (keyword_parsing) {
      char *start_ptr = lexptr;
      lexptr++;
      while (1) {
	c = *lexptr++;
	if (c == '\\')
810
	  c = parse_escape (&lexptr, mask);
Charles Hannum committed
811 812 813
	else if (c == '"')
	  break;
      }
814
      yylval.name.address = tokstart;
Charles Hannum committed
815 816 817 818 819 820 821 822 823
      yylval.name.length = lexptr - start_ptr;
      return NAME;
    }
    yyerror ("string constants not allowed in #if expressions");
    return ERROR;
  }

  if (c >= '0' && c <= '9' && !keyword_parsing) {
    /* It's a number */
824 825 826
    for (namelen = 1; ; namelen++) {
      int d = tokstart[namelen];
      if (! ((is_idchar[d] || d == '.')
827 828 829
	     || ((d == '-' || d == '+')
		 && (c == 'e' || c == 'E'
		     || ((c == 'p' || c == 'P') && ! c89))
830 831 832 833
		 && ! traditional)))
	break;
      c = d;
    }
Charles Hannum committed
834 835 836 837 838 839 840
    return parse_number (namelen);
  }

  /* It is a name.  See how long it is.  */

  if (keyword_parsing) {
    for (namelen = 0;; namelen++) {
841
      if (is_space[tokstart[namelen]])
Charles Hannum committed
842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858
	break;
      if (tokstart[namelen] == '(' || tokstart[namelen] == ')')
	break;
      if (tokstart[namelen] == '"' || tokstart[namelen] == '\'')
	break;
    }
  } else {
    if (!is_idstart[c]) {
      yyerror ("Invalid token in expression");
      return ERROR;
    }

    for (namelen = 0; is_idchar[tokstart[namelen]]; namelen++)
      ;
  }
  
  lexptr += namelen;
859
  yylval.name.address = tokstart;
Charles Hannum committed
860 861 862 863 864 865 866 867 868 869
  yylval.name.length = namelen;
  return NAME;
}


/* Parse a C escape sequence.  STRING_PTR points to a variable
   containing a pointer to the string to parse.  That pointer
   is updated past the characters we use.  The value of the
   escape sequence is returned.

870 871 872
   RESULT_MASK is used to mask out the result;
   an error is reported if bits are lost thereby.

Charles Hannum committed
873 874 875 876 877 878 879 880 881
   A negative value means the sequence \ newline was seen,
   which is supposed to be equivalent to nothing at all.

   If \ is followed by a null character, we return a negative
   value and leave the string pointer pointing at the null character.

   If \ is followed by 000, we return 0 and leave the string pointer
   after the zeros.  A value of 0 does not mean end of string.  */

882
HOST_WIDE_INT
883
parse_escape (string_ptr, result_mask)
Charles Hannum committed
884
     char **string_ptr;
885
     HOST_WIDE_INT result_mask;
Charles Hannum committed
886 887 888 889 890 891 892 893 894
{
  register int c = *(*string_ptr)++;
  switch (c)
    {
    case 'a':
      return TARGET_BELL;
    case 'b':
      return TARGET_BS;
    case 'e':
895 896 897
    case 'E':
      if (pedantic)
	pedwarn ("non-ANSI-standard escape sequence, `\\%c'", c);
Charles Hannum committed
898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923
      return 033;
    case 'f':
      return TARGET_FF;
    case 'n':
      return TARGET_NEWLINE;
    case 'r':
      return TARGET_CR;
    case 't':
      return TARGET_TAB;
    case 'v':
      return TARGET_VT;
    case '\n':
      return -2;
    case 0:
      (*string_ptr)--;
      return 0;
      
    case '0':
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
      {
924
	register HOST_WIDE_INT i = c - '0';
Charles Hannum committed
925 926 927 928 929 930 931 932 933 934 935 936
	register int count = 0;
	while (++count < 3)
	  {
	    c = *(*string_ptr)++;
	    if (c >= '0' && c <= '7')
	      i = (i << 3) + c - '0';
	    else
	      {
		(*string_ptr)--;
		break;
	      }
	  }
937
	if (i != (i & result_mask))
Charles Hannum committed
938
	  {
939 940
	    i &= result_mask;
	    pedwarn ("octal escape sequence out of range");
Charles Hannum committed
941 942 943 944 945
	  }
	return i;
      }
    case 'x':
      {
Jeff Law committed
946
	register unsigned_HOST_WIDE_INT i = 0, overflow = 0;
947
	register int digits_found = 0, digit;
Charles Hannum committed
948 949 950 951
	for (;;)
	  {
	    c = *(*string_ptr)++;
	    if (c >= '0' && c <= '9')
952
	      digit = c - '0';
Charles Hannum committed
953
	    else if (c >= 'a' && c <= 'f')
954
	      digit = c - 'a' + 10;
Charles Hannum committed
955
	    else if (c >= 'A' && c <= 'F')
956
	      digit = c - 'A' + 10;
Charles Hannum committed
957 958 959 960 961
	    else
	      {
		(*string_ptr)--;
		break;
	      }
962 963 964
	    overflow |= i ^ (i << 4 >> 4);
	    i = (i << 4) + digit;
	    digits_found = 1;
Charles Hannum committed
965
	  }
966 967
	if (!digits_found)
	  yyerror ("\\x used with no following hex digits");
968
	if (overflow | (i != (i & result_mask)))
Charles Hannum committed
969
	  {
970 971
	    i &= result_mask;
	    pedwarn ("hex escape sequence out of range");
Charles Hannum committed
972 973 974 975 976 977 978 979
	  }
	return i;
      }
    default:
      return c;
    }
}

980
static void
Charles Hannum committed
981 982 983
yyerror (s)
     char *s;
{
984
  error ("%s", s);
985
  skip_evaluation = 0;
Charles Hannum committed
986 987
  longjmp (parse_return_error, 1);
}
988 989 990 991

static void
integer_overflow ()
{
992
  if (!skip_evaluation && pedantic)
993
    pedwarn ("integer overflow in preprocessor expression");
994 995
}

996
static HOST_WIDE_INT
997 998
left_shift (a, b)
     struct constant *a;
Jeff Law committed
999
     unsigned_HOST_WIDE_INT b;
1000
{
1001 1002 1003
   /* It's unclear from the C standard whether shifts can overflow.
      The following code ignores overflow; perhaps a C standard
      interpretation ruling is needed.  */
1004
  if (b >= HOST_BITS_PER_WIDE_INT)
1005
    return 0;
1006
  else
Jeff Law committed
1007
    return (unsigned_HOST_WIDE_INT) a->value << b;
1008 1009
}

1010
static HOST_WIDE_INT
1011 1012
right_shift (a, b)
     struct constant *a;
Jeff Law committed
1013
     unsigned_HOST_WIDE_INT b;
1014
{
1015 1016
  if (b >= HOST_BITS_PER_WIDE_INT)
    return a->signedp ? a->value >> (HOST_BITS_PER_WIDE_INT - 1) : 0;
1017
  else if (a->signedp)
1018
    return a->value >> b;
1019
  else
Jeff Law committed
1020
    return (unsigned_HOST_WIDE_INT) a->value >> b;
1021
}
Charles Hannum committed
1022 1023 1024 1025

/* This page contains the entry point to this file.  */

/* Parse STRING as an expression, and complain if this fails
Jeff Law committed
1026 1027 1028 1029 1030
   to use up all of the contents of STRING.
   STRING may contain '\0' bytes; it is terminated by the first '\n'
   outside a string constant, so that we can diagnose '\0' properly.
   If WARN_UNDEFINED is nonzero, warn if undefined identifiers are evaluated.
   We do not support C comments.  They should be removed before
Charles Hannum committed
1031 1032
   this function is called.  */

1033
HOST_WIDE_INT
Jeff Law committed
1034
parse_c_expression (string, warn_undefined)
Charles Hannum committed
1035
     char *string;
Jeff Law committed
1036
     int warn_undefined;
Charles Hannum committed
1037 1038
{
  lexptr = string;
Jeff Law committed
1039
  warn_undef = warn_undefined;
Charles Hannum committed
1040 1041 1042 1043 1044 1045 1046

  /* if there is some sort of scanning error, just return 0 and assume
     the parsing routine has printed an error message somewhere.
     there is surely a better thing to do than this.     */
  if (setjmp (parse_return_error))
    return 0;

1047 1048 1049
  if (yyparse () != 0)
    abort ();

1050
  if (*lexptr != '\n')
Charles Hannum committed
1051 1052 1053 1054 1055 1056
    error ("Junk after end of expression.");

  return expression_value;	/* set by yyparse () */
}

#ifdef TEST_EXP_READER
1057 1058

#if YYDEBUG
Charles Hannum committed
1059
extern int yydebug;
1060 1061 1062 1063 1064 1065 1066
#endif

int pedantic;
int traditional;

int main PROTO((int, char **));
static void initialize_random_junk PROTO((void));
Jeff Law committed
1067
static void print_unsigned_host_wide_int PROTO((unsigned_HOST_WIDE_INT));
Charles Hannum committed
1068 1069 1070

/* Main program for testing purposes.  */
int
1071 1072 1073
main (argc, argv)
     int argc;
     char **argv;
Charles Hannum committed
1074 1075 1076
{
  int n, c;
  char buf[1024];
Jeff Law committed
1077
  unsigned_HOST_WIDE_INT u;
Charles Hannum committed
1078

1079 1080 1081 1082 1083
  pedantic = 1 < argc;
  traditional = 2 < argc;
#if YYDEBUG
  yydebug = 3 < argc;
#endif
Charles Hannum committed
1084 1085 1086 1087 1088
  initialize_random_junk ();

  for (;;) {
    printf ("enter expression: ");
    n = 0;
1089
    while ((buf[n] = c = getchar ()) != '\n' && c != EOF)
Charles Hannum committed
1090
      n++;
1091
    if (c == EOF)
Charles Hannum committed
1092
      break;
Jeff Law committed
1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106
    parse_c_expression (buf, 1);
    printf ("parser returned ");
    u = (unsigned_HOST_WIDE_INT) expression_value;
    if (expression_value < 0 && expression_signedp) {
      u = -u;
      printf ("-");
    }
    if (u == 0)
      printf ("0");
    else
      print_unsigned_host_wide_int (u);
    if (! expression_signedp)
      printf("u");
    printf ("\n");
Charles Hannum committed
1107 1108 1109 1110 1111
  }

  return 0;
}

Jeff Law committed
1112 1113 1114 1115 1116 1117 1118 1119 1120 1121
static void
print_unsigned_host_wide_int (u)
     unsigned_HOST_WIDE_INT u;
{
  if (u) {
    print_unsigned_host_wide_int (u / 10);
    putchar ('0' + (int) (u % 10));
  }
}

Charles Hannum committed
1122 1123 1124 1125
/* table to tell if char can be part of a C identifier. */
unsigned char is_idchar[256];
/* table to tell if char can be first char of a c identifier. */
unsigned char is_idstart[256];
1126 1127
/* table to tell if c is horizontal or vertical space.  */
unsigned char is_space[256];
Charles Hannum committed
1128 1129 1130 1131

/*
 * initialize random junk in the hash table and maybe other places
 */
1132
static void
Charles Hannum committed
1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155
initialize_random_junk ()
{
  register int i;

  /*
   * Set up is_idchar and is_idstart tables.  These should be
   * faster than saying (is_alpha (c) || c == '_'), etc.
   * Must do set up these things before calling any routines tthat
   * refer to them.
   */
  for (i = 'a'; i <= 'z'; i++) {
    ++is_idchar[i - 'a' + 'A'];
    ++is_idchar[i];
    ++is_idstart[i - 'a' + 'A'];
    ++is_idstart[i];
  }
  for (i = '0'; i <= '9'; i++)
    ++is_idchar[i];
  ++is_idchar['_'];
  ++is_idstart['_'];
  ++is_idchar['$'];
  ++is_idstart['$'];

1156 1157 1158 1159 1160 1161
  ++is_space[' '];
  ++is_space['\t'];
  ++is_space['\v'];
  ++is_space['\f'];
  ++is_space['\n'];
  ++is_space['\r'];
Charles Hannum committed
1162 1163
}

1164
void
1165
error VPROTO ((char * msg, ...))
Charles Hannum committed
1166
{
1167
#ifndef ANSI_PROTOTYPES
1168 1169
  char * msg;
#endif
1170 1171 1172
  va_list args;

  VA_START (args, msg);
1173
 
1174
#ifndef ANSI_PROTOTYPES
1175 1176 1177
  msg = va_arg (args, char *);
#endif
 
1178 1179 1180 1181
  fprintf (stderr, "error: ");
  vfprintf (stderr, msg, args);
  fprintf (stderr, "\n");
  va_end (args);
Charles Hannum committed
1182 1183
}

1184
void
1185
pedwarn VPROTO ((char * msg, ...))
1186
{
1187
#ifndef ANSI_PROTOTYPES
1188 1189
  char * msg;
#endif
1190 1191 1192
  va_list args;

  VA_START (args, msg);
1193
 
1194
#ifndef ANSI_PROTOTYPES
1195 1196 1197
  msg = va_arg (args, char *);
#endif
 
1198 1199 1200 1201 1202 1203 1204
  fprintf (stderr, "pedwarn: ");
  vfprintf (stderr, msg, args);
  fprintf (stderr, "\n");
  va_end (args);
}

void
1205
warning VPROTO ((char * msg, ...))
Charles Hannum committed
1206
{
1207
#ifndef ANSI_PROTOTYPES
1208 1209
  char * msg;
#endif
1210 1211 1212
  va_list args;

  VA_START (args, msg);
1213
 
1214
#ifndef ANSI_PROTOTYPES
1215 1216 1217
  msg = va_arg (args, char *);
#endif
 
1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231
  fprintf (stderr, "warning: ");
  vfprintf (stderr, msg, args);
  fprintf (stderr, "\n");
  va_end (args);
}

int
check_assertion (name, sym_length, tokens_specified, tokens)
     U_CHAR *name;
     int sym_length;
     int tokens_specified;
     struct arglist *tokens;
{
  return 0;
Charles Hannum committed
1232 1233 1234 1235
}

struct hashnode *
lookup (name, len, hash)
1236
     U_CHAR *name;
Charles Hannum committed
1237 1238 1239 1240 1241
     int len;
     int hash;
{
  return (DEFAULT_SIGNED_CHAR) ? 0 : ((struct hashnode *) -1);
}
1242 1243 1244 1245 1246 1247 1248

GENERIC_PTR
xmalloc (size)
     size_t size;
{
  return (GENERIC_PTR) malloc (size);
}
Charles Hannum committed
1249
#endif