/* YACC parser for Ada expressions, for GDB.
- Copyright (C) 1986, 1989, 1990, 1991, 1993, 1994, 1997, 2000, 2003, 2004,
- 2007, 2008 Free Software Foundation, Inc.
+ Copyright (C) 1986-2013 Free Software Foundation, Inc.
-This file is part of GDB.
+ This file is part of GDB.
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA. */
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* Parse an Ada expression from text in a string,
and return the result as a struct expression pointer.
#include "frame.h"
#include "block.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
yacc generated parsers in gdb. These are only the variables
#define yytoks ada_toks /* With YYDEBUG defined */
#define yyname ada_name /* With YYDEBUG defined */
#define yyrule ada_rule /* With YYDEBUG defined */
+#define yyss ada_yyss
+#define yysslim ada_yysslim
+#define yyssp ada_yyssp
+#define yystacksize ada_yystacksize
+#define yyvs ada_yyvs
+#define yyvsp ada_yyvsp
#ifndef YYDEBUG
#define YYDEBUG 1 /* Default to yydebug support */
static void write_int (LONGEST, struct type *);
-static void write_object_renaming (struct block *, const char *, int,
+static void write_object_renaming (const struct block *, const char *, int,
const char *, int);
-static struct type* write_var_or_type (struct block *, struct stoken);
+static struct type* write_var_or_type (const struct block *, struct stoken);
static void write_name_assoc (struct stoken);
static LONGEST convert_char_literal (struct type *, LONGEST);
-static void write_ambiguous_var (struct block *, char *, int);
+static void write_ambiguous_var (const struct block *, char *, int);
static struct type *type_int (void);
static struct type *type_char (void);
+static struct type *type_boolean (void);
+
static struct type *type_system_address (void);
%}
%token <typed_val> INT NULL_PTR CHARLIT
%token <typed_val_float> FLOAT
+%token TRUEKEYWORD FALSEKEYWORD
%token COLONCOLON
%token <sval> STRING NAME DOT_ID
%type <bval> block
{ $$ = $1 + 1; }
;
-simple_exp : '{' var_or_type '}' simple_exp %prec '.'
+primary : '{' var_or_type '}' primary %prec '.'
/* GDB extension */
{
if ($2 == NULL)
type_prefix
| /* EMPTY */
{ write_exp_elt_opcode (OP_TYPE);
- write_exp_elt_type (builtin_type_void);
+ write_exp_elt_type (parse_type->builtin_void);
write_exp_elt_opcode (OP_TYPE); }
;
}
;
+primary : TRUEKEYWORD
+ { write_int (1, type_boolean ()); }
+ | FALSEKEYWORD
+ { write_int (0, type_boolean ()); }
+ ;
+
primary : NEW NAME
{ error (_("NEW not implemented.")); }
;
/* Emit expression to access an instance of SYM, in block BLOCK (if
* non-NULL), and with :: qualification ORIG_LEFT_CONTEXT. */
static void
-write_var_from_sym (struct block *orig_left_context,
- struct block *block,
+write_var_from_sym (const struct block *orig_left_context,
+ const struct block *block,
struct symbol *sym)
{
if (orig_left_context == NULL && symbol_read_needs_frame (sym))
write_exp_elt_opcode (OP_VAR_VALUE);
}
-/* Write integer constant ARG of type TYPE. */
+/* Write integer or boolean constant ARG of type TYPE. */
static void
write_int (LONGEST arg, struct type *type)
* new encoding entirely (FIXME pnh 7/20/2007). */
static void
-write_object_renaming (struct block *orig_left_context,
+write_object_renaming (const struct block *orig_left_context,
const char *renamed_entity, int renamed_entity_len,
const char *renaming_expr, int max_depth)
{
char *name;
enum { SIMPLE_INDEX, LOWER_BOUND, UPPER_BOUND } slice_state;
- struct symbol *sym;
- struct block *block;
+ struct ada_symbol_info sym_info;
if (max_depth <= 0)
error (_("Could not find renamed symbol"));
if (orig_left_context == NULL)
orig_left_context = get_selected_block (NULL);
- name = obsavestring (renamed_entity, renamed_entity_len, &temp_parse_space);
- sym = ada_lookup_encoded_symbol (name, orig_left_context, VAR_DOMAIN,
- &block, NULL);
- if (sym == NULL)
+ name = obstack_copy0 (&temp_parse_space, renamed_entity, renamed_entity_len);
+ ada_lookup_encoded_symbol (name, orig_left_context, VAR_DOMAIN, &sym_info);
+ if (sym_info.sym == NULL)
error (_("Could not find renamed variable: %s"), ada_decode (name));
- else if (SYMBOL_CLASS (sym) == LOC_TYPEDEF)
+ else if (SYMBOL_CLASS (sym_info.sym) == LOC_TYPEDEF)
/* We have a renaming of an old-style renaming symbol. Don't
trust the block information. */
- block = orig_left_context;
+ sym_info.block = orig_left_context;
{
const char *inner_renamed_entity;
int inner_renamed_entity_len;
const char *inner_renaming_expr;
- switch (ada_parse_renaming (sym, &inner_renamed_entity,
+ switch (ada_parse_renaming (sym_info.sym, &inner_renamed_entity,
&inner_renamed_entity_len,
&inner_renaming_expr))
{
case ADA_NOT_RENAMING:
- write_var_from_sym (orig_left_context, block, sym);
+ write_var_from_sym (orig_left_context, sym_info.block, sym_info.sym);
break;
case ADA_OBJECT_RENAMING:
- write_object_renaming (block,
+ write_object_renaming (sym_info.block,
inner_renamed_entity, inner_renamed_entity_len,
inner_renaming_expr, max_depth - 1);
break;
break;
case 'L':
slice_state = LOWER_BOUND;
+ /* FALLTHROUGH */
case 'S':
renaming_expr += 1;
if (isdigit (*renaming_expr))
{
const char *end;
char *index_name;
- struct symbol *index_sym;
+ struct ada_symbol_info index_sym_info;
end = strchr (renaming_expr, 'X');
if (end == NULL)
end = renaming_expr + strlen (renaming_expr);
index_name =
- obsavestring (renaming_expr, end - renaming_expr,
- &temp_parse_space);
+ obstack_copy0 (&temp_parse_space, renaming_expr,
+ end - renaming_expr);
renaming_expr = end;
- index_sym = ada_lookup_encoded_symbol (index_name, NULL,
- VAR_DOMAIN, &block,
- NULL);
- if (index_sym == NULL)
+ ada_lookup_encoded_symbol (index_name, NULL, VAR_DOMAIN,
+ &index_sym_info);
+ if (index_sym_info.sym == NULL)
error (_("Could not find %s"), index_name);
- else if (SYMBOL_CLASS (index_sym) == LOC_TYPEDEF)
+ else if (SYMBOL_CLASS (index_sym_info.sym) == LOC_TYPEDEF)
/* Index is an old-style renaming symbol. */
- block = orig_left_context;
- write_var_from_sym (NULL, block, index_sym);
+ index_sym_info.block = orig_left_context;
+ write_var_from_sym (NULL, index_sym_info.block,
+ index_sym_info.sym);
}
if (slice_state == SIMPLE_INDEX)
{
if (end == NULL)
end = renaming_expr + strlen (renaming_expr);
field_name.length = end - renaming_expr;
- field_name.ptr = xmalloc (end - renaming_expr + 1);
+ field_name.ptr = malloc (end - renaming_expr + 1);
strncpy (field_name.ptr, renaming_expr, end - renaming_expr);
field_name.ptr[end - renaming_expr] = '\000';
renaming_expr = end;
name = ada_encode (raw_name);
nsyms = ada_lookup_symbol_list (name, context, VAR_DOMAIN, &syms);
- if (context == NULL &&
- (nsyms == 0 || SYMBOL_CLASS (syms[0].sym) != LOC_BLOCK))
+ if (context == NULL
+ && (nsyms == 0 || SYMBOL_CLASS (syms[0].sym) != LOC_BLOCK))
symtab = lookup_symtab (name);
else
symtab = NULL;
case LOC_REGISTER:
case LOC_ARG:
case LOC_REF_ARG:
- case LOC_REGPARM:
case LOC_REGPARM_ADDR:
case LOC_LOCAL:
- case LOC_LOCAL_ARG:
- case LOC_BASEREG:
- case LOC_BASEREG_ARG:
case LOC_COMPUTED:
- case LOC_COMPUTED_ARG:
return NULL;
default:
break;
find_primitive_type (char *name)
{
struct type *type;
- type = language_lookup_primitive_type_by_name (current_language,
- current_gdbarch,
+ type = language_lookup_primitive_type_by_name (parse_language,
+ parse_gdbarch,
name);
if (type == NULL && strcmp ("system__address", name) == 0)
type = type_system_address ();
{
/* Check to see if we have a regular definition of this
type that just didn't happen to have been read yet. */
- int ntypes;
struct symbol *sym;
char *expanded_name =
(char *) alloca (strlen (name) + sizeof ("standard__"));
strcpy (expanded_name, "standard__");
strcat (expanded_name, name);
- sym = ada_lookup_symbol (expanded_name, NULL, VAR_DOMAIN, NULL, NULL);
+ sym = ada_lookup_symbol (expanded_name, NULL, VAR_DOMAIN, NULL);
if (sym != NULL && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
type = SYMBOL_TYPE (sym);
}
return -1;
}
+/* If NAME is a string beginning with a separator (either '__', or
+ '.'), chop this separator and return the result; else, return
+ NAME. */
+
+static char *
+chop_separator (char *name)
+{
+ if (*name == '.')
+ return name + 1;
+
+ if (name[0] == '_' && name[1] == '_')
+ return name + 2;
+
+ return name;
+}
+
/* Given that SELS is a string of the form (<sep><identifier>)*, where
<sep> is '__' or '.', write the indicated sequence of
STRUCTOP_STRUCT expression operators. */
while (*sels != '\0')
{
struct stoken field_name;
- char *p;
- while (*sels == '_' || *sels == '.')
- sels += 1;
- p = sels;
+ char *p = chop_separator (sels);
+ sels = p;
while (*sels != '\0' && *sels != '.'
&& (sels[0] != '_' || sels[1] != '_'))
sels += 1;
a temporary symbol that is valid until the next call to ada_parse.
*/
static void
-write_ambiguous_var (struct block *block, char *name, int len)
+write_ambiguous_var (const struct block *block, char *name, int len)
{
struct symbol *sym =
obstack_alloc (&temp_parse_space, sizeof (struct symbol));
memset (sym, 0, sizeof (struct symbol));
SYMBOL_DOMAIN (sym) = UNDEF_DOMAIN;
- SYMBOL_LINKAGE_NAME (sym) = obsavestring (name, len, &temp_parse_space);
+ SYMBOL_LINKAGE_NAME (sym) = obstack_copy0 (&temp_parse_space, name, len);
SYMBOL_LANGUAGE (sym) = language_ada;
write_exp_elt_opcode (OP_VAR_VALUE);
write_exp_elt_opcode (OP_VAR_VALUE);
}
+/* A convenient wrapper around ada_get_field_index that takes
+ a non NUL-terminated FIELD_NAME0 and a FIELD_NAME_LEN instead
+ of a NUL-terminated field name. */
+
+static int
+ada_nget_field_index (const struct type *type, const char *field_name0,
+ int field_name_len, int maybe_missing)
+{
+ char *field_name = alloca ((field_name_len + 1) * sizeof (char));
+
+ strncpy (field_name, field_name0, field_name_len);
+ field_name[field_name_len] = '\0';
+ return ada_get_field_index (type, field_name, maybe_missing);
+}
+
+/* If encoded_field_name is the name of a field inside symbol SYM,
+ then return the type of that field. Otherwise, return NULL.
+
+ This function is actually recursive, so if ENCODED_FIELD_NAME
+ doesn't match one of the fields of our symbol, then try to see
+ if ENCODED_FIELD_NAME could not be a succession of field names
+ (in other words, the user entered an expression of the form
+ TYPE_NAME.FIELD1.FIELD2.FIELD3), in which case we evaluate
+ each field name sequentially to obtain the desired field type.
+ In case of failure, we return NULL. */
+
+static struct type *
+get_symbol_field_type (struct symbol *sym, char *encoded_field_name)
+{
+ char *field_name = encoded_field_name;
+ char *subfield_name;
+ struct type *type = SYMBOL_TYPE (sym);
+ int fieldno;
+
+ if (type == NULL || field_name == NULL)
+ return NULL;
+ type = check_typedef (type);
+
+ while (field_name[0] != '\0')
+ {
+ field_name = chop_separator (field_name);
+
+ fieldno = ada_get_field_index (type, field_name, 1);
+ if (fieldno >= 0)
+ return TYPE_FIELD_TYPE (type, fieldno);
+
+ subfield_name = field_name;
+ while (*subfield_name != '\0' && *subfield_name != '.'
+ && (subfield_name[0] != '_' || subfield_name[1] != '_'))
+ subfield_name += 1;
+
+ if (subfield_name[0] == '\0')
+ return NULL;
+
+ fieldno = ada_nget_field_index (type, field_name,
+ subfield_name - field_name, 1);
+ if (fieldno < 0)
+ return NULL;
+
+ type = TYPE_FIELD_TYPE (type, fieldno);
+ field_name = subfield_name;
+ }
+
+ return NULL;
+}
/* Look up NAME0 (an unencoded identifier or dotted name) in BLOCK (or
expression_block_context if NULL). If it denotes a type, return
identifier). */
static struct type*
-write_var_or_type (struct block *block, struct stoken name0)
+write_var_or_type (const struct block *block, struct stoken name0)
{
int depth;
char *encoded_name;
encoded_name = ada_encode (name0.ptr);
name_len = strlen (encoded_name);
- encoded_name = obsavestring (encoded_name, name_len, &temp_parse_space);
+ encoded_name = obstack_copy0 (&temp_parse_space, encoded_name, name_len);
for (depth = 0; depth < MAX_RENAMING_CHAIN_LENGTH; depth += 1)
{
int tail_index;
FIXME pnh 7/20/2007. */
if (nsyms == 1)
{
- struct symbol *renaming =
- ada_find_renaming_symbol (SYMBOL_LINKAGE_NAME (syms[0].sym),
- syms[0].block);
+ struct symbol *ren_sym =
+ ada_find_renaming_symbol (syms[0].sym, syms[0].block);
- if (renaming != NULL)
- syms[0].sym = renaming;
+ if (ren_sym != NULL)
+ syms[0].sym = ren_sym;
}
type_sym = select_possible_type_sym (syms, nsyms);
if (type_sym != NULL)
{
- struct type *type = SYMBOL_TYPE (type_sym);
-
- if (TYPE_CODE (type) == TYPE_CODE_VOID)
- error (_("`%s' matches only void type name(s)"), name0.ptr);
- else if (tail_index == name_len)
- return type;
+ struct type *field_type;
+
+ if (tail_index == name_len)
+ return SYMBOL_TYPE (type_sym);
+
+ /* We have some extraneous characters after the type name.
+ If this is an expression "TYPE_NAME.FIELD0.[...].FIELDN",
+ then try to get the type of FIELDN. */
+ field_type
+ = get_symbol_field_type (type_sym, encoded_name + tail_index);
+ if (field_type != NULL)
+ return field_type;
else
- error (_("Invalid attempt to select from type: \"%s\"."), name0.ptr);
+ error (_("Invalid attempt to select from type: \"%s\"."),
+ name0.ptr);
}
else if (tail_index == name_len && nsyms == 0)
{
}
else if (nsyms == 0)
{
- int i;
struct minimal_symbol *msym
= ada_lookup_simple_minsym (encoded_name);
if (msym != NULL)
{
- write_exp_msymbol (msym, lookup_function_type (type_int ()),
- type_int ());
+ write_exp_msymbol (msym);
/* Maybe cause error here rather than later? FIXME? */
write_selectors (encoded_name + tail_index);
return NULL;
char name[7];
int f;
- if (type == NULL || TYPE_CODE (type) != TYPE_CODE_ENUM)
+ if (type == NULL)
+ return val;
+ type = check_typedef (type);
+ if (TYPE_CODE (type) != TYPE_CODE_ENUM)
return val;
- sprintf (name, "QU%02x", (int) val);
+
+ xsnprintf (name, sizeof (name), "QU%02x", (int) val);
for (f = 0; f < TYPE_NFIELDS (type); f += 1)
{
if (strcmp (name, TYPE_FIELD_NAME (type, f)) == 0)
- return TYPE_FIELD_BITPOS (type, f);
+ return TYPE_FIELD_ENUMVAL (type, f);
}
return val;
}
static struct type *
type_int (void)
{
- return builtin_type (current_gdbarch)->builtin_int;
+ return parse_type->builtin_int;
}
static struct type *
type_long (void)
{
- return builtin_type (current_gdbarch)->builtin_long;
+ return parse_type->builtin_long;
}
static struct type *
type_long_long (void)
{
- return builtin_type (current_gdbarch)->builtin_long_long;
+ return parse_type->builtin_long_long;
}
static struct type *
type_float (void)
{
- return builtin_type (current_gdbarch)->builtin_float;
+ return parse_type->builtin_float;
}
static struct type *
type_double (void)
{
- return builtin_type (current_gdbarch)->builtin_double;
+ return parse_type->builtin_double;
}
static struct type *
type_long_double (void)
{
- return builtin_type (current_gdbarch)->builtin_long_double;
+ return parse_type->builtin_long_double;
}
static struct type *
type_char (void)
{
- return language_string_char_type (current_language, current_gdbarch);
+ return language_string_char_type (parse_language, parse_gdbarch);
+}
+
+static struct type *
+type_boolean (void)
+{
+ return parse_type->builtin_bool;
}
static struct type *
type_system_address (void)
{
struct type *type
- = language_lookup_primitive_type_by_name (current_language,
- current_gdbarch,
+ = language_lookup_primitive_type_by_name (parse_language,
+ parse_gdbarch,
"system__address");
- return type != NULL ? type : lookup_pointer_type (builtin_type_void);
+ return type != NULL ? type : parse_type->builtin_data_ptr;
}
+/* Provide a prototype to silence -Wmissing-prototypes. */
+extern initialize_file_ftype _initialize_ada_exp;
+
void
_initialize_ada_exp (void)
{