* corelow.c (core_close): Don't hardcode the core's pid.
[deliverable/binutils-gdb.git] / gdb / c-exp.y
index 40dbc93efb099111ff3e856c70ae81786be3593d..d4bbbccd362b7aae41864a483e26d4ba62d96e91 100644 (file)
@@ -1,6 +1,7 @@
 /* YACC parser for C expressions, for GDB.
    Copyright (C) 1986, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
-   1998, 1999, 2000, 2003, 2004, 2006, 2007 Free Software Foundation, Inc.
+   1998, 1999, 2000, 2003, 2004, 2006, 2007, 2008, 2009
+   Free Software Foundation, Inc.
 
 This file is part of GDB.
 
@@ -53,6 +54,10 @@ Boston, MA 02110-1301, USA.  */
 #include "block.h"
 #include "cp-support.h"
 #include "dfp.h"
+#include "gdb_assert.h"
+#include "macroscope.h"
+
+#define parse_type builtin_type (parse_gdbarch)
 
 /* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
    as well as gratuitiously global symbol names, so we can have multiple
@@ -62,7 +67,7 @@ Boston, MA 02110-1301, USA.  */
    generators need to be fixed instead of adding those names to this list. */
 
 #define        yymaxdepth c_maxdepth
-#define        yyparse c_parse
+#define        yyparse c_parse_internal
 #define        yylex   c_lex
 #define        yyerror c_error
 #define        yylval  c_lval
@@ -179,8 +184,9 @@ static int parse_number (char *, int, int, YYSTYPE *);
 
 %token <sval> STRING
 %token <ssym> NAME /* BLOCKNAME defined below to give it higher precedence. */
+%token <voidval> COMPLETE
 %token <tsym> TYPENAME
-%type <sval> name
+%type <sval> name string_exp
 %type <ssym> name_not_typename
 %type <tsym> typename
 
@@ -300,6 +306,23 @@ exp        :       exp ARROW name
                          write_exp_elt_opcode (STRUCTOP_PTR); }
        ;
 
