OSDN Git Service

* real.h (struct real_value): Add signalling.
[pf3gnuchains/gcc-fork.git] / gcc / read-rtl.c
index febab50..95bc2fe 100644 (file)
@@ -1,33 +1,32 @@
 /* RTL reader for GNU C Compiler.
-   Copyright (C) 1987, 1988, 1991, 1994, 1997, 1998, 1999, 2000, 2001
+   Copyright (C) 1987, 1988, 1991, 1994, 1997, 1998, 1999, 2000, 2001, 2002
    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 "hconfig.h"
+#include "bconfig.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "rtl.h"
 #include "obstack.h"
 #include "hashtab.h"
 
-#define        obstack_chunk_alloc     xmalloc
-#define        obstack_chunk_free      free
-
 static htab_t md_constants;
 
 static void fatal_with_file_and_line PARAMS ((FILE *, const char *, ...))
@@ -37,9 +36,11 @@ static void read_name                PARAMS ((char *, FILE *));
 static char *read_string       PARAMS ((struct obstack *, FILE *, int));
 static char *read_quoted_string        PARAMS ((struct obstack *, FILE *));
 static char *read_braced_string        PARAMS ((struct obstack *, FILE *));
-static unsigned def_hash PARAMS ((const void *));
+static void read_escape                PARAMS ((struct obstack *, FILE *));
+static hashval_t def_hash      PARAMS ((const void *));
 static int def_name_eq_p PARAMS ((const void *, const void *));
 static void read_constants PARAMS ((FILE *infile, char *tmp_char));
+static void validate_const_int PARAMS ((FILE *, const char *));
 
 /* Subroutines of read_rtx.  */
 
