Indented file using gdb_indent.sh.
[deliverable/binutils-gdb.git] / gdb / p-exp.y
index edf34ca7a583f6d3cb9cffc8880acf284cfd054a..7333f6d04a0dbff8036b84a8ca150a42c723fa96 100644 (file)
@@ -1,5 +1,5 @@
 /* YACC parser for Pascal expressions, for GDB.
-   Copyright (C) 2000
+   Copyright 2000
    Free Software Foundation, Inc.
 
 This file is part of GDB.
@@ -37,8 +37,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
    too messy, particularly when such includes can be inserted at random
    times by the parser generator.  */
 
-/* FIXME: there are still 21 shift/reduce conflicts
-   Other known bugs or limitations:
+/* Known bugs or limitations:
     - pascal string operations are not supported at all.
     - there are some problems with boolean types.
     - Pascal type hexadecimal constants are not supported
@@ -58,11 +57,6 @@ 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 */
 
-/* MSVC uses strnicmp instead of strncasecmp */
-#ifdef _MSC_VER
-#define strncasecmp strnicmp
-#endif
-
 /* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
    as well as gratuitiously global symbol names, so we can have multiple
    yacc generated parsers in gdb.  Note that these are only the variables
@@ -156,9 +150,15 @@ static char * uptok (char *, int);
 /* YYSTYPE gets defined by %union */
 static int
 parse_number (char *, int, int, YYSTYPE *);
+
+static struct type *current_type;
+
+static void push_current_type ();
+static void pop_current_type ();
+static int search_field;
 %}
 
-%type <voidval> exp exp1 type_exp start variable qualified_name
+%type <voidval> exp exp1 type_exp start normal_start variable qualified_name
 %type <tval> type typebase
 /* %type <bval> block */
 
@@ -176,7 +176,8 @@ parse_number (char *, int, int, YYSTYPE *);
    Contexts where this distinction is not important can use the
    nonterminal "name", which matches either NAME or TYPENAME.  */
 
-%token <sval> STRING
+%token <sval> STRING 
+%token <sval> FIELDNAME
 %token <ssym> NAME /* BLOCKNAME defined below to give it higher precedence. */
 %token <tsym> TYPENAME
 %type <sval> name
@@ -217,6 +218,7 @@ parse_number (char *, int, int, YYSTYPE *);
 %left '*' '/'
 %right UNARY INCREMENT DECREMENT
 %right ARROW '.' '[' '('
+%left '^'
 %token <ssym> BLOCKNAME
 %type <bval> block
 %left COLONCOLON
@@ -224,15 +226,21 @@ parse_number (char *, int, int, YYSTYPE *);
 \f
 %%
 
-start   :      exp1
+start   :      { current_type = NULL;
+                 search_field = 0;
+               }
+               normal_start;
+
+normal_start   :
+               exp1
        |       type_exp
        ;
 
 type_exp:      type
                        { write_exp_elt_opcode(OP_TYPE);
                          write_exp_elt_type($1);
-                         write_exp_elt_opcode(OP_TYPE);}
-       ;
+                         write_exp_elt_opcode(OP_TYPE);
+                         current_type = $1; } ;
 
 /* Expressions, including the comma operator.  */
 exp1   :       exp
@@ -242,10 +250,14 @@ exp1      :       exp
 
 /* Expressions, not including the comma operator.  */
 exp    :       exp '^'   %prec UNARY
-                       { write_exp_elt_opcode (UNOP_IND); }
+                       { write_exp_elt_opcode (UNOP_IND);
+                         if (current_type) 
+                           current_type = TYPE_TARGET_TYPE (current_type); }
 
 exp    :       '@' exp    %prec UNARY
-                       { write_exp_elt_opcode (UNOP_ADDR); }
+                       { write_exp_elt_opcode (UNOP_ADDR); 
+                         if (current_type)
+                           current_type = TYPE_POINTER_TYPE (current_type); }
 
 exp    :       '-' exp    %prec UNARY
                        { write_exp_elt_opcode (UNOP_NEG); }