+exp    :       exp ARROW name COMPLETE
+                       { mark_struct_expression ();
+                         write_exp_elt_opcode (STRUCTOP_PTR);
+                         write_exp_string ($3);
+                         write_exp_elt_opcode (STRUCTOP_PTR); }
+       ;
+
+exp    :       exp ARROW COMPLETE
+                       { struct stoken s;
+                         mark_struct_expression ();
+                         write_exp_elt_opcode (STRUCTOP_PTR);
+                         s.ptr = "";
+                         s.length = 0;
+                         write_exp_string (s);
+                         write_exp_elt_opcode (STRUCTOP_PTR); }
+       ;
+
 exp    :       exp ARROW qualified_name
                        { /* exp->type::name becomes exp->*(&type::name) */
                          /* Note: this doesn't work if name is a
@@ -318,6 +341,23 @@ exp        :       exp '.' name
                          write_exp_elt_opcode (STRUCTOP_STRUCT); }
        ;
 
+exp    :       exp '.' name COMPLETE
+                       { mark_struct_expression ();
+                         write_exp_elt_opcode (STRUCTOP_STRUCT);
+                         write_exp_string ($3);
+                         write_exp_elt_opcode (STRUCTOP_STRUCT); }
+       ;
+
+exp    :       exp '.' COMPLETE
+                       { struct stoken s;
+                         mark_struct_expression ();
+                         write_exp_elt_opcode (STRUCTOP_STRUCT);
+                         s.ptr = "";
+                         s.length = 0;
+                         write_exp_string (s);
+                         write_exp_elt_opcode (STRUCTOP_STRUCT); }
+       ;
+
 exp    :       exp '.' qualified_name
                        { /* exp.type::name becomes exp.*(&type::name) */
                          /* Note: this doesn't work if name is a
@@ -518,13 +558,40 @@ exp       :       VARIABLE
 
 exp    :       SIZEOF '(' type ')'     %prec UNARY
                        { write_exp_elt_opcode (OP_LONG);
-                         write_exp_elt_type (builtin_type (current_gdbarch)->builtin_int);
+                         write_exp_elt_type (parse_type->builtin_int);
                          CHECK_TYPEDEF ($3);
                          write_exp_elt_longcst ((LONGEST) TYPE_LENGTH ($3));
                          write_exp_elt_opcode (OP_LONG); }
        ;
 
-exp    :       STRING
+string_exp:
+               STRING
+                       {
+                         /* We copy the string here, and not in the
+                            lexer, to guarantee that we do not leak a
+                            string.  Note that we follow the
+                            NUL-termination convention of the
+                            lexer.  */
+                         $$.length = $1.length;
+                         $$.ptr = malloc ($1.length + 1);
+                         memcpy ($$.ptr, $1.ptr, $1.length + 1);
+                       }
+
+       |       string_exp STRING
+                       {
+                         /* Note that we NUL-terminate here, but just
+                            for convenience.  */
+                         struct stoken t;
+                         t.length = $1.length + $2.length;
+                         t.ptr = malloc (t.length + 1);
+                         memcpy (t.ptr, $1.ptr, $1.length);
+                         memcpy (t.ptr + $1.length, $2.ptr, $2.length + 1);
+                         free ($1.ptr);
+                         $$ = t;
+                       }
+               ;
+
+exp    :       string_exp
                        { /* C strings are converted into array constants with
                             an explicit null byte added at the end.  Thus
                             the array upper bound is the string length.
@@ -534,31 +601,33 @@ exp       :       STRING
                          while (count-- > 0)
                            {
                              write_exp_elt_opcode (OP_LONG);
-                             write_exp_elt_type (builtin_type (current_gdbarch)->builtin_char);
+                             write_exp_elt_type (parse_type->builtin_char);
                              write_exp_elt_longcst ((LONGEST)(*sp++));
                              write_exp_elt_opcode (OP_LONG);
                            }
                          write_exp_elt_opcode (OP_LONG);
-                         write_exp_elt_type (builtin_type (current_gdbarch)->builtin_char);
+                         write_exp_elt_type (parse_type->builtin_char);
                          write_exp_elt_longcst ((LONGEST)'\0');
                          write_exp_elt_opcode (OP_LONG);
                          write_exp_elt_opcode (OP_ARRAY);
                          write_exp_elt_longcst ((LONGEST) 0);
                          write_exp_elt_longcst ((LONGEST) ($1.length));
-                         write_exp_elt_opcode (OP_ARRAY); }
+                         write_exp_elt_opcode (OP_ARRAY);
+                         free ($1.ptr);
+                       }
        ;
 
 /* C++.  */
 exp     :       TRUEKEYWORD    
                         { write_exp_elt_opcode (OP_LONG);
-                          write_exp_elt_type (builtin_type (current_gdbarch)->builtin_bool);
+                          write_exp_elt_type (parse_type->builtin_bool);
                           write_exp_elt_longcst ((LONGEST) 1);
                           write_exp_elt_opcode (OP_LONG); }
        ;
 
 exp     :       FALSEKEYWORD   
                         { write_exp_elt_opcode (OP_LONG);
-                          write_exp_elt_type (builtin_type (current_gdbarch)->builtin_bool);
+                          write_exp_elt_type (parse_type->builtin_bool);
                           write_exp_elt_longcst ((LONGEST) 0);
                           write_exp_elt_opcode (OP_LONG); }
        ;
@@ -582,8 +651,7 @@ block       :       BLOCKNAME
 block  :       block COLONCOLON name
                        { struct symbol *tem
                            = lookup_symbol (copy_name ($3), $1,
-                                            VAR_DOMAIN, (int *) NULL,
-                                            (struct symtab **) NULL);
+                                            VAR_DOMAIN, (int *) NULL);
                          if (!tem || SYMBOL_CLASS (tem) != LOC_BLOCK)
                            error ("No function \"%s\" in specified context.",
                                   copy_name ($3));
@@ -593,8 +661,7 @@ block       :       block COLONCOLON name
 variable:      block COLONCOLON name
                        { struct symbol *sym;
                          sym = lookup_symbol (copy_name ($3), $1,
-                                              VAR_DOMAIN, (int *) NULL,
-                                              (struct symtab **) NULL);
+                                              VAR_DOMAIN, (int *) NULL);
                          if (sym == 0)
                            error ("No symbol \"%s\" in specified context.",
                                   copy_name ($3));
@@ -654,8 +721,7 @@ variable:   qualified_name
 
                          sym =
                            lookup_symbol (name, (const struct block *) NULL,
-                                          VAR_DOMAIN, (int *) NULL,
-                                          (struct symtab **) NULL);
+                                          VAR_DOMAIN, (int *) NULL);
                          if (sym)
                            {
                              write_exp_elt_opcode (OP_VAR_VALUE);
@@ -667,16 +733,11 @@ variable: qualified_name
 
                          msymbol = lookup_minimal_symbol (name, NULL, NULL);
                          if (msymbol != NULL)
-                           {
-                             write_exp_msymbol (msymbol,
-                                                lookup_function_type (builtin_type (current_gdbarch)->builtin_int),
-                                                builtin_type (current_gdbarch)->builtin_int);
-                           }
+                           write_exp_msymbol (msymbol);
+                         else if (!have_full_symbols () && !have_partial_symbols ())
+                           error ("No symbol table is loaded.  Use the \"file\" command.");
                          else
-                           if (!have_full_symbols () && !have_partial_symbols ())
-                             error ("No symbol table is loaded.  Use the \"file\" command.");
-                           else
-                             error ("No symbol \"%s\" in current context.", name);
+                           error ("No symbol \"%s\" in current context.", name);
                        }
        ;
 
@@ -723,11 +784,7 @@ variable:  name_not_typename
                              msymbol =
                                lookup_minimal_symbol (arg, NULL, NULL);
                              if (msymbol != NULL)
