2009-03-17 Paul Pluzhnikov <ppluzhnikov@google.com>
[deliverable/binutils-gdb.git] / gdb / c-exp.y
index 3d2d1aa661f724b0b87b521359f1fb89b74e2e7b..d4bbbccd362b7aae41864a483e26d4ba62d96e91 100644 (file)
@@ -1,6 +1,6 @@
 /* YACC parser for C expressions, for GDB.
-   Copyright 1986, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
-   1998, 1999, 2000
+   Copyright (C) 1986, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+   1998, 1999, 2000, 2003, 2004, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
 
 This file is part of GDB.
@@ -17,7 +17,8 @@ GNU General Public License for more details.
 
 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.  */
+Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 /* Parse a C expression from text in a string,
    and return the result as a  struct expression  pointer.
@@ -49,9 +50,14 @@ 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 "charset.h"
+#include "block.h"
+#include "cp-support.h"
+#include "dfp.h"
+#include "gdb_assert.h"
+#include "macroscope.h"
 
-/* Flag indicating we're dealing with HP-compiled objects */ 
-extern int hp_som_som_object_present;
+#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
@@ -61,7 +67,7 @@ extern int hp_som_som_object_present;
    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
@@ -89,6 +95,8 @@ extern int hp_som_som_object_present;
 #define        yylloc  c_lloc
 #define yyreds c_reds          /* With YYDEBUG defined */
 #define yytoks c_toks          /* With YYDEBUG defined */
+#define yyname c_name          /* With YYDEBUG defined */
+#define yyrule c_rule          /* With YYDEBUG defined */
 #define yylhs  c_yylhs
 #define yylen  c_yylen
 #define yydefred c_yydefred
@@ -100,9 +108,11 @@ extern int hp_som_som_object_present;
 #define yycheck         c_yycheck
 
 #ifndef YYDEBUG
-#define        YYDEBUG 0               /* Default to no yydebug support */
+#define        YYDEBUG 1               /* Default to yydebug support */
 #endif
 
+#define YYFPRINTF parser_fprintf
+
 int yyparse (void);
 
 static int yylex (void);
@@ -126,6 +136,10 @@ void yyerror (char *);
       DOUBLEST dval;
       struct type *type;
     } typed_val_float;
+    struct {
+      gdb_byte val[16];
+      struct type *type;
+    } typed_val_decfloat;
     struct symbol *sym;
     struct type *tval;
     struct stoken sval;
@@ -147,7 +161,7 @@ static int parse_number (char *, int, int, YYSTYPE *);
 
 %type <voidval> exp exp1 type_exp start variable qualified_name lcurly
 %type <lval> rcurly
-%type <tval> type typebase
+%type <tval> type typebase qualified_type
 %type <tvec> nonempty_typelist
 /* %type <bval> block */
 
@@ -158,6 +172,7 @@ static int parse_number (char *, int, int, YYSTYPE *);
 
 %token <typed_val_int> INT
 %token <typed_val_float> FLOAT
+%token <typed_val_decfloat> DECFLOAT
 
 /* Both NAME and TYPENAME tokens represent symbols in the input,
    and both convey their data as strings.
@@ -169,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
 
@@ -194,7 +210,6 @@ static int parse_number (char *, int, int, YYSTYPE *);
 %token <opcode> ASSIGN_MODIFY
 
 /* C++ */
-%token THIS
 %token TRUEKEYWORD
 %token FALSEKEYWORD
 
@@ -243,14 +258,20 @@ exp1      :       exp
 /* Expressions, not including the comma operator.  */
 exp    :       '*' exp    %prec UNARY
                        { write_exp_elt_opcode (UNOP_IND); }
+       ;
 
 exp    :       '&' exp    %prec UNARY
                        { write_exp_elt_opcode (UNOP_ADDR); }
+       ;
 
 exp    :       '-' exp    %prec UNARY
                        { write_exp_elt_opcode (UNOP_NEG); }
        ;
 
+exp    :       '+' exp    %prec UNARY
+                       { write_exp_elt_opcode (UNOP_PLUS); }
+       ;
+
 exp    :       '!' exp    %prec UNARY
                        { write_exp_elt_opcode (UNOP_LOGICAL_NOT); }
        ;
@@ -285,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
@@ -303,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
@@ -487,6 +542,13 @@ exp        :       FLOAT
                          write_exp_elt_opcode (OP_DOUBLE); }
        ;
 
+exp    :       DECFLOAT
+                       { write_exp_elt_opcode (OP_DECFLOAT);
+                         write_exp_elt_type ($1.type);
+                         write_exp_elt_decfloatcst ($1.val);
+                         write_exp_elt_opcode (OP_DECFLOAT); }
+       ;
+
 exp    :       variable
        ;
 