@@ -263,24 +275,55 @@ exp       :       DECREMENT  '(' exp ')'   %prec UNARY
                        { write_exp_elt_opcode (UNOP_PREDECREMENT); }
        ;
 
-exp    :       exp '.' name
+exp    :       exp '.' { search_field = 1; } 
+               FIELDNAME 
+               /* name */
                        { write_exp_elt_opcode (STRUCTOP_STRUCT);
-                         write_exp_string ($3);
-                         write_exp_elt_opcode (STRUCTOP_STRUCT); }
-       ;
-
-exp    :       exp '[' exp1 ']'
-                       { write_exp_elt_opcode (BINOP_SUBSCRIPT); }
-       ;
+                         write_exp_string ($4); 
+                         write_exp_elt_opcode (STRUCTOP_STRUCT);
+                         search_field = 0; 
+                         if (current_type)
+                           { while (TYPE_CODE (current_type) == TYPE_CODE_PTR)
+                               current_type = TYPE_TARGET_TYPE (current_type);
+                             current_type = lookup_struct_elt_type (
+                               current_type, $4.ptr, false); };
+                        } ; 
+exp    :       exp '['
+                       /* We need to save the current_type value */
+                       { char *arrayname; 
+                         int arrayfieldindex;
+                         arrayfieldindex = is_pascal_string_type (
+                               current_type, NULL, NULL,
+                               NULL, NULL, &arrayname); 
+                         if (arrayfieldindex) 
+                           {
+                             struct stoken stringsval;
+                             stringsval.ptr = alloca (strlen (arrayname) + 1);
+                             stringsval.length = strlen (arrayname);
+                             strcpy (stringsval.ptr, arrayname);
+                             current_type = TYPE_FIELD_TYPE (current_type,
+                               arrayfieldindex - 1); 
+                             write_exp_elt_opcode (STRUCTOP_STRUCT);
+                             write_exp_string (stringsval); 
+                             write_exp_elt_opcode (STRUCTOP_STRUCT);
+                           }
+                         push_current_type ();  }
+               exp1 ']'
+                       { pop_current_type ();
+                         write_exp_elt_opcode (BINOP_SUBSCRIPT);
+                         if (current_type)
+                           current_type = TYPE_TARGET_TYPE (current_type); }
 
 exp    :       exp '('
                        /* This is to save the value of arglist_len
                           being accumulated by an outer function call.  */
-                       { start_arglist (); }
+                       { push_current_type ();
+                         start_arglist (); }
                arglist ')'     %prec ARROW
                        { write_exp_elt_opcode (OP_FUNCALL);
                          write_exp_elt_longcst ((LONGEST) end_arglist ());
-                         write_exp_elt_opcode (OP_FUNCALL); }
+                         write_exp_elt_opcode (OP_FUNCALL); 
+                         pop_current_type (); }
        ;
 
 arglist        :
@@ -293,7 +336,8 @@ arglist     :
 exp    :       type '(' exp ')' %prec UNARY
                        { write_exp_elt_opcode (UNOP_CAST);
                          write_exp_elt_type ($1);
-                         write_exp_elt_opcode (UNOP_CAST); }
+                         write_exp_elt_opcode (UNOP_CAST); 
+                         current_type = $1; }
        ;
 
 exp    :       '(' exp1 ')'
@@ -572,9 +616,11 @@ variable:  name_not_typename
                              write_exp_elt_block (NULL);
                              write_exp_elt_sym (sym);
                              write_exp_elt_opcode (OP_VAR_VALUE);