-                               {
-                                 write_exp_msymbol (msymbol,
-                                                    lookup_function_type (builtin_type (current_gdbarch)->builtin_int),
-                                                    builtin_type (current_gdbarch)->builtin_int);
-                               }
+                               write_exp_msymbol (msymbol);
                              else if (!have_full_symbols () && !have_partial_symbols ())
                                error ("No symbol table is loaded.  Use the \"file\" command.");
                              else
@@ -817,61 +874,61 @@ typebase  /* Implements (approximately): (type-qualifier)* type-specifier */
        :       TYPENAME
                        { $$ = $1.type; }
        |       INT_KEYWORD
-                       { $$ = builtin_type (current_gdbarch)->builtin_int; }
+                       { $$ = parse_type->builtin_int; }
        |       LONG
-                       { $$ = builtin_type (current_gdbarch)->builtin_long; }
+                       { $$ = parse_type->builtin_long; }
        |       SHORT
-                       { $$ = builtin_type (current_gdbarch)->builtin_short; }
+                       { $$ = parse_type->builtin_short; }
        |       LONG INT_KEYWORD
-                       { $$ = builtin_type (current_gdbarch)->builtin_long; }
+                       { $$ = parse_type->builtin_long; }
        |       LONG SIGNED_KEYWORD INT_KEYWORD
-                       { $$ = builtin_type (current_gdbarch)->builtin_long; }
+                       { $$ = parse_type->builtin_long; }
        |       LONG SIGNED_KEYWORD
-                       { $$ = builtin_type (current_gdbarch)->builtin_long; }
+                       { $$ = parse_type->builtin_long; }
        |       SIGNED_KEYWORD LONG INT_KEYWORD
-                       { $$ = builtin_type (current_gdbarch)->builtin_long; }
+                       { $$ = parse_type->builtin_long; }
        |       UNSIGNED LONG INT_KEYWORD
-                       { $$ = builtin_type (current_gdbarch)->builtin_unsigned_long; }
+                       { $$ = parse_type->builtin_unsigned_long; }
        |       LONG UNSIGNED INT_KEYWORD
-                       { $$ = builtin_type (current_gdbarch)->builtin_unsigned_long; }
+                       { $$ = parse_type->builtin_unsigned_long; }
        |       LONG UNSIGNED
-                       { $$ = builtin_type (current_gdbarch)->builtin_unsigned_long; }
+                       { $$ = parse_type->builtin_unsigned_long; }
        |       LONG LONG
-                       { $$ = builtin_type (current_gdbarch)->builtin_long_long; }
+                       { $$ = parse_type->builtin_long_long; }
        |       LONG LONG INT_KEYWORD
-                       { $$ = builtin_type (current_gdbarch)->builtin_long_long; }
+                       { $$ = parse_type->builtin_long_long; }
        |       LONG LONG SIGNED_KEYWORD INT_KEYWORD
-                       { $$ = builtin_type (current_gdbarch)->builtin_long_long; }
+                       { $$ = parse_type->builtin_long_long; }
        |       LONG LONG SIGNED_KEYWORD
-                       { $$ = builtin_type (current_gdbarch)->builtin_long_long; }
+                       { $$ = parse_type->builtin_long_long; }
        |       SIGNED_KEYWORD LONG LONG
-                       { $$ = builtin_type (current_gdbarch)->builtin_long_long; }
+                       { $$ = parse_type->builtin_long_long; }
        |       SIGNED_KEYWORD LONG LONG INT_KEYWORD
-                       { $$ = builtin_type (current_gdbarch)->builtin_long_long; }
+                       { $$ = parse_type->builtin_long_long; }
        |       UNSIGNED LONG LONG
-                       { $$ = builtin_type (current_gdbarch)->builtin_unsigned_long_long; }
+                       { $$ = parse_type->builtin_unsigned_long_long; }
        |       UNSIGNED LONG LONG INT_KEYWORD
-                       { $$ = builtin_type (current_gdbarch)->builtin_unsigned_long_long; }
+                       { $$ = parse_type->builtin_unsigned_long_long; }
        |       LONG LONG UNSIGNED
-                       { $$ = builtin_type (current_gdbarch)->builtin_unsigned_long_long; }
+                       { $$ = parse_type->builtin_unsigned_long_long; }
        |       LONG LONG UNSIGNED INT_KEYWORD
-                       { $$ = builtin_type (current_gdbarch)->builtin_unsigned_long_long; }
+                       { $$ = parse_type->builtin_unsigned_long_long; }
        |       SHORT INT_KEYWORD
-                       { $$ = builtin_type (current_gdbarch)->builtin_short; }
+                       { $$ = parse_type->builtin_short; }
        |       SHORT SIGNED_KEYWORD INT_KEYWORD
-                       { $$ = builtin_type (current_gdbarch)->builtin_short; }
+                       { $$ = parse_type->builtin_short; }
        |       SHORT SIGNED_KEYWORD
-                       { $$ = builtin_type (current_gdbarch)->builtin_short; }
+                       { $$ = parse_type->builtin_short; }
        |       UNSIGNED SHORT INT_KEYWORD