@@ -496,13 +558,40 @@ exp       :       VARIABLE
 
 exp    :       SIZEOF '(' type ')'     %prec UNARY
                        { write_exp_elt_opcode (OP_LONG);
-                         write_exp_elt_type (builtin_type_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.
@@ -512,36 +601,33 @@ exp       :       STRING
                          while (count-- > 0)
                            {
                              write_exp_elt_opcode (OP_LONG);
-                             write_exp_elt_type (builtin_type_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_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    :       THIS
-                       { write_exp_elt_opcode (OP_THIS);
-                         write_exp_elt_opcode (OP_THIS); }
-       ;
-
 exp     :       TRUEKEYWORD    
                         { write_exp_elt_opcode (OP_LONG);
-                          write_exp_elt_type (builtin_type_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_bool);
+                          write_exp_elt_type (parse_type->builtin_bool);
                           write_exp_elt_longcst ((LONGEST) 0);
                           write_exp_elt_opcode (OP_LONG); }
        ;
@@ -565,8 +651,7 @@ block       :       BLOCKNAME
 block  :       block COLONCOLON name
                        { struct symbol *tem
                            = lookup_symbol (copy_name ($3), $1,
-                                            VAR_NAMESPACE, (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));
@@ -576,8 +661,7 @@ block       :       block COLONCOLON name
 variable:      block COLONCOLON name
                        { struct symbol *sym;
                          sym = lookup_symbol (copy_name ($3), $1,
-                                              VAR_NAMESPACE, (int *) NULL,
-                                              (struct symtab **) NULL);
+                                              VAR_DOMAIN, (int *) NULL);
                          if (sym == 0)
                            error ("No symbol \"%s\" in specified context.",
                                   copy_name ($3));
@@ -593,7 +677,8 @@ qualified_name:     typebase COLONCOLON name
                        {
                          struct type *type = $1;
                          if (TYPE_CODE (type) != TYPE_CODE_STRUCT
-                             && TYPE_CODE (type) != TYPE_CODE_UNION)
+                             && TYPE_CODE (type) != TYPE_CODE_UNION
+                             && TYPE_CODE (type) != TYPE_CODE_NAMESPACE)
                            error ("`%s' is not defined as an aggregate type.",
                                   TYPE_NAME (type));
 
@@ -607,7 +692,8 @@ qualified_name:     typebase COLONCOLON name
                          struct type *type = $1;
                          struct stoken tmp_token;
                          if (TYPE_CODE (type) != TYPE_CODE_STRUCT
-                             && TYPE_CODE (type) != TYPE_CODE_UNION)
+                             && TYPE_CODE (type) != TYPE_CODE_UNION
+                             && TYPE_CODE (type) != TYPE_CODE_NAMESPACE)
                            error ("`%s' is not defined as an aggregate type.",
                                   TYPE_NAME (type));
 
@@ -635,8 +721,7 @@ variable:   qualified_name
 
                          sym =
                            lookup_symbol (name, (const struct block *) NULL,
-                                          VAR_NAMESPACE, (int *) NULL,
-                                          (struct symtab **) NULL);
+                                          VAR_DOMAIN, (int *) NULL);
                          if (sym)
                            {
                              write_exp_elt_opcode (OP_VAR_VALUE);
@@ -648,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_int),
-                                                builtin_type_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);
                        }
        ;
 
@@ -699,16 +779,12 @@ variable: name_not_typename
                          else
                            {
                              struct minimal_symbol *msymbol;
-                             register char *arg = copy_name ($1.stoken);
+                             char *arg = copy_name ($1.stoken);
 
                              msymbol =
                                lookup_minimal_symbol (arg, NULL, NULL);
                              if (msymbol != NULL)
-                               {
-                                 write_exp_msymbol (msymbol,
-                                                    lookup_function_type (builtin_type_int),
-                                                    builtin_type_int);
-                               }
+                               write_exp_msymbol (msymbol);
                              else if (!have_full_symbols () && !have_partial_symbols ())
                                error ("No symbol table is loaded.  Use the \"file\" command.");
                              else
@@ -780,10 +856,10 @@ array_mod:        '[' ']'
 func_mod:      '(' ')'
                        { $$ = 0; }
        |       '(' nonempty_typelist ')'
-                       { free ((PTR)$2); $$ = 0; }
+                       { free ($2); $$ = 0; }
        ;
 
-/* We used to try to recognize more pointer to member types here, but
+/* We used to try to recognize pointer to member types here, but
    that didn't work (shift/reduce conflicts meant that these rules never
    got executed).  The problem is that
      int (foo::bar::baz::bizzle)
@@ -792,43 +868,67 @@ func_mod: '(' ')'
    is a pointer to member type.  Stroustrup loses again!  */
 
 type   :       ptype
-       |       typebase COLONCOLON '*'
-                       { $$ = lookup_member_type (builtin_type_int, $1); }
        ;
 
 typebase  /* Implements (approximately): (type-qualifier)* type-specifier */
        :       TYPENAME
                        { $$ = $1.type; }
        |       INT_KEYWORD
-                       { $$ = builtin_type_int; }
+                       { $$ = parse_type->builtin_int; }
        |       LONG
-                       { $$ = builtin_type_long; }
+                       { $$ = parse_type->builtin_long; }
        |       SHORT
-                       { $$ = builtin_type_short; }
+                       { $$ = parse_type->builtin_short; }
        |       LONG INT_KEYWORD
-                       { $$ = builtin_type_long; }
+                       { $$ = parse_type->builtin_long; }
+       |       LONG SIGNED_KEYWORD INT_KEYWORD
+                       { $$ = parse_type->builtin_long; }
+       |       LONG SIGNED_KEYWORD
+                       { $$ = parse_type->builtin_long; }
+       |       SIGNED_KEYWORD LONG INT_KEYWORD
+                       { $$ = parse_type->builtin_long; }
        |       UNSIGNED LONG INT_KEYWORD
-                       { $$ = builtin_type_unsigned_long; }
+                       { $$ = parse_type->builtin_unsigned_long; }
+       |       LONG UNSIGNED INT_KEYWORD
+                       { $$ = parse_type->builtin_unsigned_long; }
+       |       LONG UNSIGNED
+                       { $$ = parse_type->builtin_unsigned_long; }
        |       LONG LONG
-                       { $$ = builtin_type_long_long; }
+                       { $$ = parse_type->builtin_long_long; }
        |       LONG LONG INT_KEYWORD
-                       { $$ = builtin_type_long_long; }
-       |       UNSIGNED LONG LONG
-                       { $$ = builtin_type_unsigned_long_long; }
-       |       UNSIGNED LONG LONG INT_KEYWORD
-                       { $$ = builtin_type_unsigned_long_long; }
+                       { $$ = parse_type->builtin_long_long; }
+       |       LONG LONG SIGNED_KEYWORD INT_KEYWORD
+                       { $$ = parse_type->builtin_long_long; }
+       |       LONG LONG SIGNED_KEYWORD
+                       { $$ = parse_type->builtin_long_long; }
        |       SIGNED_KEYWORD LONG LONG
-                       { $$ = lookup_signed_typename ("long long"); }
+                       { $$ = parse_type->builtin_long_long; }
        |       SIGNED_KEYWORD LONG LONG INT_KEYWORD
-                       { $$ = lookup_signed_typename ("long long"); }
+                       { $$ = parse_type->builtin_long_long; }
+       |       UNSIGNED LONG LONG
+                       { $$ = parse_type->builtin_unsigned_long_long; }
+       |       UNSIGNED LONG LONG INT_KEYWORD
+                       { $$ = parse_type->builtin_unsigned_long_long; }
+       |       LONG LONG UNSIGNED
+                       { $$ = parse_type->builtin_unsigned_long_long; }
+       |       LONG LONG UNSIGNED INT_KEYWORD
+                       { $$ = parse_type->builtin_unsigned_long_long; }
        |       SHORT INT_KEYWORD
-                       { $$ = builtin_type_short; }
+                       { $$ = parse_type->builtin_short; }
+       |       SHORT SIGNED_KEYWORD INT_KEYWORD
+                       { $$ = parse_type->builtin_short; }
+       |       SHORT SIGNED_KEYWORD
+                       { $$ = parse_type->builtin_short; }
        |       UNSIGNED SHORT INT_KEYWORD
-                       { $$ = builtin_type_unsigned_short; }
+                       { $$ = parse_type->builtin_unsigned_short; }
+       |       SHORT UNSIGNED 
+                       { $$ = parse_type->builtin_unsigned_short; }
+       |       SHORT UNSIGNED INT_KEYWORD
+                       { $$ = parse_type->builtin_unsigned_short; }
        |       DOUBLE_KEYWORD
-                       { $$ = builtin_type_double; }
+                       { $$ = parse_type->builtin_double; }
        |       LONG DOUBLE_KEYWORD
-                       { $$ = builtin_type_long_double; }
+                       { $$ = parse_type->builtin_long_double; }
        |       STRUCT name
                        { $$ = lookup_struct (copy_name ($2),
                                              expression_context_block); }
@@ -844,11 +944,11 @@ typebase  /* Implements (approximately): (type-qualifier)* type-specifier */
        |       UNSIGNED typename
                        { $$ = lookup_unsigned_typename (TYPE_NAME($2.type)); }
        |       UNSIGNED
-                       { $$ = builtin_type_unsigned_int; }
+                       { $$ = parse_type->builtin_unsigned_int; }
        |       SIGNED_KEYWORD typename
                        { $$ = lookup_signed_typename (TYPE_NAME($2.type)); }
        |       SIGNED_KEYWORD
-                       { $$ = builtin_type_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. */         
@@ -860,6 +960,77 @@ typebase  /* Implements (approximately): (type-qualifier)* type-specifier */
                        { $$ = follow_types ($2); }
        | typebase const_or_volatile_or_space_identifier_noopt 
                        { $$ = follow_types ($1); }
+       | qualified_type
+       ;
+
+/* FIXME: carlton/2003-09-25: This next bit leads to lots of
+   reduce-reduce conflicts, because the parser doesn't know whether or
+   not to use qualified_name or qualified_type: the rules are
+   identical.  If the parser is parsing 'A::B::x', then, when it sees
+   the second '::', it knows that the expression to the left of it has
+   to be a type, so it uses qualified_type.  But if it is parsing just
+   'A::B', then it doesn't have any way of knowing which rule to use,
+   so there's a reduce-reduce conflict; it picks qualified_name, since
+   that occurs earlier in this file than qualified_type.
+
+   There's no good way to fix this with the grammar as it stands; as
+   far as I can tell, some of the problems arise from ambiguities that
+   GDB introduces ('start' can be either an expression or a type), but
+   some of it is inherent to the nature of C++ (you want to treat the
+   input "(FOO)" fairly differently depending on whether FOO is an
+   expression or a type, and if FOO is a complex expression, this can
+   be hard to determine at the right time).  Fortunately, it works
+   pretty well in most cases.  For example, if you do 'ptype A::B',
+   where A::B is a nested type, then the parser will mistakenly
+   misidentify it as an expression; but evaluate_subexp will get
+   called with 'noside' set to EVAL_AVOID_SIDE_EFFECTS, and everything
+   will work out anyways.  But there are situations where the parser
+   will get confused: the most common one that I've run into is when
+   you want to do
+
+     print *((A::B *) x)"
+
+   where the parser doesn't realize that A::B has to be a type until
+   it hits the first right paren, at which point it's too late.  (The
+   workaround is to type "print *(('A::B' *) x)" instead.)  (And
+   another solution is to fix our symbol-handling code so that the
+   user never wants to type something like that in the first place,
+   because we get all the types right without the user's help!)
+
+   Perhaps we could fix this by making the lexer smarter.  Some of
+   this functionality used to be in the lexer, but in a way that
+   worked even less well than the current solution: that attempt
+   involved having the parser sometimes handle '::' and having the
+   lexer sometimes handle it, and without a clear division of
+   responsibility, it quickly degenerated into a big mess.  Probably
+   the eventual correct solution will give more of a role to the lexer
+   (ideally via code that is shared between the lexer and
+   decode_line_1), but I'm not holding my breath waiting for somebody
+   to get around to cleaning this up...  */
+
+qualified_type: typebase COLONCOLON name
+               {
+                 struct type *type = $1;
+                 struct type *new_type;
+                 char *ncopy = alloca ($3.length + 1);
+
+                 memcpy (ncopy, $3.ptr, $3.length);
+                 ncopy[$3.length] = '\0';
+
+                 if (TYPE_CODE (type) != TYPE_CODE_STRUCT
+                     && TYPE_CODE (type) != TYPE_CODE_UNION
+                     && TYPE_CODE (type) != TYPE_CODE_NAMESPACE)
+                   error ("`%s' is not defined as an aggregate type.",
+                          TYPE_NAME (type));
+
+                 new_type = cp_lookup_nested_type (type, ncopy,
+                                                   expression_context_block);
+                 if (new_type == NULL)
+                   error ("No type \"%s\" within class or namespace \"%s\".",
+                          ncopy, TYPE_NAME (type));
+                 
+                 $$ = new_type;
+               }
        ;
 
 typename:      TYPENAME
@@ -867,19 +1038,19 @@ typename:        TYPENAME
                {
                  $$.stoken.ptr = "int";
                  $$.stoken.length = 3;
-                 $$.type = builtin_type_int;
+                 $$.type = parse_type->builtin_int;
                }
        |       LONG
                {
                  $$.stoken.ptr = "long";
                  $$.stoken.length = 4;
-                 $$.type = builtin_type_long;
+                 $$.type = parse_type->builtin_long;
                }
        |       SHORT
                {
                  $$.stoken.ptr = "short";
                  $$.stoken.length = 5;
-                 $$.type = builtin_type_short;
+                 $$.type = parse_type->builtin_short;
                }
        ;
 
@@ -942,20 +1113,20 @@ name_not_typename :      NAME
 
 static int
 parse_number (p, len, parsed_float, putithere)
-     register char *p;
-     register int len;
+     char *p;
+     int len;
      int parsed_float;
      YYSTYPE *putithere;
 {
   /* FIXME: Shouldn't these be unsigned?  We don't deal with negative values
      here, and we do kind of silly things like cast to unsigned.  */
-  register LONGEST n = 0;
-  register LONGEST prevn = 0;
+  LONGEST n = 0;
+  LONGEST prevn = 0;
   ULONGEST un;
 
-  register int i = 0;
-  register int c;
-  register int base = input_radix;
+  int i = 0;
+  int c;
+  int base = input_radix;
   int unsigned_p = 0;
 
   /* Number of "L" suffixes encountered.  */
@@ -971,44 +1142,72 @@ parse_number (p, len, parsed_float, putithere)
   if (parsed_float)
     {
       /* It's a float since it contains a point or an exponent.  */
-      char c;
-      int num = 0;     /* number of tokens scanned by scanf */
-      char saved_char = p[len];
+      char *s;
+      int num; /* number of tokens scanned by scanf */
+      char saved_char;
 
-      p[len] = 0;      /* null-terminate the token */
-      if (sizeof (putithere->typed_val_float.dval) <= sizeof (float))
-       num = sscanf (p, "%g%c", (float *) &putithere->typed_val_float.dval,&c);
-      else if (sizeof (putithere->typed_val_float.dval) <= sizeof (double))
-       num = sscanf (p, "%lg%c", (double *) &putithere->typed_val_float.dval,&c);
-      else
+      /* If it ends at "df", "dd" or "dl", take it as type of decimal floating
+         point.  Return DECFLOAT.  */
+
+      if (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'f')
        {
-#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.
-            This at least wins with values representable in the range
-            of doubles. */
-         double temp;
-         num = sscanf (p, "%lg%c", &temp,&c);
-         putithere->typed_val_float.dval = temp;
-#endif
+         p[len - 2] = '\0';
+         putithere->typed_val_decfloat.type
+           = parse_type->builtin_decfloat;
+         decimal_from_string (putithere->typed_val_decfloat.val, 4, p);
+         p[len - 2] = 'd';
+         return DECFLOAT;
+       }
+
+      if (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'd')
+       {
+         p[len - 2] = '\0';
+         putithere->typed_val_decfloat.type
+           = parse_type->builtin_decdouble;
+         decimal_from_string (putithere->typed_val_decfloat.val, 8, p);
+         p[len - 2] = 'd';
+         return DECFLOAT;
        }
+
+      if (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'l')
+       {
+         p[len - 2] = '\0';
+         putithere->typed_val_decfloat.type
+           = parse_type->builtin_declong;
+         decimal_from_string (putithere->typed_val_decfloat.val, 16, p);
+         p[len - 2] = 'd';
+         return DECFLOAT;
+       }
+
+      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)            /* check scanf found ONLY a float ... */
-       return ERROR;
-      /* See if it has `f' or `l' suffix (float or long double).  */
-
-      c = tolower (p[len - 1]);
-
-      if (c == 'f')
-       putithere->typed_val_float.type = builtin_type_float;
-      else if (c == 'l')
-       putithere->typed_val_float.type = builtin_type_long_double;
-      else if (isdigit (c) || c == '.')
-       putithere->typed_val_float.type = builtin_type_double;
-      else
-       return ERROR;
 
+      if (num == 1)
+       putithere->typed_val_float.type = 
+         parse_type->builtin_double;
+
+      if (num == 2 )
+       {
+         /* See if it has any float suffix: 'f' for float, 'l' for long 
+            double.  */
+         if (!strcasecmp (s, "f"))
+           putithere->typed_val_float.type = 
+             parse_type->builtin_float;
+         else if (!strcasecmp (s, "l"))
+           putithere->typed_val_float.type = 
+             parse_type->builtin_long_double;
+         else
+           {
+             free (s);
+             return ERROR;
+           }
+       }
+
+      free (s);
       return FLOAT;
     }
 
@@ -1104,16 +1303,16 @@ parse_number (p, len, parsed_float, putithere)
      shift it right and see whether anything remains.  Note that we
      can't shift sizeof (LONGEST) * HOST_CHAR_BIT bits or more in one
      operation, because many compilers will warn about such a shift
-     (which always produces a zero result).  Sometimes TARGET_INT_BIT
-     or TARGET_LONG_BIT will be that big, sometimes not.  To deal with
+     (which always produces a zero result).  Sometimes gdbarch_int_bit
+     or gdbarch_long_bit will be that big, sometimes not.  To deal with
      the case where it is we just always shift the value more than
      once, with fewer bits each time.  */
 
   un = (ULONGEST)n >> 2;
   if (long_p == 0
-      && (un >> (TARGET_INT_BIT - 2)) == 0)
+      && (un >> (gdbarch_int_bit (parse_gdbarch) - 2)) == 0)
     {
-      high_bit = ((ULONGEST)1) << (TARGET_INT_BIT-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,
@@ -1121,27 +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_unsigned_int;
-      signed_type = builtin_type_int;
+      unsigned_type = parse_type->builtin_unsigned_int;
+      signed_type = parse_type->builtin_int;
     }
   else if (long_p <= 1
-          && (un >> (TARGET_LONG_BIT - 2)) == 0)
+          && (un >> (gdbarch_long_bit (parse_gdbarch) - 2)) == 0)
     {
-      high_bit = ((ULONGEST)1) << (TARGET_LONG_BIT-1);
-      unsigned_type = builtin_type_unsigned_long;
-      signed_type = builtin_type_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 < TARGET_LONG_LONG_BIT)
+      if (sizeof (ULONGEST) * HOST_CHAR_BIT 
+         < gdbarch_long_long_bit (parse_gdbarch))
        /* A long long does not fit in a LONGEST.  */
        shift = (sizeof (ULONGEST) * HOST_CHAR_BIT - 1);
       else
-       shift = (TARGET_LONG_LONG_BIT - 1);
+       shift = (gdbarch_long_long_bit (parse_gdbarch) - 1);
       high_bit = (ULONGEST) 1 << shift;
-      unsigned_type = builtin_type_unsigned_long_long;
-      signed_type = builtin_type_long_long;
+      unsigned_type = parse_type->builtin_unsigned_long_long;
+      signed_type = parse_type->builtin_long_long;
     }
 
    putithere->typed_val_int.val = n;
@@ -1166,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
@@ -1211,19 +1534,32 @@ yylex ()
   int tempbufindex;
   static char *tempbuf;
   static int tempbufsize;
-  struct symbol * sym_class = NULL;
   char * token_string = NULL;
   int class_prefix = 0;
-  int unquoted_expr;
-   
+  int saw_structop = last_was_structop;
+  char *copy;
+
+  last_was_structop = 0;
+
  retry:
 
-  unquoted_expr = 1;
+  /* Check if this is a macro invocation that we need to expand.  */
+  if (! scanning_macro_expansion ())
+    {
+      char *expanded = macro_expand_next (&lexptr,
+                                          standard_macro_lookup,
+                                          expression_macro_scope);
+
+      if (expanded)
+        scan_macro_expansion (expanded);
+    }
+
+  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;
@@ -1232,17 +1568,38 @@ 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;
+       if (in_parse_field && tokentab2[i].token == ARROW)
+         last_was_structop = 1;
        return tokentab2[i].token;
       }
 
   switch (c = *tokstart)
     {
     case 0:
-      return 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 ())
+        {
+          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;
 
     case ' ':
     case '\t':
@@ -1260,9 +1617,18 @@ yylex ()
        c = parse_escape (&lexptr);
       else if (c == '\'')
        error ("Empty character constant.");
+      else if (! host_char_to_target (c, &c))
+        {
+          int toklen = lexptr - tokstart + 1;
+          char *tok = alloca (toklen + 1);
+          memcpy (tok, tokstart, toklen);
+          tok[toklen] = '\0';
+          error ("There is no character corresponding to %s in the target "
+                 "character set `%s'.", tok, target_charset ());
+        }
 
       yylval.typed_val_int.val = c;
-      yylval.typed_val_int.type = builtin_type_char;
+      yylval.typed_val_int.type = parse_type->builtin_char;
 
       c = *lexptr++;
       if (c != '\'')
@@ -1271,7 +1637,6 @@ yylex ()
          if (namelen > 2)
            {
              lexptr = tokstart + namelen;
-              unquoted_expr = 0;
              if (lexptr[-1] != '\'')
                error ("Unmatched single quote.");
              namelen -= 2;
@@ -1295,7 +1660,9 @@ yylex ()
       return c;
 
     case ',':
-      if (comma_terminates && paren_depth == 0)
+      if (comma_terminates
+          && paren_depth == 0
+          && ! scanning_macro_expansion ())
        return 0;
       lexptr++;
       return c;
@@ -1303,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':
@@ -1319,7 +1690,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'))
@@ -1408,6 +1779,8 @@ yylex ()
       tempbufindex = 0;
 
       do {
+        char *char_start_pos = tokptr;
+
        /* Grow the static temp buffer if necessary, including allocating
           the first one on demand. */
        if (tempbufindex + 1 >= tempbufsize)
@@ -1430,7 +1803,19 @@ yylex ()
            tempbuf[tempbufindex++] = c;
            break;
          default:
-           tempbuf[tempbufindex++] = *tokptr++;
+           c = *tokptr++;
+            if (! host_char_to_target (c, &c))
+              {
+                int len = tokptr - char_start_pos;
+                char *copy = alloca (len + 1);
+                memcpy (copy, char_start_pos, len);
+                copy[len] = '\0';
+
+                error ("There is no character corresponding to `%s' "
+                       "in the target character set `%s'.",
+                       copy, target_charset ());
+              }
+            tempbuf[tempbufindex++] = c;
            break;
          }
       } while ((*tokptr != '"') && (*tokptr != '\0'));
@@ -1474,9 +1859,13 @@ yylex ()
       c = tokstart[++namelen];
     }
 
