* config/sparc/tm-sp64.h (CALL_DUMMY): Store and retrieve
[deliverable/binutils-gdb.git] / gdb / ch-exp.c
index 28f44fd2e7f2222eb80f975e18e4d05861bcc0f1..45436a3bee8f2316eea816f2d64ab53cd1cdf430 100644 (file)
@@ -26,15 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
    during the process of parsing; the lower levels of the tree always
    come first in the result.
 
-   Note that malloc's and realloc's in this file are transformed to
-   xmalloc and xrealloc respectively by the same sed command in the
-   makefile that remaps any other malloc/realloc inserted by the parser
-   generator.  Doing this with #defines and trying to control the interaction
-   with include files (<malloc.h> and <stdlib.h> for example) just became
-   too messy, particularly when such includes can be inserted at random
-   times by the parser generator.
-
-   Also note that the language accepted by this parser is more liberal
+   Note that the language accepted by this parser is more liberal
    than the one accepted by an actual Chill compiler.  For example, the
    language rule that a simple name string can not be one of the reserved
    simple name strings is not enforced (e.g "case" is not treated as a
@@ -52,7 +44,7 @@ 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 "language.h"
@@ -63,11 +55,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "symfile.h" /* Required by objfiles.h.  */
 #include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
 
+#ifdef __GNUC__
+#define INLINE __inline__
+#endif
+
 typedef union
 
   {
     LONGEST lval;
-    unsigned LONGEST ulval;
+    ULONGEST ulval;
     struct {
       LONGEST val;
       struct type *type;
@@ -83,6 +79,7 @@ typedef union
 enum ch_terminal {
   END_TOKEN = 0,
   /* '\001' ... '\xff' come first. */
+  OPEN_PAREN = '(',
   TOKEN_NOT_READ = 999,
   INTEGER_LITERAL,
   BOOLEAN_LITERAL,
@@ -94,7 +91,7 @@ enum ch_terminal {
   CHARACTER_STRING_LITERAL,
   BIT_STRING_LITERAL,
   TYPENAME,
-  FIELD_NAME,
+  DOT_FIELD_NAME, /* '.' followed by <field name> */
   CASE,
   OF,
   ESAC,
@@ -138,13 +135,55 @@ enum ch_terminal {
 };
 
 /* Forward declarations. */
-static void parse_expr ();
-static void parse_primval ();
-static void parse_untyped_expr ();
-static int parse_opt_untyped_expr ();
-static void parse_if_expression_body PARAMS((void));
+
 static void write_lower_upper_value PARAMS ((enum exp_opcode, struct type *));
-static enum ch_terminal ch_lex ();
+static enum ch_terminal match_bitstring_literal PARAMS ((void));
+static enum ch_terminal match_integer_literal PARAMS ((void));
+static enum ch_terminal match_character_literal PARAMS ((void));
+static enum ch_terminal match_string_literal PARAMS ((void));
+static enum ch_terminal match_float_literal PARAMS ((void));
+static enum ch_terminal match_float_literal PARAMS ((void));
+static int decode_integer_literal PARAMS ((LONGEST *, char **));
+static int decode_integer_value PARAMS ((int, char **, LONGEST *));
+static char *match_simple_name_string PARAMS ((void));
+static void growbuf_by_size PARAMS ((int));
+static void parse_untyped_expr PARAMS ((void));
+static void parse_if_expression PARAMS ((void));
+static void parse_else_alternative PARAMS ((void));
+static void parse_then_alternative PARAMS ((void));
+static void parse_expr PARAMS ((void));
+static void parse_operand0 PARAMS ((void));
+static void parse_operand1 PARAMS ((void));
+static void parse_operand2 PARAMS ((void));
+static void parse_operand3 PARAMS ((void));
+static void parse_operand4 PARAMS ((void));
+static void parse_operand5 PARAMS ((void));
+static void parse_operand6 PARAMS ((void));
+static void parse_primval PARAMS ((void));
+static void parse_tuple PARAMS ((struct type *));
+static void parse_opt_element_list PARAMS ((struct type *));
+static void parse_tuple_element PARAMS ((struct type *));
+static void parse_named_record_element PARAMS ((void));
+static void parse_call PARAMS ((void));
+static struct type *parse_mode_or_normal_call PARAMS ((void));
+#if 0
+static struct type *parse_mode_call PARAMS ((void));
+#endif
+static void parse_unary_call PARAMS ((void));
+static int parse_opt_untyped_expr PARAMS ((void));
+static void parse_case_label PARAMS ((void));
+static int expect PARAMS ((enum ch_terminal, char *));
+static void parse_expr PARAMS ((void));
+static void parse_primval PARAMS ((void));
+static void parse_untyped_expr PARAMS ((void));
+static int parse_opt_untyped_expr PARAMS ((void));
+static void parse_if_expression_body PARAMS((void));
+static enum ch_terminal ch_lex PARAMS ((void));
+INLINE static enum ch_terminal PEEK_TOKEN PARAMS ((void));
+static enum ch_terminal peek_token_ PARAMS ((int));
+static void forward_token_ PARAMS ((void));
+static void require PARAMS ((enum ch_terminal));
+static int check_token PARAMS ((enum ch_terminal));
 
 #define MAX_LOOK_AHEAD 2
 static enum ch_terminal terminal_buffer[MAX_LOOK_AHEAD+1] = {
@@ -154,10 +193,7 @@ static YYSTYPE val_buffer[MAX_LOOK_AHEAD+1];
 
 /*int current_token, lookahead_token;*/
 
-#ifdef __GNUC__
-__inline__
-#endif
-static enum ch_terminal
+INLINE static enum ch_terminal
 PEEK_TOKEN()
 {
   if (terminal_buffer[0] == TOKEN_NOT_READ)
@@ -184,6 +220,8 @@ peek_token_ (i)
   return terminal_buffer[i];
 }
 
+#if 0
+
 static void
 pushback_token (code, node)
      enum ch_terminal code;
@@ -201,6 +239,8 @@ pushback_token (code, node)
   val_buffer[0] = node;
 }
 
+#endif
+
 static void
 forward_token_()
 {
@@ -217,7 +257,7 @@ forward_token_()
 /* Skip the next token.
    if it isn't TOKEN, the parser is broken. */
 
-void
+static void
 require(token)
      enum ch_terminal token;
 {
@@ -230,7 +270,7 @@ require(token)
   FORWARD_TOKEN();
 }
 
-int
+static int
 check_token (token)
      enum ch_terminal token;
 {
@@ -243,8 +283,8 @@ check_token (token)
 /* return 0 if expected token was not found,
    else return 1.
 */
-int
-expect(token, message)
+static int
+expect (token, message)
      enum ch_terminal token;
      char *message;
 {
@@ -253,7 +293,7 @@ expect(token, message)
       if (message)
        error (message);
       else if (token < 256)
-       error ("syntax error - expected a '%c' here '%s'", token, lexptr);
+       error ("syntax error - expected a '%c' here \"%s\"", token, lexptr);
       else
        error ("syntax error");
       return 0;
@@ -411,7 +451,9 @@ parse_unary_call ()
 
 /* Parse NAME '(' MODENAME ')'. */
 
-struct type *
+#if 0
+
+static struct type *
 parse_mode_call ()
 {
   struct type *type;
@@ -425,7 +467,9 @@ parse_mode_call ()
   return type;
 }
 
-struct type *
+#endif
+
+static struct type *
 parse_mode_or_normal_call ()
 {
   struct type *type;
@@ -478,7 +522,7 @@ parse_call ()
     }
   else
     arglist_len = 0;
-  expect (')', "expected ')' here");
+  expect (')', NULL);
   arg_count = end_arglist ();
   write_exp_elt_opcode (MULTI_SUBSCRIPT);
   write_exp_elt_longcst (arg_count);
@@ -488,8 +532,12 @@ parse_call ()
 static void
 parse_named_record_element ()
 {
-  struct stoken label = PEEK_LVAL ().sval;
-  expect (FIELD_NAME, "expected a field name here `%s'", lexptr);
+  struct stoken label;
+  char buf[256];
+
+  label = PEEK_LVAL ().sval;
+  sprintf (buf, "expected a field name here `%s'", lexptr);
+  expect (DOT_FIELD_NAME, buf);
   if (check_token (','))
     parse_named_record_element ();
   else if (check_token (':'))
@@ -501,12 +549,13 @@ parse_named_record_element ()
   write_exp_elt_opcode (OP_LABELED);
 }
 
-/* Returns one or nore TREE_LIST nodes, in reverse order. */
+/* Returns one or more TREE_LIST nodes, in reverse order. */
 
 static void
-parse_tuple_element ()
+parse_tuple_element (type)
+     struct type *type;
 {
-  if (PEEK_TOKEN () == FIELD_NAME)
+  if (PEEK_TOKEN () == DOT_FIELD_NAME)
     {
       /* Parse a labelled structure tuple. */
       parse_named_record_element ();
@@ -518,7 +567,32 @@ parse_tuple_element ()
       if (check_token ('*'))
        {
          expect (')', "missing ')' after '*' case label list");
-         error ("(*) not implemented in case label list");
+         if (type)
+           {
+             if (TYPE_CODE (type) == TYPE_CODE_ARRAY)
+               {
+                 /* do this as a range from low to high */
+                 struct type *range_type = TYPE_FIELD_TYPE (type, 0);
+                 LONGEST low_bound, high_bound;
+                 if (get_discrete_bounds (range_type, &low_bound, &high_bound) < 0)
+                   error ("cannot determine bounds for (*)");
+                 /* lower bound */
+                 write_exp_elt_opcode (OP_LONG);
+                 write_exp_elt_type (range_type);
+                 write_exp_elt_longcst (low_bound);
+                 write_exp_elt_opcode (OP_LONG);
+                 /* upper bound */
+                 write_exp_elt_opcode (OP_LONG);
+                 write_exp_elt_type (range_type);
+                 write_exp_elt_longcst (high_bound);
+                 write_exp_elt_opcode (OP_LONG);
+                 write_exp_elt_opcode (BINOP_RANGE);
+               }
+             else
+               error ("(*) in invalid context");
+           }
+         else
+           error ("(*) only possible with modename in front of tuple (mode[..])");
        }
       else
        {
@@ -544,14 +618,15 @@ parse_tuple_element ()
 /* Matches:  a COMMA-separated list of tuple elements.
    Returns a list (of TREE_LIST nodes). */
 static void
-parse_opt_element_list ()
+parse_opt_element_list (type)
+     struct type *type;
 {
   arglist_len = 0;
   if (PEEK_TOKEN () == ']')
     return;
   for (;;)
     {
-      parse_tuple_element ();
+      parse_tuple_element (type);
       arglist_len++;
       if (PEEK_TOKEN () == ']')
        break;
@@ -567,16 +642,25 @@ static void
 parse_tuple (mode)
      struct type *mode;
 {
+  struct type *type;
+  if (mode)
+    type = check_typedef (mode);
+  else
+    type = 0;
   require ('[');
   start_arglist ();
-  parse_opt_element_list ();
+  parse_opt_element_list (type);
   expect (']', "missing ']' after tuple");
   write_exp_elt_opcode (OP_ARRAY);
   write_exp_elt_longcst ((LONGEST) 0);
   write_exp_elt_longcst ((LONGEST) end_arglist () - 1);
   write_exp_elt_opcode (OP_ARRAY);
-  if (mode)
+  if (type)
     {
+      if (TYPE_CODE (type) != TYPE_CODE_ARRAY
+         && TYPE_CODE (type) != TYPE_CODE_STRUCT
+         && TYPE_CODE (type) != TYPE_CODE_SET)
+       error ("invalid tuple mode");
       write_exp_elt_opcode (UNOP_CAST);
       write_exp_elt_type (mode);
       write_exp_elt_opcode (UNOP_CAST);
@@ -595,7 +679,7 @@ parse_primval ()
     case CHARACTER_LITERAL:
       write_exp_elt_opcode (OP_LONG);
       write_exp_elt_type (PEEK_LVAL ().typed_val.type);
-      write_exp_elt_longcst ((LONGEST) (PEEK_LVAL ().typed_val.val));
+      write_exp_elt_longcst (PEEK_LVAL ().typed_val.val);
       write_exp_elt_opcode (OP_LONG);
       FORWARD_TOKEN ();
       break;
@@ -640,6 +724,7 @@ parse_primval ()
       if (PEEK_TOKEN () != TYPENAME)
        error ("missing MODENAME after ARRAY()");
       type = PEEK_LVAL().tsym.type;
+      FORWARD_TOKEN ();
       expect ('(', NULL);
       parse_expr ();
       expect (')', "missing right parenthesis");
@@ -683,12 +768,21 @@ parse_primval ()
       write_exp_elt_type (builtin_type_int);
       write_exp_elt_opcode (UNOP_CAST);
       break;
+    case CARD:
+      parse_unary_call ();
+      write_exp_elt_opcode (UNOP_CARD);
+      break;
+    case MAX_TOKEN:
+      parse_unary_call ();
+      write_exp_elt_opcode (UNOP_CHMAX);
+      break;
+    case MIN_TOKEN:
+      parse_unary_call ();
+      write_exp_elt_opcode (UNOP_CHMIN);
+      break;
     case PRED:      op_name = "PRED"; goto unimplemented_unary_builtin;
     case SUCC:      op_name = "SUCC"; goto unimplemented_unary_builtin;
     case ABS:       op_name = "ABS";  goto unimplemented_unary_builtin;
-    case CARD:      op_name = "CARD"; goto unimplemented_unary_builtin;
-    case MAX_TOKEN: op_name = "MAX";  goto unimplemented_unary_builtin;
-    case MIN_TOKEN: op_name = "MIN";  goto unimplemented_unary_builtin;
     unimplemented_unary_builtin:
       parse_unary_call ();
       error ("not implemented:  %s builtin function", op_name);
@@ -751,7 +845,7 @@ parse_primval ()
     {
       switch (PEEK_TOKEN ())
        {
-       case FIELD_NAME:
+       case DOT_FIELD_NAME:
          write_exp_elt_opcode (STRUCTOP_STRUCT);
          write_exp_string (PEEK_LVAL ().sval);
          write_exp_elt_opcode (STRUCTOP_STRUCT);
@@ -769,7 +863,7 @@ parse_primval ()
            }
          write_exp_elt_opcode (UNOP_IND);
          continue;
-       case '(':
+       case OPEN_PAREN:
          parse_call ();
          continue;
        case CHARACTER_STRING_LITERAL:
@@ -781,6 +875,55 @@ parse_primval ()
          write_exp_elt_longcst (1);
          write_exp_elt_opcode (MULTI_SUBSCRIPT);
          continue;
+       case END_TOKEN:
+       case TOKEN_NOT_READ:
+       case INTEGER_LITERAL:
+       case BOOLEAN_LITERAL:
+       case FLOAT_LITERAL:
+       case GENERAL_PROCEDURE_NAME:
+       case LOCATION_NAME:
+       case EMPTINESS_LITERAL:
+       case TYPENAME:
+       case CASE:
+       case OF:
+       case ESAC:
+       case LOGIOR:
+       case ORIF:
+       case LOGXOR:
+       case LOGAND:
+       case ANDIF:
+       case NOTEQUAL:
+       case GEQ:
+       case LEQ:
+       case IN:
+       case SLASH_SLASH:
+       case MOD:
+       case REM:
+       case NOT:
+       case RECEIVE:
+       case UP:
+       case IF:
+       case THEN:
+       case ELSE:
+       case FI:
+       case ELSIF:
+       case ILLEGAL_TOKEN:
+       case NUM:
+       case PRED:
+       case SUCC:
+       case ABS:
+       case CARD:
+       case MAX_TOKEN:
+       case MIN_TOKEN:
+       case ADDR_TOKEN:
+       case SIZE:
+       case UPPER:
+       case LOWER:
+       case LENGTH:
+       case ARRAY:
+       case GDB_VARIABLE:
+       case GDB_ASSIGNMENT:
+         break;
        }
       break;
     }
@@ -1086,11 +1229,11 @@ growbuf_by_size (count)
   tempbufsize += growby;
   if (tempbuf == NULL)
     {
-      tempbuf = (char *) malloc (tempbufsize);
+      tempbuf = (char *) xmalloc (tempbufsize);
     }
   else
     {
-      tempbuf = (char *) realloc (tempbuf, tempbufsize);
+      tempbuf = (char *) xrealloc (tempbuf, tempbufsize);
     }
 }
 
@@ -1404,23 +1547,67 @@ static enum ch_terminal
 match_string_literal ()
 {
   char *tokptr = lexptr;
+  int in_ctrlseq = 0;
+  LONGEST ival;
 
   for (tempbufindex = 0, tokptr++; *tokptr != '\0'; tokptr++)
     {
       CHECKBUF (1);
-      if (*tokptr == *lexptr)
+    tryagain: ;
+      if (in_ctrlseq)
        {
-         if (*(tokptr + 1) == *lexptr)
+         /* skip possible whitespaces */
+         while ((*tokptr == ' ' || *tokptr == '\t') && *tokptr)
+           tokptr++;
+         if (*tokptr == ')')
            {
+             in_ctrlseq = 0;
              tokptr++;
+             goto tryagain;
+           }
+         else if (*tokptr != ',')
+           error ("Invalid control sequence");
+         tokptr++;
+         /* skip possible whitespaces */
+         while ((*tokptr == ' ' || *tokptr == '\t') && *tokptr)
+           tokptr++;
+         if (!decode_integer_literal (&ival, &tokptr))
+           error ("Invalid control sequence");
+         tokptr--;
+       }
+      else if (*tokptr == *lexptr)
+       {
+         if (*(tokptr + 1) == *lexptr)
+           {
+             ival = *tokptr++;
            }
          else
            {
              break;
            }
        }
-      tempbuf[tempbufindex++] = *tokptr;
+      else if (*tokptr == '^')
+       {
+         if (*(tokptr + 1) == '(')
+           {
+             in_ctrlseq = 1;
+             tokptr += 2;
+             if (!decode_integer_literal (&ival, &tokptr))
+               error ("Invalid control sequence");
+             tokptr--;
+           }
+         else if (*(tokptr + 1) == '^')
+           ival = *tokptr++;
+         else
+           error ("Invalid control sequence");
+       }
+      else
+       ival = *tokptr;
+      tempbuf[tempbufindex++] = ival;
     }
+  if (in_ctrlseq)
+    error ("Invalid control sequence");
+
   if (*tokptr == '\0'                                  /* no terminator */
       || (tempbufindex == 1 && *tokptr == '\''))       /* char literal */
     {
@@ -1449,12 +1636,6 @@ match_string_literal ()
    Note that more than a single character, enclosed in single quotes, is
    a string literal.
 
-   Also note that the control sequence form is not in GNU Chill since it
-   is ambiguous with the string literal form using single quotes.  I.E.
-   is '^(7)' a character literal or a string literal.  In theory it it
-   possible to tell by context, but GNU Chill doesn't accept the control
-   sequence form, so neither do we (for now the code is disabled).
-
    Returns CHARACTER_LITERAL if a match is found.
    */
 
@@ -1483,28 +1664,39 @@ match_character_literal ()
       /* Determine which form we have, either a control sequence or the
         single character form. */
       
-      if ((*tokptr == '^') && (*(tokptr + 1) == '('))
+      if (*tokptr == '^')
        {
-#if 0     /* Disable, see note above. -fnf */
-         /* Match and decode a control sequence.  Return zero if we don't
-            find a valid integer literal, or if the next unconsumed character
-            after the integer literal is not the trailing ')'.
-            FIXME:  We currently don't handle the multiple integer literal
-            form. */
-         tokptr += 2;
-         if (!decode_integer_literal (&ival, &tokptr) || (*tokptr++ != ')'))
+         if (*(tokptr + 1) == '(')
            {
-             return (0);
+             /* Match and decode a control sequence.  Return zero if we don't
+                find a valid integer literal, or if the next unconsumed character
+                after the integer literal is not the trailing ')'. */
+             tokptr += 2;
+             if (!decode_integer_literal (&ival, &tokptr) || (*tokptr++ != ')'))
+               {
+                 return (0);
+               }
            }
-#else
-         return (0);
-#endif
+         else if (*(tokptr + 1) == '^')
+           {
+             ival = *tokptr;
+             tokptr += 2;
+           }
+         else
+           /* fail */
+           error ("Invalid control sequence");
+       }
+      else if (*tokptr == '\'')
+       {
+         /* this must be duplicated */
+         ival = *tokptr;
+         tokptr += 2;
        }
       else
        {
          ival = *tokptr++;
        }
-      
+
       /* The trailing quote has not yet been consumed.  If we don't find
         it, then we have no match. */
       
@@ -1542,8 +1734,8 @@ match_integer_literal ()
   else 
     {
       yylval.typed_val.val = ival;
-#ifdef CC_HAS_LONG_LONG
-      if (ival > 2147483647 || ival < -2147483648)
+#if defined(CC_HAS_LONG_LONG) && defined(__STDC__)
+      if (ival > (LONGEST)2147483647U || ival < -(LONGEST)2147483648U)
        yylval.typed_val.type = builtin_type_long_long;
       else
 #endif
@@ -1618,7 +1810,8 @@ match_bitstring_literal ()
            digit += 10;
            break;
          default:
-           error ("Invalid character in bitstring or integer.");
+           /* this is not a bitstring literal, probably an integer */
+           return 0;
        }
       if (digit >= 1 << bits_per_char)
        {
@@ -1918,6 +2111,9 @@ ch_lex ()
              case LOC_OPTIMIZED_OUT:
                error ("Symbol \"%s\" names no location.", inputname);
                break;
+             case LOC_UNRESOLVED:
+               error ("unhandled SYMBOL_CLASS in ch_lex()");
+               break;
              }
          }
        else if (!have_full_symbols () && !have_partial_symbols ())
@@ -1941,7 +2137,7 @@ ch_lex ()
          inputname = match_simple_name_string ();
          if (!inputname)
            return '.';
-         return FIELD_NAME;
+         return DOT_FIELD_NAME;
       }
 
     return (ILLEGAL_TOKEN);
@@ -1956,7 +2152,6 @@ write_lower_upper_value (opcode, type)
     write_exp_elt_opcode (opcode);
   else
     {
-      extern LONGEST type_lower_upper ();
       struct type *result_type;
       LONGEST val = type_lower_upper (opcode, type, &result_type);
       write_exp_elt_opcode (OP_LONG);
This page took 0.031331 seconds and 4 git commands to generate.