-                       { $$ = builtin_type (current_gdbarch)->builtin_unsigned_short; }
+                       { $$ = parse_type->builtin_unsigned_short; }
        |       SHORT UNSIGNED 
-                       { $$ = builtin_type (current_gdbarch)->builtin_unsigned_short; }
+                       { $$ = parse_type->builtin_unsigned_short; }
        |       SHORT UNSIGNED INT_KEYWORD
-                       { $$ = builtin_type (current_gdbarch)->builtin_unsigned_short; }
+                       { $$ = parse_type->builtin_unsigned_short; }
        |       DOUBLE_KEYWORD
-                       { $$ = builtin_type (current_gdbarch)->builtin_double; }
+                       { $$ = parse_type->builtin_double; }
        |       LONG DOUBLE_KEYWORD
-                       { $$ = builtin_type (current_gdbarch)->builtin_long_double; }
+                       { $$ = parse_type->builtin_long_double; }
        |       STRUCT name
                        { $$ = lookup_struct (copy_name ($2),
                                              expression_context_block); }
@@ -887,11 +944,11 @@ typebase  /* Implements (approximately): (type-qualifier)* type-specifier */
        |       UNSIGNED typename
                        { $$ = lookup_unsigned_typename (TYPE_NAME($2.type)); }
        |       UNSIGNED
-                       { $$ = builtin_type (current_gdbarch)->builtin_unsigned_int; }
+                       { $$ = parse_type->builtin_unsigned_int; }
        |       SIGNED_KEYWORD typename
                        { $$ = lookup_signed_typename (TYPE_NAME($2.type)); }
        |       SIGNED_KEYWORD
-                       { $$ = builtin_type (current_gdbarch)->builtin_int; }
+                       { $$ = parse_type->builtin_int; }
                 /* It appears that this rule for templates is never
                    reduced; template recognition happens by lookahead
                    in the token processing code in yylex. */         
@@ -981,19 +1038,19 @@ typename:        TYPENAME
                {
                  $$.stoken.ptr = "int";
                  $$.stoken.length = 3;
-                 $$.type = builtin_type (current_gdbarch)->builtin_int;
+                 $$.type = parse_type->builtin_int;
                }
        |       LONG
                {
                  $$.stoken.ptr = "long";
                  $$.stoken.length = 4;
-                 $$.type = builtin_type (current_gdbarch)->builtin_long;
+                 $$.type = parse_type->builtin_long;
                }
        |       SHORT
                {
                  $$.stoken.ptr = "short";
                  $$.stoken.length = 5;
-                 $$.type = builtin_type (current_gdbarch)->builtin_short;
+                 $$.type = parse_type->builtin_short;
                }
        ;
 
