Remove sanitized-out Magic Cap support, will never be released
[deliverable/binutils-gdb.git] / gdb / c-exp.y
index eae0794766c7b49ab9899c791920a6493ee67991..7ea6c1f9b04fbcab316008a2d2ba40a37fae25e1 100644 (file)
@@ -1,5 +1,5 @@
 /* YACC parser for C expressions, for GDB.
-   Copyright (C) 1986, 1989, 1990, 1991, 1993, 1994
+   Copyright (C) 1986, 1989, 1990, 1991, 1993, 1994, 1996, 1997
    Free Software Foundation, Inc.
 
 This file is part of GDB.
@@ -38,7 +38,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 %{
 
 #include "defs.h"
-#include <string.h>
+#include "gdb_string.h"
+#include <ctype.h>
 #include "expression.h"
 #include "value.h"
 #include "parser-defs.h"
@@ -119,8 +120,11 @@ yyerror PARAMS ((char *));
     struct {
       LONGEST val;
       struct type *type;
-    } typed_val;
-    double dval;
+    } typed_val_int;
+    struct {
+      DOUBLEST dval;
+      struct type *type;
+    } typed_val_float;
     struct symbol *sym;
     struct type *tval;
     struct stoken sval;
@@ -152,8 +156,8 @@ parse_number PARAMS ((char *, int, int, YYSTYPE *));
 %type <tval> ptype
 %type <lval> array_mod
 
-%token <typed_val> INT
-%token <dval> FLOAT
+%token <typed_val_int> INT
+%token <typed_val_float> FLOAT
 
 /* Both NAME and TYPENAME tokens represent symbols in the input,
    and both convey their data as strings.
@@ -183,7 +187,7 @@ parse_number PARAMS ((char *, int, int, YYSTYPE *));
 
 /* Special type cases, put in to allow the parser to distinguish different
    legal basetypes.  */
-%token SIGNED_KEYWORD LONG SHORT INT_KEYWORD CONST_KEYWORD VOLATILE_KEYWORD
+%token SIGNED_KEYWORD LONG SHORT INT_KEYWORD CONST_KEYWORD VOLATILE_KEYWORD DOUBLE_KEYWORD
 
 %token <voidval> VARIABLE
 
@@ -464,8 +468,8 @@ exp :       NAME_OR_INT
                        { YYSTYPE val;
                          parse_number ($1.stoken.ptr, $1.stoken.length, 0, &val);
                          write_exp_elt_opcode (OP_LONG);
-                         write_exp_elt_type (val.typed_val.type);
-                         write_exp_elt_longcst ((LONGEST)val.typed_val.val);
+                         write_exp_elt_type (val.typed_val_int.type);
+                         write_exp_elt_longcst ((LONGEST)val.typed_val_int.val);
                          write_exp_elt_opcode (OP_LONG);
                        }
        ;
@@ -473,8 +477,8 @@ exp :       NAME_OR_INT
 
 exp    :       FLOAT
                        { write_exp_elt_opcode (OP_DOUBLE);
-                         write_exp_elt_type (builtin_type_double);
-                         write_exp_elt_dblcst ($1);
+                         write_exp_elt_type ($1.type);
+                         write_exp_elt_dblcst ($1.dval);
                          write_exp_elt_opcode (OP_DOUBLE); }
        ;
 
@@ -488,6 +492,7 @@ exp :       VARIABLE
 exp    :       SIZEOF '(' type ')'     %prec UNARY
                        { write_exp_elt_opcode (OP_LONG);
                          write_exp_elt_type (builtin_type_int);
+                         CHECK_TYPEDEF ($3);
                          write_exp_elt_longcst ((LONGEST) TYPE_LENGTH ($3));
                          write_exp_elt_opcode (OP_LONG); }
        ;
@@ -590,15 +595,14 @@ qualified_name:   typebase COLONCOLON name
                            error ("`%s' is not defined as an aggregate type.",
                                   TYPE_NAME (type));
 
