OSDN Git Service

* cpplib.c (if_directive_nameo): Add static prototype.
[pf3gnuchains/gcc-fork.git] / gcc / cexp.y
index 470c45d..410f671 100644 (file)
@@ -1,5 +1,5 @@
 /* Parse C expressions for CCCP.
-   Copyright (C) 1987, 1992, 1994, 1995, 1996 Free Software Foundation.
+   Copyright (C) 1987, 92, 94-98, 1999 Free Software Foundation.
 
 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
@@ -26,37 +26,16 @@ Boston, MA 02111-1307, USA.
    
 %{
 #include "config.h"
+
+#include "system.h"
+#include "intl.h"
 #include <setjmp.h>
 /* #define YYDEBUG 1 */
 
-/* The following symbols should be autoconfigured:
-       HAVE_STDLIB_H
-       STDC_HEADERS
-   In the mean time, we'll get by with approximations based
-   on existing GCC configuration symbols.  */
-
-#ifdef POSIX
-# ifndef HAVE_STDLIB_H
-# define HAVE_STDLIB_H 1
-# endif
-# ifndef STDC_HEADERS
-# define STDC_HEADERS 1
-# endif
-#endif /* defined (POSIX) */
-
-#if STDC_HEADERS
-# include <string.h>
-#endif
-
-#if HAVE_STDLIB_H || defined (MULTIBYTE_CHARS)
-# include <stdlib.h>
-#endif
-
 #ifdef MULTIBYTE_CHARS
+#include "mbchar.h"
 #include <locale.h>
-#endif
-
-#include <stdio.h>
+#endif /* MULTIBYTE_CHARS */
 
 typedef unsigned char U_CHAR;
 
@@ -68,80 +47,15 @@ struct arglist {
   int argno;
 };
 
-/* Define a generic NULL if one hasn't already been defined.  */
-
-#ifndef NULL
-#define NULL 0
-#endif
-
-#ifndef GENERIC_PTR
-#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
-#define GENERIC_PTR void *
-#else
-#define GENERIC_PTR char *
-#endif
-#endif
-
-#ifndef NULL_PTR
-#define NULL_PTR ((GENERIC_PTR)0)
-#endif
-
-/* Find the largest host integer type and set its size and type.
-   Don't blindly use `long'; on some crazy hosts it is shorter than `int'.  */
-
-#ifndef HOST_BITS_PER_WIDE_INT
-
-#if HOST_BITS_PER_LONG > HOST_BITS_PER_INT
-#define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_LONG
-#define HOST_WIDE_INT long
-#else
-#define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_INT
-#define HOST_WIDE_INT int
-#endif
-
-#endif
-
-#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 6)
-# define __attribute__(x)
-#endif
-
-#ifndef PROTO
-# if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
-#  define PROTO(ARGS) ARGS
-# else
-#  define PROTO(ARGS) ()
-# endif
-#endif
-
-#if defined (__STDC__) && defined (HAVE_VPRINTF)
-# include <stdarg.h>
-# define VA_START(va_list, var) va_start (va_list, var)
-# define PRINTF_ALIST(msg) char *msg, ...
-# define PRINTF_DCL(msg)
-# define PRINTF_PROTO(ARGS, m, n) PROTO (ARGS) __attribute__ ((format (printf, m, n)))
-#else
-# include <varargs.h>
-# define VA_START(va_list, var) va_start (va_list)
-# define PRINTF_ALIST(msg) msg, va_alist
-# define PRINTF_DCL(msg) char *msg; va_dcl
-# define PRINTF_PROTO(ARGS, m, n) () __attribute__ ((format (printf, m, n)))
-# define vfprintf(file, msg, args) \
-    { \
-      char *a0 = va_arg(args, char *); \
-      char *a1 = va_arg(args, char *); \
-      char *a2 = va_arg(args, char *); \
-      char *a3 = va_arg(args, char *); \
-      fprintf (file, msg, a0, a1, a2, a3); \
-    }
-#endif
-
-#define PRINTF_PROTO_1(ARGS) PRINTF_PROTO(ARGS, 1, 2)
-
-HOST_WIDE_INT parse_c_expression PROTO((char *));
+HOST_WIDEST_INT parse_c_expression PROTO((char *, int));
 
 static int yylex PROTO((void));
