summaryrefslogtreecommitdiff
path: root/gdb/ada-exp.y
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/ada-exp.y')
-rw-r--r--gdb/ada-exp.y223
1 files changed, 186 insertions, 37 deletions
diff --git a/gdb/ada-exp.y b/gdb/ada-exp.y
index 16ba336df4a..8660205809a 100644
--- a/gdb/ada-exp.y
+++ b/gdb/ada-exp.y
@@ -68,6 +68,9 @@ struct name_info {
static struct parser_state *pstate = NULL;
+/* The original expression string. */
+static const char *original_expr;
+
int yyparse (void);
static int yylex (void);
@@ -82,6 +85,9 @@ static void write_object_renaming (struct parser_state *,
static struct type* write_var_or_type (struct parser_state *,
const struct block *, struct stoken);
+static struct type *write_var_or_type_completion (struct parser_state *,
+ const struct block *,
+ struct stoken);
static void write_name_assoc (struct parser_state *, struct stoken);
@@ -98,12 +104,14 @@ static struct type *type_long_long (struct parser_state *);
static struct type *type_long_double (struct parser_state *);
-static struct type *type_char (struct parser_state *);
+static struct type *type_for_char (struct parser_state *, ULONGEST);
static struct type *type_boolean (struct parser_state *);
static struct type *type_system_address (struct parser_state *);
+static std::string find_completion_bounds (struct parser_state *);
+
using namespace expr;
/* Handle Ada type resolution for OP. DEPROCEDURE_P and CONTEXT_TYPE
@@ -290,7 +298,7 @@ ada_funcall (int nargs)
int array_arity = 0;
struct type *callee_t = nullptr;
if (vvo == nullptr
- || SYMBOL_DOMAIN (vvo->get_symbol ()) != UNDEF_DOMAIN)
+ || vvo->get_symbol ()->domain () != UNDEF_DOMAIN)
{
struct value *callee_v = callee->evaluate (nullptr,
pstate->expout.get (),
@@ -393,6 +401,30 @@ pop_associations (int n)
return result;
}
+/* Expression completer for attributes. */
+struct ada_tick_completer : public expr_completion_base
+{
+ explicit ada_tick_completer (std::string &&name)
+ : m_name (std::move (name))
+ {
+ }
+
+ bool complete (struct expression *exp,
+ completion_tracker &tracker) override;
+
+private:
+
+ std::string m_name;
+};
+
+/* Make a new ada_tick_completer and wrap it in a unique pointer. */
+static std::unique_ptr<expr_completion_base>
+make_tick_completer (struct stoken tok)
+{
+ return (std::unique_ptr<expr_completion_base>
+ (new ada_tick_completer (std::string (tok.ptr, tok.length))));
+}
+
%}
%union
@@ -420,12 +452,10 @@ pop_associations (int n)
%token <typed_val_float> FLOAT
%token TRUEKEYWORD FALSEKEYWORD
%token COLONCOLON
-%token <sval> STRING NAME DOT_ID
+%token <sval> STRING NAME DOT_ID TICK_COMPLETE DOT_COMPLETE NAME_COMPLETE
%type <bval> block
%type <lval> arglist tick_arglist
-%token DOT_ALL
-
/* Special type cases, put in to allow the parser to distinguish different
legal basetypes. */
%token <sval> DOLLAR_VARIABLE
@@ -449,10 +479,11 @@ pop_associations (int n)
%right TICK_ACCESS TICK_ADDRESS TICK_FIRST TICK_LAST TICK_LENGTH
%right TICK_MAX TICK_MIN TICK_MODULUS
%right TICK_POS TICK_RANGE TICK_SIZE TICK_TAG TICK_VAL
+%right TICK_COMPLETE
/* The following are right-associative only so that reductions at this
precedence have lower precedence than '.' and '('. The syntax still
forces a.b.c, e.g., to be LEFT-associated. */
-%right '.' '(' '[' DOT_ID DOT_ALL
+%right '.' '(' '[' DOT_ID DOT_COMPLETE
%token NEW OTHERS
@@ -481,15 +512,31 @@ exp1 : exp
;
/* Expressions, not including the sequencing operator. */
-primary : primary DOT_ALL
- { ada_wrap<ada_unop_ind_operation> (); }
- ;
primary : primary DOT_ID
{
+ if (strcmp ($2.ptr, "all") == 0)
+ ada_wrap<ada_unop_ind_operation> ();
+ else
+ {
+ operation_up arg = ada_pop ();
+ pstate->push_new<ada_structop_operation>
+ (std::move (arg), copy_name ($2));
+ }
+ }
+ ;
+
+primary : primary DOT_COMPLETE
+ {
+ /* This is done even for ".all", because
+ that might be a prefix. */
operation_up arg = ada_pop ();
- pstate->push_new<ada_structop_operation>
- (std::move (arg), copy_name ($2));
+ ada_structop_operation *str_op
+ = (new ada_structop_operation
+ (std::move (arg), copy_name ($2)));
+ str_op->set_prefix (find_completion_bounds (pstate));
+ pstate->push (operation_up (str_op));
+ pstate->mark_struct_expression (str_op);
}
;
@@ -649,7 +696,7 @@ simple_exp : simple_exp '+' simple_exp
;
simple_exp : simple_exp '&' simple_exp
- { ada_wrap2<concat_operation> (BINOP_CONCAT); }
+ { ada_wrap2<ada_concat_operation> (BINOP_CONCAT); }
;
simple_exp : simple_exp '-' simple_exp
@@ -784,6 +831,10 @@ primary : primary TICK_ACCESS
{ ada_addrof (); }
| primary TICK_ADDRESS
{ ada_addrof (type_system_address (pstate)); }
+ | primary TICK_COMPLETE
+ {
+ pstate->mark_completion (make_tick_completer ($2));
+ }
| primary TICK_FIRST tick_arglist
{
operation_up arg = ada_pop ();
@@ -899,8 +950,20 @@ primary : NEW NAME
var_or_type: NAME %prec VAR
{ $$ = write_var_or_type (pstate, NULL, $1); }
+ | NAME_COMPLETE %prec VAR
+ {
+ $$ = write_var_or_type_completion (pstate,
+ NULL,
+ $1);
+ }
| block NAME %prec VAR
{ $$ = write_var_or_type (pstate, $1, $2); }
+ | block NAME_COMPLETE %prec VAR
+ {
+ $$ = write_var_or_type_completion (pstate,
+ $1,
+ $2);
+ }
| NAME TICK_ACCESS
{
$$ = write_var_or_type (pstate, NULL, $1);
@@ -1080,6 +1143,10 @@ ada_parse (struct parser_state *par_state)
scoped_restore pstate_restore = make_scoped_restore (&pstate);
gdb_assert (par_state != NULL);
pstate = par_state;
+ original_expr = par_state->lexptr;
+
+ scoped_restore restore_yydebug = make_scoped_restore (&yydebug,
+ parser_debug);
lexer_init (yyin); /* (Re-)initialize lexer. */
obstack_free (&temp_parse_space, NULL);
@@ -1157,7 +1224,7 @@ write_object_renaming (struct parser_state *par_state,
ada_lookup_encoded_symbol (name, orig_left_context, VAR_DOMAIN, &sym_info);
if (sym_info.symbol == NULL)
error (_("Could not find renamed variable: %s"), ada_decode (name).c_str ());
- else if (SYMBOL_CLASS (sym_info.symbol) == LOC_TYPEDEF)
+ else if (sym_info.symbol->aclass () == LOC_TYPEDEF)
/* We have a renaming of an old-style renaming symbol. Don't
trust the block information. */
sym_info.block = orig_left_context;
@@ -1226,7 +1293,7 @@ write_object_renaming (struct parser_state *par_state,
VAR_DOMAIN, &index_sym_info);
if (index_sym_info.symbol == NULL)
error (_("Could not find %s"), index_name);
- else if (SYMBOL_CLASS (index_sym_info.symbol) == LOC_TYPEDEF)
+ else if (index_sym_info.symbol->aclass () == LOC_TYPEDEF)
/* Index is an old-style renaming symbol. */
index_sym_info.block = orig_left_context;
write_var_from_sym (par_state, index_sym_info);
@@ -1296,14 +1363,14 @@ block_lookup (const struct block *context, const char *raw_name)
= ada_lookup_symbol_list (name, context, VAR_DOMAIN);
if (context == NULL
- && (syms.empty () || SYMBOL_CLASS (syms[0].symbol) != LOC_BLOCK))
+ && (syms.empty () || syms[0].symbol->aclass () != LOC_BLOCK))
symtab = lookup_symtab (name);
else
symtab = NULL;
if (symtab != NULL)
- result = BLOCKVECTOR_BLOCK (SYMTAB_BLOCKVECTOR (symtab), STATIC_BLOCK);
- else if (syms.empty () || SYMBOL_CLASS (syms[0].symbol) != LOC_BLOCK)
+ result = symtab->compunit ()->blockvector ()->static_block ();
+ else if (syms.empty () || syms[0].symbol->aclass () != LOC_BLOCK)
{
if (context == NULL)
error (_("No file or function \"%s\"."), raw_name);
@@ -1314,7 +1381,7 @@ block_lookup (const struct block *context, const char *raw_name)
{
if (syms.size () > 1)
warning (_("Function name \"%s\" ambiguous here"), raw_name);
- result = SYMBOL_BLOCK_VALUE (syms[0].symbol);
+ result = syms[0].symbol->value_block ();
}
return result;
@@ -1329,13 +1396,13 @@ select_possible_type_sym (const std::vector<struct block_symbol> &syms)
preferred_index = -1; preferred_type = NULL;
for (i = 0; i < syms.size (); i += 1)
- switch (SYMBOL_CLASS (syms[i].symbol))
+ switch (syms[i].symbol->aclass ())
{
case LOC_TYPEDEF:
- if (ada_prefer_type (SYMBOL_TYPE (syms[i].symbol), preferred_type))
+ if (ada_prefer_type (syms[i].symbol->type (), preferred_type))
{
preferred_index = i;
- preferred_type = SYMBOL_TYPE (syms[i].symbol);
+ preferred_type = syms[i].symbol->type ();
}
break;
case LOC_REGISTER:
@@ -1373,8 +1440,8 @@ find_primitive_type (struct parser_state *par_state, const char *name)
strcpy (expanded_name, "standard__");
strcat (expanded_name, name);
sym = ada_lookup_symbol (expanded_name, NULL, VAR_DOMAIN).symbol;
- if (sym != NULL && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
- type = SYMBOL_TYPE (sym);
+ if (sym != NULL && sym->aclass () == LOC_TYPEDEF)
+ type = sym->type ();
}
return type;
@@ -1408,10 +1475,12 @@ chop_separator (const char *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. */
-static void
+ STRUCTOP_STRUCT expression operators. Returns a pointer to the
+ last operation that was pushed. */
+static ada_structop_operation *
write_selectors (struct parser_state *par_state, const char *sels)
{
+ ada_structop_operation *result = nullptr;
while (*sels != '\0')
{
const char *p = chop_separator (sels);
@@ -1420,9 +1489,11 @@ write_selectors (struct parser_state *par_state, const char *sels)
&& (sels[0] != '_' || sels[1] != '_'))
sels += 1;
operation_up arg = ada_pop ();
- pstate->push_new<ada_structop_operation>
- (std::move (arg), std::string (p, sels - p));
+ result = new ada_structop_operation (std::move (arg),
+ std::string (p, sels - p));
+ pstate->push (operation_up (result));
}
+ return result;
}
/* Write a variable access (OP_VAR_VALUE) to ambiguous encoded name
@@ -1435,7 +1506,7 @@ write_ambiguous_var (struct parser_state *par_state,
{
struct symbol *sym = new (&temp_parse_space) symbol ();
- SYMBOL_DOMAIN (sym) = UNDEF_DOMAIN;
+ sym->set_domain (UNDEF_DOMAIN);
sym->set_linkage_name (obstack_strndup (&temp_parse_space, name, len));
sym->set_language (language_ada, nullptr);
@@ -1474,7 +1545,7 @@ get_symbol_field_type (struct symbol *sym, const char *encoded_field_name)
{
const char *field_name = encoded_field_name;
const char *subfield_name;
- struct type *type = SYMBOL_TYPE (sym);
+ struct type *type = sym->type ();
int fieldno;
if (type == NULL || field_name == NULL)
@@ -1549,10 +1620,14 @@ write_var_or_type (struct parser_state *par_state,
int terminator = encoded_name[tail_index];
encoded_name[tail_index] = '\0';
- std::vector<struct block_symbol> syms
- = ada_lookup_symbol_list (encoded_name, block, VAR_DOMAIN);
+ /* In order to avoid double-encoding, we want to only pass
+ the decoded form to lookup functions. */
+ std::string decoded_name = ada_decode (encoded_name);
encoded_name[tail_index] = terminator;
+ std::vector<struct block_symbol> syms
+ = ada_lookup_symbol_list (decoded_name.c_str (), block, VAR_DOMAIN);
+
type_sym = select_possible_type_sym (syms);
if (type_sym != NULL)
@@ -1595,7 +1670,7 @@ write_var_or_type (struct parser_state *par_state,
struct type *field_type;
if (tail_index == name_len)
- return SYMBOL_TYPE (type_sym);
+ return type_sym->type ();
/* We have some extraneous characters after the type name.
If this is an expression "TYPE_NAME.FIELD0.[...].FIELDN",
@@ -1626,7 +1701,7 @@ write_var_or_type (struct parser_state *par_state,
else if (syms.empty ())
{
struct bound_minimal_symbol msym
- = ada_lookup_simple_minsym (encoded_name);
+ = ada_lookup_simple_minsym (decoded_name.c_str ());
if (msym.minsym != NULL)
{
par_state->push_new<ada_var_msym_value_operation> (msym);
@@ -1665,6 +1740,72 @@ write_var_or_type (struct parser_state *par_state,
}
+/* Because ada_completer_word_break_characters does not contain '.' --
+ and it cannot easily be added, this breaks other completions -- we
+ have to recreate the completion word-splitting here, so that we can
+ provide a prefix that is then used when completing field names.
+ Without this, an attempt like "complete print abc.d" will give a
+ result like "print def" rather than "print abc.def". */
+
+static std::string
+find_completion_bounds (struct parser_state *par_state)
+{
+ const char *end = pstate->lexptr;
+ /* First the end of the prefix. Here we stop at the token start or
+ at '.' or space. */
+ for (; end > original_expr && end[-1] != '.' && !isspace (end[-1]); --end)
+ {
+ /* Nothing. */
+ }
+ /* Now find the start of the prefix. */
+ const char *ptr = end;
+ /* Here we allow '.'. */
+ for (;
+ ptr > original_expr && (ptr[-1] == '.'
+ || ptr[-1] == '_'
+ || (ptr[-1] >= 'a' && ptr[-1] <= 'z')
+ || (ptr[-1] >= 'A' && ptr[-1] <= 'Z')
+ || (ptr[-1] & 0xff) >= 0x80);
+ --ptr)
+ {
+ /* Nothing. */
+ }
+ /* ... except, skip leading spaces. */
+ ptr = skip_spaces (ptr);
+
+ return std::string (ptr, end);
+}
+
+/* A wrapper for write_var_or_type that is used specifically when
+ completion is requested for the last of a sequence of
+ identifiers. */
+
+static struct type *
+write_var_or_type_completion (struct parser_state *par_state,
+ const struct block *block, struct stoken name0)
+{
+ int tail_index = chop_selector (name0.ptr, name0.length);
+ /* If there's no separator, just defer to ordinary symbol
+ completion. */
+ if (tail_index == -1)
+ return write_var_or_type (par_state, block, name0);
+
+ std::string copy (name0.ptr, tail_index);
+ struct type *type = write_var_or_type (par_state, block,
+ { copy.c_str (),
+ (int) copy.length () });
+ /* For completion purposes, it's enough that we return a type
+ here. */
+ if (type != nullptr)
+ return type;
+
+ ada_structop_operation *op = write_selectors (par_state,
+ name0.ptr + tail_index);
+ op->set_prefix (find_completion_bounds (par_state));
+ par_state->mark_struct_expression (op);
+ return nullptr;
+}
+
/* Write a left side of a component association (e.g., NAME in NAME =>
exp). If NAME has the form of a selected component, write it as an
ordinary expression. If it is a simple variable that unambiguously
@@ -1690,7 +1831,7 @@ write_name_assoc (struct parser_state *par_state, struct stoken name)
par_state->expression_context_block,
VAR_DOMAIN);
- if (syms.size () != 1 || SYMBOL_CLASS (syms[0].symbol) == LOC_TYPEDEF)
+ if (syms.size () != 1 || syms[0].symbol->aclass () == LOC_TYPEDEF)
pstate->push_new<ada_string_operation> (copy_name (name));
else
write_var_from_sym (par_state, syms[0]);
@@ -1727,10 +1868,18 @@ type_long_double (struct parser_state *par_state)
}
static struct type *
-type_char (struct parser_state *par_state)
+type_for_char (struct parser_state *par_state, ULONGEST value)
{
- return language_string_char_type (par_state->language (),
- par_state->gdbarch ());
+ if (value <= 0xff)
+ return language_string_char_type (par_state->language (),
+ par_state->gdbarch ());
+ else if (value <= 0xffff)
+ return language_lookup_primitive_type (par_state->language (),
+ par_state->gdbarch (),
+ "wide_character");
+ return language_lookup_primitive_type (par_state->language (),
+ par_state->gdbarch (),
+ "wide_wide_character");
}
static struct type *