From gdb-patches-return-33876-listarch-gdb-patches=sources dot redhat dot com at sources dot redhat dot com Wed Jun 16 08:34:43 2004 Return-Path: Delivered-To: listarch-gdb-patches at sources dot redhat dot com Received: (qmail 1499 invoked by alias); 16 Jun 2004 08:34:41 -0000 Mailing-List: contact gdb-patches-help at sources dot redhat dot com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner at sources dot redhat dot com Delivered-To: mailing list gdb-patches at sources dot redhat dot com Received: (qmail 1426 invoked from network); 16 Jun 2004 08:34:24 -0000 Received: from unknown (HELO nile.gnat.com) (205.232.38.5) by sourceware dot org with SMTP; 16 Jun 2004 08:34:24 -0000 Received: from localhost (localhost [127.0.0.1]) by nile dot gnat dot com (Postfix) with ESMTP id B2980F281F for ; Wed, 16 Jun 2004 04:34:23 -0400 (EDT) Received: from nile.gnat.com ([127.0.0.1]) by localhost (nile dot gnat dot com [127 dot 0 dot 0 dot 1]) (amavisd-new, port 10024) with LMTP id 22648-01-4 for ; Wed, 16 Jun 2004 04:34:22 -0400 (EDT) Received: by nile.gnat.com (Postfix, from userid 1345) id C3B5CF2C03; Wed, 16 Jun 2004 04:34:22 -0400 (EDT) From: Paul Hilfinger To: gdb-patches at sources dot redhat dot com Cc: In-reply-to: (message from Jim Blandy on 09 Jun 2004 02:23:18 -0500) Subject: [PATCH]: Further updates to ada-* files References: <20040608090758.C59CAF2940@nile.gnat.com> Message-Id: <20040616083422.C3B5CF2C03@nile.gnat.com> Date: Wed, 16 Jun 2004 04:34:22 -0400 (EDT) X-Virus-Scanned: by amavisd-new at nile.gnat.com I have committed the following patch to some Ada files, first to keep up-to-date with ACT's sources, and second to conditionalize out a bunch of source code that we are not yet using in the public version for the benefit of reviewers. Paul Hilfinger ACT, Inc. 2004-06-16 Paul N. Hilfinger * ada-tasks.c: Rename build_task_list to ada_build_task_list, and make it non-static. * ada-lang.h (task_control_block): declaration moved from ada-task.c to ada-lang.h; this is needed to be able to implement the kill command in multi-task mode. (task_ptid): Ditto. (task_entry): Ditto. (task_list): Ditto. (ada_build_task_list): Ditto. * ada-lang.c: Conditionalize routines and data structures related to breakpoints, exceptions, completion, and symbol caching on GNAT_GDB, since these are not yet used in the submitted public sources. (ada_main_name): Editorial: Move definition out of exception-related code. Index: gdb/ada-lang.c =================================================================== RCS file: /cvs/src/src/gdb/ada-lang.c,v retrieving revision 1.37 diff -u -p -r1.37 ada-lang.c --- gdb/ada-lang.c 8 Jun 2004 08:42:03 -0000 1.37 +++ gdb/ada-lang.c 16 Jun 2004 08:10:22 -0000 @@ -18,6 +18,19 @@ You should have received a copy of the G along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* Sections of code marked + + #ifdef GNAT_GDB + ... + #endif + + indicate sections that are used in sources distributed by + ACT, Inc., but not yet integrated into the public tree (where + GNAT_GDB is not defined). They are retained here nevertheless + to minimize the problems of maintaining different versions + of the source and to make the full source available. */ + #include "defs.h" #include #include "gdb_string.h" @@ -62,6 +75,7 @@ Foundation, Inc., 675 Mass Ave, Cambridg #define TRUNCATION_TOWARDS_ZERO ((-5 / 2) == -2) #endif +#ifdef GNAT_GDB /* A structure that contains a vector of strings. The main purpose of this type is to group the vector and its associated parameters in one structure. This makes it easier @@ -76,6 +90,7 @@ struct string_vector static struct string_vector xnew_string_vector (int initial_size); static void string_vector_append (struct string_vector *sv, char *str); +#endif /* GNAT_GDB */ static const char *ada_unqualified_name (const char *decoded_name); static char *add_angle_brackets (const char *str); @@ -332,6 +347,8 @@ static struct obstack symbol_list_obstac /* Utilities */ +#ifdef GNAT_GDB + /* Create a new empty string_vector struct with an initial size of INITIAL_SIZE. */ @@ -392,6 +409,8 @@ add_angle_brackets (const char *str) return result; } +#endif /* GNAT_GDB */ + static char * ada_get_gdb_completer_word_break_characters (void) { @@ -705,6 +724,37 @@ ada_update_initial_language (enum langua return lang; } + +/* If the main procedure is written in Ada, then return its name. + The result is good until the next call. Return NULL if the main + procedure doesn't appear to be in Ada. */ + +char * +ada_main_name (void) +{ + struct minimal_symbol *msym; + CORE_ADDR main_program_name_addr; + static char main_program_name[1024]; + /* For Ada, the name of the main procedure is stored in a specific + string constant, generated by the binder. Look for that symbol, + extract its address, and then read that string. If we didn't find + that string, then most probably the main procedure is not written + in Ada. */ + msym = lookup_minimal_symbol (ADA_MAIN_PROGRAM_SYMBOL_NAME, NULL, NULL); + + if (msym != NULL) + { + main_program_name_addr = SYMBOL_VALUE_ADDRESS (msym); + if (main_program_name_addr == 0) + error ("Invalid address for Ada main program name."); + + extract_string (main_program_name_addr, main_program_name); + return main_program_name; + } + + /* The main procedure doesn't seem to be in Ada. */ + return NULL; +} /* Symbols */ @@ -3597,6 +3647,13 @@ ada_convert_actuals (struct value *func, /* Experimental Symbol Cache Module */ +/* This module may well have been OBE, due to improvements in the + symbol-table module. So until proven otherwise, it is disabled in + the submitted public code, and may be removed from all sources + in the future. */ + +#ifdef GNAT_GDB + /* This section implements a simple, fixed-sized hash table for those Ada-mode symbols that get looked up in the course of executing the user's commands. The size is fixed on the grounds that there are not @@ -3686,6 +3743,22 @@ cache_symbol (const char *name, domain_e e->symtab = symtab; e->block = block; } + +#else +static int +lookup_cached_symbol (const char *name, domain_enum namespace, + struct symbol **sym, struct block **block, + struct symtab **symtab) +{ + return 0; +} + +static void +cache_symbol (const char *name, domain_enum namespace, struct symbol *sym, + struct block *block, struct symtab *symtab) +{ +} +#endif /* GNAT_GDB */ /* Symbol Lookup */ @@ -3841,817 +3914,530 @@ defns_collected (struct obstack *obstack return (struct ada_symbol_info *) obstack_base (obstackp); } -/* 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. */ +/* Look, in partial_symtab PST, for symbol NAME in given namespace. + Check the global symbols if GLOBAL, the static symbols if not. + Do wild-card match if WILD. */ -static const char * -symbol_completion_match (const char *sym_name, - const char *text, int text_len, - int wild_match, int encoded) +static struct partial_symbol * +ada_lookup_partial_symbol (struct partial_symtab *pst, const char *name, + int global, domain_enum namespace, int wild) { - char *result; - const int verbatim_match = (text[0] == '<'); - int match = 0; + struct partial_symbol **start; + int name_len = strlen (name); + int length = (global ? pst->n_global_syms : pst->n_static_syms); + int i; - if (verbatim_match) + if (length == 0) { - /* Strip the leading angle bracket. */ - text = text + 1; - text_len--; + return (NULL); } - /* 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; - } + start = (global ? + pst->objfile->global_psymbols.list + pst->globals_offset : + pst->objfile->static_psymbols.list + pst->statics_offset); - if (match && !verbatim_match) + if (wild) { - /* 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 (i = 0; i < length; i += 1) + { + struct partial_symbol *psym = start[i]; - for (tmp = sym_name; *tmp != '\0' && !isupper (*tmp); tmp++); - if (*tmp != '\0') - match = 0; + if (SYMBOL_DOMAIN (psym) == namespace && + wild_match (name, name_len, SYMBOL_LINKAGE_NAME (psym))) + return psym; + } + return NULL; } + else + { + if (global) + { + int U; + i = 0; + U = length - 1; + while (U - i > 4) + { + int M = (U + i) >> 1; + struct partial_symbol *psym = start[M]; + if (SYMBOL_LINKAGE_NAME (psym)[0] < name[0]) + i = M + 1; + else if (SYMBOL_LINKAGE_NAME (psym)[0] > name[0]) + U = M - 1; + else if (strcmp (SYMBOL_LINKAGE_NAME (psym), name) < 0) + i = M + 1; + else + U = M; + } + } + else + i = 0; - /* Second: Try wild matching... */ + while (i < length) + { + struct partial_symbol *psym = start[i]; - 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 (SYMBOL_DOMAIN (psym) == namespace) + { + int cmp = strncmp (name, SYMBOL_LINKAGE_NAME (psym), name_len); - if (strncmp (sym_name, text, text_len) == 0) - match = 1; - } + if (cmp < 0) + { + if (global) + break; + } + else if (cmp == 0 + && is_name_suffix (SYMBOL_LINKAGE_NAME (psym) + + name_len)) + return psym; + } + i += 1; + } - /* Finally: If we found a mach, prepare the result to return. */ + if (global) + { + int U; + i = 0; + U = length - 1; + while (U - i > 4) + { + int M = (U + i) >> 1; + struct partial_symbol *psym = start[M]; + if (SYMBOL_LINKAGE_NAME (psym)[0] < '_') + i = M + 1; + else if (SYMBOL_LINKAGE_NAME (psym)[0] > '_') + U = M - 1; + else if (strcmp (SYMBOL_LINKAGE_NAME (psym), "_ada_") < 0) + i = M + 1; + else + U = M; + } + } + else + i = 0; - if (!match) - return NULL; + while (i < length) + { + struct partial_symbol *psym = start[i]; - if (verbatim_match) - sym_name = add_angle_brackets (sym_name); + if (SYMBOL_DOMAIN (psym) == namespace) + { + int cmp; - if (!encoded) - sym_name = ada_decode (sym_name); + cmp = (int) '_' - (int) SYMBOL_LINKAGE_NAME (psym)[0]; + if (cmp == 0) + { + cmp = strncmp ("_ada_", SYMBOL_LINKAGE_NAME (psym), 5); + if (cmp == 0) + cmp = strncmp (name, SYMBOL_LINKAGE_NAME (psym) + 5, + name_len); + } - return sym_name; + if (cmp < 0) + { + if (global) + break; + } + else if (cmp == 0 + && is_name_suffix (SYMBOL_LINKAGE_NAME (psym) + + name_len + 5)) + return psym; + } + i += 1; + } + } + return NULL; } -/* 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. +/* Find a symbol table containing symbol SYM or NULL if none. */ - 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 (struct string_vector *sv, - const char *sym_name, - const char *text, int text_len, - const char *orig_text, const char *word, - int wild_match, int encoded) +static struct symtab * +symtab_for_sym (struct symbol *sym) { - 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); - } + struct symtab *s; + struct objfile *objfile; + struct block *b; + struct symbol *tmp_sym; + struct dict_iterator iter; + int j; - string_vector_append (sv, completion); + ALL_SYMTABS (objfile, s) + { + switch (SYMBOL_CLASS (sym)) + { + case LOC_CONST: + case LOC_STATIC: + case LOC_TYPEDEF: + case LOC_REGISTER: + case LOC_LABEL: + case LOC_BLOCK: + case LOC_CONST_BYTES: + b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK); + ALL_BLOCK_SYMBOLS (b, iter, tmp_sym) if (sym == tmp_sym) + return s; + b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK); + ALL_BLOCK_SYMBOLS (b, iter, tmp_sym) if (sym == tmp_sym) + return s; + break; + default: + break; + } + switch (SYMBOL_CLASS (sym)) + { + case LOC_REGISTER: + case LOC_ARG: + case LOC_REF_ARG: + case LOC_REGPARM: + case LOC_REGPARM_ADDR: + case LOC_LOCAL: + case LOC_TYPEDEF: + case LOC_LOCAL_ARG: + case LOC_BASEREG: + case LOC_BASEREG_ARG: + case LOC_COMPUTED: + case LOC_COMPUTED_ARG: + for (j = FIRST_LOCAL_BLOCK; + j < BLOCKVECTOR_NBLOCKS (BLOCKVECTOR (s)); j += 1) + { + b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), j); + ALL_BLOCK_SYMBOLS (b, iter, tmp_sym) if (sym == tmp_sym) + return s; + } + break; + default: + break; + } + } + return NULL; } -/* Return a list of possible symbol names completing TEXT0. The list - is NULL terminated. WORD is the entire command on which completion - is made. */ +/* Return a minimal symbol matching NAME according to Ada decoding + rules. Returns NULL if there is no such minimal symbol. Names + prefixed with "standard__" are handled specially: "standard__" is + first stripped off, and only static and global symbols are searched. */ -char ** -ada_make_symbol_completion_list (const char *text0, const char *word) +struct minimal_symbol * +ada_lookup_simple_minsym (const char *name) { - /* Note: This function is almost a copy of make_symbol_completion_list(), - except it has been adapted for Ada. It is somewhat of a shame to - duplicate so much code, but we don't really have the infrastructure - yet to develop a language-aware version of he symbol completer... */ - char *text; - int text_len; - int wild_match; - int encoded; - struct string_vector result = xnew_string_vector (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; + struct minimal_symbol *msymbol; + int wild_match; - if (text0[0] == '<') + if (strncmp (name, "standard__", sizeof ("standard__") - 1) == 0) { - text = xstrdup (text0); - make_cleanup (xfree, text); - text_len = strlen (text); + name += sizeof ("standard__") - 1; 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]); + wild_match = (strstr (name, "__") == NULL); - /* FIXME: brobecker/2003-09-17: When we get rid of ADA_RETAIN_DOTS, - we can restrict the wild_match check to searching "__" only. */ - wild_match = (strstr (text0, "__") == NULL - && strchr (text0, '.') == NULL); - encoded = (strstr (text0, "__") != NULL); - } + ALL_MSYMBOLS (objfile, msymbol) + { + if (ada_match_name (SYMBOL_LINKAGE_NAME (msymbol), name, wild_match) + && MSYMBOL_TYPE (msymbol) != mst_solib_trampoline) + return msymbol; + } - /* First, look at the partial symtab symbols. */ - ALL_PSYMTABS (objfile, ps) - { - struct partial_symbol **psym; + return NULL; +} - /* If the psymtab's been read in we'll get it when we search - through the blockvector. */ - if (ps->readin) - continue; +/* Return up minimal symbol for NAME, folded and encoded according to + Ada conventions, or NULL if none. The last two arguments are ignored. */ - 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 (&result, SYMBOL_LINKAGE_NAME (*psym), - text, text_len, text0, word, - wild_match, encoded); - } +static struct minimal_symbol * +ada_lookup_minimal_symbol (const char *name, const char *sfile, + struct objfile *objf) +{ + return ada_lookup_simple_minsym (ada_encode (name)); +} - 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 (&result, SYMBOL_LINKAGE_NAME (*psym), - text, text_len, text0, word, - wild_match, encoded); - } - } +/* For all subprograms that statically enclose the subprogram of the + selected frame, add symbols matching identifier NAME in DOMAIN + and their blocks to the list of data in OBSTACKP, as for + ada_add_block_symbols (q.v.). If WILD, treat as NAME with a + wildcard prefix. */ - /* 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). */ +static void +add_symbols_from_enclosing_procs (struct obstack *obstackp, + const char *name, domain_enum namespace, + int wild_match) +{ +#ifdef HAVE_ADD_SYMBOLS_FROM_ENCLOSING_PROCS + /* Use a heuristic to find the frames of enclosing subprograms: treat the + pointer-sized value at location 0 from the local-variable base of a + frame as a static link, and then search up the call stack for a + frame with that same local-variable base. */ + static struct symbol static_link_sym; + static struct symbol *static_link; + struct value *target_link_val; - ALL_MSYMBOLS (objfile, msymbol) - { - QUIT; - symbol_completion_add (&result, SYMBOL_LINKAGE_NAME (msymbol), - text, text_len, text0, word, - wild_match, encoded); - } + struct cleanup *old_chain = make_cleanup (null_cleanup, NULL); + struct frame_info *frame; - /* Search upwards from currently selected frame (so that we can - complete on local vars. */ + if (! target_has_stack) + return; - for (b = get_selected_block (0); b != NULL; b = BLOCK_SUPERBLOCK (b)) + if (static_link == NULL) { - if (!BLOCK_SUPERBLOCK (b)) - surrounding_static_block = b; /* For elmin of dups */ - - ALL_BLOCK_SYMBOLS (b, iter, sym) - { - symbol_completion_add (&result, SYMBOL_LINKAGE_NAME (sym), - text, text_len, text0, word, - wild_match, encoded); - } + /* Initialize the local variable symbol that stands for the + static link (when there is one). */ + static_link = &static_link_sym; + SYMBOL_LINKAGE_NAME (static_link) = ""; + SYMBOL_LANGUAGE (static_link) = language_unknown; + SYMBOL_CLASS (static_link) = LOC_LOCAL; + SYMBOL_DOMAIN (static_link) = VAR_DOMAIN; + SYMBOL_TYPE (static_link) = lookup_pointer_type (builtin_type_void); + SYMBOL_VALUE (static_link) = + -(long) TYPE_LENGTH (SYMBOL_TYPE (static_link)); } - /* 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 (&result, SYMBOL_LINKAGE_NAME (sym), - text, text_len, text0, word, - wild_match, encoded); - } - } + frame = get_selected_frame (); + if (frame == NULL + || inside_main_func (get_frame_address_in_block (frame))) + return; - 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 (&result, SYMBOL_LINKAGE_NAME (sym), - text, text_len, text0, word, - wild_match, encoded); - } - } - - /* Append the closing NULL entry. */ - string_vector_append (&result, NULL); + target_link_val = read_var_value (static_link, frame); + while (target_link_val != NULL + && num_defns_collected (obstackp) == 0 + && frame_relative_level (frame) <= MAX_ENCLOSING_FRAME_LEVELS) + { + CORE_ADDR target_link = value_as_address (target_link_val); - return (result.array); -} + frame = get_prev_frame (frame); + if (frame == NULL) + break; -/* Look, in partial_symtab PST, for symbol NAME in given namespace. - Check the global symbols if GLOBAL, the static symbols if not. - Do wild-card match if WILD. */ + if (get_frame_locals_address (frame) == target_link) + { + struct block *block; + + QUIT; -static struct partial_symbol * -ada_lookup_partial_symbol (struct partial_symtab *pst, const char *name, - int global, domain_enum namespace, int wild) -{ - struct partial_symbol **start; - int name_len = strlen (name); - int length = (global ? pst->n_global_syms : pst->n_static_syms); - int i; + block = get_frame_block (frame, 0); + while (block != NULL && block_function (block) != NULL + && num_defns_collected (obstackp) == 0) + { + QUIT; - if (length == 0) - { - return (NULL); + ada_add_block_symbols (obstackp, block, name, namespace, + NULL, NULL, wild_match); + + block = BLOCK_SUPERBLOCK (block); + } + } } - start = (global ? - pst->objfile->global_psymbols.list + pst->globals_offset : - pst->objfile->static_psymbols.list + pst->statics_offset); - - if (wild) - { - for (i = 0; i < length; i += 1) - { - struct partial_symbol *psym = start[i]; + do_cleanups (old_chain); +#endif +} - if (SYMBOL_DOMAIN (psym) == namespace && - wild_match (name, name_len, SYMBOL_LINKAGE_NAME (psym))) - return psym; - } - return NULL; - } - else - { - if (global) - { - int U; - i = 0; - U = length - 1; - while (U - i > 4) - { - int M = (U + i) >> 1; - struct partial_symbol *psym = start[M]; - if (SYMBOL_LINKAGE_NAME (psym)[0] < name[0]) - i = M + 1; - else if (SYMBOL_LINKAGE_NAME (psym)[0] > name[0]) - U = M - 1; - else if (strcmp (SYMBOL_LINKAGE_NAME (psym), name) < 0) - i = M + 1; - else - U = M; - } - } - else - i = 0; +/* FIXME: The next two routines belong in symtab.c */ - while (i < length) - { - struct partial_symbol *psym = start[i]; +static void restore_language (void* lang) +{ + set_language ((enum language) lang); +} - if (SYMBOL_DOMAIN (psym) == namespace) - { - int cmp = strncmp (name, SYMBOL_LINKAGE_NAME (psym), name_len); +/* As for lookup_symbol, but performed as if the current language + were LANG. */ - if (cmp < 0) - { - if (global) - break; - } - else if (cmp == 0 - && is_name_suffix (SYMBOL_LINKAGE_NAME (psym) - + name_len)) - return psym; - } - i += 1; - } +struct symbol * +lookup_symbol_in_language (const char *name, const struct block *block, + domain_enum domain, enum language lang, + int *is_a_field_of_this, struct symtab **symtab) +{ + struct cleanup *old_chain + = make_cleanup (restore_language, (void*) current_language->la_language); + struct symbol *result; + set_language (lang); + result = lookup_symbol (name, block, domain, is_a_field_of_this, symtab); + do_cleanups (old_chain); + return result; +} - if (global) - { - int U; - i = 0; - U = length - 1; - while (U - i > 4) - { - int M = (U + i) >> 1; - struct partial_symbol *psym = start[M]; - if (SYMBOL_LINKAGE_NAME (psym)[0] < '_') - i = M + 1; - else if (SYMBOL_LINKAGE_NAME (psym)[0] > '_') - U = M - 1; - else if (strcmp (SYMBOL_LINKAGE_NAME (psym), "_ada_") < 0) - i = M + 1; - else - U = M; - } - } - else - i = 0; +/* True if TYPE is definitely an artificial type supplied to a symbol + for which no debugging information was given in the symbol file. */ - while (i < length) - { - struct partial_symbol *psym = start[i]; +static int +is_nondebugging_type (struct type *type) +{ + char *name = ada_type_name (type); + return (name != NULL && strcmp (name, "") == 0); +} - if (SYMBOL_DOMAIN (psym) == namespace) - { - int cmp; +/* Remove any non-debugging symbols in SYMS[0 .. NSYMS-1] that definitely + duplicate other symbols in the list (The only case I know of where + this happens is when object files containing stabs-in-ecoff are + linked with files containing ordinary ecoff debugging symbols (or no + debugging symbols)). Modifies SYMS to squeeze out deleted entries. + Returns the number of items in the modified list. */ - cmp = (int) '_' - (int) SYMBOL_LINKAGE_NAME (psym)[0]; - if (cmp == 0) - { - cmp = strncmp ("_ada_", SYMBOL_LINKAGE_NAME (psym), 5); - if (cmp == 0) - cmp = strncmp (name, SYMBOL_LINKAGE_NAME (psym) + 5, - name_len); - } +static int +remove_extra_symbols (struct ada_symbol_info *syms, int nsyms) +{ + int i, j; - if (cmp < 0) + i = 0; + while (i < nsyms) + { + if (SYMBOL_LINKAGE_NAME (syms[i].sym) != NULL + && SYMBOL_CLASS (syms[i].sym) == LOC_STATIC + && is_nondebugging_type (SYMBOL_TYPE (syms[i].sym))) + { + for (j = 0; j < nsyms; j += 1) + { + if (i != j + && SYMBOL_LINKAGE_NAME (syms[j].sym) != NULL + && strcmp (SYMBOL_LINKAGE_NAME (syms[i].sym), + SYMBOL_LINKAGE_NAME (syms[j].sym)) == 0 + && SYMBOL_CLASS (syms[i].sym) == SYMBOL_CLASS (syms[j].sym) + && SYMBOL_VALUE_ADDRESS (syms[i].sym) + == SYMBOL_VALUE_ADDRESS (syms[j].sym)) { - if (global) - break; + int k; + for (k = i + 1; k < nsyms; k += 1) + syms[k - 1] = syms[k]; + nsyms -= 1; + goto NextSymbol; } - else if (cmp == 0 - && is_name_suffix (SYMBOL_LINKAGE_NAME (psym) - + name_len + 5)) - return psym; } - i += 1; } + i += 1; + NextSymbol: + ; } - return NULL; + return nsyms; } -/* Find a symbol table containing symbol SYM or NULL if none. */ +/* Given a type that corresponds to a renaming entity, use the type name + to extract the scope (package name or function name, fully qualified, + and following the GNAT encoding convention) where this renaming has been + defined. The string returned needs to be deallocated after use. */ -static struct symtab * -symtab_for_sym (struct symbol *sym) +static char * +xget_renaming_scope (struct type *renaming_type) { - struct symtab *s; - struct objfile *objfile; - struct block *b; - struct symbol *tmp_sym; - struct dict_iterator iter; - int j; + /* The renaming types adhere to the following convention: + _____. + So, to extract the scope, we search for the "___XR" extension, + and then backtrack until we find the first "__". */ + + const char *name = type_name_no_tag (renaming_type); + char *suffix = strstr (name, "___XR"); + char *last; + int scope_len; + char *scope; - ALL_SYMTABS (objfile, s) - { - switch (SYMBOL_CLASS (sym)) - { - case LOC_CONST: - case LOC_STATIC: - case LOC_TYPEDEF: - case LOC_REGISTER: - case LOC_LABEL: - case LOC_BLOCK: - case LOC_CONST_BYTES: - b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK); - ALL_BLOCK_SYMBOLS (b, iter, tmp_sym) if (sym == tmp_sym) - return s; - b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK); - ALL_BLOCK_SYMBOLS (b, iter, tmp_sym) if (sym == tmp_sym) - return s; - break; - default: - break; - } - switch (SYMBOL_CLASS (sym)) - { - case LOC_REGISTER: - case LOC_ARG: - case LOC_REF_ARG: - case LOC_REGPARM: - case LOC_REGPARM_ADDR: - case LOC_LOCAL: - case LOC_TYPEDEF: - case LOC_LOCAL_ARG: - case LOC_BASEREG: - case LOC_BASEREG_ARG: - case LOC_COMPUTED: - case LOC_COMPUTED_ARG: - for (j = FIRST_LOCAL_BLOCK; - j < BLOCKVECTOR_NBLOCKS (BLOCKVECTOR (s)); j += 1) - { - b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), j); - ALL_BLOCK_SYMBOLS (b, iter, tmp_sym) if (sym == tmp_sym) - return s; - } - break; - default: - break; - } - } - return NULL; -} - -/* Return a minimal symbol matching NAME according to Ada decoding - rules. Returns NULL if there is no such minimal symbol. Names - prefixed with "standard__" are handled specially: "standard__" is - first stripped off, and only static and global symbols are searched. */ - -struct minimal_symbol * -ada_lookup_simple_minsym (const char *name) -{ - struct objfile *objfile; - struct minimal_symbol *msymbol; - int wild_match; - - if (strncmp (name, "standard__", sizeof ("standard__") - 1) == 0) - { - name += sizeof ("standard__") - 1; - wild_match = 0; - } - else - wild_match = (strstr (name, "__") == NULL); + /* Now, backtrack a bit until we find the first "__". Start looking + at suffix - 3, as the part is at least one character long. */ - ALL_MSYMBOLS (objfile, msymbol) - { - if (ada_match_name (SYMBOL_LINKAGE_NAME (msymbol), name, wild_match) - && MSYMBOL_TYPE (msymbol) != mst_solib_trampoline) - return msymbol; - } + for (last = suffix - 3; last > name; last--) + if (last[0] == '_' && last[1] == '_') + break; + + /* Make a copy of scope and return it. */ - return NULL; -} + scope_len = last - name; + scope = (char *) xmalloc ((scope_len + 1) * sizeof (char)); -/* Return up minimal symbol for NAME, folded and encoded according to - Ada conventions, or NULL if none. The last two arguments are ignored. */ + strncpy (scope, name, scope_len); + scope[scope_len] = '\0'; -static struct minimal_symbol * -ada_lookup_minimal_symbol (const char *name, const char *sfile, - struct objfile *objf) -{ - return ada_lookup_simple_minsym (ada_encode (name)); + return scope; } -/* For all subprograms that statically enclose the subprogram of the - selected frame, add symbols matching identifier NAME in DOMAIN - and their blocks to the list of data in OBSTACKP, as for - ada_add_block_symbols (q.v.). If WILD, treat as NAME with a - wildcard prefix. */ +/* Return nonzero if NAME corresponds to a package name. */ -static void -add_symbols_from_enclosing_procs (struct obstack *obstackp, - const char *name, domain_enum namespace, - int wild_match) +static int +is_package_name (const char *name) { -#ifdef HAVE_ADD_SYMBOLS_FROM_ENCLOSING_PROCS - /* Use a heuristic to find the frames of enclosing subprograms: treat the - pointer-sized value at location 0 from the local-variable base of a - frame as a static link, and then search up the call stack for a - frame with that same local-variable base. */ - static struct symbol static_link_sym; - static struct symbol *static_link; - struct value *target_link_val; - - struct cleanup *old_chain = make_cleanup (null_cleanup, NULL); - struct frame_info *frame; + /* Here, We take advantage of the fact that no symbols are generated + for packages, while symbols are generated for each function. + So the condition for NAME represent a package becomes equivalent + to NAME not existing in our list of symbols. There is only one + small complication with library-level functions (see below). */ - if (! target_has_stack) - return; + char *fun_name; + + /* If it is a function that has not been defined at library level, + then we should be able to look it up in the symbols. */ + if (standard_lookup (name, NULL, VAR_DOMAIN) != NULL) + return 0; - if (static_link == NULL) - { - /* Initialize the local variable symbol that stands for the - static link (when there is one). */ - static_link = &static_link_sym; - SYMBOL_LINKAGE_NAME (static_link) = ""; - SYMBOL_LANGUAGE (static_link) = language_unknown; - SYMBOL_CLASS (static_link) = LOC_LOCAL; - SYMBOL_DOMAIN (static_link) = VAR_DOMAIN; - SYMBOL_TYPE (static_link) = lookup_pointer_type (builtin_type_void); - SYMBOL_VALUE (static_link) = - -(long) TYPE_LENGTH (SYMBOL_TYPE (static_link)); - } + /* Library-level function names start with "_ada_". See if function + "_ada_" followed by NAME can be found. */ - frame = get_selected_frame (); - if (frame == NULL - || inside_main_func (get_frame_address_in_block (frame))) - return; + /* Do a quick check that NAME does not contain "__", since library-level + functions names can not contain "__" in them. */ + if (strstr (name, "__") != NULL) + return 0; - target_link_val = read_var_value (static_link, frame); - while (target_link_val != NULL - && num_defns_collected (obstackp) == 0 - && frame_relative_level (frame) <= MAX_ENCLOSING_FRAME_LEVELS) - { - CORE_ADDR target_link = value_as_address (target_link_val); + fun_name = (char *) alloca (strlen (name) + 5 + 1); + xasprintf (&fun_name, "_ada_%s", name); - frame = get_prev_frame (frame); - if (frame == NULL) - break; + return (standard_lookup (fun_name, NULL, VAR_DOMAIN) == NULL); +} - if (get_frame_locals_address (frame) == target_link) - { - struct block *block; - - QUIT; +/* Return nonzero if SYM corresponds to a renaming entity that is + visible from FUNCTION_NAME. */ - block = get_frame_block (frame, 0); - while (block != NULL && block_function (block) != NULL - && num_defns_collected (obstackp) == 0) - { - QUIT; +static int +renaming_is_visible (const struct symbol *sym, char *function_name) +{ + char *scope = xget_renaming_scope (SYMBOL_TYPE (sym)); - ada_add_block_symbols (obstackp, block, name, namespace, - NULL, NULL, wild_match); - - block = BLOCK_SUPERBLOCK (block); - } - } - } + make_cleanup (xfree, scope); - do_cleanups (old_chain); -#endif -} + /* If the rename has been defined in a package, then it is visible. */ + if (is_package_name (scope)) + return 1; -/* FIXME: The next two routines belong in symtab.c */ + /* Check that the rename is in the current function scope by checking + that its name starts with SCOPE. */ + + /* If the function name starts with "_ada_", it means that it is + a library-level function. Strip this prefix before doing the + comparison, as the encoding for the renaming does not contain + this prefix. */ + if (strncmp (function_name, "_ada_", 5) == 0) + function_name += 5; -static void restore_language (void* lang) -{ - set_language ((enum language) lang); + return (strncmp (function_name, scope, strlen (scope)) == 0); } -/* As for lookup_symbol, but performed as if the current language - were LANG. */ - -struct symbol * -lookup_symbol_in_language (const char *name, const struct block *block, - domain_enum domain, enum language lang, - int *is_a_field_of_this, struct symtab **symtab) -{ - struct cleanup *old_chain - = make_cleanup (restore_language, (void*) current_language->la_language); - struct symbol *result; - set_language (lang); - result = lookup_symbol (name, block, domain, is_a_field_of_this, symtab); - do_cleanups (old_chain); - return result; -} +/* Iterates over the SYMS list and remove any entry that corresponds to + a renaming entity that is not visible from the function associated + with CURRENT_BLOCK. + + Rationale: + GNAT emits a type following a specified encoding for each renaming + entity. Unfortunately, STABS currently does not support the definition + of types that are local to a given lexical block, so all renamings types + are emitted at library level. As a consequence, if an application + contains two renaming entities using the same name, and a user tries to + print the value of one of these entities, the result of the ada symbol + lookup will also contain the wrong renaming type. -/* True if TYPE is definitely an artificial type supplied to a symbol - for which no debugging information was given in the symbol file. */ + This function partially covers for this limitation by attempting to + remove from the SYMS list renaming symbols that should be visible + from CURRENT_BLOCK. However, there does not seem be a 100% reliable + method with the current information available. The implementation + below has a couple of limitations (FIXME: brobecker-2003-05-12): + + - When the user tries to print a rename in a function while there + is another rename entity defined in a package: Normally, the + rename in the function has precedence over the rename in the + package, so the latter should be removed from the list. This is + currently not the case. + + - This function will incorrectly remove valid renames if + the CURRENT_BLOCK corresponds to a function which symbol name + has been changed by an "Export" pragma. As a consequence, + the user will be unable to print such rename entities. */ static int -is_nondebugging_type (struct type *type) -{ - char *name = ada_type_name (type); - return (name != NULL && strcmp (name, "") == 0); -} - -/* Remove any non-debugging symbols in SYMS[0 .. NSYMS-1] that definitely - duplicate other symbols in the list (The only case I know of where - this happens is when object files containing stabs-in-ecoff are - linked with files containing ordinary ecoff debugging symbols (or no - debugging symbols)). Modifies SYMS to squeeze out deleted entries. - Returns the number of items in the modified list. */ - -static int -remove_extra_symbols (struct ada_symbol_info *syms, int nsyms) -{ - int i, j; - - i = 0; - while (i < nsyms) - { - if (SYMBOL_LINKAGE_NAME (syms[i].sym) != NULL - && SYMBOL_CLASS (syms[i].sym) == LOC_STATIC - && is_nondebugging_type (SYMBOL_TYPE (syms[i].sym))) - { - for (j = 0; j < nsyms; j += 1) - { - if (i != j - && SYMBOL_LINKAGE_NAME (syms[j].sym) != NULL - && strcmp (SYMBOL_LINKAGE_NAME (syms[i].sym), - SYMBOL_LINKAGE_NAME (syms[j].sym)) == 0 - && SYMBOL_CLASS (syms[i].sym) == SYMBOL_CLASS (syms[j].sym) - && SYMBOL_VALUE_ADDRESS (syms[i].sym) - == SYMBOL_VALUE_ADDRESS (syms[j].sym)) - { - int k; - for (k = i + 1; k < nsyms; k += 1) - syms[k - 1] = syms[k]; - nsyms -= 1; - goto NextSymbol; - } - } - } - i += 1; - NextSymbol: - ; - } - return nsyms; -} - -/* Given a type that corresponds to a renaming entity, use the type name - to extract the scope (package name or function name, fully qualified, - and following the GNAT encoding convention) where this renaming has been - defined. The string returned needs to be deallocated after use. */ - -static char * -xget_renaming_scope (struct type *renaming_type) -{ - /* The renaming types adhere to the following convention: - _____. - So, to extract the scope, we search for the "___XR" extension, - and then backtrack until we find the first "__". */ - - const char *name = type_name_no_tag (renaming_type); - char *suffix = strstr (name, "___XR"); - char *last; - int scope_len; - char *scope; - - /* Now, backtrack a bit until we find the first "__". Start looking - at suffix - 3, as the part is at least one character long. */ - - for (last = suffix - 3; last > name; last--) - if (last[0] == '_' && last[1] == '_') - break; - - /* Make a copy of scope and return it. */ - - scope_len = last - name; - scope = (char *) xmalloc ((scope_len + 1) * sizeof (char)); - - strncpy (scope, name, scope_len); - scope[scope_len] = '\0'; - - return scope; -} - -/* Return nonzero if NAME corresponds to a package name. */ - -static int -is_package_name (const char *name) -{ - /* Here, We take advantage of the fact that no symbols are generated - for packages, while symbols are generated for each function. - So the condition for NAME represent a package becomes equivalent - to NAME not existing in our list of symbols. There is only one - small complication with library-level functions (see below). */ - - char *fun_name; - - /* If it is a function that has not been defined at library level, - then we should be able to look it up in the symbols. */ - if (standard_lookup (name, NULL, VAR_DOMAIN) != NULL) - return 0; - - /* Library-level function names start with "_ada_". See if function - "_ada_" followed by NAME can be found. */ - - /* Do a quick check that NAME does not contain "__", since library-level - functions names can not contain "__" in them. */ - if (strstr (name, "__") != NULL) - return 0; - - fun_name = (char *) alloca (strlen (name) + 5 + 1); - xasprintf (&fun_name, "_ada_%s", name); - - return (standard_lookup (fun_name, NULL, VAR_DOMAIN) == NULL); -} - -/* Return nonzero if SYM corresponds to a renaming entity that is - visible from FUNCTION_NAME. */ - -static int -renaming_is_visible (const struct symbol *sym, char *function_name) -{ - char *scope = xget_renaming_scope (SYMBOL_TYPE (sym)); - - make_cleanup (xfree, scope); - - /* If the rename has been defined in a package, then it is visible. */ - if (is_package_name (scope)) - return 1; - - /* Check that the rename is in the current function scope by checking - that its name starts with SCOPE. */ - - /* If the function name starts with "_ada_", it means that it is - a library-level function. Strip this prefix before doing the - comparison, as the encoding for the renaming does not contain - this prefix. */ - if (strncmp (function_name, "_ada_", 5) == 0) - function_name += 5; - - return (strncmp (function_name, scope, strlen (scope)) == 0); -} - -/* Iterates over the SYMS list and remove any entry that corresponds to - a renaming entity that is not visible from the function associated - with CURRENT_BLOCK. - - Rationale: - GNAT emits a type following a specified encoding for each renaming - entity. Unfortunately, STABS currently does not support the definition - of types that are local to a given lexical block, so all renamings types - are emitted at library level. As a consequence, if an application - contains two renaming entities using the same name, and a user tries to - print the value of one of these entities, the result of the ada symbol - lookup will also contain the wrong renaming type. - - This function partially covers for this limitation by attempting to - remove from the SYMS list renaming symbols that should be visible - from CURRENT_BLOCK. However, there does not seem be a 100% reliable - method with the current information available. The implementation - below has a couple of limitations (FIXME: brobecker-2003-05-12): - - - When the user tries to print a rename in a function while there - is another rename entity defined in a package: Normally, the - rename in the function has precedence over the rename in the - package, so the latter should be removed from the list. This is - currently not the case. - - - This function will incorrectly remove valid renames if - the CURRENT_BLOCK corresponds to a function which symbol name - has been changed by an "Export" pragma. As a consequence, - the user will be unable to print such rename entities. */ - -static int -remove_out_of_scope_renamings (struct ada_symbol_info *syms, - int nsyms, - struct block *current_block) +remove_out_of_scope_renamings (struct ada_symbol_info *syms, + int nsyms, + struct block *current_block) { struct symbol *current_function; char *current_function_name; @@ -5179,166 +4965,460 @@ wild_match (const char *patn0, int patn_ name += 1; name_len -= 1; } - } - - return 0; -} + } + + return 0; +} + + +/* Add symbols from BLOCK matching identifier NAME in DOMAIN to + vector *defn_symbols, updating the list of symbols in OBSTACKP + (if necessary). If WILD, treat as NAME with a wildcard prefix. + OBJFILE is the section containing BLOCK. + SYMTAB is recorded with each symbol added. */ + +static void +ada_add_block_symbols (struct obstack *obstackp, + struct block *block, const char *name, + domain_enum domain, struct objfile *objfile, + struct symtab *symtab, int wild) +{ + struct dict_iterator iter; + int name_len = strlen (name); + /* A matching argument symbol, if any. */ + struct symbol *arg_sym; + /* Set true when we find a matching non-argument symbol. */ + int found_sym; + struct symbol *sym; + + arg_sym = NULL; + found_sym = 0; + if (wild) + { + struct symbol *sym; + ALL_BLOCK_SYMBOLS (block, iter, sym) + { + if (SYMBOL_DOMAIN (sym) == domain && + wild_match (name, name_len, SYMBOL_LINKAGE_NAME (sym))) + { + switch (SYMBOL_CLASS (sym)) + { + case LOC_ARG: + case LOC_LOCAL_ARG: + case LOC_REF_ARG: + case LOC_REGPARM: + case LOC_REGPARM_ADDR: + case LOC_BASEREG_ARG: + case LOC_COMPUTED_ARG: + arg_sym = sym; + break; + case LOC_UNRESOLVED: + continue; + default: + found_sym = 1; + add_defn_to_vec (obstackp, + fixup_symbol_section (sym, objfile), + block, symtab); + break; + } + } + } + } + else + { + ALL_BLOCK_SYMBOLS (block, iter, sym) + { + if (SYMBOL_DOMAIN (sym) == domain) + { + int cmp = strncmp (name, SYMBOL_LINKAGE_NAME (sym), name_len); + if (cmp == 0 + && is_name_suffix (SYMBOL_LINKAGE_NAME (sym) + name_len)) + { + switch (SYMBOL_CLASS (sym)) + { + case LOC_ARG: + case LOC_LOCAL_ARG: + case LOC_REF_ARG: + case LOC_REGPARM: + case LOC_REGPARM_ADDR: + case LOC_BASEREG_ARG: + case LOC_COMPUTED_ARG: + arg_sym = sym; + break; + case LOC_UNRESOLVED: + break; + default: + found_sym = 1; + add_defn_to_vec (obstackp, + fixup_symbol_section (sym, objfile), + block, symtab); + break; + } + } + } + } + } + + if (!found_sym && arg_sym != NULL) + { + add_defn_to_vec (obstackp, + fixup_symbol_section (arg_sym, objfile), + block, symtab); + } + + if (!wild) + { + arg_sym = NULL; + found_sym = 0; + + ALL_BLOCK_SYMBOLS (block, iter, sym) + { + if (SYMBOL_DOMAIN (sym) == domain) + { + int cmp; + + cmp = (int) '_' - (int) SYMBOL_LINKAGE_NAME (sym)[0]; + if (cmp == 0) + { + cmp = strncmp ("_ada_", SYMBOL_LINKAGE_NAME (sym), 5); + if (cmp == 0) + cmp = strncmp (name, SYMBOL_LINKAGE_NAME (sym) + 5, + name_len); + } + + if (cmp == 0 + && is_name_suffix (SYMBOL_LINKAGE_NAME (sym) + name_len + 5)) + { + switch (SYMBOL_CLASS (sym)) + { + case LOC_ARG: + case LOC_LOCAL_ARG: + case LOC_REF_ARG: + case LOC_REGPARM: + case LOC_REGPARM_ADDR: + case LOC_BASEREG_ARG: + case LOC_COMPUTED_ARG: + arg_sym = sym; + break; + case LOC_UNRESOLVED: + break; + default: + found_sym = 1; + add_defn_to_vec (obstackp, + fixup_symbol_section (sym, objfile), + block, symtab); + break; + } + } + } + end_loop2: ; + } + + /* NOTE: This really shouldn't be needed for _ada_ symbols. + They aren't parameters, right? */ + if (!found_sym && arg_sym != NULL) + { + add_defn_to_vec (obstackp, + fixup_symbol_section (arg_sym, objfile), + block, symtab); + } + } +} + +#ifdef GNAT_GDB + + /* 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; +} + +/* 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 (struct string_vector *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); + } + + string_vector_append (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. */ + +char ** +ada_make_symbol_completion_list (const char *text0, const char *word) +{ + /* Note: This function is almost a copy of make_symbol_completion_list(), + except it has been adapted for Ada. It is somewhat of a shame to + duplicate so much code, but we don't really have the infrastructure + yet to develop a language-aware version of he symbol completer... */ + char *text; + int text_len; + int wild_match; + int encoded; + struct string_vector result = xnew_string_vector (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]); + + /* FIXME: brobecker/2003-09-17: When we get rid of ADA_RETAIN_DOTS, + we can restrict the wild_match check to searching "__" only. */ + wild_match = (strstr (text0, "__") == NULL + && strchr (text0, '.') == NULL); + encoded = (strstr (text0, "__") != NULL); + } + + /* 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 (&result, 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 (&result, 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). */ -/* Add symbols from BLOCK matching identifier NAME in DOMAIN to - vector *defn_symbols, updating the list of symbols in OBSTACKP - (if necessary). If WILD, treat as NAME with a wildcard prefix. - OBJFILE is the section containing BLOCK. - SYMTAB is recorded with each symbol added. */ + ALL_MSYMBOLS (objfile, msymbol) + { + QUIT; + symbol_completion_add (&result, SYMBOL_LINKAGE_NAME (msymbol), + text, text_len, text0, word, + wild_match, encoded); + } -static void -ada_add_block_symbols (struct obstack *obstackp, - struct block *block, const char *name, - domain_enum domain, struct objfile *objfile, - struct symtab *symtab, int wild) -{ - struct dict_iterator iter; - int name_len = strlen (name); - /* A matching argument symbol, if any. */ - struct symbol *arg_sym; - /* Set true when we find a matching non-argument symbol. */ - int found_sym; - struct symbol *sym; + /* Search upwards from currently selected frame (so that we can + complete on local vars. */ - arg_sym = NULL; - found_sym = 0; - if (wild) - { - struct symbol *sym; - ALL_BLOCK_SYMBOLS (block, iter, sym) - { - if (SYMBOL_DOMAIN (sym) == domain && - wild_match (name, name_len, SYMBOL_LINKAGE_NAME (sym))) - { - switch (SYMBOL_CLASS (sym)) - { - case LOC_ARG: - case LOC_LOCAL_ARG: - case LOC_REF_ARG: - case LOC_REGPARM: - case LOC_REGPARM_ADDR: - case LOC_BASEREG_ARG: - case LOC_COMPUTED_ARG: - arg_sym = sym; - break; - case LOC_UNRESOLVED: - continue; - default: - found_sym = 1; - add_defn_to_vec (obstackp, - fixup_symbol_section (sym, objfile), - block, symtab); - break; - } - } - } - } - else + for (b = get_selected_block (0); b != NULL; b = BLOCK_SUPERBLOCK (b)) { - ALL_BLOCK_SYMBOLS (block, iter, sym) + if (!BLOCK_SUPERBLOCK (b)) + surrounding_static_block = b; /* For elmin of dups */ + + ALL_BLOCK_SYMBOLS (b, iter, sym) { - if (SYMBOL_DOMAIN (sym) == domain) - { - int cmp = strncmp (name, SYMBOL_LINKAGE_NAME (sym), name_len); - if (cmp == 0 - && is_name_suffix (SYMBOL_LINKAGE_NAME (sym) + name_len)) - { - switch (SYMBOL_CLASS (sym)) - { - case LOC_ARG: - case LOC_LOCAL_ARG: - case LOC_REF_ARG: - case LOC_REGPARM: - case LOC_REGPARM_ADDR: - case LOC_BASEREG_ARG: - case LOC_COMPUTED_ARG: - arg_sym = sym; - break; - case LOC_UNRESOLVED: - break; - default: - found_sym = 1; - add_defn_to_vec (obstackp, - fixup_symbol_section (sym, objfile), - block, symtab); - break; - } - } - } + symbol_completion_add (&result, SYMBOL_LINKAGE_NAME (sym), + text, text_len, text0, word, + wild_match, encoded); } } - if (!found_sym && arg_sym != NULL) - { - add_defn_to_vec (obstackp, - fixup_symbol_section (arg_sym, objfile), - block, symtab); - } - - if (!wild) - { - arg_sym = NULL; - found_sym = 0; + /* Go through the symtabs and check the externs and statics for + symbols which match. */ - ALL_BLOCK_SYMBOLS (block, iter, sym) - { - if (SYMBOL_DOMAIN (sym) == domain) - { - int cmp; + ALL_SYMTABS (objfile, s) + { + QUIT; + b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK); + ALL_BLOCK_SYMBOLS (b, iter, sym) + { + symbol_completion_add (&result, SYMBOL_LINKAGE_NAME (sym), + text, text_len, text0, word, + wild_match, encoded); + } + } - cmp = (int) '_' - (int) SYMBOL_LINKAGE_NAME (sym)[0]; - if (cmp == 0) - { - cmp = strncmp ("_ada_", SYMBOL_LINKAGE_NAME (sym), 5); - if (cmp == 0) - cmp = strncmp (name, SYMBOL_LINKAGE_NAME (sym) + 5, - name_len); - } + 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 (&result, SYMBOL_LINKAGE_NAME (sym), + text, text_len, text0, word, + wild_match, encoded); + } + } - if (cmp == 0 - && is_name_suffix (SYMBOL_LINKAGE_NAME (sym) + name_len + 5)) - { - switch (SYMBOL_CLASS (sym)) - { - case LOC_ARG: - case LOC_LOCAL_ARG: - case LOC_REF_ARG: - case LOC_REGPARM: - case LOC_REGPARM_ADDR: - case LOC_BASEREG_ARG: - case LOC_COMPUTED_ARG: - arg_sym = sym; - break; - case LOC_UNRESOLVED: - break; - default: - found_sym = 1; - add_defn_to_vec (obstackp, - fixup_symbol_section (sym, objfile), - block, symtab); - break; - } - } - } - end_loop2: ; - } + /* Append the closing NULL entry. */ + string_vector_append (&result, NULL); - /* NOTE: This really shouldn't be needed for _ada_ symbols. - They aren't parameters, right? */ - if (!found_sym && arg_sym != NULL) - { - add_defn_to_vec (obstackp, - fixup_symbol_section (arg_sym, objfile), - block, symtab); - } - } + return (result.array); } + +#endif /* GNAT_GDB */ +#ifdef GNAT_GDB /* Breakpoint-related */ /* Import message from symtab.c. */ @@ -6041,37 +6121,6 @@ extended_canonical_line_spec (struct sym return r; } -/* If the main procedure is written in Ada, then return its name. - The result is good until the next call. Return NULL if the main - procedure doesn't appear to be in Ada. */ - -char * -ada_main_name (void) -{ - struct minimal_symbol *msym; - CORE_ADDR main_program_name_addr; - static char main_program_name[1024]; - /* For Ada, the name of the main procedure is stored in a specific - string constant, generated by the binder. Look for that symbol, - extract its address, and then read that string. If we didn't find - that string, then most probably the main procedure is not written - in Ada. */ - msym = lookup_minimal_symbol (ADA_MAIN_PROGRAM_SYMBOL_NAME, NULL, NULL); - - if (msym != NULL) - { - main_program_name_addr = SYMBOL_VALUE_ADDRESS (msym); - if (main_program_name_addr == 0) - error ("Invalid address for Ada main program name."); - - extract_string (main_program_name_addr, main_program_name); - return main_program_name; - } - - /* The main procedure doesn't seem to be in Ada. */ - return NULL; -} - /* Return type of Ada breakpoint associated with bp_stat: 0 if not an Ada-specific breakpoint, 1 for break on specific exception, 2 for break on unhandled exception, 3 for assert. */ @@ -6079,12 +6128,8 @@ ada_main_name (void) static int ada_exception_breakpoint_type (bpstat bs) { -#ifdef GNAT_GDB return ((! bs || ! bs->breakpoint_at) ? 0 : bs->breakpoint_at->break_on_exception); -#else - return 0; -#endif } /* True iff FRAME is very likely to be that of a function that is @@ -6285,7 +6330,6 @@ exception_name_from_cond (const char *co int ada_print_exception_breakpoint_nontask (struct breakpoint *b) { -#ifdef GNAT_GDB if (b->break_on_exception == 1) { if (b->cond_string) /* the breakpoint is on a specific exception. */ @@ -6314,9 +6358,6 @@ ada_print_exception_breakpoint_nontask ( else return 0; return 1; -#else - return 0; -#endif } /* Print task identifier for breakpoint B, if it is an Ada-specific @@ -6325,13 +6366,11 @@ ada_print_exception_breakpoint_nontask ( void ada_print_exception_breakpoint_task (struct breakpoint *b) { -#ifdef GNAT_GDB if (b->task != 0) { ui_out_text (uiout, " task "); ui_out_field_int (uiout, "task", b->task); } -#endif } int @@ -6476,8 +6515,8 @@ ada_breakpoint_rewrite (char *arg, int * } return arg; } +#endif - /* Field Access */ /* True if field number FIELD_NUM in struct or union type TYPE is supposed @@ -10098,7 +10137,7 @@ const struct language_defn ada_language_ #ifdef GNAT_GDB ada_lookup_symbol, ada_lookup_minimal_symbol, -#endif +#endif /* GNAT_GDB */ &ada_exp_descriptor, parse, ada_error, @@ -10134,7 +10173,7 @@ const struct language_defn ada_language_ #ifdef GNAT_GDB ada_translate_error_message, /* Substitute Ada-specific terminology in errors and warnings. */ -#endif +#endif /* GNAT_GDB */ LANG_MAGIC }; @@ -10186,17 +10225,17 @@ _initialize_ada_language (void) deprecated_register_gdbarch_swap (NULL, 0, build_ada_types); add_language (&ada_language_defn); + varsize_limit = 65536; #ifdef GNAT_GDB add_show_from_set (add_set_cmd ("varsize-limit", class_support, var_uinteger, (char *) &varsize_limit, "Set maximum bytes in dynamic-sized object.", &setlist), &showlist); -#endif - varsize_limit = 65536; + obstack_init (&cache_space); +#endif /* GNAT_GDB */ obstack_init (&symbol_list_obstack); - obstack_init (&cache_space); decoded_names_store = htab_create_alloc_ex (256, htab_hash_string, (int (*) (const void *, const void *)) streq, Index: gdb/ada-lang.h =================================================================== RCS file: /cvs/src/src/gdb/ada-lang.h,v retrieving revision 1.8 diff -u -p -r1.8 ada-lang.h --- gdb/ada-lang.h 8 Jun 2004 08:42:04 -0000 1.8 +++ gdb/ada-lang.h 16 Jun 2004 08:10:22 -0000 @@ -124,6 +124,41 @@ struct ada_symbol_info { struct symtab* symtab; }; +/* Ada task structures. */ + +/* Ada task control block, as defined in the GNAT runt-time library. */ + +struct task_control_block +{ + char state; + CORE_ADDR parent; + int priority; + char image [32]; + int image_len; /* This field is not always present in the ATCB. */ + CORE_ADDR call; + CORE_ADDR thread; + CORE_ADDR lwp; /* This field is not always present in the ATCB. */ +}; + +struct task_ptid +{ + int pid; /* The Process id */ + long lwp; /* The Light Weight Process id */ + long tid; /* The Thread id */ +}; +typedef struct task_ptid task_ptid_t; + +struct task_entry +{ + CORE_ADDR task_id; + struct task_control_block atcb; + int task_num; + int known_tasks_index; + struct task_entry *next_task; + task_ptid_t task_ptid; + int stack_per; +}; + extern struct type *builtin_type_ada_int; extern struct type *builtin_type_ada_short; extern struct type *builtin_type_ada_long; @@ -136,9 +171,13 @@ extern struct type *builtin_type_ada_nat extern struct type *builtin_type_ada_positive; extern struct type *builtin_type_ada_system_address; -/* The maximum number of tasks known to the Ada runtime */ +/* The maximum number of tasks known to the Ada runtime. */ extern const int MAX_NUMBER_OF_KNOWN_TASKS; +/* task entry list. */ +extern struct task_entry *task_list; + + /* Assuming V points to an array of S objects, make sure that it contains at least M objects, updating V and S as necessary. */ @@ -393,6 +432,8 @@ extern void ada_find_printable_frame (st extern void ada_reset_thread_registers (void); +extern int ada_build_task_list (void); + /* Look up a symbol by name using the search conventions of a specific language (optional block, optional symtab). FIXME: Should be symtab.h. */ @@ -403,5 +444,4 @@ extern struct symbol *lookup_symbol_in_l enum language, int *, struct symtab **); - #endif Index: gdb/ada-tasks.c =================================================================== RCS file: /cvs/src/src/gdb/ada-tasks.c,v retrieving revision 1.9 diff -u -p -r1.9 ada-tasks.c --- gdb/ada-tasks.c 2 Jun 2004 09:55:36 -0000 1.9 +++ gdb/ada-tasks.c 16 Jun 2004 08:10:22 -0000 @@ -62,18 +62,6 @@ enum task_states Master_Phase_2_Sleep }; -struct task_control_block -{ - char state; - CORE_ADDR parent; - int priority; - char image [32]; - int image_len; /* This field is not always present in the ATCB. */ - CORE_ADDR call; - CORE_ADDR thread; - CORE_ADDR lwp; /* This field is not always present in the ATCB. */ -}; - /* The index of certain important fields in the Ada Task Control Block record and sub-records. */ @@ -102,25 +90,6 @@ struct tcb_fieldnos #define TASK_LWP(atcb) extract_unsigned_integer (&(atcb).lwp, sizeof ((atcb).lwp)) #endif -struct task_ptid -{ - int pid; /* The Process id */ - long lwp; /* The Light Weight Process id */ - long tid; /* The Thread id */ -}; -typedef struct task_ptid task_ptid_t; - -struct task_entry -{ - CORE_ADDR task_id; - struct task_control_block atcb; - int task_num; - int known_tasks_index; - struct task_entry *next_task; - task_ptid_t task_ptid; - int stack_per; -}; - /* FIXME: move all this conditional compilation in description files or in configure.in */ @@ -267,7 +236,6 @@ static void get_tcb_call_type_info (stru int *atcb_call_self_fieldno); static CORE_ADDR get_known_tasks_addr (void); static int read_known_tasks_array (void); -static int build_task_list (void); static void value_as_string (char *dest, struct value *val, int length); static struct task_control_block read_atcb (CORE_ADDR atcb_addr); static CORE_ADDR read_caller (const CORE_ADDR call); @@ -283,9 +251,9 @@ static void ada_tasks_attach_observers ( int ada__tasks_check_symbol_table = 1; CORE_ADDR pthread_kern_addr = 0; +struct task_entry *task_list = NULL; /* Local global variables. */ -static struct task_entry *task_list = NULL; /* When non-zero, this flag indicates that the current task_list is obsolete, and should be recomputed before it is accessed. */ @@ -850,8 +818,8 @@ read_known_tasks_array (void) the inferior. Prints an appropriate message and returns non-zero if it failed to build this list. */ -static int -build_task_list (void) +int +ada_build_task_list (void) { if (!target_has_stack) error ("No stack"); @@ -1306,7 +1274,7 @@ info_tasks (char *arg, int from_tty) static void info_tasks_command (char *arg, int from_tty) { - const int task_list_built = build_task_list (); + const int task_list_built = ada_build_task_list (); if (!task_list_built) return; @@ -1358,13 +1326,10 @@ switch_to_task (struct task_entry *new_t select_frame (get_current_frame ()); return ret_code; } - else if (task_ptid_get_pid (new_task->task_ptid) != 0) /* ?? */ - { - switch_to_thread (task_ptid_get_ptid (new_task->task_ptid)); - return 0; - } + + switch_to_thread (task_ptid_get_ptid (new_task->task_ptid)); #endif - return -1; + return 0; } /* Print a message telling the user id of the current task. @@ -1412,7 +1377,7 @@ task_command_1 (char *tidstr, int from_t static void task_command (char *tidstr, int from_tty) { - const int task_list_built = build_task_list (); + const int task_list_built = ada_build_task_list (); if (!task_list_built) return;