-  /* The token "if" terminates the expression and is NOT 
-     removed from the input stream.  */
-  if (namelen == 2 && tokstart[0] == 'i' && tokstart[1] == 'f')
+  /* The token "if" terminates the expression and is NOT removed from
+     the input stream.  It doesn't count if it appears in the
+     expansion of a macro.  */
+  if (namelen == 2
+      && tokstart[0] == 'i'
+      && tokstart[1] == 'f'
+      && ! scanning_macro_expansion ())
     {
       return 0;
     }
@@ -1485,116 +1874,44 @@ yylex ()
 
   tryname:
 
-  /* Catch specific keywords.  Should be done with a data structure.  */
-  switch (namelen)
-    {
-    case 8:
-      if (STREQN (tokstart, "unsigned", 8))
-       return UNSIGNED;
-      if (current_language->la_language == language_cplus
-         && STREQN (tokstart, "template", 8))
-       return TEMPLATE;
-      if (STREQN (tokstart, "volatile", 8))
-       return VOLATILE_KEYWORD;
-      break;
-    case 6:
-      if (STREQN (tokstart, "struct", 6))
-       return STRUCT;
-      if (STREQN (tokstart, "signed", 6))
-       return SIGNED_KEYWORD;
-      if (STREQN (tokstart, "sizeof", 6))      
-       return SIZEOF;
-      if (STREQN (tokstart, "double", 6))      
-       return DOUBLE_KEYWORD;
-      break;
-    case 5:
-      if (current_language->la_language == language_cplus)
-        {
-          if (STREQN (tokstart, "false", 5))
-            return FALSEKEYWORD;
-          if (STREQN (tokstart, "class", 5))
-            return CLASS;
-        }
-      if (STREQN (tokstart, "union", 5))
-       return UNION;
-      if (STREQN (tokstart, "short", 5))
-       return SHORT;
-      if (STREQN (tokstart, "const", 5))
-       return CONST_KEYWORD;
-      break;
-    case 4:
-      if (STREQN (tokstart, "enum", 4))
-       return ENUM;
-      if (STREQN (tokstart, "long", 4))
-       return LONG;
-      if (current_language->la_language == language_cplus)
-          {
-            if (STREQN (tokstart, "true", 4))
-              return TRUEKEYWORD;
-
-            if (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))
-       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);
       return VARIABLE;
     }
   
