#include "valprint.h"
#include "source.h"
#include "observer.h"
+#include "vec.h"
#ifndef ADA_RETAIN_DOTS
#define ADA_RETAIN_DOTS 0
#define TRUNCATION_TOWARDS_ZERO ((-5 / 2) == -2)
#endif
-
static void extract_string (CORE_ADDR addr, char *buf);
static void modify_general_field (char *, LONGEST, int, int);
/* Utilities */
+/* Given DECODED_NAME a string holding a symbol name in its
+ decoded form (ie using the Ada dotted notation), returns
+ its unqualified name. */
+
+static const char *
+ada_unqualified_name (const char *decoded_name)
+{
+ const char *result = strrchr (decoded_name, '.');
+
+ if (result != NULL)
+ result++; /* Skip the dot... */
+ else
+ result = decoded_name;
+
+ return result;
+}
+
+/* Return a string starting with '<', followed by STR, and '>'.
+ The result is good until the next call. */
+
+static char *
+add_angle_brackets (const char *str)
+{
+ static char *result = NULL;
+
+ xfree (result);
+ result = (char *) xmalloc ((strlen (str) + 3) * sizeof (char));
+
+ sprintf (result, "<%s>", str);
+ return result;
+}
static char *
ada_get_gdb_completer_word_break_characters (void)
{
struct symbol *sym;
struct block **blocks;
- const char *raw_name = ada_type_name (ada_check_typedef (type));
- char *name = (char *) alloca (strlen (raw_name) + 1);
- char *tail = strstr (raw_name, "___XP");
+ char *raw_name = ada_type_name (ada_check_typedef (type));
+ char *name;
+ char *tail;
struct type *shadow_type;
long bits;
int i, n;
+ if (!raw_name)
+ raw_name = ada_type_name (desc_base_type (type));
+
+ if (!raw_name)
+ return NULL;
+
+ name = (char *) alloca (strlen (raw_name) + 1);
+ tail = strstr (raw_name, "___XP");
type = desc_base_type (type);
memcpy (name, raw_name, tail - raw_name);
return NULL;
}
- if (BITS_BIG_ENDIAN && ada_is_modular_type (value_type (arr)))
+ if (gdbarch_bits_big_endian (current_gdbarch)
+ && ada_is_modular_type (value_type (arr)))
{
/* This is a (right-justified) modular type representing a packed
array with no wrapper. In order to interpret the value through
int len = (bit_size + bit_offset + HOST_CHAR_BIT - 1) / 8;
/* Transmit bytes from least to most significant; delta is the direction
the indices move. */
- int delta = BITS_BIG_ENDIAN ? -1 : 1;
+ int delta = gdbarch_bits_big_endian (current_gdbarch) ? -1 : 1;
type = ada_check_typedef (type);
v = allocate_value (type);
bytes = (unsigned char *) (valaddr + offset);
}
- else if (value_lazy (obj))
+ else if (VALUE_LVAL (obj) == lval_memory && value_lazy (obj))
{
v = value_at (type,
VALUE_ADDRESS (obj) + value_offset (obj) + offset);
memset (unpacked, 0, TYPE_LENGTH (type));
return v;
}
- else if (BITS_BIG_ENDIAN)
+ else if (gdbarch_bits_big_endian (current_gdbarch))
{
src = len - 1;
if (has_negatives (type)
targ_offset %= HOST_CHAR_BIT;
source += src_offset / HOST_CHAR_BIT;
src_offset %= HOST_CHAR_BIT;
- if (BITS_BIG_ENDIAN)
+ if (gdbarch_bits_big_endian (current_gdbarch))
{
accum = (unsigned char) *source;
source += 1;
fromval = value_cast (type, fromval);
read_memory (to_addr, buffer, len);
- if (BITS_BIG_ENDIAN)
+ if (gdbarch_bits_big_endian (current_gdbarch))
move_bits (buffer, value_bitpos (toval),
value_contents (fromval),
TYPE_LENGTH (value_type (fromval)) * TARGET_CHAR_BIT -
else
bits = value_bitsize (component);
- if (BITS_BIG_ENDIAN)
+ if (gdbarch_bits_big_endian (current_gdbarch))
move_bits (value_contents_writeable (container) + offset_in_container,
value_bitpos (container) + bit_offset_in_container,
value_contents (val),
int *chosen = (int *) alloca (sizeof (int) * nsyms);
int n_chosen;
int first_choice = (max_results == 1) ? 1 : 2;
+ const char *select_mode = multiple_symbols_select_mode ();
if (max_results < 1)
error (_("Request to select 0 symbols!"));
if (nsyms <= 1)
return nsyms;
+ if (select_mode == multiple_symbols_cancel)
+ error (_("\
+canceled because the command is ambiguous\n\
+See set/show multiple-symbol."));
+
+ /* If select_mode is "all", then return all possible symbols.
+ Only do that if more than one symbol can be selected, of course.
+ Otherwise, display the menu as usual. */
+ if (select_mode == multiple_symbols_all && max_results > 1)
+ return nsyms;
+
printf_unfiltered (_("[0] cancel\n"));
if (max_results > 1)
printf_unfiltered (_("[1] all\n"));
int is_all_choice, char *annotation_suffix)
{
char *args;
- const char *prompt;
+ char *prompt;
int n_chosen;
int first_choice = is_all_choice ? 2 : 1;
prompt = getenv ("PS2");
if (prompt == NULL)
- prompt = ">";
+ prompt = "> ";
- printf_unfiltered (("%s "), prompt);
- gdb_flush (gdb_stdout);
-
- args = command_line_input ((char *) NULL, 0, annotation_suffix);
+ args = command_line_input (prompt, 0, annotation_suffix);
if (args == NULL)
error_no_arg (_("one or more choice numbers"));
if (gdbarch_frame_align_p (current_gdbarch))
*sp = gdbarch_frame_align (current_gdbarch, *sp);
}
+ VALUE_LVAL (val) = lval_memory;
write_memory (VALUE_ADDRESS (val), value_contents_raw (val), len);
}
allocating any necessary descriptors (fat pointers), or copies of
values not residing in memory, updating it as needed. */
-static struct value *
-convert_actual (struct value *actual, struct type *formal_type0,
- CORE_ADDR *sp)
+struct value *
+ada_convert_actual (struct value *actual, struct type *formal_type0,
+ CORE_ADDR *sp)
{
struct type *actual_type = ada_check_typedef (value_type (actual));
struct type *formal_type = ada_check_typedef (formal_type0);
if (ada_is_array_descriptor_type (formal_target)
&& TYPE_CODE (actual_target) == TYPE_CODE_ARRAY)
return make_array_descriptor (formal_type, actual, sp);
- else if (TYPE_CODE (formal_type) == TYPE_CODE_PTR)
+ else if (TYPE_CODE (formal_type) == TYPE_CODE_PTR
+ || TYPE_CODE (formal_type) == TYPE_CODE_REF)
{
+ struct value *result;
if (TYPE_CODE (formal_target) == TYPE_CODE_ARRAY
&& ada_is_array_descriptor_type (actual_target))
- return desc_data (actual);
+ result = desc_data (actual);
else if (TYPE_CODE (actual_type) != TYPE_CODE_PTR)
{
if (VALUE_LVAL (actual) != lval_memory)
TYPE_LENGTH (actual_type));
actual = ensure_lval (val, sp);
}
- return value_addr (actual);
+ result = value_addr (actual);
}
+ else
+ return actual;
+ return value_cast_pointers (formal_type, result);
}
else if (TYPE_CODE (actual_type) == TYPE_CODE_PTR)
return ada_value_ind (actual);
else
return descriptor;
}
-
-
-/* Assuming a dummy frame has been established on the target, perform any
- conversions needed for calling function FUNC on the NARGS actual
- parameters in ARGS, other than standard C conversions. Does
- nothing if FUNC does not have Ada-style prototype data, or if NARGS
- does not match the number of arguments expected. Use *SP as a
- stack pointer for additional data that must be pushed, updating its
- value as needed. */
-
-void
-ada_convert_actuals (struct value *func, int nargs, struct value *args[],
- CORE_ADDR *sp)
-{
- int i;
-
- if (TYPE_NFIELDS (value_type (func)) == 0
- || nargs != TYPE_NFIELDS (value_type (func)))
- return;
-
- for (i = 0; i < nargs; i += 1)
- args[i] =
- convert_actual (args[i], TYPE_FIELD_TYPE (value_type (func), i), sp);
-}
\f
/* Dummy definitions for an experimental caching module that is not
* used in the public sources. */
names (e.g., XVE) are not included here. Currently, the possible suffixes
are given by either of the regular expression:
- (__[0-9]+)?[.$][0-9]+ [nested subprogram suffix, on platforms such
- as GNU/Linux]
- ___[0-9]+ [nested subprogram suffix, on platforms such as HP/UX]
- _E[0-9]+[bs]$ [protected object entry suffixes]
+ [.$][0-9]+ [nested subprogram suffix, on platforms such as GNU/Linux]
+ ___[0-9]+ [nested subprogram suffix, on platforms such as HP/UX]
+ _E[0-9]+[bs]$ [protected object entry suffixes]
(X[nb]*)?((\$|__)[0-9](_?[0-9]+)|___(JM|LJM|X([FDBUP].*|R[^T]?)))?$
- */
+
+ Also, any leading "__[0-9]+" sequence is skipped before the suffix
+ match is performed. This sequence is used to differentiate homonyms,
+ is an optional part of a valid name suffix. */
static int
is_name_suffix (const char *str)
const char *matching;
const int len = strlen (str);
- /* (__[0-9]+)?\.[0-9]+ */
- matching = str;
+ /* Skip optional leading __[0-9]+. */
+
if (len > 3 && str[0] == '_' && str[1] == '_' && isdigit (str[2]))
{
- matching += 3;
- while (isdigit (matching[0]))
- matching += 1;
- if (matching[0] == '\0')
- return 1;
+ str += 3;
+ while (isdigit (str[0]))
+ str += 1;
}
+
+ /* [.$][0-9]+ */
- if (matching[0] == '.' || matching[0] == '$')
+ if (str[0] == '.' || str[0] == '$')
{
- matching += 1;
+ matching = str + 1;
while (isdigit (matching[0]))
matching += 1;
if (matching[0] == '\0')
}
/* ___[0-9]+ */
+
if (len > 3 && str[0] == '_' && str[1] == '_' && str[2] == '_')
{
matching = str + 3;
str += 1;
}
}
+
if (str[0] == '\000')
return 1;
+
if (str[0] == '_')
{
if (str[1] != '_' || str[2] == '\000')
}
}
\f
+
+ /* Symbol Completion */
+
+/* If SYM_NAME is a completion candidate for TEXT, return this symbol
+ name in a form that's appropriate for the completion. The result
+ does not need to be deallocated, but is only good until the next call.
+
+ TEXT_LEN is equal to the length of TEXT.
+ Perform a wild match if WILD_MATCH is set.
+ ENCODED should be set if TEXT represents the start of a symbol name
+ in its encoded form. */
+
+static const char *
+symbol_completion_match (const char *sym_name,
+ const char *text, int text_len,
+ int wild_match, int encoded)
+{
+ char *result;
+ const int verbatim_match = (text[0] == '<');
+ int match = 0;
+
+ if (verbatim_match)
+ {
+ /* Strip the leading angle bracket. */
+ text = text + 1;
+ text_len--;
+ }
+
+ /* First, test against the fully qualified name of the symbol. */
+
+ if (strncmp (sym_name, text, text_len) == 0)
+ match = 1;
+
+ if (match && !encoded)
+ {
+ /* One needed check before declaring a positive match is to verify
+ that iff we are doing a verbatim match, the decoded version
+ of the symbol name starts with '<'. Otherwise, this symbol name
+ is not a suitable completion. */
+ const char *sym_name_copy = sym_name;
+ int has_angle_bracket;
+
+ sym_name = ada_decode (sym_name);
+ has_angle_bracket = (sym_name[0] == '<');
+ match = (has_angle_bracket == verbatim_match);
+ sym_name = sym_name_copy;
+ }
+
+ if (match && !verbatim_match)
+ {
+ /* When doing non-verbatim match, another check that needs to
+ be done is to verify that the potentially matching symbol name
+ does not include capital letters, because the ada-mode would
+ not be able to understand these symbol names without the
+ angle bracket notation. */
+ const char *tmp;
+
+ for (tmp = sym_name; *tmp != '\0' && !isupper (*tmp); tmp++);
+ if (*tmp != '\0')
+ match = 0;
+ }
+
+ /* Second: Try wild matching... */
+
+ if (!match && wild_match)
+ {
+ /* Since we are doing wild matching, this means that TEXT
+ may represent an unqualified symbol name. We therefore must
+ also compare TEXT against the unqualified name of the symbol. */
+ sym_name = ada_unqualified_name (ada_decode (sym_name));
+
+ if (strncmp (sym_name, text, text_len) == 0)
+ match = 1;
+ }
+
+ /* Finally: If we found a mach, prepare the result to return. */
+
+ if (!match)
+ return NULL;
+
+ if (verbatim_match)
+ sym_name = add_angle_brackets (sym_name);
+
+ if (!encoded)
+ sym_name = ada_decode (sym_name);
+
+ return sym_name;
+}
+
+typedef char *char_ptr;
+DEF_VEC_P (char_ptr);
+
+/* A companion function to ada_make_symbol_completion_list().
+ Check if SYM_NAME represents a symbol which name would be suitable
+ to complete TEXT (TEXT_LEN is the length of TEXT), in which case
+ it is appended at the end of the given string vector SV.
+
+ ORIG_TEXT is the string original string from the user command
+ that needs to be completed. WORD is the entire command on which
+ completion should be performed. These two parameters are used to
+ determine which part of the symbol name should be added to the
+ completion vector.
+ if WILD_MATCH is set, then wild matching is performed.
+ ENCODED should be set if TEXT represents a symbol name in its
+ encoded formed (in which case the completion should also be
+ encoded). */
+
+static void
+symbol_completion_add (VEC(char_ptr) **sv,
+ const char *sym_name,
+ const char *text, int text_len,
+ const char *orig_text, const char *word,
+ int wild_match, int encoded)
+{
+ const char *match = symbol_completion_match (sym_name, text, text_len,
+ wild_match, encoded);
+ char *completion;
+
+ if (match == NULL)
+ return;
+
+ /* We found a match, so add the appropriate completion to the given
+ string vector. */
+
+ if (word == orig_text)
+ {
+ completion = xmalloc (strlen (match) + 5);
+ strcpy (completion, match);
+ }
+ else if (word > orig_text)
+ {
+ /* Return some portion of sym_name. */
+ completion = xmalloc (strlen (match) + 5);
+ strcpy (completion, match + (word - orig_text));
+ }
+ else
+ {
+ /* Return some of ORIG_TEXT plus sym_name. */
+ completion = xmalloc (strlen (match) + (orig_text - word) + 5);
+ strncpy (completion, word, orig_text - word);
+ completion[orig_text - word] = '\0';
+ strcat (completion, match);
+ }
+
+ VEC_safe_push (char_ptr, *sv, completion);
+}
+
+/* Return a list of possible symbol names completing TEXT0. The list
+ is NULL terminated. WORD is the entire command on which completion
+ is made. */
+
+static char **
+ada_make_symbol_completion_list (char *text0, char *word)
+{
+ char *text;
+ int text_len;
+ int wild_match;
+ int encoded;
+ VEC(char_ptr) *completions = VEC_alloc (char_ptr, 128);
+ struct symbol *sym;
+ struct symtab *s;
+ struct partial_symtab *ps;
+ struct minimal_symbol *msymbol;
+ struct objfile *objfile;
+ struct block *b, *surrounding_static_block = 0;
+ int i;
+ struct dict_iterator iter;
+
+ if (text0[0] == '<')
+ {
+ text = xstrdup (text0);
+ make_cleanup (xfree, text);
+ text_len = strlen (text);
+ wild_match = 0;
+ encoded = 1;
+ }
+ else
+ {
+ text = xstrdup (ada_encode (text0));
+ make_cleanup (xfree, text);
+ text_len = strlen (text);
+ for (i = 0; i < text_len; i++)
+ text[i] = tolower (text[i]);
+
+ encoded = (strstr (text0, "__") != NULL);
+ /* If the name contains a ".", then the user is entering a fully
+ qualified entity name, and the match must not be done in wild
+ mode. Similarly, if the user wants to complete what looks like
+ an encoded name, the match must not be done in wild mode. */
+ wild_match = (strchr (text0, '.') == NULL && !encoded);
+ }
+
+ /* First, look at the partial symtab symbols. */
+ ALL_PSYMTABS (objfile, ps)
+ {
+ struct partial_symbol **psym;
+
+ /* If the psymtab's been read in we'll get it when we search
+ through the blockvector. */
+ if (ps->readin)
+ continue;
+
+ for (psym = objfile->global_psymbols.list + ps->globals_offset;
+ psym < (objfile->global_psymbols.list + ps->globals_offset
+ + ps->n_global_syms); psym++)
+ {
+ QUIT;
+ symbol_completion_add (&completions, SYMBOL_LINKAGE_NAME (*psym),
+ text, text_len, text0, word,
+ wild_match, encoded);
+ }
+
+ for (psym = objfile->static_psymbols.list + ps->statics_offset;
+ psym < (objfile->static_psymbols.list + ps->statics_offset
+ + ps->n_static_syms); psym++)
+ {
+ QUIT;
+ symbol_completion_add (&completions, SYMBOL_LINKAGE_NAME (*psym),
+ text, text_len, text0, word,
+ wild_match, encoded);
+ }
+ }
+
+ /* At this point scan through the misc symbol vectors and add each
+ symbol you find to the list. Eventually we want to ignore
+ anything that isn't a text symbol (everything else will be
+ handled by the psymtab code above). */
+
+ ALL_MSYMBOLS (objfile, msymbol)
+ {
+ QUIT;
+ symbol_completion_add (&completions, SYMBOL_LINKAGE_NAME (msymbol),
+ text, text_len, text0, word, wild_match, encoded);
+ }
+
+ /* Search upwards from currently selected frame (so that we can
+ complete on local vars. */
+
+ for (b = get_selected_block (0); b != NULL; b = BLOCK_SUPERBLOCK (b))
+ {
+ if (!BLOCK_SUPERBLOCK (b))
+ surrounding_static_block = b; /* For elmin of dups */
+
+ ALL_BLOCK_SYMBOLS (b, iter, sym)
+ {
+ symbol_completion_add (&completions, SYMBOL_LINKAGE_NAME (sym),
+ text, text_len, text0, word,
+ wild_match, encoded);
+ }
+ }
+
+ /* Go through the symtabs and check the externs and statics for
+ symbols which match. */
+
+ ALL_SYMTABS (objfile, s)
+ {
+ QUIT;
+ b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK);
+ ALL_BLOCK_SYMBOLS (b, iter, sym)
+ {
+ symbol_completion_add (&completions, SYMBOL_LINKAGE_NAME (sym),
+ text, text_len, text0, word,
+ wild_match, encoded);
+ }
+ }
+
+ ALL_SYMTABS (objfile, s)
+ {
+ QUIT;
+ b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK);
+ /* Don't do this block twice. */
+ if (b == surrounding_static_block)
+ continue;
+ ALL_BLOCK_SYMBOLS (b, iter, sym)
+ {
+ symbol_completion_add (&completions, SYMBOL_LINKAGE_NAME (sym),
+ text, text_len, text0, word,
+ wild_match, encoded);
+ }
+ }
+
+ /* Append the closing NULL entry. */
+ VEC_safe_push (char_ptr, completions, NULL);
+
+ /* Make a copy of the COMPLETIONS VEC before we free it, and then
+ return the copy. It's unfortunate that we have to make a copy
+ of an array that we're about to destroy, but there is nothing much
+ we can do about it. Fortunately, it's typically not a very large
+ array. */
+ {
+ const size_t completions_size =
+ VEC_length (char_ptr, completions) * sizeof (char *);
+ char **result = malloc (completions_size);
+
+ memcpy (result, VEC_address (char_ptr, completions), completions_size);
+
+ VEC_free (char_ptr, completions);
+ return result;
+ }
+}
+
/* Field Access */
/* Return non-zero if TYPE is a pointer to the GNAT dispatch table used
{
int others_clause;
int i;
- int disp;
- struct type *discrim_type;
char *discrim_name = ada_variant_discrim_name (var_type);
+ struct value *outer;
+ struct value *discrim;
LONGEST discrim_val;
- disp = 0;
- discrim_type =
- ada_lookup_struct_elt_type (outer_type, discrim_name, 1, 1, &disp);
- if (discrim_type == NULL)
+ outer = value_from_contents_and_address (outer_type, outer_valaddr, 0);
+ discrim = ada_value_struct_elt (outer, discrim_name, 1);
+ if (discrim == NULL)
return -1;
- discrim_val = unpack_long (discrim_type, outer_valaddr + disp);
+ discrim_val = value_as_long (discrim);
others_clause = -1;
for (i = 0; i < TYPE_NFIELDS (var_type); i += 1)
struct type *
ada_check_typedef (struct type *type)
{
+ if (type == NULL)
+ return NULL;
+
CHECK_TYPEDEF (type);
if (type == NULL || TYPE_CODE (type) != TYPE_CODE_ENUM
|| !TYPE_STUB (type)
struct type *type = ada_check_typedef (value_type (val));
if (ada_is_aligner_type (type))
{
- struct value *v = value_struct_elt (&val, NULL, "F",
- NULL, "internal structure");
+ struct value *v = ada_value_struct_elt (val, "F", 0);
struct type *val_type = ada_check_typedef (value_type (v));
if (ada_type_name (val_type) == NULL)
TYPE_NAME (val_type) = ada_type_name (type);
ada_val_print, /* Print a value using appropriate syntax */
ada_value_print, /* Print a top-level value */
NULL, /* Language specific skip_trampoline */
- NULL, /* value_of_this */
+ NULL, /* name_of_this */
ada_lookup_symbol_nonlocal, /* Looking up non-local symbols. */
basic_lookup_transparent_type, /* lookup_transparent_type */
ada_la_decode, /* Language specific symbol demangler */
0, /* c-style arrays */
1, /* String lower bound */
ada_get_gdb_completer_word_break_characters,
+ ada_make_symbol_completion_list,
ada_language_arch_info,
ada_print_array_index,
default_pass_by_reference,