@@ -1085,52 +1142,53 @@ parse_number (p, len, parsed_float, putithere)
   if (parsed_float)
     {
       /* It's a float since it contains a point or an exponent.  */
-      char *s = malloc (len);
-      int num = 0;     /* number of tokens scanned by scanf */
-      char saved_char = p[len];
-
-      p[len] = 0;      /* null-terminate the token */
+      char *s;
+      int num; /* number of tokens scanned by scanf */
+      char saved_char;
 
       /* If it ends at "df", "dd" or "dl", take it as type of decimal floating
          point.  Return DECFLOAT.  */
 
-      if (p[len - 2] == 'd' && p[len - 1] == 'f')
+      if (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'f')
        {
          p[len - 2] = '\0';
          putithere->typed_val_decfloat.type
-           = builtin_type (current_gdbarch)->builtin_decfloat;
+           = parse_type->builtin_decfloat;
          decimal_from_string (putithere->typed_val_decfloat.val, 4, p);
-         p[len] = saved_char;
-         return (DECFLOAT);
+         p[len - 2] = 'd';
+         return DECFLOAT;
        }
 
-      if (p[len - 2] == 'd' && p[len - 1] == 'd')
+      if (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'd')
        {
          p[len - 2] = '\0';
          putithere->typed_val_decfloat.type
-           = builtin_type (current_gdbarch)->builtin_decdouble;
+           = parse_type->builtin_decdouble;
          decimal_from_string (putithere->typed_val_decfloat.val, 8, p);
-         p[len] = saved_char;
-         return (DECFLOAT);
+         p[len - 2] = 'd';
+         return DECFLOAT;
        }
 
-      if (p[len - 2] == 'd' && p[len - 1] == 'l')
+      if (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'l')
        {
          p[len - 2] = '\0';
          putithere->typed_val_decfloat.type
-           = builtin_type (current_gdbarch)->builtin_declong;
+           = parse_type->builtin_declong;
          decimal_from_string (putithere->typed_val_decfloat.val, 16, p);
-         p[len] = saved_char;
-         return (DECFLOAT);
+         p[len - 2] = 'd';
+         return DECFLOAT;
        }
 
-      num = sscanf (p, DOUBLEST_SCAN_FORMAT "%s",
+      s = malloc (len);
+      saved_char = p[len];
+      p[len] = 0;      /* null-terminate the token */
+      num = sscanf (p, "%" DOUBLEST_SCAN_FORMAT "%s",
                    &putithere->typed_val_float.dval, s);
       p[len] = saved_char;     /* restore the input stream */
 
       if (num == 1)
        putithere->typed_val_float.type = 
-         builtin_type (current_gdbarch)->builtin_double;
+         parse_type->builtin_double;
 
       if (num == 2 )
        {
@@ -1138,10 +1196,10 @@ parse_number (p, len, parsed_float, putithere)
             double.  */
          if (!strcasecmp (s, "f"))
            putithere->typed_val_float.type = 
-             builtin_type (current_gdbarch)->builtin_float;
+             parse_type->builtin_float;
          else if (!strcasecmp (s, "l"))
            putithere->typed_val_float.type = 
-             builtin_type (current_gdbarch)->builtin_long_double;
+             parse_type->builtin_long_double;
          else
            {
              free (s);
@@ -1252,9 +1310,9 @@ parse_number (p, len, parsed_float, putithere)
 
   un = (ULONGEST)n >> 2;
   if (long_p == 0
-      && (un >> (gdbarch_int_bit (current_gdbarch) - 2)) == 0)
+      && (un >> (gdbarch_int_bit (parse_gdbarch) - 2)) == 0)
     {
-      high_bit = ((ULONGEST)1) << (gdbarch_int_bit (current_gdbarch) - 1);
+      high_bit = ((ULONGEST)1) << (gdbarch_int_bit (parse_gdbarch) - 1);
 
       /* A large decimal (not hex or octal) constant (between INT_MAX
         and UINT_MAX) is a long or unsigned long, according to ANSI,
@@ -1262,28 +1320,28 @@ parse_number (p, len, parsed_float, putithere)
         int.  This probably should be fixed.  GCC gives a warning on
         such constants.  */
 
-      unsigned_type = builtin_type (current_gdbarch)->builtin_unsigned_int;
-      signed_type = builtin_type (current_gdbarch)->builtin_int;
+      unsigned_type = parse_type->builtin_unsigned_int;
+      signed_type = parse_type->builtin_int;
     }
   else if (long_p <= 1
-          && (un >> (gdbarch_long_bit (current_gdbarch) - 2)) == 0)
+          && (un >> (gdbarch_long_bit (parse_gdbarch) - 2)) == 0)
     {
-      high_bit = ((ULONGEST)1) << (gdbarch_long_bit (current_gdbarch) - 1);
-      unsigned_type = builtin_type (current_gdbarch)->builtin_unsigned_long;
-      signed_type = builtin_type (current_gdbarch)->builtin_long;
+      high_bit = ((ULONGEST)1) << (gdbarch_long_bit (parse_gdbarch) - 1);
+      unsigned_type = parse_type->builtin_unsigned_long;
+      signed_type = parse_type->builtin_long;
     }
   else
     {
       int shift;
       if (sizeof (ULONGEST) * HOST_CHAR_BIT 
-         < gdbarch_long_long_bit (current_gdbarch))
+         < gdbarch_long_long_bit (parse_gdbarch))
        /* A long long does not fit in a LONGEST.  */
        shift = (sizeof (ULONGEST) * HOST_CHAR_BIT - 1);
       else
-       shift = (gdbarch_long_long_bit (current_gdbarch) - 1);
+       shift = (gdbarch_long_long_bit (parse_gdbarch) - 1);
       high_bit = (ULONGEST) 1 << shift;
-      unsigned_type = builtin_type (current_gdbarch)->builtin_unsigned_long_long;
-      signed_type = builtin_type (current_gdbarch)->builtin_long_long;
+      unsigned_type = parse_type->builtin_unsigned_long_long;
+      signed_type = parse_type->builtin_long_long;
     }
 
    putithere->typed_val_int.val = n;
@@ -1308,38 +1366,161 @@ struct token
   char *operator;
   int token;
   enum exp_opcode opcode;
+  int cxx_only;
 };
 
 static const struct token tokentab3[] =
   {
-    {">>=", ASSIGN_MODIFY, BINOP_RSH},
-    {"<<=", ASSIGN_MODIFY, BINOP_LSH}
+    {">>=", ASSIGN_MODIFY, BINOP_RSH, 0},
+    {"<<=", ASSIGN_MODIFY, BINOP_LSH, 0}
   };
 
 static const struct token tokentab2[] =
   {
-    {"+=", ASSIGN_MODIFY, BINOP_ADD},
-    {"-=", ASSIGN_MODIFY, BINOP_SUB},
-    {"*=", ASSIGN_MODIFY, BINOP_MUL},
-    {"/=", ASSIGN_MODIFY, BINOP_DIV},
-    {"%=", ASSIGN_MODIFY, BINOP_REM},
-    {"|=", ASSIGN_MODIFY, BINOP_BITWISE_IOR},
-    {"&=", ASSIGN_MODIFY, BINOP_BITWISE_AND},
-    {"^=", ASSIGN_MODIFY, BINOP_BITWISE_XOR},
-    {"++", INCREMENT, BINOP_END},
-    {"--", DECREMENT, BINOP_END},
-    {"->", ARROW, BINOP_END},
-    {"&&", ANDAND, BINOP_END},
-    {"||", OROR, BINOP_END},
-    {"::", COLONCOLON, BINOP_END},
-    {"<<", LSH, BINOP_END},
-    {">>", RSH, BINOP_END},
-    {"==", EQUAL, BINOP_END},
-    {"!=", NOTEQUAL, BINOP_END},
-    {"<=", LEQ, BINOP_END},
-    {">=", GEQ, BINOP_END}
+    {"+=", ASSIGN_MODIFY, BINOP_ADD, 0},
+    {"-=", ASSIGN_MODIFY, BINOP_SUB, 0},
+    {"*=", ASSIGN_MODIFY, BINOP_MUL, 0},
+    {"/=", ASSIGN_MODIFY, BINOP_DIV, 0},
+    {"%=", ASSIGN_MODIFY, BINOP_REM, 0},
+    {"|=", ASSIGN_MODIFY, BINOP_BITWISE_IOR, 0},
+    {"&=", ASSIGN_MODIFY, BINOP_BITWISE_AND, 0},
+    {"^=", ASSIGN_MODIFY, BINOP_BITWISE_XOR, 0},
+    {"++", INCREMENT, BINOP_END, 0},
+    {"--", DECREMENT, BINOP_END, 0},
+    {"->", ARROW, BINOP_END, 0},
+    {"&&", ANDAND, BINOP_END, 0},
+    {"||", OROR, BINOP_END, 0},
+    {"::", COLONCOLON, BINOP_END, 0},
+    {"<<", LSH, BINOP_END, 0},
+    {">>", RSH, BINOP_END, 0},
+    {"==", EQUAL, BINOP_END, 0},
+    {"!=", NOTEQUAL, BINOP_END, 0},
+    {"<=", LEQ, BINOP_END, 0},
+    {">=", GEQ, BINOP_END, 0}
   };
 
