OSDN Git Service

* Makefile.in (INSTALL_CPP, UNINSTALL_CPP): Remove.
[pf3gnuchains/gcc-fork.git] / gcc / c-lex.c
index 02c85a0..2ecc147 100644 (file)
@@ -2,33 +2,34 @@
    Copyright (C) 1987, 1988, 1989, 1992, 1994, 1995, 1996, 1997
    1998, 1999, 2000 Free Software Foundation, Inc.
 
-This file is part of GNU CC.
+This file is part of GCC.
 
-GNU CC 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.
+GCC 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.
 
-GNU CC 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.
+GCC 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 GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
 
 #include "config.h"
 #include "system.h"
 
+#include "real.h"
 #include "rtl.h"
-#include "expr.h"
 #include "tree.h"
+#include "expr.h"
 #include "input.h"
 #include "output.h"
-#include "c-lex.h"
 #include "c-tree.h"
+#include "c-common.h"
 #include "flags.h"
 #include "timevar.h"
 #include "cpplib.h"
@@ -39,13 +40,6 @@ Boston, MA 02111-1307, USA.  */
 #include "splay-tree.h"
 #include "debug.h"
 
-/* MULTIBYTE_CHARS support only works for native compilers.
-   ??? Ideally what we want is to model widechar support after
-   the current floating point support.  */
-#ifdef CROSS_COMPILE
-#undef MULTIBYTE_CHARS
-#endif
-
 #ifdef MULTIBYTE_CHARS
 #include "mbchar.h"
 #include <locale.h>
@@ -54,16 +48,16 @@ Boston, MA 02111-1307, USA.  */
 #define GET_ENVIRONMENT(ENV_VALUE,ENV_NAME) ((ENV_VALUE) = getenv (ENV_NAME))
 #endif
 
-/* The input filename as understood by CPP, where "" represents stdin.  */
-static const char *cpp_filename;
+/* The current line map.  */
+static const struct line_map *map;
+
+/* The line used to refresh the lineno global variable after each token.  */
+static unsigned int src_lineno;
 
 /* We may keep statistics about how long which files took to compile.  */
 static int header_time, body_time;
 static splay_tree file_info_tree;
 
-/* Cause the `yydebug' variable to be defined.  */
-#define YYDEBUG 1
-
 /* File used for outputting assembler code.  */
 extern FILE *asm_out_file;
 
@@ -73,24 +67,27 @@ extern FILE *asm_out_file;
 /* Number of bytes in a wide character.  */
 #define WCHAR_BYTES (WCHAR_TYPE_SIZE / BITS_PER_UNIT)
 
-int indent_level;        /* Number of { minus number of }. */
 int pending_lang_change; /* If we need to switch languages - C++ only */
 int c_header_level;     /* depth in C headers - C++ only */
 
 /* Nonzero tells yylex to ignore \ in string constants.  */
 static int ignore_escape_flag;
 
-static void parse_float                PARAMS ((PTR));
 static tree lex_number         PARAMS ((const char *, unsigned int));
-static tree lex_string         PARAMS ((const char *, unsigned int, int));
+static tree lex_string         PARAMS ((const unsigned char *, unsigned int,
+                                        int));
 static tree lex_charconst      PARAMS ((const cpp_token *));
 static void update_header_times        PARAMS ((const char *));
 static int dump_one_header     PARAMS ((splay_tree_node, void *));
-static void cb_ident           PARAMS ((cpp_reader *, const cpp_string *));
-static void cb_file_change    PARAMS ((cpp_reader *, const cpp_file_change *));
-static void cb_def_pragma      PARAMS ((cpp_reader *));
-static void cb_define          PARAMS ((cpp_reader *, cpp_hashnode *));
-static void cb_undef           PARAMS ((cpp_reader *, cpp_hashnode *));
+static void cb_line_change     PARAMS ((cpp_reader *, const cpp_token *, int));
+static void cb_ident           PARAMS ((cpp_reader *, unsigned int,
+                                        const cpp_string *));
+static void cb_file_change    PARAMS ((cpp_reader *, const struct line_map *));
+static void cb_def_pragma      PARAMS ((cpp_reader *, unsigned int));
+static void cb_define          PARAMS ((cpp_reader *, unsigned int,
+                                        cpp_hashnode *));
+static void cb_undef           PARAMS ((cpp_reader *, unsigned int,
+                                        cpp_hashnode *));
 \f
 const char *
 init_c_lex (filename)
