2004-06-13 Andrew Cagney <cagney@gnu.org>
[deliverable/binutils-gdb.git] / gdb / jv-exp.y
index d20499385461f3f18230239fa4ff172bc724441a..41da7d0f3fdcf2470a52a66e5f2fb56f8090ee91 100644 (file)
@@ -1,5 +1,5 @@
 /* YACC parser for Java expressions, for GDB.
-   Copyright (C) 1997.
+   Copyright 1997, 1998, 1999, 2000
    Free Software Foundation, Inc.
 
 This file is part of GDB.
@@ -18,14 +18,14 @@ You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
-/* Parse a C expression from text in a string,
+/* Parse a Java expression from text in a string,
    and return the result as a  struct expression  pointer.
    That structure contains arithmetic operations in reverse polish,
    with constants represented by operations that are followed by special data.
    See expression.h for the details of the format.
    What is important here is that it can be built up sequentially
    during the process of parsing; the lower levels of the tree always
-   come first in the result.
+   come first in the result.  Well, almost always; see ArrayAccess.
 
    Note that malloc's and realloc's in this file are transformed to
    xmalloc and xrealloc respectively by the same sed command in the
@@ -48,6 +48,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "bfd.h" /* Required by objfiles.h.  */
 #include "symfile.h" /* Required by objfiles.h.  */
 #include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
+#include "block.h"
 
 /* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
    as well as gratuitiously global symbol names, so we can have multiple
@@ -85,6 +86,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #define        yylloc  java_lloc
 #define yyreds java_reds               /* With YYDEBUG defined */
 #define yytoks java_toks               /* With YYDEBUG defined */
+#define yyname java_name               /* With YYDEBUG defined */
+#define yyrule java_rule               /* With YYDEBUG defined */
 #define yylhs  java_yylhs
 #define yylen  java_yylen
 #define yydefred java_yydefred
@@ -96,20 +99,23 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #define yycheck         java_yycheck
 
 #ifndef YYDEBUG
-#define        YYDEBUG 0               /* Default to no yydebug support */
+#define        YYDEBUG 1               /* Default to yydebug support */
 #endif
 
-int
-yyparse PARAMS ((void));
+#define YYFPRINTF parser_fprintf
 
-static int
-yylex PARAMS ((void));
+int yyparse (void);
 
-void
-yyerror PARAMS ((char *));
+static int yylex (void);
+
+void yyerror (char *);
+
+static struct type *java_type_from_name (struct stoken);
+static void push_expression_name (struct stoken);
+static void push_fieldnames (struct stoken);
 
-static struct type * java_type_from_name PARAMS ((struct stoken));
-static void push_variable PARAMS ((struct stoken));
+static struct expression *copy_exp (struct expression *, int);
+static void insert_exp (int, struct expression *);
 
 %}
 
@@ -141,13 +147,12 @@ static void push_variable PARAMS ((struct stoken));
 
 %{
 /* YYSTYPE gets defined by %union */
-static int
-parse_number PARAMS ((char *, int, int, YYSTYPE *));
+static int parse_number (char *, int, int, YYSTYPE *);
 %}
 
 %type <lval> rcurly Dims Dims_opt
 %type <tval> ClassOrInterfaceType ClassType /* ReferenceType Type ArrayType */
-%type <tval> IntegralType FloatingPointType NumericType PrimitiveType
+%type <tval> IntegralType FloatingPointType NumericType PrimitiveType ArrayType PrimitiveOrArrayType
 
 %token <typed_val_int> INTEGER_LITERAL
 %token <typed_val_float> FLOATING_POINT_LITERAL
@@ -175,7 +180,7 @@ parse_number PARAMS ((char *, int, int, YYSTYPE *));
 
 %token <opcode> ASSIGN_MODIFY
 
-%token THIS SUPER NEW
+%token SUPER NEW
 
 %left ','
 %right '=' ASSIGN_MODIFY
@@ -197,7 +202,20 @@ parse_number PARAMS ((char *, int, int, YYSTYPE *));
 %%
 
 start   :      exp1