-                         if (!STREQ (type_name_no_tag (type), $4.ptr))
-                           error ("invalid destructor `%s::~%s'",
-                                  type_name_no_tag (type), $4.ptr);
-
                          tmp_token.ptr = (char*) alloca ($4.length + 2);
                          tmp_token.length = $4.length + 1;
                          tmp_token.ptr[0] = '~';
                          memcpy (tmp_token.ptr+1, $4.ptr, $4.length);
                          tmp_token.ptr[tmp_token.length] = 0;
+
+                         /* Check for valid destructor name.  */
+                         destructor_name_p (tmp_token.ptr, type);
                          write_exp_elt_opcode (OP_SCOPE);
                          write_exp_elt_type (type);
                          write_exp_string (tmp_token);
@@ -796,6 +800,10 @@ typebase  /* Implements (approximately): (type-qualifier)* type-specifier */
                        { $$ = builtin_type_short; }
        |       UNSIGNED SHORT INT_KEYWORD
                        { $$ = builtin_type_unsigned_short; }
+       |       DOUBLE_KEYWORD
+                       { $$ = builtin_type_double; }
+       |       LONG DOUBLE_KEYWORD
+                       { $$ = builtin_type_long_double; }
        |       STRUCT name
                        { $$ = lookup_struct (copy_name ($2),
                                              expression_context_block); }
@@ -897,7 +905,7 @@ parse_number (p, len, parsed_float, putithere)
      here, and we do kind of silly things like cast to unsigned.  */
   register LONGEST n = 0;
   register LONGEST prevn = 0;
-  unsigned LONGEST un;
+  ULONGEST un;
 
   register int i = 0;
   register int c;
@@ -910,14 +918,51 @@ parse_number (p, len, parsed_float, putithere)
   /* We have found a "L" or "U" suffix.  */
   int found_suffix = 0;
 
-  unsigned LONGEST high_bit;
+  ULONGEST high_bit;
   struct type *signed_type;
   struct type *unsigned_type;
 
   if (parsed_float)
     {
       /* It's a float since it contains a point or an exponent.  */
-      putithere->dval = atof (p);
+      char c;
+      int num = 0;     /* number of tokens scanned by scanf */
+      char saved_char = p[len];
+
+      p[len] = 0;      /* null-terminate the token */
+      if (sizeof (putithere->typed_val_float.dval) <= sizeof (float))
+       num = sscanf (p, "%g%c", (float *) &putithere->typed_val_float.dval,&c);
+      else if (sizeof (putithere->typed_val_float.dval) <= sizeof (double))
+       num = sscanf (p, "%lg%c", (double *) &putithere->typed_val_float.dval,&c);
+      else
+       {
+#ifdef PRINTF_HAS_LONG_DOUBLE
+         num = sscanf (p, "%Lg%c", &putithere->typed_val_float.dval,&c);
+#else
+         /* Scan it into a double, then assign it to the long double.
+            This at least wins with values representable in the range
+            of doubles. */
+         double temp;
+         num = sscanf (p, "%lg%c", &temp,&c);
+         putithere->typed_val_float.dval = temp;
+#endif
+       }
+      p[len] = saved_char;     /* restore the input stream */
+      if (num != 1)            /* check scanf found ONLY a float ... */
+       return ERROR;
+      /* See if it has `f' or `l' suffix (float or long double).  */
+
+      c = tolower (p[len - 1]);
+
+      if (c == 'f')
+       putithere->typed_val_float.type = builtin_type_float;
+      else if (c == 'l')
+       putithere->typed_val_float.type = builtin_type_long_double;
+      else if (isdigit (c) || c == '.')
+       putithere->typed_val_float.type = builtin_type_double;
+      else
+       return ERROR;
+
       return FLOAT;
     }
 
@@ -1000,7 +1045,7 @@ parse_number (p, len, parsed_float, putithere)
         on 0x123456789 when LONGEST is 32 bits.  */
       if (c != 'l' && c != 'u' && n != 0)
        {       
-         if ((unsigned_p && (unsigned LONGEST) prevn >= (unsigned LONGEST) n))
+         if ((unsigned_p && (ULONGEST) prevn >= (ULONGEST) n))
            error ("Numeric constant too large.");
        }
       prevn = n;
@@ -1018,11 +1063,11 @@ parse_number (p, len, parsed_float, putithere)
      the case where it is we just always shift the value more than
      once, with fewer bits each time.  */
 