+/* Identifier-like tokens.  */
+static const struct token ident_tokens[] =
+  {
+    {"unsigned", UNSIGNED, OP_NULL, 0},
+    {"template", TEMPLATE, OP_NULL, 1},
+    {"volatile", VOLATILE_KEYWORD, OP_NULL, 0},
+    {"struct", STRUCT, OP_NULL, 0},
+    {"signed", SIGNED_KEYWORD, OP_NULL, 0},
+    {"sizeof", SIZEOF, OP_NULL, 0},
+    {"double", DOUBLE_KEYWORD, OP_NULL, 0},
+    {"false", FALSEKEYWORD, OP_NULL, 1},
+    {"class", CLASS, OP_NULL, 1},
+    {"union", UNION, OP_NULL, 0},
+    {"short", SHORT, OP_NULL, 0},
+    {"const", CONST_KEYWORD, OP_NULL, 0},
+    {"enum", ENUM, OP_NULL, 0},
+    {"long", LONG, OP_NULL, 0},
+    {"true", TRUEKEYWORD, OP_NULL, 1},
+    {"int", INT_KEYWORD, OP_NULL, 0},
+
+    {"and", ANDAND, BINOP_END, 1},
+    {"and_eq", ASSIGN_MODIFY, BINOP_BITWISE_AND, 1},
+    {"bitand", '&', OP_NULL, 1},
+    {"bitor", '|', OP_NULL, 1},
+    {"compl", '~', OP_NULL, 1},
+    {"not", '!', OP_NULL, 1},
+    {"not_eq", NOTEQUAL, BINOP_END, 1},
+    {"or", OROR, BINOP_END, 1},
+    {"or_eq", ASSIGN_MODIFY, BINOP_BITWISE_IOR, 1},
+    {"xor", '^', OP_NULL, 1},
+    {"xor_eq", ASSIGN_MODIFY, BINOP_BITWISE_XOR, 1}
+  };
+
+/* When we find that lexptr (the global var defined in parse.c) is
+   pointing at a macro invocation, we expand the invocation, and call
+   scan_macro_expansion to save the old lexptr here and point lexptr
+   into the expanded text.  When we reach the end of that, we call
+   end_macro_expansion to pop back to the value we saved here.  The
+   macro expansion code promises to return only fully-expanded text,
+   so we don't need to "push" more than one level.
+
+   This is disgusting, of course.  It would be cleaner to do all macro
+   expansion beforehand, and then hand that to lexptr.  But we don't
+   really know where the expression ends.  Remember, in a command like
+
+     (gdb) break *ADDRESS if CONDITION
+
+   we evaluate ADDRESS in the scope of the current frame, but we
+   evaluate CONDITION in the scope of the breakpoint's location.  So
+   it's simply wrong to try to macro-expand the whole thing at once.  */
+static char *macro_original_text;
+
+/* We save all intermediate macro expansions on this obstack for the
+   duration of a single parse.  The expansion text may sometimes have
+   to live past the end of the expansion, due to yacc lookahead.
+   Rather than try to be clever about saving the data for a single
+   token, we simply keep it all and delete it after parsing has
+   completed.  */
+static struct obstack expansion_obstack;
+
+static void
+scan_macro_expansion (char *expansion)
+{
+  char *copy;
+
+  /* We'd better not be trying to push the stack twice.  */
+  gdb_assert (! macro_original_text);
+
+  /* Copy to the obstack, and then free the intermediate
+     expansion.  */
+  copy = obstack_copy0 (&expansion_obstack, expansion, strlen (expansion));
+  xfree (expansion);
+
+  /* Save the old lexptr value, so we can return to it when we're done
+     parsing the expanded text.  */
+  macro_original_text = lexptr;
+  lexptr = copy;
+}
+
+
+static int
+scanning_macro_expansion (void)
+{
+  return macro_original_text != 0;
+}
+
+
+static void 
+finished_macro_expansion (void)
+{
+  /* There'd better be something to pop back to.  */
+  gdb_assert (macro_original_text);
+
+  /* Pop back to the original text.  */
+  lexptr = macro_original_text;
+  macro_original_text = 0;
+}
+
+
+static void
+scan_macro_cleanup (void *dummy)
+{
+  if (macro_original_text)
+    finished_macro_expansion ();
+
+  obstack_free (&expansion_obstack, NULL);
+}
+
+
+/* The scope used for macro expansion.  */
+static struct macro_scope *expression_macro_scope;
+
+/* This is set if a NAME token appeared at the very end of the input
+   string, with no whitespace separating the name from the EOF.  This
+   is used only when parsing to do field name completion.  */
+static int saw_name_at_eof;
+
+/* This is set if the previously-returned token was a structure
+   operator -- either '.' or ARROW.  This is used only when parsing to
+   do field name completion.  */
+static int last_was_structop;
+
 /* Read one token, getting characters through lexptr.  */
 
 static int