-/*     |       type_exp FIXME */
+       |       type_exp
+       ;
+
+type_exp:      PrimitiveOrArrayType
+               {
+                 write_exp_elt_opcode(OP_TYPE);
+                 write_exp_elt_type($1);
+                 write_exp_elt_opcode(OP_TYPE);
+               }
+       ;
+
+PrimitiveOrArrayType:
+               PrimitiveType
+       |       ArrayType
        ;
 
 StringLiteral:
@@ -209,7 +227,7 @@ StringLiteral:
                }
 ;
 
-Literal        :
+Literal:
        INTEGER_LITERAL
                { write_exp_elt_opcode (OP_LONG);
                  write_exp_elt_type ($1.type);
@@ -290,14 +308,12 @@ ClassType:
        ClassOrInterfaceType
 ;
 
-/* UNUSED:
 ArrayType:
        PrimitiveType Dims
                { $$ = java_array_type ($1, $2); }
 |      Name Dims
                { $$ = java_array_type (java_type_from_name ($1), $2); }
 ;
-*/
 
 Name:
        IDENTIFIER
@@ -350,9 +366,6 @@ Primary:
 
 PrimaryNoNewArray:
        Literal
-|      THIS
-               { write_exp_elt_opcode (OP_THIS);
-                 write_exp_elt_opcode (OP_THIS); }
 |      '(' Expression ')'
 |      ClassInstanceCreationExpression
 |      FieldAccess
@@ -377,7 +390,8 @@ rcurly:
 
 ClassInstanceCreationExpression:
        NEW ClassType '(' ArgumentList_opt ')'
-               { error ("FIXME - ClassInstanceCreationExpression"); }
+               { internal_error (__FILE__, __LINE__,
+                                 _("FIXME - ClassInstanceCreationExpression")); }
 ;
 
 ArgumentList:
@@ -395,9 +409,11 @@ ArgumentList_opt:
 
 ArrayCreationExpression:
        NEW PrimitiveType DimExprs Dims_opt
-               { error ("FIXME - ArrayCreatiionExpression"); }
+               { internal_error (__FILE__, __LINE__,
+                                 _("FIXME - ArrayCreationExpression")); }
 |      NEW ClassOrInterfaceType DimExprs Dims_opt
-               { error ("FIXME - ArrayCreatiionExpression"); }
+               { internal_error (__FILE__, __LINE__,
+                                 _("FIXME - ArrayCreationExpression")); }
 ;
 
 DimExprs:
@@ -424,24 +440,41 @@ Dims_opt:
 
 FieldAccess:
        Primary '.' SimpleName
-               { write_exp_elt_opcode (STRUCTOP_STRUCT);
-                 write_exp_string ($3);
-                 write_exp_elt_opcode (STRUCTOP_STRUCT); }
+               { push_fieldnames ($3); }
+|      VARIABLE '.' SimpleName
+               { push_fieldnames ($3); }
 /*|    SUPER '.' SimpleName { FIXME } */
 ;
 
 MethodInvocation:
        Name '(' ArgumentList_opt ')'
-               { error ("method invocation not implemented"); }
+               { error (_("Method invocation not implemented")); }
 |      Primary '.' SimpleName '(' ArgumentList_opt ')'
-               { error ("method invocation not implemented"); }
+               { error (_("Method invocation not implemented")); }
 |      SUPER '.' SimpleName '(' ArgumentList_opt ')'
-               { error ("method invocation not implemented"); }
+               { error (_("Method invocation not implemented")); }
 ;
 
 ArrayAccess:
        Name '[' Expression ']'
-               { error ("ArrayAccess"); } /* FIXME - NASTY */
+                {
+                  /* Emit code for the Name now, then exchange it in the
+                    expout array with the Expression's code.  We could
+                    introduce a OP_SWAP code or a reversed version of
+                    BINOP_SUBSCRIPT, but that makes the rest of GDB pay
+                    for our parsing kludges.  */
+                 struct expression *name_expr;
+
+                 push_expression_name ($1);
+                 name_expr = copy_exp (expout, expout_ptr);
+                 expout_ptr -= name_expr->nelts;
+                 insert_exp (expout_ptr-length_of_subexp (expout, expout_ptr),
+                             name_expr);
+                 free (name_expr);
+                 write_exp_elt_opcode (BINOP_SUBSCRIPT);
+               }
+|      VARIABLE '[' Expression ']'
+               { write_exp_elt_opcode (BINOP_SUBSCRIPT); }
 |      PrimaryNoNewArray '[' Expression ']'
                { write_exp_elt_opcode (BINOP_SUBSCRIPT); }
 ;
@@ -449,7 +482,7 @@ ArrayAccess:
 PostfixExpression:
        Primary
 |      Name
-               { push_variable ($1); }
+               { push_expression_name ($1); }
 |      VARIABLE
                /* Already written by write_dollar_variable. */
 |      PostIncrementExpression
@@ -501,7 +534,27 @@ CastExpression:
                { write_exp_elt_opcode (UNOP_CAST);
                  write_exp_elt_type (java_array_type ($2, $3));
                  write_exp_elt_opcode (UNOP_CAST); }
-|      '(' Expression ')' UnaryExpressionNotPlusMinus /* FIXME */
+|      '(' Expression ')' UnaryExpressionNotPlusMinus
+               {
+                 int exp_size = expout_ptr;
+                 int last_exp_size = length_of_subexp(expout, expout_ptr);
+                 struct type *type;
+                 int i;
+                 int base = expout_ptr - last_exp_size - 3;
+                 if (base < 0 || expout->elts[base+2].opcode != OP_TYPE)
+                   error (_("Invalid cast expression"));
+                 type = expout->elts[base+1].type;
+                 /* Remove the 'Expression' and slide the
+                    UnaryExpressionNotPlusMinus down to replace it. */
+                 for (i = 0;  i < last_exp_size;  i++)
+                   expout->elts[base + i] = expout->elts[base + i + 3];
+                 expout_ptr -= 3;
+                 if (TYPE_CODE (type) == TYPE_CODE_STRUCT)
+                   type = lookup_pointer_type (type);
+                 write_exp_elt_opcode (UNOP_CAST);
+                 write_exp_elt_type (type);
+                 write_exp_elt_opcode (UNOP_CAST);
+               }
 |      '(' Name Dims ')' UnaryExpressionNotPlusMinus
                { write_exp_elt_opcode (UNOP_CAST);
                  write_exp_elt_type (java_array_type (java_type_from_name ($2), $3));
@@ -608,7 +661,7 @@ Assignment:
 
 LeftHandSide:
        ForcedName
-               { push_variable ($1); }
+               { push_expression_name ($1); }
 |      VARIABLE
                /* Already written by write_dollar_variable. */
 |      FieldAccess
@@ -629,16 +682,16 @@ Expression:
 
 static int
 parse_number (p, len, parsed_float, putithere)
-     register char *p;
-     register int len;
+     char *p;
+     int len;
      int parsed_float;
      YYSTYPE *putithere;
 {
-  register ULONGEST n = 0;
+  ULONGEST n = 0;
   ULONGEST limit, limit_div_base;
 
-  register int c;
-  register int base = input_radix;
+  int c;
+  int base = input_radix;
 
   struct type *type;
 
@@ -656,7 +709,7 @@ parse_number (p, len, parsed_float, putithere)
        num = sscanf (p, "%lg%c", (double *) &putithere->typed_val_float.dval, &c);
       else
        {
-#ifdef PRINTF_HAS_LONG_DOUBLE
+#ifdef SCANF_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.
@@ -682,7 +735,7 @@ parse_number (p, len, parsed_float, putithere)
        return ERROR;
 
       return FLOATING_POINT_LITERAL;
-}
+    }
 
   /* Handle base-switching prefixes 0x, 0t, 0d, 0 */
   if (p[0] == '0')
@@ -716,13 +769,13 @@ parse_number (p, len, parsed_float, putithere)
       }
 
   c = p[len-1];
+  /* A paranoid calculation of (1<<64)-1. */
   limit = (ULONGEST)0xffffffff;
+  limit = ((limit << 16) << 16) | limit;
   if (c == 'l' || c == 'L')
     {
       type = java_long_type;
       len--;
-      /* A paranoid calculation of (1<<64)-1. */
-      limit = ((limit << 16) << 16) | limit;
     }
   else
     {
@@ -735,26 +788,32 @@ parse_number (p, len, parsed_float, putithere)
       c = *p++;
       if (c >= '0' && c <= '9')
        c -= '0';
+      else if (c >= 'A' && c <= 'Z')
+       c -= 'A' - 10;
+      else if (c >= 'a' && c <= 'z')
+       c -= 'a' - 10;
       else
-       {
-         if (c >= 'A' && c <= 'Z')
-           c += 'a' - 'A';
-         if (c >= 'a' && c - 'a' + 10 < base)
-           c -= 'a' + 10;
-         else
-           return ERROR;       /* Char not a digit */
-       }
+       return ERROR;   /* Char not a digit */
       if (c >= base)
        return ERROR;
       if (n > limit_div_base
          || (n *= base) > limit - c)
-       error ("Numeric constant too large.");
+       error (_("Numeric constant too large"));
       n += c;
        }
 
-   putithere->typed_val_int.val = n;
-   putithere->typed_val_int.type = type;
-   return INTEGER_LITERAL;
+  /* If the type is bigger than a 32-bit signed integer can be, implicitly
+     promote to long.  Java does not do this, so mark it as builtin_type_uint64
+     rather than java_long_type.  0x80000000 will become -0x80000000 instead
+     of 0x80000000L, because we don't know the sign at this point.
+  */
+  if (type == java_int_type && n > (ULONGEST)0x80000000)
+    type = builtin_type_uint64;
+
+  putithere->typed_val_int.val = n;
+  putithere->typed_val_int.type = type;
+
+  return INTEGER_LITERAL;
 }
 
 struct token