-                           }
+                             current_type = sym->type; }
                          else if ($1.is_a_field_of_this)
                            {
+                             struct value * this_val;
+                             struct type * this_type;
                              /* Object pascal: it hangs off of `this'.  Must
                                 not inadvertently convert from a method call
                                 to data ref.  */
@@ -586,6 +632,18 @@ variable:  name_not_typename
                              write_exp_elt_opcode (STRUCTOP_PTR);
                              write_exp_string ($1.stoken);
                              write_exp_elt_opcode (STRUCTOP_PTR);
+                             /* we need type of this */
+                             this_val = value_of_this (0); 
+                             if (this_val)
+                               this_type = this_val->type;
+                             else
+                               this_type = NULL;
+                             if (this_type)
+                               current_type = lookup_struct_elt_type (
+                                 this_type,
+                                 $1.stoken.ptr, false);
+                             else
+                               current_type = NULL; 
                            }
                          else
                            {
@@ -858,14 +916,13 @@ parse_number (p, len, parsed_float, putithere)
     }
   else
     {
-      high_bit = (((ULONGEST)1)
-                 << (TARGET_LONG_LONG_BIT - 32 - 1)
-                 << 16
-                 << 16);
-      if (high_bit == 0)
+      int shift;
+      if (sizeof (ULONGEST) * HOST_CHAR_BIT < TARGET_LONG_LONG_BIT)
        /* A long long does not fit in a LONGEST.  */
-       high_bit =
-         (ULONGEST)1 << (sizeof (LONGEST) * HOST_CHAR_BIT - 1);
+       shift = (sizeof (ULONGEST) * HOST_CHAR_BIT - 1);
+      else
+       shift = (TARGET_LONG_LONG_BIT - 1);
+      high_bit = (ULONGEST) 1 << shift;
       unsigned_type = builtin_type_unsigned_long_long;
       signed_type = builtin_type_long_long;
     }
@@ -887,6 +944,36 @@ parse_number (p, len, parsed_float, putithere)
    return INT;
 }
 
+
+struct type_push
+{
+  struct type *stored;
+  struct type_push *next;
+};
+
+static struct type_push *tp_top = NULL;
+
+static void push_current_type ()
+{
+  struct type_push *tpnew;
+  tpnew = (struct type_push *) malloc (sizeof (struct type_push));
+  tpnew->next = tp_top;
+  tpnew->stored = current_type;
+  current_type = NULL;
+  tp_top = tpnew; 
+}
+
+static void pop_current_type ()
+{
+  struct type_push *tp = tp_top;
+  if (tp)
+    {
+      current_type = tp->stored;
+      tp_top = tp->next;
+      xfree (tp);
+    }
+}
+
 struct token
 {
   char *operator;
@@ -913,8 +1000,8 @@ static const struct token tokentab2[] =
     {"<>", NOTEQUAL, BINOP_END},
     {"<=", LEQ, BINOP_END},
     {">=", GEQ, BINOP_END},
-    {":=", ASSIGN, BINOP_END}
-  };
+    {":=", ASSIGN, BINOP_END},
+    {"::", COLONCOLON, BINOP_END} };
 
 /* Allocate uppercased var */
 /* make an uppercased copy of tokstart */
@@ -953,6 +1040,8 @@ yylex ()
 
  retry:
 
+  prev_lexptr = lexptr;
+
   tokstart = lexptr;
   explen = strlen (lexptr);
   /* See if it is a special token of length 3.  */
@@ -1153,6 +1242,7 @@ yylex ()
          {
            tempbuf = (char *) realloc (tempbuf, tempbufsize += 64);
          }
