/* 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
+ Free Software Foundation, Inc.
This file is part of GDB.
#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
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
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;
%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.
%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
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
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
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
;
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.
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); }
;
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));
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));
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);
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);
}
;
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
: 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); }
| 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. */
{
$$.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;
}
;
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];
+ 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 (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'f')
+ {
+ 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",
+ 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 )
{
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);
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,
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;
{">=", GEQ, BINOP_END}
};
+/* 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
static int tempbufsize;
char * token_string = NULL;
int class_prefix = 0;
-
+ int saw_structop = last_was_structop;
+
+ 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);
{
lexptr += 2;
yylval.opcode = tokentab2[i].opcode;
+ if (in_parse_field && tokentab2[i].token == ARROW)
+ last_was_structop = 1;
return tokentab2[i].token;
}
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 ())
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;
}
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 != '\'')
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':
case 8:
if (strncmp (tokstart, "unsigned", 8) == 0)
return UNSIGNED;
- if (current_language->la_language == language_cplus
+ if (parse_language->la_language == language_cplus
&& strncmp (tokstart, "template", 8) == 0)
return TEMPLATE;
if (strncmp (tokstart, "volatile", 8) == 0)
return DOUBLE_KEYWORD;
break;
case 5:
- if (current_language->la_language == language_cplus)
+ if (parse_language->la_language == language_cplus)
{
if (strncmp (tokstart, "false", 5) == 0)
return FALSEKEYWORD;
return ENUM;
if (strncmp (tokstart, "long", 4) == 0)
return LONG;
- if (current_language->la_language == language_cplus)
+ if (parse_language->la_language == language_cplus)
{
if (strncmp (tokstart, "true", 4) == 0)
return TRUEKEYWORD;
sym = lookup_symbol (tmp, 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). */
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, tmp);
if (yylval.tsym.type != NULL)
return TYPENAME;
/* 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;