-static void yyerror PROTO((char *)) __attribute__ ((noreturn));
-static HOST_WIDE_INT expression_value;
+static void yyerror PVPROTO((const char *, ...))
+  ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
+static HOST_WIDEST_INT expression_value;
+#ifdef TEST_EXP_READER
+static int expression_signedp;
+#endif
 
 static jmp_buf parse_return_error;
 
@@ -152,8 +66,11 @@ static int keyword_parsing = 0;
    This is a count, since unevaluated expressions can nest.  */
 static int skip_evaluation;
 
+/* Nonzero means warn if undefined identifiers are evaluated.  */
+static int warn_undef;
+
 /* some external tables of character types */
-extern unsigned char is_idstart[], is_idchar[], is_hor_space[];
+extern unsigned char is_idstart[], is_idchar[], is_space[];
 
 /* Flag for -pedantic.  */
 extern int pedantic;
@@ -161,6 +78,9 @@ extern int pedantic;
 /* Flag for -traditional.  */
 extern int traditional;
 
+/* Flag for -lang-c89.  */
+extern int c89;
+
 #ifndef CHAR_TYPE_SIZE
 #define CHAR_TYPE_SIZE BITS_PER_UNIT
 #endif
@@ -193,17 +113,13 @@ extern int traditional;
 #define MAX_WCHAR_TYPE_SIZE WCHAR_TYPE_SIZE
 #endif
 
-#if MAX_CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT
-#define MAX_CHAR_TYPE_MASK (~ (~ (HOST_WIDE_INT) 0 << MAX_CHAR_TYPE_SIZE))
-#else
-#define MAX_CHAR_TYPE_MASK (~ (HOST_WIDE_INT) 0)
-#endif
+#define MAX_CHAR_TYPE_MASK (MAX_CHAR_TYPE_SIZE < HOST_BITS_PER_WIDEST_INT \
+                           ? (~ (~ (HOST_WIDEST_INT) 0 << MAX_CHAR_TYPE_SIZE)) \
+                           : ~ (HOST_WIDEST_INT) 0)
 
-#if MAX_WCHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT
-#define MAX_WCHAR_TYPE_MASK (~ (~ (HOST_WIDE_INT) 0 << MAX_WCHAR_TYPE_SIZE))
-#else
-#define MAX_WCHAR_TYPE_MASK (~ (HOST_WIDE_INT) 0)
-#endif
+#define MAX_WCHAR_TYPE_MASK (MAX_WCHAR_TYPE_SIZE < HOST_BITS_PER_WIDEST_INT \
+                            ? ~ (~ (HOST_WIDEST_INT) 0 << MAX_WCHAR_TYPE_SIZE) \
+                            : ~ (HOST_WIDEST_INT) 0)
 
 /* 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.
@@ -217,17 +133,17 @@ extern int traditional;
 
 struct constant;
 
-GENERIC_PTR xmalloc PROTO((size_t));
-HOST_WIDE_INT parse_escape PROTO((char **, HOST_WIDE_INT));
+HOST_WIDEST_INT parse_escape PROTO((char **, HOST_WIDEST_INT));
 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 *, ...));
+void error PVPROTO((const char *, ...)) ATTRIBUTE_PRINTF_1;
+void verror PROTO((const char *, va_list));
+void pedwarn PVPROTO((const char *, ...)) ATTRIBUTE_PRINTF_1;
+void warning PVPROTO((const char *, ...)) ATTRIBUTE_PRINTF_1;
 
 static int parse_number PROTO((int));
-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));
+static HOST_WIDEST_INT left_shift PROTO((struct constant *, unsigned HOST_WIDEST_INT));
+static HOST_WIDEST_INT right_shift PROTO((struct constant *, unsigned HOST_WIDEST_INT));
 static void integer_overflow PROTO((void));
 
 /* `signedp' values */
@@ -236,7 +152,7 @@ static void integer_overflow PROTO((void));
 %}
 
 %union {
-  struct constant {HOST_WIDE_INT value; int signedp;} integer;
+  struct constant {HOST_WIDEST_INT value; int signedp;} integer;
   struct name {U_CHAR *address; int length;} name;
   struct arglist *keywords;
 }
@@ -266,7 +182,12 @@ static void integer_overflow PROTO((void));
 %%
 
 start   :      exp1
-               { expression_value = $1.value; }
+               {
+                 expression_value = $1.value;
+#ifdef TEST_EXP_READER
+                 expression_signedp = $1.signedp;
+#endif
+               }
        ;
 
 /* Expressions, including the comma operator.  */