-  un = (unsigned LONGEST)n >> 2;
+  un = (ULONGEST)n >> 2;
   if (long_p == 0
       && (un >> (TARGET_INT_BIT - 2)) == 0)
     {
-      high_bit = ((unsigned LONGEST)1) << (TARGET_INT_BIT-1);
+      high_bit = ((ULONGEST)1) << (TARGET_INT_BIT-1);
 
       /* A large decimal (not hex or octal) constant (between INT_MAX
         and UINT_MAX) is a long or unsigned long, according to ANSI,
@@ -1036,36 +1081,36 @@ parse_number (p, len, parsed_float, putithere)
   else if (long_p <= 1
           && (un >> (TARGET_LONG_BIT - 2)) == 0)
     {
-      high_bit = ((unsigned LONGEST)1) << (TARGET_LONG_BIT-1);
+      high_bit = ((ULONGEST)1) << (TARGET_LONG_BIT-1);
       unsigned_type = builtin_type_unsigned_long;
       signed_type = builtin_type_long;
     }
   else
     {
-      high_bit = (((unsigned LONGEST)1)
+      high_bit = (((ULONGEST)1)
                  << (TARGET_LONG_LONG_BIT - 32 - 1)
                  << 16
                  << 16);
       if (high_bit == 0)
        /* A long long does not fit in a LONGEST.  */
        high_bit =
-         (unsigned LONGEST)1 << (sizeof (LONGEST) * HOST_CHAR_BIT - 1);
+         (ULONGEST)1 << (sizeof (LONGEST) * HOST_CHAR_BIT - 1);
       unsigned_type = builtin_type_unsigned_long_long;
       signed_type = builtin_type_long_long;
     }
 
-   putithere->typed_val.val = n;
+   putithere->typed_val_int.val = n;
 
    /* If the high bit of the worked out type is set then this number
       has to be unsigned. */
 
    if (unsigned_p || (n & high_bit)) 
      {
-       putithere->typed_val.type = unsigned_type;
+       putithere->typed_val_int.type = unsigned_type;
      }
    else 
      {
-       putithere->typed_val.type = signed_type;
+       putithere->typed_val_int.type = signed_type;
      }
 
    return INT;
@@ -1165,8 +1210,8 @@ yylex ()
       else if (c == '\'')
        error ("Empty character constant.");
 
-      yylval.typed_val.val = c;
-      yylval.typed_val.type = builtin_type_char;
+      yylval.typed_val_int.val = c;
+      yylval.typed_val_int.type = builtin_type_char;
 
       c = *lexptr++;
       if (c != '\'')
@@ -1359,15 +1404,30 @@ yylex ()
        (c == '_' || c == '$' || (c >= '0' && c <= '9')
        || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '<');)
     {
-       if (c == '<')
-        {
-          int i = namelen;
-          while (tokstart[++i] && tokstart[i] != '>');
-          if (tokstart[i] == '>')
-            namelen = i;
-         }
-       c = tokstart[++namelen];
-     }
+      /* Template parameter lists are part of the name.
+        FIXME: This mishandles `print $a<4&&$a>3'.  */
+
+      if (c == '<')
+       {
+         int i = namelen;
+         int nesting_level = 1;
+         while (tokstart[++i])
+           {
+             if (tokstart[i] == '<')
+               nesting_level++;
+             else if (tokstart[i] == '>')
+               {
+                 if (--nesting_level == 0)
+                   break;
+               }
+           }
+         if (tokstart[i] == '>')
+           namelen = i;
+         else
+           break;
+       }
+      c = tokstart[++namelen];
+    }
 
   /* The token "if" terminates the expression and is NOT 
      removed from the input stream.  */
@@ -1399,6 +1459,8 @@ yylex ()
        return SIGNED_KEYWORD;
       if (STREQN (tokstart, "sizeof", 6))      
        return SIZEOF;
+      if (STREQN (tokstart, "double", 6))      
+       return DOUBLE_KEYWORD;
       break;
     case 5:
       if (current_language->la_language == language_cplus
This page took 0.028871 seconds and 4 git commands to generate.