@@ -808,10 +867,12 @@ yylex ()
   
  retry:
 
+  prev_lexptr = lexptr;
+
   tokstart = lexptr;
   /* See if it is a special token of length 3.  */
   for (i = 0; i < sizeof tokentab3 / sizeof tokentab3[0]; i++)
-    if (STREQN (tokstart, tokentab3[i].operator, 3))
+    if (strncmp (tokstart, tokentab3[i].operator, 3) == 0)
       {
        lexptr += 3;
        yylval.opcode = tokentab3[i].opcode;
@@ -820,7 +881,7 @@ yylex ()
 
   /* See if it is a special token of length 2.  */
   for (i = 0; i < sizeof tokentab2 / sizeof tokentab2[0]; i++)
-    if (STREQN (tokstart, tokentab2[i].operator, 2))
+    if (strncmp (tokstart, tokentab2[i].operator, 2) == 0)
       {
        lexptr += 2;
        yylval.opcode = tokentab2[i].opcode;
@@ -847,10 +908,10 @@ yylex ()
       if (c == '\\')
        c = parse_escape (&lexptr);
       else if (c == '\'')
-       error ("Empty character constant.");
+       error (_("Empty character constant"));
 
       yylval.typed_val_int.val = c;
-      yylval.typed_val_int.type = builtin_type_char;
+      yylval.typed_val_int.type = java_char_type;
 
       c = *lexptr++;
       if (c != '\'')
@@ -860,12 +921,12 @@ yylex ()
            {
              lexptr = tokstart + namelen;
              if (lexptr[-1] != '\'')
-               error ("Unmatched single quote.");
+               error (_("Unmatched single quote"));
              namelen -= 2;
              tokstart++;
              goto tryname;
            }
-         error ("Invalid character constant.");
+         error (_("Invalid character constant"));
        }
       return INTEGER_LITERAL;
 
@@ -906,7 +967,7 @@ yylex ()
       {
        /* It's a number.  */
        int got_dot = 0, got_e = 0, toktype;
-       register char *p = tokstart;
+       char *p = tokstart;
        int hex = input_radix > 10;
 
        if (c == '0' && (p[1] == 'x' || p[1] == 'X'))
@@ -950,7 +1011,7 @@ yylex ()
 
            memcpy (err_copy, tokstart, p - tokstart);
            err_copy[p - tokstart] = 0;
-           error ("Invalid number \"%s\".", err_copy);
+           error (_("Invalid number \"%s\""), err_copy);
          }
        lexptr = p;
        return toktype;
@@ -1022,7 +1083,7 @@ yylex ()
       } while ((*tokptr != '"') && (*tokptr != '\0'));
       if (*tokptr++ != '"')
        {
-         error ("Unterminated string in expression.");
+         error (_("Unterminated string in expression"));
        }
       tempbuf[tempbufindex] = '\0';    /* See note above */
       yylval.sval.ptr = tempbuf;