@@ -99,7 +96,7 @@ init_c_lex (filename)
   struct cpp_callbacks *cb;
   struct c_fileinfo *toplevel;
 
-  /* Set up filename timing.  Must happen before cpp_start_read.  */
+  /* Set up filename timing.  Must happen before cpp_read_main_file.  */
   file_info_tree = splay_tree_new ((splay_tree_compare_fn)strcmp,
                                   0,
                                   (splay_tree_delete_value_fn)free);
@@ -119,40 +116,49 @@ init_c_lex (filename)
 
   cb = cpp_get_callbacks (parse_in);
 
+  cb->line_change = cb_line_change;
   cb->ident = cb_ident;
   cb->file_change = cb_file_change;
   cb->def_pragma = cb_def_pragma;
 
   /* Set the debug callbacks if we can use them.  */
   if (debug_info_level == DINFO_LEVEL_VERBOSE
-      && (write_symbols == DWARF_DEBUG || write_symbols == DWARF2_DEBUG))
+      && (write_symbols == DWARF_DEBUG || write_symbols == DWARF2_DEBUG
+          || write_symbols == VMS_AND_DWARF2_DEBUG))
     {
       cb->define = cb_define;
       cb->undef = cb_undef;
     }
 
-
-  if (filename == 0 || !strcmp (filename, "-"))
-    filename = "stdin", cpp_filename = "";
-  else
-    cpp_filename = filename;
-
   /* Start it at 0.  */
   lineno = 0;
 
-  return filename;
+  if (filename == NULL || !strcmp (filename, "-"))
+    filename = "";
+
+  return cpp_read_main_file (parse_in, filename, ident_hash);
 }
 
 /* A thin wrapper around the real parser that initializes the 
-   integrated preprocessor after debug output has been initialized.  */
+   integrated preprocessor after debug output has been initialized.
+   Also, make sure the start_source_file debug hook gets called for
+   the primary source file.  */
 
-int
-yyparse()
+void
+c_common_parse_file (set_yydebug)
+     int set_yydebug ATTRIBUTE_UNUSED;
 {
-  if (! cpp_start_read (parse_in, cpp_filename))
-    return 1;                  /* cpplib has emitted an error.  */
+#if YYDEBUG != 0
+  yydebug = set_yydebug;
+#else
+  warning ("YYDEBUG not defined");
+#endif
 
-  return yyparse_1();
+  (*debug_hooks->start_source_file) (lineno, input_filename);
+  cpp_finish_options (parse_in);
+
+  yyparse ();
+  free_parser_stacks ();
 }
 
 struct c_fileinfo *
@@ -218,110 +224,109 @@ dump_time_statistics ()
   splay_tree_foreach (file_info_tree, dump_one_header, 0);
 }
 
-/* Not yet handled: #pragma, #define, #undef.
-   No need to deal with linemarkers under normal conditions.  */
-
 static void
-cb_ident (pfile, str)
+cb_ident (pfile, line, str)
      cpp_reader *pfile ATTRIBUTE_UNUSED;
+     unsigned int line ATTRIBUTE_UNUSED;
      const cpp_string *str ATTRIBUTE_UNUSED;
 {
 #ifdef ASM_OUTPUT_IDENT
   if (! flag_no_ident)
     {
       /* Convert escapes in the string.  */
-      tree value = lex_string ((const char *)str->text, str->len, 0);
+      tree value = lex_string (str->text, str->len, 0);
       ASM_OUTPUT_IDENT (asm_out_file, TREE_STRING_POINTER (value));
     }
 #endif
 }
 
+/* Called at the start of every non-empty line.  TOKEN is the first
+   lexed token on the line.  Used for diagnostic line numbers.  */
 static void
-cb_file_change (pfile, fc)
+cb_line_change (pfile, token, parsing_args)
      cpp_reader *pfile ATTRIBUTE_UNUSED;