@@ -52,28 +53,20 @@ const char *read_rtx_filename = "<unknown>";
 static void
 fatal_with_file_and_line VPARAMS ((FILE *infile, const char *msg, ...))
 {
-#ifndef ANSI_PROTOTYPES
-  FILE *infile;
-  const char *msg;
-#endif
-  va_list ap;
   char context[64];
   size_t i;
   int c;
 
-  VA_START (ap, msg);
-
-#ifndef ANSI_PROTOTYPES
-  infile = va_arg (ap, FILE *);
-  msg = va_arg (ap, const char *);
-#endif
+  VA_OPEN (ap, msg);
+  VA_FIXEDARG (ap, FILE *, infile);
+  VA_FIXEDARG (ap, const char *, msg);
 
   fprintf (stderr, "%s:%d: ", read_rtx_filename, read_rtx_lineno);
   vfprintf (stderr, msg, ap);
   putc ('\n', stderr);
 
   /* Gather some following context.  */
-  for (i = 0; i < sizeof(context)-1; ++i)
+  for (i = 0; i < sizeof (context)-1; ++i)
     {
       c = getc (infile);
       if (c == EOF)
@@ -87,7 +80,7 @@ fatal_with_file_and_line VPARAMS ((FILE *infile, const char *msg, ...))
   fprintf (stderr, "%s:%d: following context is `%s'\n",
           read_rtx_filename, read_rtx_lineno, context);
 
-  va_end (ap);
+  VA_CLOSE (ap);
   exit (1);
 }
 
@@ -112,7 +105,8 @@ int
 read_skip_spaces (infile)
      FILE *infile;
 {
-  register int c;
+  int c;
+
   while (1)
     {
       c = getc (infile);
@@ -134,7 +128,7 @@ read_skip_spaces (infile)
 
        case '/':
          {
-           register int prevc;
+           int prevc;
            c = getc (infile);
            if (c != '*')
              fatal_expected_char (infile, '*', c);
@@ -165,15 +159,15 @@ read_name (str, infile)
      char *str;
      FILE *infile;
 {
-  register char *p;
-  register int c;
+  char *p;
+  int c;
 
-  c = read_skip_spaces(infile);
+  c = read_skip_spaces (infile);
 
   p = str;
   while (1)
     {
-      if (c == ' ' || c == '\n' || c == '\t' || c == '\f')
+      if (c == ' ' || c == '\n' || c == '\t' || c == '\f' || c == '\r')
        break;
       if (c == ':' || c == ')' || c == ']' || c == '"' || c == '/'
          || c == '(' || c == '[')
@@ -211,6 +205,61 @@ read_name (str, infile)
     }
 }
 
+/* Subroutine of the string readers.  Handles backslash escapes.
+   Caller has read the backslash, but not placed it into the obstack.  */
+static void
+read_escape (ob, infile)
+     struct obstack *ob;
+     FILE *infile;
+{
+  int c = getc (infile);
+
+  switch (c)
+    {
+      /* Backslash-newline is replaced by nothing, as in C.  */
+    case '\n':
+      read_rtx_lineno++;
+      return;
+
+      /* \" \' \\ are replaced by the second character.  */
+    case '\\':
+    case '"':
+    case '\'':
+      break;
+
+      /* Standard C string escapes:
+        \a \b \f \n \r \t \v
+        \[0-7] \x
+        all are passed through to the output string unmolested.
+        In normal use these wind up in a string constant processed
+        by the C compiler, which will translate them appropriately.
+        We do not bother checking that \[0-7] are followed by up to
+        two octal digits, or that \x is followed by N hex digits.
+        \? \u \U are left out because they are not in traditional C.  */
+    case 'a': case 'b': case 'f': case 'n': case 'r': case 't': case 'v':
+    case '0': case '1': case '2': case '3': case '4': case '5': case '6':
+    case '7': case 'x':
+      obstack_1grow (ob, '\\');
+      break;
+
+      /* \; makes stuff for a C string constant containing
+        newline and tab.  */
+    case ';':
+      obstack_grow (ob, "\\n\\t", 4);
+      return;
+
+      /* pass anything else through, but issue a warning.  */
+    default:
+      fprintf (stderr, "%s:%d: warning: unrecognized escape \\%c\n",
+              read_rtx_filename, read_rtx_lineno, c);
+      obstack_1grow (ob, '\\');
+      break;
+    }
+
+  obstack_1grow (ob, c);
+}
+
+
 /* Read a double-quoted string onto the obstack.  Caller has scanned
    the leading quote.  */
 static char *
@@ -219,6 +268,7 @@ read_quoted_string (ob, infile)
      FILE *infile;
 {
   int c;
+
   while (1)
     {
       c = getc (infile); /* Read the string  */
@@ -226,27 +276,8 @@ read_quoted_string (ob, infile)
        read_rtx_lineno++;
       else if (c == '\\')
        {
-         c = getc (infile);    /* Read the string  */
-         /* \; makes stuff for a C string constant containing
-            newline and tab.  */
-         if (c == ';')
-           {
-             obstack_grow (ob, "\\n\\t", 4);
-             continue;
-           }
-         else if (c == '\n')
-           /* \-newline: delete the backslash and update our idea of
-              the line number.  */
-           read_rtx_lineno++;
-         else if (c == '\\' || c == '"')
-           ; /* \", \\ are a literal quote and backslash.  */
-         else
-           /* Backslash escapes we do not recognize are left unmolested.
-              They may be handled by the C compiler (e.g. \n, \t) */
-           {
-             ungetc (c, infile);  /* put it back */
-             c = '\\';
-           }
+         read_escape (ob, infile);
+         continue;
        }
       else if (c == '"')
        break;
@@ -281,32 +312,13 @@ read_braced_string (ob, infile)
        brace_depth--;
       else if (c == '\\')
        {
-         c = getc (infile);    /* Read the string  */
-         /* \; makes stuff for a C string constant containing
-            newline and tab.  */
-         if (c == ';')
-           {
-             obstack_grow (ob, "\\n\\t", 4);
-             continue;
-           }
-         else if (c == '\n')
-           /* \-newline: delete the backslash and update our idea of
-              the line number.  */
-           read_rtx_lineno++;
-         else if (c == '\\')
-           ; /* \\ is a literal backslash */
-         else
-           /* Backslash escapes we do not recognize are left unmolested.
-              They may be handled by the C compiler (e.g. \n, \t) */
-           {
-             ungetc (c, infile);  /* put it back */
-             c = '\\';
-           }
+         read_escape (ob, infile);
+         continue;
        }
 
       obstack_1grow (ob, c);
     }
-      
+
   obstack_1grow (ob, 0);
   return obstack_finish (ob);
 }
@@ -342,7 +354,7 @@ read_string (ob, infile, star_if_braced)
     }
   else
     fatal_with_file_and_line (infile, "expected `\"' or `{', found `%c'", c);
-       
+
   if (saw_paren)
     {
       c = read_skip_spaces (infile);
@@ -356,14 +368,16 @@ read_string (ob, infile, star_if_braced)
 /* Provide a version of a function to read a long long if the system does
    not provide one.  */
 #if HOST_BITS_PER_WIDE_INT > HOST_BITS_PER_LONG && !defined(HAVE_ATOLL) && !defined(HAVE_ATOQ)
+HOST_WIDE_INT atoll PARAMS ((const char *));
+
 HOST_WIDE_INT
-atoll(p)
+atoll (p)
     const char *p;
 {
   int neg = 0;
   HOST_WIDE_INT tmp_wide;
 
-  while (ISSPACE(*p))
+  while (ISSPACE (*p))
     p++;
   if (*p == '-')
     neg = 1, p++;
@@ -371,13 +385,13 @@ atoll(p)
     p++;
 
   tmp_wide = 0;
-  while (ISDIGIT(*p))
+  while (ISDIGIT (*p))
     {
       HOST_WIDE_INT new_wide = tmp_wide*10 + (*p - '0');
       if (new_wide < tmp_wide)
        {
          /* Return INT_MAX equiv on overflow.  */
-         tmp_wide = (~(unsigned HOST_WIDE_INT)0) >> 1;
+         tmp_wide = (~(unsigned HOST_WIDE_INT) 0) >> 1;
          break;
        }
       tmp_wide = new_wide;
@@ -391,12 +405,12 @@ atoll(p)
 #endif
 
 /* Given a constant definition, return a hash code for its name.  */
-static unsigned
+static hashval_t
 def_hash (def)
      const void *def;
 {
   unsigned result, i;
-  const char *string = ((const struct md_constant *)def)->name;
+  const char *string = ((const struct md_constant *) def)->name;
 
   for (result = i = 0;*string++ != '\0'; i++)
     result += ((unsigned char) *string << (i % CHAR_BIT));
@@ -408,8 +422,8 @@ static int
 def_name_eq_p (def1, def2)
      const void *def1, *def2;
 {
-  return ! strcmp (((const struct md_constant *)def1)->name,
-                  ((const struct md_constant *)def2)->name);
+  return ! strcmp (((const struct md_constant *) def1)->name,
+                  ((const struct md_constant *) def2)->name);
 }
 
 /* INFILE is a FILE pointer to read text from.  TMP_CHAR is a buffer suitable
@@ -482,6 +496,28 @@ traverse_md_constants (callback, info)
     htab_traverse (md_constants, callback, info);
 }
 
+static void
+validate_const_int (infile, string)
+     FILE *infile;
+     const char *string;
+{
+  const char *cp;
+  int valid = 1;
+
+  cp = string;
+  while (*cp && ISSPACE (*cp))
+    cp++;
+  if (*cp == '-' || *cp == '+')
+    cp++;
+  if (*cp == 0)
+    valid = 0;
+  for (; *cp; cp++)
+    if (! ISDIGIT (*cp))
+      valid = 0;
+  if (!valid)
+    fatal_with_file_and_line (infile, "invalid decimal constant \"%s\"\n", string);
+}
+
 /* Read an rtx in printed representation from INFILE
    and return an actual rtx in core constructed accordingly.
    read_rtx is not used in the compiler proper, but rather in
@@ -491,15 +527,15 @@ rtx
 read_rtx (infile)
      FILE *infile;
 {
-  register int i, j;
+  int i, j;
   RTX_CODE tmp_code;
-  register const char *format_ptr;
+  const char *format_ptr;
   /* tmp_char is a buffer used for reading decimal integers
      and names of rtx types and machine modes.
      Therefore, 256 must be enough.  */
   char tmp_char[256];
   rtx return_rtx;
-  register int c;
+  int c;
   int tmp_int;
   HOST_WIDE_INT tmp_wide;
 
@@ -598,7 +634,7 @@ again:
          {
            XVEC (return_rtx, i) = 0;
            break;
-         }
+         }
        /* Now process the vector.  */
 
       case 'E':
@@ -643,6 +679,7 @@ again:
            break;
          }
 
+      case 'T':
       case 's':
        {
          char *stringbuf;
@@ -651,11 +688,8 @@ again:
             DEFINE_INSN_AND_SPLIT, or DEFINE_PEEPHOLE automatically
             gets a star inserted as its first character, if it is
             written with a brace block instead of a string constant.  */
-         int star_if_braced =
-           ((i == 3 && (GET_CODE (return_rtx) == DEFINE_INSN
-                        || GET_CODE (return_rtx) == DEFINE_INSN_AND_SPLIT))
-            || (i == 2 && GET_CODE (return_rtx) == DEFINE_PEEPHOLE));
-           
+         int star_if_braced = (format_ptr[-1] == 'T');
+
          stringbuf = read_string (&rtl_obstack, infile, star_if_braced);
 
          /* For insn patterns, we want to provide a default name
@@ -680,12 +714,16 @@ again:
              stringbuf = (char *) obstack_finish (&rtl_obstack);
            }
 
-         XSTR (return_rtx, i) = stringbuf;
+         if (star_if_braced)
+           XTMPL (return_rtx, i) = stringbuf;
+         else
+           XSTR (return_rtx, i) = stringbuf;
        }
        break;
 
       case 'w':
        read_name (tmp_char, infile);
+       validate_const_int (infile, tmp_char);
 #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
        tmp_wide = atoi (tmp_char);
 #else
@@ -707,6 +745,7 @@ again:
       case 'i':
       case 'n':
        read_name (tmp_char, infile);
+       validate_const_int (infile, tmp_char);
        tmp_int = atoi (tmp_char);
        XINT (return_rtx, i) = tmp_int;
        break;