@@ -1034,21 +1095,26 @@ yylex ()
   if (!(c == '_' || c == '$'
        || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')))
     /* We must have come across a bad character (e.g. ';').  */
-    error ("Invalid character '%c' in expression.", c);
+    error (_("Invalid character '%c' in expression"), c);
 
   /* It's a name.  See how long it is.  */
   namelen = 0;
   for (c = tokstart[namelen];
-       (c == '_' || c == '$' || (c >= '0' && c <= '9')
-       || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '<');)
+       (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;
-         }
+      if (c == '<')
+       {
+         int i = namelen;
+         while (tokstart[++i] && tokstart[i] != '>');
+         if (tokstart[i] == '>')
+           namelen = i;
+       }
        c = tokstart[++namelen];
      }
 
@@ -1067,54 +1133,43 @@ yylex ()
   switch (namelen)
     {
     case 7:
-      if (STREQN (tokstart, "boolean", 7))
+      if (DEPRECATED_STREQN (tokstart, "boolean", 7))
        return BOOLEAN;
       break;
     case 6:
-      if (STREQN (tokstart, "double", 6))      
+      if (DEPRECATED_STREQN (tokstart, "double", 6))      
        return DOUBLE;
       break;
     case 5:
-      if (STREQN (tokstart, "short", 5))
+      if (DEPRECATED_STREQN (tokstart, "short", 5))
        return SHORT;
-      if (STREQN (tokstart, "false", 5))
+      if (DEPRECATED_STREQN (tokstart, "false", 5))
        {
          yylval.lval = 0;
          return BOOLEAN_LITERAL;
        }
-      if (STREQN (tokstart, "super", 5))
+      if (DEPRECATED_STREQN (tokstart, "super", 5))
        return SUPER;
-      if (STREQN (tokstart, "float", 5))
+      if (DEPRECATED_STREQN (tokstart, "float", 5))
        return FLOAT;
       break;
     case 4:
-      if (STREQN (tokstart, "long", 4))
+      if (DEPRECATED_STREQN (tokstart, "long", 4))
        return LONG;
-      if (STREQN (tokstart, "byte", 4))
+      if (DEPRECATED_STREQN (tokstart, "byte", 4))
        return BYTE;
-      if (STREQN (tokstart, "char", 4))
+      if (DEPRECATED_STREQN (tokstart, "char", 4))
        return CHAR;
-      if (STREQN (tokstart, "true", 4))
+      if (DEPRECATED_STREQN (tokstart, "true", 4))
        {
          yylval.lval = 1;
          return BOOLEAN_LITERAL;
        }
-      if (current_language->la_language == language_cplus
-         && STREQN (tokstart, "this", 4))
-       {
-         static const char this_name[] =
-                                { CPLUS_MARKER, 't', 'h', 'i', 's', '\0' };
-
-         if (lookup_symbol (this_name, expression_context_block,
-                            VAR_NAMESPACE, (int *) NULL,
-                            (struct symtab **) NULL))
-           return THIS;
-       }
       break;
     case 3:
-      if (STREQN (tokstart, "int", 3))
+      if (strncmp (tokstart, "int", 3) == 0)
        return INT;
-      if (STREQN (tokstart, "new", 3))
+      if (strncmp (tokstart, "new", 3) == 0)
        return NEW;
       break;
     default:
@@ -1148,7 +1203,13 @@ void
 yyerror (msg)
      char *msg;
 {
-  error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr);
+  if (prev_lexptr)
+    lexptr = prev_lexptr;
+
+  if (msg)
+    error (_("%s: near `%s'"), msg, lexptr);
+  else
+    error (_("error in expression, near `%s'"), lexptr);
 }
 
 static struct type *
@@ -1159,22 +1220,22 @@ java_type_from_name (name)
   char *tmp = copy_name (name);
   struct type *typ = java_lookup_class (tmp);
   if (typ == NULL || TYPE_CODE (typ) != TYPE_CODE_STRUCT)
-    error ("No class named %s.", tmp);
+    error (_("No class named `%s'"), tmp);
   return typ;
 }
 
