X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fc-exp.y;h=d4bbbccd362b7aae41864a483e26d4ba62d96e91;hb=d24948ac99c35f17a60e856cb0125ff91b80045b;hp=706b4074d88cb77179966b8dc3342c3d53c5ee01;hpb=f83f82bc153ade6a787dd5084f125a4cd7a6a2de;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/c-exp.y b/gdb/c-exp.y index 706b4074d8..d4bbbccd36 100644 --- a/gdb/c-exp.y +++ b/gdb/c-exp.y @@ -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, 2003, 2004 + 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. @@ -52,6 +53,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "charset.h" #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 @@ -61,7 +67,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 @@ -130,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; @@ -162,6 +172,7 @@ static int parse_number (char *, int, int, YYSTYPE *); %token INT %token FLOAT +%token DECFLOAT /* Both NAME and TYPENAME tokens represent symbols in the input, and both convey their data as strings. @@ -173,8 +184,9 @@ static int parse_number (char *, int, int, YYSTYPE *); %token STRING %token NAME /* BLOCKNAME defined below to give it higher precedence. */ +%token COMPLETE %token TYPENAME -%type name +%type name string_exp %type name_not_typename %type typename @@ -256,6 +268,10 @@ 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); } ; @@ -290,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 @@ -308,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 @@ -492,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 ; @@ -501,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. @@ -517,31 +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 : 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_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)); @@ -576,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)); @@ -637,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); @@ -650,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); } ; @@ -706,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_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 @@ -785,7 +859,7 @@ func_mod: '(' ')' { 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) @@ -794,69 +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 - { $$ = builtin_type_long; } + { $$ = parse_type->builtin_long; } | LONG SIGNED_KEYWORD - { $$ = builtin_type_long; } + { $$ = parse_type->builtin_long; } | SIGNED_KEYWORD LONG INT_KEYWORD - { $$ = builtin_type_long; } + { $$ = parse_type->builtin_long; } | UNSIGNED LONG INT_KEYWORD - { $$ = builtin_type_unsigned_long; } + { $$ = parse_type->builtin_unsigned_long; } | LONG UNSIGNED INT_KEYWORD - { $$ = builtin_type_unsigned_long; } + { $$ = parse_type->builtin_unsigned_long; } | LONG UNSIGNED - { $$ = builtin_type_unsigned_long; } + { $$ = parse_type->builtin_unsigned_long; } | LONG LONG - { $$ = builtin_type_long_long; } + { $$ = parse_type->builtin_long_long; } | LONG LONG INT_KEYWORD - { $$ = builtin_type_long_long; } + { $$ = parse_type->builtin_long_long; } | LONG LONG SIGNED_KEYWORD INT_KEYWORD - { $$ = builtin_type_long_long; } + { $$ = parse_type->builtin_long_long; } | LONG LONG SIGNED_KEYWORD - { $$ = builtin_type_long_long; } + { $$ = parse_type->builtin_long_long; } | SIGNED_KEYWORD LONG LONG - { $$ = builtin_type_long_long; } + { $$ = parse_type->builtin_long_long; } | SIGNED_KEYWORD LONG LONG INT_KEYWORD - { $$ = builtin_type_long_long; } + { $$ = parse_type->builtin_long_long; } | UNSIGNED LONG LONG - { $$ = builtin_type_unsigned_long_long; } + { $$ = parse_type->builtin_unsigned_long_long; } | UNSIGNED LONG LONG INT_KEYWORD - { $$ = builtin_type_unsigned_long_long; } + { $$ = parse_type->builtin_unsigned_long_long; } | LONG LONG UNSIGNED - { $$ = builtin_type_unsigned_long_long; } + { $$ = parse_type->builtin_unsigned_long_long; } | LONG LONG UNSIGNED INT_KEYWORD - { $$ = builtin_type_unsigned_long_long; } + { $$ = parse_type->builtin_unsigned_long_long; } | SHORT INT_KEYWORD - { $$ = builtin_type_short; } + { $$ = parse_type->builtin_short; } | SHORT SIGNED_KEYWORD INT_KEYWORD - { $$ = builtin_type_short; } + { $$ = parse_type->builtin_short; } | SHORT SIGNED_KEYWORD - { $$ = builtin_type_short; } + { $$ = parse_type->builtin_short; } | UNSIGNED SHORT INT_KEYWORD - { $$ = builtin_type_unsigned_short; } + { $$ = parse_type->builtin_unsigned_short; } | SHORT UNSIGNED - { $$ = builtin_type_unsigned_short; } + { $$ = parse_type->builtin_unsigned_short; } | SHORT UNSIGNED INT_KEYWORD - { $$ = builtin_type_unsigned_short; } + { $$ = 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); } @@ -872,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. */ @@ -966,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; } ; @@ -1070,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; } @@ -1203,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, @@ -1220,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; @@ -1265,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 @@ -1310,26 +1534,27 @@ 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: /* 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); } prev_lexptr = lexptr; - unquoted_expr = 1; tokstart = lexptr; /* See if it is a special token of length 3. */ @@ -1347,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; } @@ -1355,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 ()) @@ -1362,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; @@ -1392,7 +1628,7 @@ yylex () } 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 != '\'') @@ -1401,7 +1637,6 @@ yylex () if (namelen > 2) { lexptr = tokstart + namelen; - unquoted_expr = 0; if (lexptr[-1] != '\'') error ("Unmatched single quote."); namelen -= 2; @@ -1435,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': @@ -1635,111 +1874,44 @@ 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); 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. */ - - /* NOTE: carlton/2003-09-24: I don't entirely understand the - HP-specific code, either here or in linespec. Having said that, - I suspect that we're actually moving towards their model: we want - symbols whose names are fully qualified, which matches the - description above. */ - 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, + 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). */ @@ -1753,7 +1925,7 @@ yylex () { /* See if it's a file name. */ struct symtab *symtab; - symtab = lookup_symtab (tmp); + symtab = lookup_symtab (copy); if (symtab) { @@ -1770,7 +1942,10 @@ yylex () yylval.tsym.type = SYMBOL_TYPE (sym); 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, @@ -1793,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;