-     const cpp_file_change *fc;
+     const cpp_token *token;
+     int parsing_args ATTRIBUTE_UNUSED;
 {
-  if (fc->reason == FC_ENTER)
+  src_lineno = SOURCE_LINE (map, token->line);
+}
+
+static void
+cb_file_change (pfile, new_map)
+     cpp_reader *pfile ATTRIBUTE_UNUSED;
+     const struct line_map *new_map;
+{
+  unsigned int to_line = SOURCE_LINE (new_map, new_map->to_line);
+
+  if (new_map->reason == LC_ENTER)
     {
       /* Don't stack the main buffer on the input stack;
         we already did in compile_file.  */
-      if (fc->from.filename)
+      if (map == NULL)
+       main_input_filename = new_map->to_file;
+      else
        {
-         lineno = fc->from.lineno;
-         push_srcloc (fc->to.filename, 1);
-         input_file_stack->indent_level = indent_level;
-         (*debug_hooks->start_source_file) (fc->from.lineno, fc->to.filename);
+          int included_at = SOURCE_LINE (new_map - 1, new_map->from_line - 1);
+
+         lineno = included_at;
+         push_srcloc (new_map->to_file, 1);
+         (*debug_hooks->start_source_file) (included_at, new_map->to_file);
 #ifndef NO_IMPLICIT_EXTERN_C
          if (c_header_level)
            ++c_header_level;
-         else if (fc->externc)
+         else if (new_map->sysp == 2)
            {
              c_header_level = 1;
              ++pending_lang_change;
            }
 #endif
        }
-      else
-       main_input_filename = fc->to.filename;
     }
-  else if (fc->reason == FC_LEAVE)
+  else if (new_map->reason == LC_LEAVE)
     {
-      /* Popping out of a file.  */
-      if (input_file_stack->next)
-       {
 #ifndef NO_IMPLICIT_EXTERN_C
-         if (c_header_level && --c_header_level == 0)
-           {
-             if (fc->externc)
-               warning ("badly nested C headers from preprocessor");
-             --pending_lang_change;
-           }
-#endif
-#if 0
-         if (indent_level != input_file_stack->indent_level)
-           {
-             warning_with_file_and_line
-               (input_filename, lineno,
-                "This file contains more '%c's than '%c's.",
-                indent_level > input_file_stack->indent_level ? '{' : '}',
-                indent_level > input_file_stack->indent_level ? '}' : '{');
-           }
-#endif
-         pop_srcloc ();
-         (*debug_hooks->end_source_file) (input_file_stack->line);
+      if (c_header_level && --c_header_level == 0)
+       {
+         if (new_map->sysp == 2)
+           warning ("badly nested C headers from preprocessor");
+         --pending_lang_change;
        }
-      else
-       error ("leaving more files than we entered");
+#endif
+      pop_srcloc ();
+      
+      (*debug_hooks->end_source_file) (to_line);
     }
 
-  update_header_times (fc->to.filename);
-  in_system_header = fc->sysp != 0;
-  input_filename = fc->to.filename;
-  lineno = fc->to.lineno;      /* Do we need this?  */
+  update_header_times (new_map->to_file);
+  in_system_header = new_map->sysp != 0;
+  input_filename = new_map->to_file;
+  lineno = to_line;
+  map = new_map;
 
   /* Hook for C++.  */
   extract_interface_info ();
 }
 
 static void
-cb_def_pragma (pfile)
+cb_def_pragma (pfile, line)
      cpp_reader *pfile;
+     unsigned int line;
 {
   /* Issue a warning message if we have been asked to do so.  Ignore
      unknown pragmas in system headers unless an explicit
-     -Wunknown-pragmas has been given. */
+     -Wunknown-pragmas has been given.  */
   if (warn_unknown_pragmas > in_system_header)
     {
       const unsigned char *space, *name = 0;
-      cpp_token s;
+      const cpp_token *s;
 
-      cpp_get_token (pfile, &s);
-      space = cpp_token_as_text (pfile, &s);
-      cpp_get_token (pfile, &s);
-      if (s.type == CPP_NAME)
-       name = cpp_token_as_text (pfile, &s);
+      s = cpp_get_token (pfile);
+      space = cpp_token_as_text (pfile, s);
+      s = cpp_get_token (pfile);
+      if (s->type == CPP_NAME)
+       name = cpp_token_as_text (pfile, s);
 
-      lineno = cpp_get_line (parse_in)->line;
+      lineno = SOURCE_LINE (map, line);
       if (name)
        warning ("ignoring #pragma %s %s", space, name);
       else
@@ -331,21 +336,23 @@ cb_def_pragma (pfile)
 
 /* #define callback for DWARF and DWARF2 debug info.  */
 static void
-cb_define (pfile, node)
+cb_define (pfile, line, node)
      cpp_reader *pfile;
+     unsigned int line;
      cpp_hashnode *node;
 {
-  (*debug_hooks->define) (cpp_get_line (pfile)->line,
+  (*debug_hooks->define) (SOURCE_LINE (map, line),
                          (const char *) cpp_macro_definition (pfile, node));
 }
 
 /* #undef callback for DWARF and DWARF2 debug info.  */
 static void
-cb_undef (pfile, node)
-     cpp_reader *pfile;
+cb_undef (pfile, line, node)
+     cpp_reader *pfile ATTRIBUTE_UNUSED;
+     unsigned int line;
      cpp_hashnode *node;
 {
-  (*debug_hooks->undef) (cpp_get_line (pfile)->line,
+  (*debug_hooks->undef) (SOURCE_LINE (map, line),
                         (const char *) NODE_NAME (node));
 }
 
@@ -661,10 +668,10 @@ utf8_extend_token (c)
 #if 0
 struct try_type
 {
-  tree *node_var;
-  char unsigned_flag;
-  char long_flag;
-  char long_long_flag;
+  tree *const node_var;
+  const char unsigned_flag;
+  const char long_flag;
+  const char long_long_flag;
 };
 
 struct try_type type_sequence[] =
@@ -678,118 +685,52 @@ struct try_type type_sequence[] =
 };
 #endif /* 0 */
 \f
-struct pf_args
-{
-  /* Input */
-  const char *str;
-  int fflag;
-  int lflag;
-  int base;
-  /* Output */
-  int conversion_errno;
-  REAL_VALUE_TYPE value;
-  tree type;
-};
-static void
-parse_float (data)
-  PTR data;
-{
-  struct pf_args * args = (struct pf_args *) data;
-  const char *typename;
-
-  args->conversion_errno = 0;
-  args->type = double_type_node;
-  typename = "double";
-
-  /* The second argument, machine_mode, of REAL_VALUE_ATOF
-     tells the desired precision of the binary result
-     of decimal-to-binary conversion.  */
-
-  if (args->fflag)
-    {
-      if (args->lflag)
-       error ("both 'f' and 'l' suffixes on floating constant");
-
-      args->type = float_type_node;
-      typename = "float";
-    }
-  else if (args->lflag)
-    {
-      args->type = long_double_type_node;
-      typename = "long double";
-    }
-  else if (flag_single_precision_constant)
-    {
-      args->type = float_type_node;
-      typename = "float";
-    }
-
-  errno = 0;
-  if (args->base == 16)
-    args->value = REAL_VALUE_HTOF (args->str, TYPE_MODE (args->type));
-  else
-    args->value = REAL_VALUE_ATOF (args->str, TYPE_MODE (args->type));
-
-  args->conversion_errno = errno;
-  /* A diagnostic is required here by some ISO C testsuites.
-     This is not pedwarn, because some people don't want
-     an error for this.  */
-  if (REAL_VALUE_ISINF (args->value) && pedantic)
-    warning ("floating point number exceeds range of '%s'", typename);
-}
 int
 c_lex (value)
      tree *value;
 {
-  cpp_token tok;
-  enum cpp_ttype type;
+  const cpp_token *tok;
 
   retry:
   timevar_push (TV_CPP);
-  cpp_get_token (parse_in, &tok);
+  do
+    tok = cpp_get_token (parse_in);
+  while (tok->type == CPP_PADDING);
   timevar_pop (TV_CPP);
 
   /* The C++ front end does horrible things with the current line
      number.  To ensure an accurate line number, we must reset it
      every time we return a token.  */
-  lineno = cpp_get_line (parse_in)->line;
+  lineno = src_lineno;
 
   *value = NULL_TREE;
-  type = tok.type;
-  switch (type)
+  switch (tok->type)
     {
-    case CPP_OPEN_BRACE:  indent_level++;  break;
-    case CPP_CLOSE_BRACE: indent_level--;  break;
-
-    /* Issue this error here, where we can get at tok.val.c.  */
+    /* Issue this error here, where we can get at tok->val.c.  */
     case CPP_OTHER:
-      if (ISGRAPH (tok.val.c))
-       error ("stray '%c' in program", tok.val.c);
+      if (ISGRAPH (tok->val.c))
+       error ("stray '%c' in program", tok->val.c);
       else
-       error ("stray '\\%o' in program", tok.val.c);
+       error ("stray '\\%o' in program", tok->val.c);
       goto retry;
       
     case CPP_NAME:
-      *value = HT_IDENT_TO_GCC_IDENT (HT_NODE (tok.val.node));
+      *value = HT_IDENT_TO_GCC_IDENT (HT_NODE (tok->val.node));
       break;
 
-    case CPP_INT:
-    case CPP_FLOAT:
     case CPP_NUMBER:
-      *value = lex_number ((const char *)tok.val.str.text, tok.val.str.len);
+      *value = lex_number ((const char *)tok->val.str.text, tok->val.str.len);
       break;
 
     case CPP_CHAR:
     case CPP_WCHAR:
-      *value = lex_charconst (&tok);
+      *value = lex_charconst (tok);
       break;
 
     case CPP_STRING:
     case CPP_WSTRING:
-      *value = lex_string ((const char *)tok.val.str.text,
-                          tok.val.str.len, tok.type == CPP_WSTRING);
+      *value = lex_string (tok->val.str.text, tok->val.str.len,
+                          tok->type == CPP_WSTRING);
       break;
 
       /* These tokens should not be visible outside cpplib.  */
@@ -801,7 +742,7 @@ c_lex (value)
     default: break;
     }
 
-  return type;
+  return tok->type;
 }
 
 #define ERROR(msgid) do { error(msgid); goto syntax_error; } while(0)
@@ -828,7 +769,7 @@ lex_number (str, len)
      Two HOST_WIDE_INTs is the largest int literal we can store.
      In order to detect overflow below, the number of parts (TOTAL_PARTS)
      must be exactly the number of parts needed to hold the bits
-     of two HOST_WIDE_INTs. */
+     of two HOST_WIDE_INTs.  */
 #define TOTAL_PARTS ((HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR) * 2)
   unsigned int parts[TOTAL_PARTS];
   
@@ -888,9 +829,10 @@ lex_number (str, len)
          /* It is not a decimal point.
             It should be a digit (perhaps a hex digit).  */
 
-         if (ISDIGIT (c))
+         if (ISDIGIT (c)
+             || (base == 16 && ISXDIGIT (c)))
            {
-             n = c - '0';
+             n = hex_value (c);
            }
          else if (base <= 10 && (c == 'e' || c == 'E'))
            {
@@ -903,14 +845,6 @@ lex_number (str, len)
              floatflag = AFTER_EXPON;
              break;   /* start of exponent */
            }
-         else if (base == 16 && c >= 'a' && c <= 'f')
-           {
-             n = c - 'a' + 10;
-           }
-         else if (base == 16 && c >= 'A' && c <= 'F')
-           {
-             n = c - 'A' + 10;
-           }
          else
            {
              p--;
@@ -938,7 +872,7 @@ lex_number (str, len)
          /* If the highest-order part overflows (gets larger than
             a host char will hold) then the whole number has 
             overflowed.  Record this and truncate the highest-order
-            part. */
+            part.  */
          if (parts[TOTAL_PARTS - 1] >> HOST_BITS_PER_CHAR)
            {
              overflow = 1;
@@ -958,14 +892,11 @@ lex_number (str, len)
   if (floatflag != NOT_FLOAT)
     {
       tree type;
-      int imag, fflag, lflag, conversion_errno;
+      const char *typename;
+      int imag, fflag, lflag;
       REAL_VALUE_TYPE real;
-      struct pf_args args;
       char *copy;
 
-      if (base == 16 && pedantic && !flag_isoc99)
-       pedwarn ("floating constant may not be in radix 16");
-
       if (base == 16 && floatflag != AFTER_EXPON)
        ERROR ("hexadecimal floating constant has no exponent");
 
@@ -1030,34 +961,45 @@ lex_number (str, len)
            ERROR ("invalid suffix on floating constant");
          }
 
-      /* Setup input for parse_float() */
-      args.str = copy;
-      args.fflag = fflag;
-      args.lflag = lflag;
-      args.base = base;
+      type = double_type_node;
+      typename = "double";
+       
+      if (fflag)
+       {
+         if (lflag)
+           ERROR ("both 'f' and 'l' suffixes on floating constant");
 
-      /* Convert string to a double, checking for overflow.  */
-      if (do_float_handler (parse_float, (PTR) &args))
+         type = float_type_node;
+         typename = "float";
+       }
+      else if (lflag)
+       {
+         type = long_double_type_node;
+         typename = "long double";
+       }
+      else if (flag_single_precision_constant)
        {
-         /* Receive output from parse_float() */
-         real = args.value;
+         type = float_type_node;
+         typename = "float";
        }
+
+      /* Warn about this only after we know we're not issuing an error.  */
+      if (base == 16 && pedantic && !flag_isoc99)
+       pedwarn ("hexadecimal floating constants are only valid in C99");
+
+      /* The second argument, machine_mode, of REAL_VALUE_ATOF
+        tells the desired precision of the binary result
+        of decimal-to-binary conversion.  */
+      if (base == 16)
+       real = REAL_VALUE_HTOF (copy, TYPE_MODE (type));
       else
-         /* We got an exception from parse_float() */
-         ERROR ("floating constant out of range");
-
-      /* Receive output from parse_float() */
-      conversion_errno = args.conversion_errno;
-      type = args.type;
-           
-#ifdef ERANGE
-      /* ERANGE is also reported for underflow,
-        so test the value to distinguish overflow from that.  */
-      if (conversion_errno == ERANGE && !flag_traditional && pedantic
-         && (REAL_VALUES_LESS (dconst1, real)
-             || REAL_VALUES_LESS (real, dconstm1)))
+       real = REAL_VALUE_ATOF (copy, TYPE_MODE (type));
+
+      /* A diagnostic is required here by some ISO C testsuites.
+        This is not pedwarn, because some people don't want
+        an error for this.  */
+      if (REAL_VALUE_ISINF (real) && pedantic)
        warning ("floating point number exceeds range of 'double'");
-#endif
 
       /* Create a node with determined type and value.  */
       if (imag)
@@ -1068,7 +1010,7 @@ lex_number (str, len)
     }
   else
     {
-      tree trad_type, ansi_type, type;
+      tree trad_type, type;
       HOST_WIDE_INT high, low;
       int spec_unsigned = 0;
       int spec_long = 0;
@@ -1077,7 +1019,7 @@ lex_number (str, len)
       int suffix_lu = 0;
       int warn = 0, i;
 
-      trad_type = ansi_type = type = NULL_TREE;
+      trad_type = type = NULL_TREE;
       while (p < str + len)
        {
          c = *p++;
@@ -1125,7 +1067,7 @@ lex_number (str, len)
            }
        }
 
-      /* If the literal overflowed, pedwarn about it now. */
+      /* If the literal overflowed, pedwarn about it now.  */
       if (overflow)
        {
          warn = 1;
@@ -1149,11 +1091,9 @@ lex_number (str, len)
       TREE_TYPE (value) = long_long_unsigned_type_node;
 
       /* If warn_traditional, calculate both the ISO type and the
-        traditional type, then see if they disagree.
-        Otherwise, calculate only the type for the dialect in use.  */
-      if (warn_traditional || flag_traditional)
+        traditional type, then see if they disagree.  */
+      if (warn_traditional)
        {
-         /* Calculate the traditional type.  */
          /* Traditionally, any constant is signed; but if unsigned is
             specified explicitly, obey that.  Use the smallest size
             with the right number of bits, except for one special
@@ -1183,50 +1123,46 @@ lex_number (str, len)
                         ? widest_unsigned_literal_type_node
                         : widest_integer_literal_type_node);
        }
-      if (warn_traditional || ! flag_traditional)
-       {
-         /* Calculate the ISO type.  */
-         if (! spec_long && ! spec_unsigned
-             && int_fits_type_p (value, integer_type_node))
-           ansi_type = integer_type_node;
-         else if (! spec_long && (base != 10 || spec_unsigned)
-                  && int_fits_type_p (value, unsigned_type_node))
-           ansi_type = unsigned_type_node;
-         else if (! spec_unsigned && !spec_long_long
-                  && int_fits_type_p (value, long_integer_type_node))
-           ansi_type = long_integer_type_node;
-         else if (! spec_long_long
-                  && int_fits_type_p (value, long_unsigned_type_node))
-           ansi_type = long_unsigned_type_node;
-         else if (! spec_unsigned
-                  && int_fits_type_p (value, long_long_integer_type_node))
-           ansi_type = long_long_integer_type_node;
-         else if (int_fits_type_p (value, long_long_unsigned_type_node))
-           ansi_type = long_long_unsigned_type_node;
-         else if (! spec_unsigned
-                  && int_fits_type_p (value, widest_integer_literal_type_node))
-           ansi_type = widest_integer_literal_type_node;
-         else
-           ansi_type = widest_unsigned_literal_type_node;
-       }
-
-      type = flag_traditional ? trad_type : ansi_type;
+       
+       /* Calculate the ISO type.  */
+       if (! spec_long && ! spec_unsigned
+           && int_fits_type_p (value, integer_type_node))
+         type = integer_type_node;
+       else if (! spec_long && (base != 10 || spec_unsigned)
+                && int_fits_type_p (value, unsigned_type_node))
+         type = unsigned_type_node;
+       else if (! spec_unsigned && !spec_long_long
+                && int_fits_type_p (value, long_integer_type_node))
+         type = long_integer_type_node;
+       else if (! spec_long_long
+                && int_fits_type_p (value, long_unsigned_type_node))
+         type = long_unsigned_type_node;
+       else if (! spec_unsigned
+                && int_fits_type_p (value, long_long_integer_type_node))
+         type = long_long_integer_type_node;
+       else if (int_fits_type_p (value, long_long_unsigned_type_node))
+         type = long_long_unsigned_type_node;
+       else if (! spec_unsigned
+                && int_fits_type_p (value, widest_integer_literal_type_node))
+         type = widest_integer_literal_type_node;
+       else
+         type = widest_unsigned_literal_type_node;
 
       /* We assume that constants specified in a non-decimal
         base are bit patterns, and that the programmer really
         meant what they wrote.  */
       if (warn_traditional && !in_system_header
-         && base == 10 && trad_type != ansi_type)
+         && base == 10 && trad_type != type)
        {
-         if (TYPE_PRECISION (trad_type) != TYPE_PRECISION (ansi_type))
-           warning ("width of integer constant changes with -traditional");
-         else if (TREE_UNSIGNED (trad_type) != TREE_UNSIGNED (ansi_type))
-           warning ("integer constant is unsigned in ISO C, signed with -traditional");
+         if (TYPE_PRECISION (trad_type) != TYPE_PRECISION (type))
+           warning ("width of integer constant is different in traditional C");
+         else if (TREE_UNSIGNED (trad_type) != TREE_UNSIGNED (type))
+           warning ("integer constant is unsigned in ISO C, signed in traditional C");
          else
-           warning ("width of integer constant may change on other systems with -traditional");
+           warning ("width of integer constant may change on other systems in traditional C");
        }
 
-      if (pedantic && !flag_traditional && (flag_isoc99 || !spec_long_long)
+      if (pedantic && (flag_isoc99 || !spec_long_long)
          && !warn
          && ((flag_isoc99
               ? TYPE_PRECISION (long_long_integer_type_node)
@@ -1236,9 +1172,9 @@ lex_number (str, len)
          pedwarn ("integer constant larger than the maximum value of %s",
                   (flag_isoc99
                    ? (TREE_UNSIGNED (type)
-                      ? "an unsigned long long int"
-                      : "a long long int")
-                   : "an unsigned long int"));
+                      ? _("an unsigned long long int")
+                      : _("a long long int"))
+                   : _("an unsigned long int")));
        }
 
       if (base == 10 && ! spec_unsigned && TREE_UNSIGNED (type))
@@ -1253,20 +1189,11 @@ lex_number (str, len)
          else
            ERROR ("complex integer constant is too wide for 'complex int'");
        }
-      else if (flag_traditional && !int_fits_type_p (value, type))
-       /* The traditional constant 0x80000000 is signed
-          but doesn't fit in the range of int.
-          This will change it to -0x80000000, which does fit.  */
-       {
-         TREE_TYPE (value) = unsigned_type (type);
-         value = convert (type, value);
-         TREE_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (value) = 0;
-       }
       else
        TREE_TYPE (value) = type;
 
       /* If it's still an integer (not a complex), and it doesn't
-        fit in the type we choose for it, then pedwarn. */
+        fit in the type we choose for it, then pedwarn.  */
 
       if (! warn
          && TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE
@@ -1285,17 +1212,15 @@ lex_number (str, len)
 
 static tree
 lex_string (str, len, wide)
-     const char *str;
+     const unsigned char *str;
      unsigned int len;
      int wide;
 {
   tree value;
   char *buf = alloca ((len + 1) * (wide ? WCHAR_BYTES : 1));
   char *q = buf;
-  const char *p = str, *limit = str + len;
-  unsigned int c;
-  unsigned width = wide ? WCHAR_TYPE_SIZE
-                       : TYPE_PRECISION (char_type_node);
+  const unsigned char *p = str, *limit = str + len;
+  cppchar_t c;
 
 #ifdef MULTIBYTE_CHARS
   /* Reset multibyte conversion state.  */
@@ -1308,10 +1233,10 @@ lex_string (str, len, wide)
       wchar_t wc;
       int char_len;
 
-      char_len = local_mbtowc (&wc, p, limit - p);
+      char_len = local_mbtowc (&wc, (const char *) p, limit - p);
       if (char_len == -1)
        {
-         warning ("Ignoring invalid multibyte character");
+         warning ("ignoring invalid multibyte character");
          char_len = 1;
          c = *p++;
        }
@@ -1325,20 +1250,10 @@ lex_string (str, len, wide)
 #endif
 
       if (c == '\\' && !ignore_escape_flag)
-       {
-         unsigned int mask;
-
-         if (width < HOST_BITS_PER_INT)
-           mask = ((unsigned int) 1 << width) - 1;
-         else
-           mask = ~0;
-         c = cpp_parse_escape (parse_in, (const unsigned char **) &p,
-                               (const unsigned char *) limit,
-                               mask, flag_traditional);
-       }
+       c = cpp_parse_escape (parse_in, &p, limit, wide);
        
-      /* Add this single character into the buffer either as a wchar_t
-        or as a single byte.  */
+      /* Add this single character into the buffer either as a wchar_t,
+        a multibyte sequence, or as a single byte.  */
       if (wide)
        {
          unsigned charwidth = TYPE_PRECISION (char_type_node);
@@ -1359,6 +1274,16 @@ lex_string (str, len, wide)
            }
          q += WCHAR_BYTES;
        }
+#ifdef MULTIBYTE_CHARS
+      else if (char_len > 1)
+       {
+         /* We're dealing with a multibyte character. */
+         for ( ; char_len >0; --char_len)
+           {
+             *q++ = *(p - char_len);
+           }
+       }
+#endif
       else
        {
          *q++ = c;
@@ -1392,31 +1317,31 @@ static tree
 lex_charconst (token)
      const cpp_token *token;
 {
-  HOST_WIDE_INT result;
-  tree value;
+  cppchar_t result;
+  tree type, value;
   unsigned int chars_seen;
+  int unsignedp;
  
-  result = cpp_interpret_charconst (parse_in, token, warn_multichar,
-                                   flag_traditional, &chars_seen);
+  result = cpp_interpret_charconst (parse_in, token,
+                                   &chars_seen, &unsignedp);
+
+  /* Cast to cppchar_signed_t to get correct sign-extension of RESULT
+     before possibly widening to HOST_WIDE_INT for build_int_2.  */
+  if (unsignedp || (cppchar_signed_t) result >= 0)
+    value = build_int_2 (result, 0);
+  else
+    value = build_int_2 ((cppchar_signed_t) result, -1);
+
   if (token->type == CPP_WCHAR)
-    {
-      value = build_int_2 (result, 0);
-      TREE_TYPE (value) = wchar_type_node;
-    }
+    type = wchar_type_node;
+  /* In C, a character constant has type 'int'.
+     In C++ 'char', but multi-char charconsts have type 'int'.  */
+  else if ((c_language == clk_c || c_language == clk_objective_c)
+          || chars_seen > 1)
+    type = integer_type_node;
   else
-    {
-      if (result < 0)
-       value = build_int_2 (result, -1);
-      else
-       value = build_int_2 (result, 0);
-      /* In C, a character constant has type 'int'.
-        In C++ 'char', but multi-char charconsts have type 'int'.  */
-      if (c_language == clk_cplusplus && chars_seen <= 1)
-       TREE_TYPE (value) = char_type_node;
-      else
-       TREE_TYPE (value) = integer_type_node;
-    }
+    type = char_type_node;
+
+  TREE_TYPE (value) = type;
   return value;
 }