-static void
-push_variable (name)
-     struct stoken name;
+/* If NAME is a valid variable name in this scope, push it and return 1.
+   Otherwise, return 0. */
+
+static int
+push_variable (struct stoken name)
 {
   char *tmp = copy_name (name);
   int is_a_field_of_this = 0;
   struct symbol *sym;
-  struct type *typ;
-  sym = lookup_symbol (tmp, expression_context_block, VAR_NAMESPACE,
+  sym = lookup_symbol (tmp, expression_context_block, VAR_DOMAIN,
                       &is_a_field_of_this, (struct symtab **) NULL);
-  if (sym)
+  if (sym && SYMBOL_CLASS (sym) != LOC_TYPEDEF)
     {
       if (symbol_read_needs_frame (sym))
        {
@@ -1189,7 +1250,7 @@ push_variable (name)
       write_exp_elt_block (NULL);
       write_exp_elt_sym (sym);
       write_exp_elt_opcode (OP_VAR_VALUE);
-      return;
+      return 1;
     }
   if (is_a_field_of_this)
     {
@@ -1203,9 +1264,131 @@ push_variable (name)
       write_exp_elt_opcode (STRUCTOP_PTR);
       write_exp_string (name);
       write_exp_elt_opcode (STRUCTOP_PTR);
+      return 1;
+    }
+  return 0;
+}
+
+/* Assuming a reference expression has been pushed, emit the
+   STRUCTOP_STRUCT ops to access the field named NAME.  If NAME is a
+   qualified name (has '.'), generate a field access for each part. */
+
+static void
+push_fieldnames (name)
+     struct stoken name;
+{
+  int i;
+  struct stoken token;
+  token.ptr = name.ptr;
+  for (i = 0;  ;  i++)
+    {
+      if (i == name.length || name.ptr[i] == '.')
+       {
+         /* token.ptr is start of current field name. */
+         token.length = &name.ptr[i] - token.ptr;
+         write_exp_elt_opcode (STRUCTOP_STRUCT);
+         write_exp_string (token);
+         write_exp_elt_opcode (STRUCTOP_STRUCT);
+         token.ptr += token.length + 1;
+       }
+      if (i >= name.length)
+       break;
+    }
+}
+
+/* Helper routine for push_expression_name.
+   Handle a qualified name, where DOT_INDEX is the index of the first '.' */
+
+static void
+push_qualified_expression_name (struct stoken name, int dot_index)
+{
+  struct stoken token;
+  char *tmp;
+  struct type *typ;
+
+  token.ptr = name.ptr;
+  token.length = dot_index;
+
+  if (push_variable (token))
+    {
+      token.ptr = name.ptr + dot_index + 1;
+      token.length = name.length - dot_index - 1;
+      push_fieldnames (token);
       return;
     }
 
+  token.ptr = name.ptr;
+  for (;;)
+    {
+      token.length = dot_index;
+      tmp = copy_name (token);
+      typ = java_lookup_class (tmp);
+      if (typ != NULL)
+       {
+         if (dot_index == name.length)
+           {
+             write_exp_elt_opcode(OP_TYPE);
+             write_exp_elt_type(typ);
+             write_exp_elt_opcode(OP_TYPE);
+             return;
+           }
+         dot_index++;  /* Skip '.' */
+         name.ptr += dot_index;
+         name.length -= dot_index;
+         dot_index = 0;
+         while (dot_index < name.length && name.ptr[dot_index] != '.') 
+           dot_index++;
+         token.ptr = name.ptr;
+         token.length = dot_index;
+         write_exp_elt_opcode (OP_SCOPE);
+         write_exp_elt_type (typ);
+         write_exp_string (token);
+         write_exp_elt_opcode (OP_SCOPE); 
+         if (dot_index < name.length)
+           {
+             dot_index++;
+             name.ptr += dot_index;
+             name.length -= dot_index;
+             push_fieldnames (name);
+           }
+         return;
+       }
+      else if (dot_index >= name.length)
+       break;
+      dot_index++;  /* Skip '.' */
+      while (dot_index < name.length && name.ptr[dot_index] != '.')
+       dot_index++;
+    }
+  error (_("unknown type `%.*s'"), name.length, name.ptr);
+}
+
+/* Handle Name in an expression (or LHS).
+   Handle VAR, TYPE, TYPE.FIELD1....FIELDN and VAR.FIELD1....FIELDN. */
+
+static void
+push_expression_name (name)
+     struct stoken name;
+{
+  char *tmp;
+  struct type *typ;
+  char *ptr;
+  int i;
+
+  for (i = 0;  i < name.length;  i++)
+    {
+      if (name.ptr[i] == '.')
+       {
+         /* It's a Qualified Expression Name. */
+         push_qualified_expression_name (name, i);
+         return;
+       }
+    }
+
+  /* It's a Simple Expression Name. */
+  
+  if (push_variable (name))
+    return;
+  tmp = copy_name (name);
   typ = java_lookup_class (tmp);
   if (typ != NULL)
     {
@@ -1225,9 +1408,62 @@ push_variable (name)
                             builtin_type_int);
        }
       else if (!have_full_symbols () && !have_partial_symbols ())
-       error ("No symbol table is loaded.  Use the \"file\" command.");
+       error (_("No symbol table is loaded.  Use the \"file\" command"));
       else
-       error ("No symbol \"%s\" in current context.", tmp);
+       error (_("No symbol \"%s\" in current context"), tmp);
     }
 
 }
