diff options
Diffstat (limited to 'gdb/ada-exp.y')
-rw-r--r-- | gdb/ada-exp.y | 223 |
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 * |