+ error (_("Internal error in encoding of renaming declaration"));
+}
+
+static const struct block*
+block_lookup (const struct block *context, const char *raw_name)
+{
+ const char *name;
+ std::vector<struct block_symbol> syms;
+ int nsyms;
+ struct symtab *symtab;
+ const struct block *result = NULL;
+
+ if (raw_name[0] == '\'')
+ {
+ raw_name += 1;
+ name = raw_name;
+ }
+ else
+ name = ada_encode (raw_name);
+
+ nsyms = ada_lookup_symbol_list (name, context, VAR_DOMAIN, &syms);
+
+ if (context == NULL
+ && (nsyms == 0 || SYMBOL_CLASS (syms[0].symbol) != LOC_BLOCK))
+ symtab = lookup_symtab (name);
+ else
+ symtab = NULL;
+
+ if (symtab != NULL)
+ result = BLOCKVECTOR_BLOCK (SYMTAB_BLOCKVECTOR (symtab), STATIC_BLOCK);
+ else if (nsyms == 0 || SYMBOL_CLASS (syms[0].symbol) != LOC_BLOCK)
+ {
+ if (context == NULL)
+ error (_("No file or function \"%s\"."), raw_name);
+ else
+ error (_("No function \"%s\" in specified context."), raw_name);
+ }
+ else
+ {
+ if (nsyms > 1)
+ warning (_("Function name \"%s\" ambiguous here"), raw_name);
+ result = SYMBOL_BLOCK_VALUE (syms[0].symbol);
+ }
+
+ return result;
+}
+
+static struct symbol*
+select_possible_type_sym (const std::vector<struct block_symbol> &syms)
+{
+ int i;
+ int preferred_index;
+ struct type *preferred_type;
+
+ preferred_index = -1; preferred_type = NULL;
+ for (i = 0; i < syms.size (); i += 1)
+ switch (SYMBOL_CLASS (syms[i].symbol))
+ {
+ case LOC_TYPEDEF:
+ if (ada_prefer_type (SYMBOL_TYPE (syms[i].symbol), preferred_type))
+ {
+ preferred_index = i;
+ preferred_type = SYMBOL_TYPE (syms[i].symbol);
+ }
+ break;
+ case LOC_REGISTER:
+ case LOC_ARG:
+ case LOC_REF_ARG:
+ case LOC_REGPARM_ADDR:
+ case LOC_LOCAL:
+ case LOC_COMPUTED:
+ return NULL;
+ default:
+ break;
+ }
+ if (preferred_type == NULL)
+ return NULL;
+ return syms[preferred_index].symbol;
+}
+
+static struct type*
+find_primitive_type (struct parser_state *par_state, char *name)
+{
+ struct type *type;
+ type = language_lookup_primitive_type (parse_language (par_state),
+ parse_gdbarch (par_state),
+ name);
+ if (type == NULL && strcmp ("system__address", name) == 0)
+ type = type_system_address (par_state);
+
+ if (type != NULL)
+ {
+ /* Check to see if we have a regular definition of this
+ type that just didn't happen to have been read yet. */
+ 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).symbol;
+ if (sym != NULL && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
+ type = SYMBOL_TYPE (sym);
+ }
+
+ return type;
+}
+
+static int
+chop_selector (char *name, int end)
+{
+ int i;
+ for (i = end - 1; i > 0; i -= 1)
+ if (name[i] == '.' || (name[i] == '_' && name[i+1] == '_'))
+ return i;
+ 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. */
+static void
+write_selectors (struct parser_state *par_state, char *sels)
+{
+ while (*sels != '\0')
+ {
+ struct stoken field_name;
+ char *p = chop_separator (sels);
+ sels = p;
+ while (*sels != '\0' && *sels != '.'
+ && (sels[0] != '_' || sels[1] != '_'))
+ sels += 1;
+ field_name.length = sels - p;
+ field_name.ptr = p;
+ write_exp_op_with_string (par_state, STRUCTOP_STRUCT, field_name);
+ }
+}
+
+/* Write a variable access (OP_VAR_VALUE) to ambiguous encoded name
+ NAME[0..LEN-1], in block context BLOCK, to be resolved later. Writes
+ a temporary symbol that is valid until the next call to ada_parse.
+ */
+static void
+write_ambiguous_var (struct parser_state *par_state,
+ const struct block *block, char *name, int len)
+{
+ struct symbol *sym = XOBNEW (&temp_parse_space, struct symbol);
+
+ memset (sym, 0, sizeof (struct symbol));
+ SYMBOL_DOMAIN (sym) = UNDEF_DOMAIN;
+ SYMBOL_LINKAGE_NAME (sym)
+ = (const char *) obstack_copy0 (&temp_parse_space, name, len);
+ SYMBOL_LANGUAGE (sym) = language_ada;
+
+ write_exp_elt_opcode (par_state, OP_VAR_VALUE);
+ write_exp_elt_block (par_state, block);
+ write_exp_elt_sym (par_state, sym);
+ write_exp_elt_opcode (par_state, 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 = (char *) 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
+ that type. Otherwise, write expression code to evaluate it as an
+ object and return NULL. In this second case, NAME0 will, in general,
+ have the form <name>(.<selector_name>)*, where <name> is an object
+ or renaming encoded in the debugging data. Calls error if no
+ prefix <name> matches a name in the debugging data (i.e., matches
+ either a complete name or, as a wild-card match, the final
+ identifier). */
+
+static struct type*
+write_var_or_type (struct parser_state *par_state,
+ const struct block *block, struct stoken name0)
+{
+ int depth;
+ char *encoded_name;
+ int name_len;
+
+ if (block == NULL)
+ block = expression_context_block;
+
+ encoded_name = ada_encode (name0.ptr);
+ name_len = strlen (encoded_name);
+ encoded_name
+ = (char *) obstack_copy0 (&temp_parse_space, encoded_name, name_len);
+ for (depth = 0; depth < MAX_RENAMING_CHAIN_LENGTH; depth += 1)
+ {
+ int tail_index;
+
+ tail_index = name_len;
+ while (tail_index > 0)
+ {
+ int nsyms;
+ std::vector<struct block_symbol> syms;
+ struct symbol *type_sym;
+ struct symbol *renaming_sym;
+ const char* renaming;
+ int renaming_len;
+ const char* renaming_expr;
+ int terminator = encoded_name[tail_index];
+
+ encoded_name[tail_index] = '\0';
+ nsyms = ada_lookup_symbol_list (encoded_name, block,
+ VAR_DOMAIN, &syms);
+ encoded_name[tail_index] = terminator;
+
+ /* A single symbol may rename a package or object. */
+
+ /* This should go away when we move entirely to new version.
+ FIXME pnh 7/20/2007. */
+ if (nsyms == 1)
+ {
+ struct symbol *ren_sym =
+ ada_find_renaming_symbol (syms[0].symbol, syms[0].block);
+
+ if (ren_sym != NULL)
+ syms[0].symbol = ren_sym;
+ }
+
+ type_sym = select_possible_type_sym (syms);
+
+ if (type_sym != NULL)
+ renaming_sym = type_sym;
+ else if (nsyms == 1)
+ renaming_sym = syms[0].symbol;
+ else
+ renaming_sym = NULL;
+
+ switch (ada_parse_renaming (renaming_sym, &renaming,
+ &renaming_len, &renaming_expr))
+ {
+ case ADA_NOT_RENAMING:
+ break;
+ case ADA_PACKAGE_RENAMING:
+ case ADA_EXCEPTION_RENAMING:
+ case ADA_SUBPROGRAM_RENAMING:
+ {
+ int alloc_len = renaming_len + name_len - tail_index + 1;
+ char *new_name
+ = (char *) obstack_alloc (&temp_parse_space, alloc_len);
+ strncpy (new_name, renaming, renaming_len);
+ strcpy (new_name + renaming_len, encoded_name + tail_index);
+ encoded_name = new_name;
+ name_len = renaming_len + name_len - tail_index;
+ goto TryAfterRenaming;
+ }
+ case ADA_OBJECT_RENAMING:
+ write_object_renaming (par_state, block, renaming, renaming_len,
+ renaming_expr, MAX_RENAMING_CHAIN_LENGTH);
+ write_selectors (par_state, encoded_name + tail_index);
+ return NULL;
+ default:
+ internal_error (__FILE__, __LINE__,
+ _("impossible value from ada_parse_renaming"));
+ }
+
+ if (type_sym != NULL)
+ {
+ 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);
+ }
+ else if (tail_index == name_len && nsyms == 0)
+ {
+ struct type *type = find_primitive_type (par_state,
+ encoded_name);
+
+ if (type != NULL)
+ return type;
+ }
+
+ if (nsyms == 1)
+ {
+ write_var_from_sym (par_state, syms[0].block, syms[0].symbol);
+ write_selectors (par_state, encoded_name + tail_index);
+ return NULL;
+ }
+ else if (nsyms == 0)
+ {
+ struct bound_minimal_symbol msym
+ = ada_lookup_simple_minsym (encoded_name);
+ if (msym.minsym != NULL)
+ {
+ write_exp_msymbol (par_state, msym);
+ /* Maybe cause error here rather than later? FIXME? */
+ write_selectors (par_state, encoded_name + tail_index);
+ return NULL;
+ }
+
+ if (tail_index == name_len
+ && strncmp (encoded_name, "standard__",
+ sizeof ("standard__") - 1) == 0)
+ error (_("No definition of \"%s\" found."), name0.ptr);
+
+ tail_index = chop_selector (encoded_name, tail_index);
+ }
+ else
+ {
+ write_ambiguous_var (par_state, block, encoded_name,
+ tail_index);
+ write_selectors (par_state, encoded_name + tail_index);
+ return NULL;
+ }
+ }
+
+ if (!have_full_symbols () && !have_partial_symbols () && block == NULL)
+ error (_("No symbol table is loaded. Use the \"file\" command."));
+ if (block == expression_context_block)
+ error (_("No definition of \"%s\" in current context."), name0.ptr);
+ else
+ error (_("No definition of \"%s\" in specified context."), name0.ptr);
+
+ TryAfterRenaming: ;
+ }
+
+ error (_("Could not find renamed symbol \"%s\""), name0.ptr);
+
+}
+
+/* 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
+ corresponds to exactly one symbol that does not denote a type or an
+ object renaming, also write it normally as an OP_VAR_VALUE.
+ Otherwise, write it as an OP_NAME.
+
+ Unfortunately, we don't know at this point whether NAME is supposed
+ to denote a record component name or the value of an array index.
+ Therefore, it is not appropriate to disambiguate an ambiguous name
+ as we normally would, nor to replace a renaming with its referent.
+ As a result, in the (one hopes) rare case that one writes an
+ aggregate such as (R => 42) where R renames an object or is an
+ ambiguous name, one must write instead ((R) => 42). */
+
+static void
+write_name_assoc (struct parser_state *par_state, struct stoken name)
+{
+ if (strchr (name.ptr, '.') == NULL)
+ {
+ std::vector<struct block_symbol> syms;
+ int nsyms = ada_lookup_symbol_list (name.ptr, expression_context_block,
+ VAR_DOMAIN, &syms);
+
+ if (nsyms != 1 || SYMBOL_CLASS (syms[0].symbol) == LOC_TYPEDEF)
+ write_exp_op_with_string (par_state, OP_NAME, name);
+ else
+ write_var_from_sym (par_state, syms[0].block, syms[0].symbol);
+ }
+ else
+ if (write_var_or_type (par_state, NULL, name) != NULL)
+ error (_("Invalid use of type."));