+
+
+/* The following two routines, copy_exp and insert_exp, aren't specific to
+   Java, so they could go in parse.c, but their only purpose is to support
+   the parsing kludges we use in this file, so maybe it's best to isolate
+   them here.  */
+
+/* Copy the expression whose last element is at index ENDPOS - 1 in EXPR
+   into a freshly malloc'ed struct expression.  Its language_defn is set
+   to null.  */
+static struct expression *
+copy_exp (expr, endpos)
+     struct expression *expr;
+     int endpos;
+{
+  int len = length_of_subexp (expr, endpos);
+  struct expression *new
+    = (struct expression *) malloc (sizeof (*new) + EXP_ELEM_TO_BYTES (len));
+  new->nelts = len;
+  memcpy (new->elts, expr->elts + endpos - len, EXP_ELEM_TO_BYTES (len));
+  new->language_defn = 0;
+
+  return new;
+}
+
+/* Insert the expression NEW into the current expression (expout) at POS.  */
+static void
+insert_exp (pos, new)
+     int pos;
+     struct expression *new;
+{
+  int newlen = new->nelts;
+
+  /* Grow expout if necessary.  In this function's only use at present,
+     this should never be necessary.  */
+  if (expout_ptr + newlen > expout_size)
+    {
+      expout_size = max (expout_size * 2, expout_ptr + newlen + 10);
+      expout = (struct expression *)
+       realloc ((char *) expout, (sizeof (struct expression)
+                                   + EXP_ELEM_TO_BYTES (expout_size)));
+    }
+
+  {
+    int i;
+
+    for (i = expout_ptr - 1; i >= pos; i--)
+      expout->elts[i + newlen] = expout->elts[i];
+  }
+  
+  memcpy (expout->elts + pos, new->elts, EXP_ELEM_TO_BYTES (newlen));
+  expout_ptr += newlen;
+}
This page took 0.033738 seconds and 4 git commands to generate.