@@ -1355,15 +1536,19 @@ yylex ()
   static int tempbufsize;
   char * token_string = NULL;
   int class_prefix = 0;
-   
+  int saw_structop = last_was_structop;
+  char *copy;
+
+  last_was_structop = 0;
+
  retry:
 
   /* Check if this is a macro invocation that we need to expand.  */
   if (! scanning_macro_expansion ())
     {
       char *expanded = macro_expand_next (&lexptr,
-                                          expression_macro_lookup_func,
-                                          expression_macro_lookup_baton);
+                                          standard_macro_lookup,
+                                          expression_macro_scope);
 
       if (expanded)
         scan_macro_expansion (expanded);
@@ -1387,6 +1572,8 @@ yylex ()
       {
        lexptr += 2;
        yylval.opcode = tokentab2[i].opcode;
+       if (in_parse_field && tokentab2[i].token == ARROW)
+         last_was_structop = 1;
        return tokentab2[i].token;
       }
 
@@ -1395,6 +1582,8 @@ yylex ()
     case 0:
       /* If we were just scanning the result of a macro expansion,
          then we need to resume scanning the original text.
+        If we're parsing for field name completion, and the previous
+        token allows such completion, return a COMPLETE token.
          Otherwise, we were already scanning the original text, and
          we're really done.  */
       if (scanning_macro_expansion ())
@@ -1402,6 +1591,13 @@ yylex ()
           finished_macro_expansion ();
           goto retry;
         }
+      else if (saw_name_at_eof)
+       {
+         saw_name_at_eof = 0;
+         return COMPLETE;
+       }
+      else if (saw_structop)
+       return COMPLETE;
       else
         return 0;
 
@@ -1432,7 +1628,7 @@ yylex ()
         }
 
       yylval.typed_val_int.val = c;
-      yylval.typed_val_int.type = builtin_type (current_gdbarch)->builtin_char;
+      yylval.typed_val_int.type = parse_type->builtin_char;
 
       c = *lexptr++;
       if (c != '\'')
@@ -1474,7 +1670,11 @@ yylex ()
     case '.':
       /* Might be a floating point number.  */
       if (lexptr[1] < '0' || lexptr[1] > '9')
-       goto symbol;            /* Nope, must be a symbol. */
+       {
+         if (in_parse_field)
+           last_was_structop = 1;
+         goto symbol;          /* Nope, must be a symbol. */
+       }
       /* FALL THRU into number case.  */
 
     case '0':
@@ -1674,65 +1874,24 @@ yylex ()
 
   tryname:
 