@@ -318,7 +239,7 @@ exp :       exp '*' exp
                                integer_overflow ();
                            }
                          else
-                           $$.value = ((unsigned HOST_WIDE_INT) $1.value
+                           $$.value = ((unsigned HOST_WIDEST_INT) $1.value
                                        * $3.value); }
        |       exp '/' exp
                        { if ($3.value == 0)
@@ -335,7 +256,7 @@ exp :       exp '*' exp
                                integer_overflow ();
                            }
                          else
-                           $$.value = ((unsigned HOST_WIDE_INT) $1.value
+                           $$.value = ((unsigned HOST_WIDEST_INT) $1.value
                                        / $3.value); }
        |       exp '%' exp
                        { if ($3.value == 0)
@@ -348,7 +269,7 @@ exp :       exp '*' exp
                          if ($$.signedp)
                            $$.value = $1.value % $3.value;
                          else
-                           $$.value = ((unsigned HOST_WIDE_INT) $1.value
+                           $$.value = ((unsigned HOST_WIDEST_INT) $1.value
                                        % $3.value); }
        |       exp '+' exp
                        { $$.value = $1.value + $3.value;
@@ -385,28 +306,28 @@ exp       :       exp '*' exp
                          if ($1.signedp & $3.signedp)
                            $$.value = $1.value <= $3.value;
                          else
-                           $$.value = ((unsigned HOST_WIDE_INT) $1.value
+                           $$.value = ((unsigned HOST_WIDEST_INT) $1.value
                                        <= $3.value); }
        |       exp GEQ exp
                        { $$.signedp = SIGNED;
                          if ($1.signedp & $3.signedp)
                            $$.value = $1.value >= $3.value;
                          else
-                           $$.value = ((unsigned HOST_WIDE_INT) $1.value
+                           $$.value = ((unsigned HOST_WIDEST_INT) $1.value
                                        >= $3.value); }
        |       exp '<' exp
                        { $$.signedp = SIGNED;
                          if ($1.signedp & $3.signedp)
                            $$.value = $1.value < $3.value;
                          else
-                           $$.value = ((unsigned HOST_WIDE_INT) $1.value
+                           $$.value = ((unsigned HOST_WIDEST_INT) $1.value
                                        < $3.value); }
        |       exp '>' exp
                        { $$.signedp = SIGNED;
                          if ($1.signedp & $3.signedp)
                            $$.value = $1.value > $3.value;
                          else
-                           $$.value = ((unsigned HOST_WIDE_INT) $1.value
+                           $$.value = ((unsigned HOST_WIDEST_INT) $1.value
                                        > $3.value); }
        |       exp '&' exp
                        { $$.value = $1.value & $3.value;
@@ -442,7 +363,10 @@ exp        :       exp '*' exp
        |       CHAR
                        { $$ = yylval.integer; }
        |       NAME
-                       { $$.value = 0;
+                       { if (warn_undef && !skip_evaluation)
+                           warning ("`%.*s' is not defined",
+                                    $1.length, $1.address);
+                         $$.value = 0;
                          $$.signedp = SIGNED; }
        ;
 
@@ -486,7 +410,7 @@ parse_number (olen)
 {
   register char *p = lexptr;
   register int c;
-  register unsigned HOST_WIDE_INT n = 0, nd, max_over_base;
+  register unsigned HOST_WIDEST_INT n = 0, nd, max_over_base;
   register int base = 10;
   register int len = olen;
   register int overflow = 0;
@@ -504,7 +428,7 @@ parse_number (olen)
     }
   }
 
-  max_over_base = (unsigned HOST_WIDE_INT) -1 / base;
+  max_over_base = (unsigned HOST_WIDEST_INT) -1 / base;
 
   for (; len > 0; len--) {
     c = *p++;
@@ -520,9 +444,9 @@ parse_number (olen)
       while (1) {
        if (c == 'l' || c == 'L')
          {
-           if (spec_long)
-             yyerror ("two `l's in integer constant");
-           spec_long = 1;
+           if (!pedantic < spec_long)
+             yyerror ("too many `l's in integer constant");
+           spec_long++;
          }
        else if (c == 'u' || c == 'U')
          {
@@ -531,14 +455,11 @@ parse_number (olen)
            yylval.integer.signedp = UNSIGNED;
          }
        else {
-         if (c == '.' || c == 'e' || c == 'E')
+         if (c == '.' || c == 'e' || c == 'E' || c == 'p' || c == 'P')
            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'",
+         else
+           yyerror ("missing white space after number `%.*s'",
                     (int) (p - lexptr - 1), lexptr);
-           yyerror (buf);
-         }
        }
 
        if (--len == 0)
@@ -556,13 +477,13 @@ parse_number (olen)
   }
 
   if (base <= largest_digit)
-    warning ("integer constant contains digits beyond the radix");
+    pedwarn ("integer constant contains digits beyond the radix");
 
   if (overflow)
-    warning ("integer constant out of range");
+    pedwarn ("integer constant out of range");
 
   /* If too big to be signed, consider it unsigned.  */
-  if (((HOST_WIDE_INT) n & yylval.integer.signedp) < 0)
+  if (((HOST_WIDEST_INT) n & yylval.integer.signedp) < 0)
     {
       if (base == 10)
        warning ("integer constant is so large that it is unsigned");
@@ -575,7 +496,7 @@ parse_number (olen)
 }
 
 struct token {
-  char *operator;
+  const char *operator;
   int token;
 };
 
@@ -603,7 +524,7 @@ yylex ()
   register unsigned char *tokstart;
   register struct token *toktab;
   int wide_flag;
-  HOST_WIDE_INT mask;
+  HOST_WIDEST_INT mask;
 
  retry:
 
@@ -615,11 +536,7 @@ yylex ()
       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);
-         }
+         yyerror ("`%s' not allowed in operand of `#if'", toktab->operator);
        return toktab->token;
       }
 
@@ -674,25 +591,20 @@ yylex ()
        handles multicharacter constants and wide characters.
        It is mostly copied from c-lex.c.  */
     {
-      register HOST_WIDE_INT result = 0;
-      register num_chars = 0;
+      register HOST_WIDEST_INT result = 0;
+      register int num_chars = 0;
+      int chars_seen = 0;
       unsigned width = MAX_CHAR_TYPE_SIZE;
       int max_chars;
-      char *token_buffer;
-
-      if (wide_flag)
-       {
-         width = MAX_WCHAR_TYPE_SIZE;
 #ifdef MULTIBYTE_CHARS
-         max_chars = MB_CUR_MAX;
-#else
-         max_chars = 1;
+      int longest_char = local_mb_cur_max ();
+      char *token_buffer = (char *) alloca (longest_char);
+      (void) local_mbtowc (NULL_PTR, NULL_PTR, 0);
 #endif
-       }
-      else
-       max_chars = MAX_LONG_TYPE_SIZE / width;
 
-      token_buffer = (char *) alloca (max_chars + 1);
+      max_chars = MAX_LONG_TYPE_SIZE / width;
+      if (wide_flag)
+       width = MAX_WCHAR_TYPE_SIZE;
 
       while (1)
        {
@@ -701,71 +613,108 @@ yylex ()
          if (c == '\'' || c == EOF)
            break;
 
+         ++chars_seen;
          if (c == '\\')
            {
              c = parse_escape (&lexptr, mask);
            }
+         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 */
+           }
 
-         num_chars++;
+         if (wide_flag)
+           {
+             if (chars_seen == 1) /* only keep the first one */
+               result = c;
+             continue;
+           }
 
          /* Merge character into result; ignore excess chars.  */
+         num_chars++;
          if (num_chars <= max_chars)
            {
-             if (width < HOST_BITS_PER_WIDE_INT)
-               result = (result << width) | c;
+             if (width < HOST_BITS_PER_INT)
+               result = (result << width) | (c & ((1 << width) - 1));
              else
                result = c;
-             token_buffer[num_chars - 1] = c;
            }
        }
 
-      token_buffer[num_chars] = 0;
-
       if (c != '\'')
        error ("malformatted character constant");
-      else if (num_chars == 0)
+      else if (chars_seen == 0)
        error ("empty character constant");
       else if (num_chars > max_chars)
        {
          num_chars = max_chars;
          error ("character constant too long");
        }
-      else if (num_chars != 1 && ! traditional)
+      else if (chars_seen != 1 && ! traditional)
        warning ("multi-character character constant");
 
       /* If char type is signed, sign-extend the constant.  */
       if (! wide_flag)
        {
          int num_bits = num_chars * width;
-
-         if (lookup ("__CHAR_UNSIGNED__", sizeof ("__CHAR_UNSIGNED__")-1, -1)
+         if (num_bits == 0)
+           /* We already got an error; avoid invalid shift.  */
+           yylval.integer.value = 0;
+         else if (lookup ((U_CHAR *) "__CHAR_UNSIGNED__",
+                     sizeof ("__CHAR_UNSIGNED__") - 1, -1)
              || ((result >> (num_bits - 1)) & 1) == 0)
            yylval.integer.value
-             = result & (~ (unsigned HOST_WIDE_INT) 0
-                         >> (HOST_BITS_PER_WIDE_INT - num_bits));
+             = result & (~ (unsigned HOST_WIDEST_INT) 0
+                         >> (HOST_BITS_PER_WIDEST_INT - num_bits));
          else
            yylval.integer.value
-             = result | ~(~ (unsigned HOST_WIDE_INT) 0
-                          >> (HOST_BITS_PER_WIDE_INT - num_bits));
+             = result | ~(~ (unsigned HOST_WIDEST_INT) 0
+                          >> (HOST_BITS_PER_WIDEST_INT - num_bits));
        }
       else
        {
-#ifdef MULTIBYTE_CHARS
-         /* Set the initial shift state and convert the next sequence.  */
-         result = 0;
-         /* In all locales L'\0' is zero and mbtowc will return zero,
-            so don't use it.  */
-         if (num_chars > 1
-             || (num_chars == 1 && token_buffer[0] != '\0'))
-           {
-             wchar_t wc;
-             (void) mbtowc (NULL_PTR, NULL_PTR, 0);
-             if (mbtowc (& wc, token_buffer, num_chars) == num_chars)
-               result = wc;
-             else
-               warning ("Ignoring invalid multibyte character");
-           }
-#endif
          yylval.integer.value = result;
        }
     }
@@ -833,7 +782,9 @@ yylex ()
     for (namelen = 1; ; namelen++) {
       int d = tokstart[namelen];
       if (! ((is_idchar[d] || d == '.')
-            || ((d == '-' || d == '+') && (c == 'e' || c == 'E')
+            || ((d == '-' || d == '+')
+                && (c == 'e' || c == 'E'
+                    || ((c == 'p' || c == 'P') && ! c89))
                 && ! traditional)))
        break;
       c = d;
@@ -845,7 +796,7 @@ yylex ()
 
   if (keyword_parsing) {
     for (namelen = 0;; namelen++) {
-      if (is_hor_space[tokstart[namelen]])
+      if (is_space[tokstart[namelen]])
        break;
       if (tokstart[namelen] == '(' || tokstart[namelen] == ')')
        break;
@@ -886,10 +837,10 @@ yylex ()
    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.  */
 
-HOST_WIDE_INT
+HOST_WIDEST_INT
 parse_escape (string_ptr, result_mask)
      char **string_ptr;
-     HOST_WIDE_INT result_mask;
+     HOST_WIDEST_INT result_mask;
 {
   register int c = *(*string_ptr)++;
   switch (c)
@@ -902,7 +853,7 @@ parse_escape (string_ptr, result_mask)
     case 'E':
       if (pedantic)
        pedwarn ("non-ANSI-standard escape sequence, `\\%c'", c);
-      return 033;
+      return TARGET_ESC;
     case 'f':
       return TARGET_FF;
     case 'n':
@@ -928,7 +879,7 @@ parse_escape (string_ptr, result_mask)
     case '6':
     case '7':
       {
-       register HOST_WIDE_INT i = c - '0';
+       register HOST_WIDEST_INT i = c - '0';
        register int count = 0;
        while (++count < 3)
          {
@@ -950,7 +901,7 @@ parse_escape (string_ptr, result_mask)
       }
     case 'x':
       {
-       register unsigned HOST_WIDE_INT i = 0, overflow = 0;
+       register unsigned HOST_WIDEST_INT i = 0, overflow = 0;
        register int digits_found = 0, digit;
        for (;;)
          {
@@ -985,67 +936,56 @@ parse_escape (string_ptr, result_mask)
 }
 
 static void
-yyerror (s)
-     char *s;
-{
-  error ("%s", s);
-  skip_evaluation = 0;
-  longjmp (parse_return_error, 1);
-}
-
-static void
 integer_overflow ()
 {
   if (!skip_evaluation && pedantic)
     pedwarn ("integer overflow in preprocessor expression");
 }
 
-static HOST_WIDE_INT
+static HOST_WIDEST_INT
 left_shift (a, b)
      struct constant *a;
-     unsigned HOST_WIDE_INT b;
+     unsigned HOST_WIDEST_INT b;
 {
    /* It's unclear from the C standard whether shifts can overflow.
       The following code ignores overflow; perhaps a C standard
       interpretation ruling is needed.  */
-  if (b >= HOST_BITS_PER_WIDE_INT)
+  if (b >= HOST_BITS_PER_WIDEST_INT)
     return 0;
   else
-    return (unsigned HOST_WIDE_INT) a->value << b;
+    return (unsigned HOST_WIDEST_INT) a->value << b;
 }
 
-static HOST_WIDE_INT
+static HOST_WIDEST_INT
 right_shift (a, b)
      struct constant *a;
-     unsigned HOST_WIDE_INT b;
+     unsigned HOST_WIDEST_INT b;
 {
-  if (b >= HOST_BITS_PER_WIDE_INT)
-    return a->signedp ? a->value >> (HOST_BITS_PER_WIDE_INT - 1) : 0;
+  if (b >= HOST_BITS_PER_WIDEST_INT)
+    return a->signedp ? a->value >> (HOST_BITS_PER_WIDEST_INT - 1) : 0;
   else if (a->signedp)
     return a->value >> b;
   else
-    return (unsigned HOST_WIDE_INT) a->value >> b;
+    return (unsigned HOST_WIDEST_INT) a->value >> b;
 }
 \f
 /* This page contains the entry point to this file.  */
 
 /* Parse STRING as an expression, and complain if this fails
-   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.  */
-/* We do not support C comments.  They should be removed before
+   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
    this function is called.  */
 
-HOST_WIDE_INT
-parse_c_expression (string)
+HOST_WIDEST_INT
+parse_c_expression (string, warn_undefined)
      char *string;
+     int warn_undefined;
 {
   lexptr = string;
-  
-  if (lexptr == 0 || *lexptr == 0) {
-    error ("empty #if expression");
-    return 0;                  /* don't include the #if group */
-  }
+  warn_undef = warn_undefined;
 
   /* if there is some sort of scanning error, just return 0 and assume
      the parsing routine has printed an error message somewhere.
@@ -1053,14 +993,35 @@ parse_c_expression (string)
   if (setjmp (parse_return_error))
     return 0;
 
-  if (yyparse ())
-    return 0;                  /* actually this is never reached
-                                  the way things stand. */
+  if (yyparse () != 0)
+    abort ();
+
   if (*lexptr != '\n')
     error ("Junk after end of expression.");
 
   return expression_value;     /* set by yyparse () */
 }
+
+static void
+yyerror VPROTO ((const char * msgid, ...))
+{
+#ifndef ANSI_PROTOTYPES
+  const char * msgid;
+#endif
+  va_list args;
+
+  VA_START (args, msgid);
+
+#ifndef ANSI_PROTOTYPES
+  msgid = va_arg (args, const char *);
+#endif
+
+  verror (msgid, args);
+  va_end (args);
+  skip_evaluation = 0;
+  longjmp (parse_return_error, 1);
+}
+
 \f
 #ifdef TEST_EXP_READER
 
@@ -1070,9 +1031,11 @@ extern int yydebug;
 
 int pedantic;
 int traditional;
+int c89;
 
 int main PROTO((int, char **));
 static void initialize_random_junk PROTO((void));
+static void print_unsigned_host_widest_int PROTO((unsigned HOST_WIDEST_INT));
 
 /* Main program for testing purposes.  */
 int
@@ -1082,11 +1045,13 @@ main (argc, argv)
 {
   int n, c;
   char buf[1024];
+  unsigned HOST_WIDEST_INT u;
 
   pedantic = 1 < argc;
   traditional = 2 < argc;
+  c89 = 3 < argc;
 #if YYDEBUG
-  yydebug = 3 < argc;
+  yydebug = 4 < argc;
 #endif
   initialize_random_junk ();
 
@@ -1097,19 +1062,41 @@ main (argc, argv)
       n++;
     if (c == EOF)
       break;
-    printf ("parser returned %ld\n", (long) parse_c_expression (buf));
+    parse_c_expression (buf, 1);
+    printf ("parser returned ");
+    u = (unsigned HOST_WIDEST_INT) expression_value;
+    if (expression_value < 0 && expression_signedp) {
+      u = -u;
+      printf ("-");
+    }
+    if (u == 0)
+      printf ("0");
+    else
+      print_unsigned_host_widest_int (u);
+    if (! expression_signedp)
+      printf("u");
+    printf ("\n");
   }
 
   return 0;
 }
 
+static void
+print_unsigned_host_widest_int (u)
+     unsigned HOST_WIDEST_INT u;
+{
+  if (u) {
+    print_unsigned_host_widest_int (u / 10);
+    putchar ('0' + (int) (u % 10));
+  }
+}
+
 /* 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];
-/* table to tell if c is horizontal space.  isspace () thinks that
-   newline is space; this is not a good idea for this program. */
-unsigned char is_hor_space[256];
+/* table to tell if c is horizontal or vertical space.  */
+unsigned char is_space[256];
 
 /*
  * initialize random junk in the hash table and maybe other places
@@ -1126,64 +1113,87 @@ initialize_random_junk ()
    * refer to them.
    */
   for (i = 'a'; i <= 'z'; i++) {
-    ++is_idchar[i - 'a' + 'A'];
+    ++is_idchar[TOUPPER(i)];
     ++is_idchar[i];
-    ++is_idstart[i - 'a' + 'A'];
+    ++is_idstart[TOUPPER(i)];
     ++is_idstart[i];
   }
   for (i = '0'; i <= '9'; i++)
     ++is_idchar[i];
   ++is_idchar['_'];
   ++is_idstart['_'];
-#if DOLLARS_IN_IDENTIFIERS
   ++is_idchar['$'];
   ++is_idstart['$'];
-#endif
 
-  /* horizontal space table */
-  ++is_hor_space[' '];
-  ++is_hor_space['\t'];
+  ++is_space[' '];
+  ++is_space['\t'];
+  ++is_space['\v'];
+  ++is_space['\f'];
+  ++is_space['\n'];
+  ++is_space['\r'];
 }
 
 void
-error (PRINTF_ALIST (msg))
-     PRINTF_DCL (msg)
+error VPROTO ((char * msgid, ...))
 {
+#ifndef ANSI_PROTOTYPES
+  char * msgid;
+#endif
   va_list args;
 
-  VA_START (args, msg);
+  VA_START (args, msgid);
+
+#ifndef ANSI_PROTOTYPES
+  msgid = va_arg (args, char *);
+#endif
+
   fprintf (stderr, "error: ");
-  vfprintf (stderr, msg, args);
+  vfprintf (stderr, _(msgid), args);
   fprintf (stderr, "\n");
   va_end (args);
 }
 
 void
-pedwarn (PRINTF_ALIST (msg))
-     PRINTF_DCL (msg)
+pedwarn VPROTO ((char * msgid, ...))
 {
+#ifndef ANSI_PROTOTYPES
+  char * msgid;
+#endif
   va_list args;
 
-  VA_START (args, msg);
+  VA_START (args, msgid);
+
+#ifndef ANSI_PROTOTYPES
+  msgid = va_arg (args, char *);
+#endif
+
   fprintf (stderr, "pedwarn: ");
-  vfprintf (stderr, msg, args);
+  vfprintf (stderr, _(msgid), args);
   fprintf (stderr, "\n");
   va_end (args);
 }
 
 void
-warning (PRINTF_ALIST (msg))
-     PRINTF_DCL (msg)
+warning VPROTO ((char * msgid, ...))
 {
+#ifndef ANSI_PROTOTYPES
+  char * msgid;
+#endif
   va_list args;
 
-  VA_START (args, msg);
+  VA_START (args, msgid);
+
+#ifndef ANSI_PROTOTYPES
+  msgid = va_arg (args, char *);
+#endif
+
   fprintf (stderr, "warning: ");
-  vfprintf (stderr, msg, args);
+  vfprintf (stderr, _(msgid), args);
   fprintf (stderr, "\n");
   va_end (args);
 }
 
+
 int
 check_assertion (name, sym_length, tokens_specified, tokens)
      U_CHAR *name;
@@ -1203,10 +1213,10 @@ lookup (name, len, hash)
   return (DEFAULT_SIGNED_CHAR) ? 0 : ((struct hashnode *) -1);
 }
 
-GENERIC_PTR
+PTR
 xmalloc (size)
-     size_t size;
+  size_t size;
 {
-  return (GENERIC_PTR) malloc (size);
+  return (PTR) malloc (size);
 }
 #endif