+
        switch (*tokptr)
          {
          case '\0':
@@ -1299,28 +1389,88 @@ yylex ()
     char *tmp = copy_name (yylval.sval);
     struct symbol *sym;
     int is_a_field_of_this = 0;
+    int is_a_field = 0;
     int hextype;
 
-    sym = lookup_symbol (tmp, expression_context_block,
-                        VAR_NAMESPACE,
-                        &is_a_field_of_this,
-                        (struct symtab **) NULL);
-    /* second chance uppercased ! */
-    if (!sym)
+
+    if (search_field && current_type)
+      is_a_field = (lookup_struct_elt_type (current_type, tmp, 1) != NULL);    
+    if (is_a_field)
+      sym = NULL;
+    else
+      sym = lookup_symbol (tmp, expression_context_block,
+                          VAR_NAMESPACE,
+                          &is_a_field_of_this,
+                          (struct symtab **) NULL);
+    /* second chance uppercased (as Free Pascal does).  */
+    if (!sym && !is_a_field_of_this && !is_a_field)
       {
-       for (i = 0;i <= namelen;i++)
+       for (i = 0; i <= namelen; i++)
          {
-           if ((tmp[i]>='a' && tmp[i]<='z'))
+           if ((tmp[i] >= 'a' && tmp[i] <= 'z'))
              tmp[i] -= ('a'-'A');
-           /* I am not sure that copy_name gives excatly the same result ! */
-           if ((tokstart[i]>='a' && tokstart[i]<='z'))
-             tokstart[i] -= ('a'-'A');
          }
-        sym = lookup_symbol (tmp, expression_context_block,
-                        VAR_NAMESPACE,
-                        &is_a_field_of_this,
-                        (struct symtab **) NULL);
+       if (search_field && current_type)
+        is_a_field = (lookup_struct_elt_type (current_type, tmp, 1) != NULL);  
+       if (is_a_field)
+        sym = NULL;
+       else
+        sym = lookup_symbol (tmp, expression_context_block,
+                        VAR_NAMESPACE,
+                        &is_a_field_of_this,
+                        (struct symtab **) NULL);
+       if (sym || is_a_field_of_this || is_a_field)
+         for (i = 0; i <= namelen; i++)
+           {
+             if ((tokstart[i] >= 'a' && tokstart[i] <= 'z'))
+               tokstart[i] -= ('a'-'A');
+           }
+      }
+    /* Third chance Capitalized (as GPC does).  */
+    if (!sym && !is_a_field_of_this && !is_a_field)
+      {
+       for (i = 0; i <= namelen; i++)
+         {
+           if (i == 0)
+             {
+              if ((tmp[i] >= 'a' && tmp[i] <= 'z'))
+                tmp[i] -= ('a'-'A');
+             }
+           else
+           if ((tmp[i] >= 'A' && tmp[i] <= 'Z'))
+             tmp[i] -= ('A'-'a');
+          }
+       if (search_field && current_type)
+        is_a_field = (lookup_struct_elt_type (current_type, tmp, 1) != NULL);  
+       if (is_a_field)
+        sym = NULL;
+       else
+        sym = lookup_symbol (tmp, expression_context_block,
+                         VAR_NAMESPACE,
+                         &is_a_field_of_this,
+                         (struct symtab **) NULL);
+       if (sym || is_a_field_of_this || is_a_field)
+          for (i = 0; i <= namelen; i++)
+            {
+              if (i == 0)
+                {
+                  if ((tokstart[i] >= 'a' && tokstart[i] <= 'z'))
+                    tokstart[i] -= ('a'-'A');
+                }
+              else
+                if ((tokstart[i] >= 'A' && tokstart[i] <= 'Z'))
+                  tokstart[i] -= ('A'-'a');
+            }
       }
+
+    if (is_a_field)
+      {
+       tempbuf = (char *) realloc (tempbuf, namelen + 1);
+       strncpy (tempbuf, tokstart, namelen); tempbuf [namelen] = 0;
+       yylval.sval.ptr = tempbuf;
+       yylval.sval.length = namelen; 
+       return FIELDNAME;
+      } 
     /* Call lookup_symtab, not lookup_partial_symtab, in case there are
        no psymtabs (coff, xcoff, or some future change to blow away the
        psymtabs once once symbols are read).  */
@@ -1453,5 +1603,8 @@ void
 yyerror (msg)
      char *msg;
 {
+  if (prev_lexptr)
+    lexptr = prev_lexptr;
+
   error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr);
 }
This page took 0.028058 seconds and 4 git commands to generate.