-  /* Look ahead and see if we can consume more of the input
-     string to get a reasonable class/namespace spec or a
-     fully-qualified name.  This is a kludge to get around the
-     HP aCC compiler's generation of symbol names with embedded
-     colons for namespace and nested classes. */ 
-  if (unquoted_expr)
-    {
-      /* Only do it if not inside single quotes */ 
-      sym_class = parse_nested_classes_for_hpacc (yylval.sval.ptr, yylval.sval.length,
-                                                  &token_string, &class_prefix, &lexptr);
-      if (sym_class)
-        {
-          /* Replace the current token with the bigger one we found */ 
-          yylval.sval.ptr = token_string;
-          yylval.sval.length = strlen (token_string);
-        }
-    }
-  
   /* Use token-type BLOCKNAME for symbols that happen to be defined as
      functions or symtabs.  If this is not so, then ...
      Use token-type TYPENAME for symbols that happen to be defined
      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,
-                        VAR_NAMESPACE,
-                        current_language->la_language == language_cplus
-                        ? &is_a_field_of_this : (int *) NULL,
-                        (struct symtab **) NULL);
+    sym = lookup_symbol (copy, expression_context_block,
+                        VAR_DOMAIN,
+                        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).  */
@@ -1608,7 +1925,7 @@ yylex ()
       {                                /* See if it's a file name. */
        struct symtab *symtab;
 
-       symtab = lookup_symtab (tmp);
+       symtab = lookup_symtab (copy);
 
        if (symtab)
          {
@@ -1619,95 +1936,16 @@ yylex ()
 
     if (sym && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
         {
-#if 1
-         /* Despite the following flaw, we need to keep this code enabled.
-            Because we can get called from check_stub_method, if we don't
-            handle nested types then it screws many operations in any
-            program which uses nested types.  */
-         /* In "A::x", if x is a member function of A and there happens
-            to be a type (nested or not, since the stabs don't make that
-            distinction) named x, then this code incorrectly thinks we
-            are dealing with nested types rather than a member function.  */
-
-         char *p;
-         char *namestart;
-         struct symbol *best_sym;
-
-         /* Look ahead to detect nested types.  This probably should be
-            done in the grammar, but trying seemed to introduce a lot
-            of shift/reduce and reduce/reduce conflicts.  It's possible
-            that it could be done, though.  Or perhaps a non-grammar, but
-            less ad hoc, approach would work well.  */
-
-         /* Since we do not currently have any way of distinguishing
-            a nested type from a non-nested one (the stabs don't tell
-            us whether a type is nested), we just ignore the
-            containing type.  */
-
-         p = lexptr;
-         best_sym = sym;
-         while (1)
-           {
-             /* Skip whitespace.  */
-             while (*p == ' ' || *p == '\t' || *p == '\n')
-               ++p;
-             if (*p == ':' && p[1] == ':')
-               {
-                 /* Skip the `::'.  */
-                 p += 2;
-                 /* Skip whitespace.  */
-                 while (*p == ' ' || *p == '\t' || *p == '\n')
-                   ++p;
-                 namestart = p;
-                 while (*p == '_' || *p == '$' || (*p >= '0' && *p <= '9')
-                        || (*p >= 'a' && *p <= 'z')
-                        || (*p >= 'A' && *p <= 'Z'))
-                   ++p;
-                 if (p != namestart)
-                   {
-                     struct symbol *cur_sym;
-                     /* As big as the whole rest of the expression, which is
-                        at least big enough.  */
-                     char *ncopy = alloca (strlen (tmp)+strlen (namestart)+3);
-                     char *tmp1;
-
-                     tmp1 = ncopy;
-                     memcpy (tmp1, tmp, strlen (tmp));
-                     tmp1 += strlen (tmp);
-                     memcpy (tmp1, "::", 2);
-                     tmp1 += 2;
-                     memcpy (tmp1, namestart, p - namestart);
-                     tmp1[p - namestart] = '\0';
-                     cur_sym = lookup_symbol (ncopy, expression_context_block,
-                                              VAR_NAMESPACE, (int *) NULL,
-                                              (struct symtab **) NULL);
-                     if (cur_sym)
-                       {
-                         if (SYMBOL_CLASS (cur_sym) == LOC_TYPEDEF)
-                           {
-                             best_sym = cur_sym;
-                             lexptr = p;
-                           }
-                         else
-                           break;
-                       }
-                     else
-                       break;
-                   }
-                 else
-                   break;
-               }
-             else
-               break;
-           }
-
-         yylval.tsym.type = SYMBOL_TYPE (best_sym);
-#else /* not 0 */
+         /* NOTE: carlton/2003-09-25: There used to be code here to
+            handle nested types.  It didn't work very well.  See the
+            comment before qualified_type for more info.  */
          yylval.tsym.type = SYMBOL_TYPE (sym);
-#endif /* not 0 */
          return TYPENAME;
         }
-    if ((yylval.tsym.type = lookup_primitive_typename (tmp)) != 0)
+    yylval.tsym.type
+      = language_lookup_primitive_type_by_name (parse_language,
+                                               parse_gdbarch, copy);
+    if (yylval.tsym.type != NULL)
       return TYPENAME;
 
     /* Input names that aren't symbols but ARE valid hex numbers,
@@ -1730,13 +1968,51 @@ 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;
 {
+  if (prev_lexptr)
+    lexptr = prev_lexptr;
+
   error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr);
 }
This page took 0.071069 seconds and 4 git commands to generate.