-  /* Catch specific keywords.  Should be done with a data structure.  */
-  switch (namelen)
-    {
-    case 8:
-      if (strncmp (tokstart, "unsigned", 8) == 0)
-       return UNSIGNED;
-      if (current_language->la_language == language_cplus
-         && strncmp (tokstart, "template", 8) == 0)
-       return TEMPLATE;
-      if (strncmp (tokstart, "volatile", 8) == 0)
-       return VOLATILE_KEYWORD;
-      break;
-    case 6:
-      if (strncmp (tokstart, "struct", 6) == 0)
-       return STRUCT;
-      if (strncmp (tokstart, "signed", 6) == 0)
-       return SIGNED_KEYWORD;
-      if (strncmp (tokstart, "sizeof", 6) == 0)
-       return SIZEOF;
-      if (strncmp (tokstart, "double", 6) == 0)
-       return DOUBLE_KEYWORD;
-      break;
-    case 5:
-      if (current_language->la_language == language_cplus)
-        {
-          if (strncmp (tokstart, "false", 5) == 0)
-            return FALSEKEYWORD;
-          if (strncmp (tokstart, "class", 5) == 0)
-            return CLASS;
-        }
-      if (strncmp (tokstart, "union", 5) == 0)
-       return UNION;
-      if (strncmp (tokstart, "short", 5) == 0)
-       return SHORT;
-      if (strncmp (tokstart, "const", 5) == 0)
-       return CONST_KEYWORD;
-      break;
-    case 4:
-      if (strncmp (tokstart, "enum", 4) == 0)
-       return ENUM;
-      if (strncmp (tokstart, "long", 4) == 0)
-       return LONG;
-      if (current_language->la_language == language_cplus)
-          {
-            if (strncmp (tokstart, "true", 4) == 0)
-              return TRUEKEYWORD;
-          }
-      break;
-    case 3:
-      if (strncmp (tokstart, "int", 3) == 0)
-       return INT_KEYWORD;
-      break;
-    default:
-      break;
-    }
-
   yylval.sval.ptr = tokstart;
   yylval.sval.length = namelen;
 
+  /* Catch specific keywords.  */
+  copy = copy_name (yylval.sval);
+  for (i = 0; i < sizeof ident_tokens / sizeof ident_tokens[0]; i++)
+    if (strcmp (copy, ident_tokens[i].operator) == 0)
+      {
+       if (ident_tokens[i].cxx_only
+           && parse_language->la_language != language_cplus)
+         break;
+
+       /* It is ok to always set this, even though we don't always
+          strictly need to.  */
+       yylval.opcode = ident_tokens[i].opcode;
+       return ident_tokens[i].token;
+      }
+
   if (*tokstart == '$')
     {
       write_dollar_variable (yylval.sval);
@@ -1745,16 +1904,14 @@ yylex ()
      currently as names of types; NAME for other symbols.
      The caller is not constrained to care about the distinction.  */
   {
-    char *tmp = copy_name (yylval.sval);
     struct symbol *sym;
     int is_a_field_of_this = 0;
     int hextype;
 
-    sym = lookup_symbol (tmp, expression_context_block,
+    sym = lookup_symbol (copy, expression_context_block,
                         VAR_DOMAIN,
-                        current_language->la_language == language_cplus
-                        ? &is_a_field_of_this : (int *) NULL,
-                        (struct symtab **) NULL);
+                        parse_language->la_language == language_cplus
+                        ? &is_a_field_of_this : (int *) NULL);
     /* 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).  */
@@ -1768,7 +1925,7 @@ yylex ()
       {                                /* See if it's a file name. */
        struct symtab *symtab;
 
-       symtab = lookup_symtab (tmp);
+       symtab = lookup_symtab (copy);
 
        if (symtab)
          {
@@ -1786,8 +1943,8 @@ yylex ()
          return TYPENAME;
         }
     yylval.tsym.type
-      = language_lookup_primitive_type_by_name (current_language,
-                                               current_gdbarch, tmp);
+      = language_lookup_primitive_type_by_name (parse_language,
+                                               parse_gdbarch, copy);
     if (yylval.tsym.type != NULL)
       return TYPENAME;
 
@@ -1811,10 +1968,45 @@ yylex ()
     /* Any other kind of symbol */
     yylval.ssym.sym = sym;
     yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+    if (in_parse_field && *lexptr == '\0')
+      saw_name_at_eof = 1;
     return NAME;
   }
 }
 
+int
+c_parse (void)
+{
+  int result;
+  struct cleanup *back_to = make_cleanup (free_current_contents,
+                                         &expression_macro_scope);
+
+  /* Set up the scope for macro expansion.  */
+  expression_macro_scope = NULL;
+
+  if (expression_context_block)
+    expression_macro_scope
+      = sal_macro_scope (find_pc_line (expression_context_pc, 0));
+  else
+    expression_macro_scope = default_macro_scope ();
+  if (! expression_macro_scope)
+    expression_macro_scope = user_macro_scope ();
+
+  /* Initialize macro expansion code.  */
+  obstack_init (&expansion_obstack);
+  gdb_assert (! macro_original_text);
+  make_cleanup (scan_macro_cleanup, 0);
+
+  /* Initialize some state used by the lexer.  */
+  last_was_structop = 0;
+  saw_name_at_eof = 0;
+
+  result = yyparse ();
+  do_cleanups (back_to);
+  return result;
+}
+
+
 void
 yyerror (msg)
      char *msg;
This page took 0.037705 seconds and 4 git commands to generate.