Split up end_symtab_from_static_block into two.
This patch is conceptually quite simple. If you look at end_symtab_from_static_block you'll see that the static_block == NULL case is completely different than the non-NULL case. There's a lot of complexity to handle the NULL case but it seems entirely unnecessary. For example, whether blockvector is NULL is decided at the start, before this for loop: for (subfile = subfiles; subfile; subfile = nextsub) Secondly, after the for loop, we test symtab for non-NULL here: /* Set this for the main source file. */ if (symtab) but symtab will only ever be non-NULL if blockvector was non-NULL. And if blockvector was non_NULL so will symtab. The other case to consider is these lines of code executed before the for loop: /* Read the line table if it has to be read separately. This is only used by xcoffread.c. */ if (objfile->sf->sym_read_linetable != NULL) objfile->sf->sym_read_linetable (objfile); /* Handle the case where the debug info specifies a different path for the main source file. It can cause us to lose track of its line number information. */ watch_main_source_file_lossage (); From my reading of the code, neither of these is useful in the static_block == NULL case. Thus we can make the code more readable by splitting these two cases up, which is what this patch does. gdb/ChangeLog: * buildsym.c (main_subfile): New static global. (free_subfiles_list): New function. (start_symtab): Set main_subfile. (restart_symtab): Replace init of subfiles, current_subfile with call to free_subfiles_list. (watch_main_source_file_lossage): Use main_subfile. (reset_symtab_globals): Replace init of current_subfile with call to free_subfiles_list. (end_symtab_without_blockvector, end_symtab_with_blockvector): New functions, split out from ... (end_symtab_from_static_block): ... here. Rewrite to call them.
This commit is contained in:
parent
f194fefb5e
commit
7bab9b58fd
2 changed files with 252 additions and 216 deletions
|
@ -1,3 +1,17 @@
|
|||
2014-11-18 Doug Evans <xdje42@gmail.com>
|
||||
|
||||
* buildsym.c (main_subfile): New static global.
|
||||
(free_subfiles_list): New function.
|
||||
(start_symtab): Set main_subfile.
|
||||
(restart_symtab): Replace init of subfiles, current_subfile with
|
||||
call to free_subfiles_list.
|
||||
(watch_main_source_file_lossage): Use main_subfile.
|
||||
(reset_symtab_globals): Replace init of current_subfile with call
|
||||
to free_subfiles_list.
|
||||
(end_symtab_without_blockvector, end_symtab_with_blockvector): New
|
||||
functions, split out from ...
|
||||
(end_symtab_from_static_block): ... here. Rewrite to call them.
|
||||
|
||||
2014-11-18 Doug Evans <xdje42@gmail.com>
|
||||
|
||||
The result of symtab expansion is always a primary symtab.
|
||||
|
|
454
gdb/buildsym.c
454
gdb/buildsym.c
|
@ -56,6 +56,12 @@
|
|||
|
||||
static struct subfile *subfiles;
|
||||
|
||||
/* The "main" subfile.
|
||||
In C this is the ".c" file (and similarly for other languages).
|
||||
This becomes the "primary" symtab of the compilation unit. */
|
||||
|
||||
static struct subfile *main_subfile;
|
||||
|
||||
/* List of free `struct pending' structures for reuse. */
|
||||
|
||||
static struct pending *free_pendings;
|
||||
|
@ -670,6 +676,26 @@ start_subfile (const char *name, const char *dirname)
|
|||
}
|
||||
}
|
||||
|
||||
/* Delete the subfiles list. */
|
||||
|
||||
static void
|
||||
free_subfiles_list (void)
|
||||
{
|
||||
struct subfile *subfile, *nextsub;
|
||||
|
||||
for (subfile = subfiles; subfile != NULL; subfile = nextsub)
|
||||
{
|
||||
nextsub = subfile->next;
|
||||
xfree (subfile->name);
|
||||
xfree (subfile->dirname);
|
||||
xfree (subfile->line_vector);
|
||||
xfree (subfile);
|
||||
}
|
||||
subfiles = NULL;
|
||||
current_subfile = NULL;
|
||||
main_subfile = NULL;
|
||||
}
|
||||
|
||||
/* For stabs readers, the first N_SO symbol is assumed to be the
|
||||
source file name, and the subfile struct is initialized using that
|
||||
assumption. If another N_SO symbol is later seen, immediately
|
||||
|
@ -862,6 +888,9 @@ start_symtab (const char *name, const char *dirname, CORE_ADDR start_addr)
|
|||
restart_symtab (start_addr);
|
||||
set_last_source_file (name);
|
||||
start_subfile (name, dirname);
|
||||
/* Save this so that we don't have to go looking for it at the end
|
||||
of the subfiles list. */
|
||||
main_subfile = current_subfile;
|
||||
}
|
||||
|
||||
/* Restart compilation for a symtab.
|
||||
|
@ -892,10 +921,10 @@ restart_symtab (CORE_ADDR start_addr)
|
|||
/* We shouldn't have any address map at this point. */
|
||||
gdb_assert (! pending_addrmap);
|
||||
|
||||
/* Initialize the list of sub source files with one entry for this
|
||||
file (the top-level source file). */
|
||||
subfiles = NULL;
|
||||
current_subfile = NULL;
|
||||
/* Reset the sub source files list. The list should already be empty,
|
||||
but free it anyway in case some code didn't finish cleaning up after
|
||||
an error. */
|
||||
free_subfiles_list ();
|
||||
}
|
||||
|
||||
/* Subroutine of end_symtab to simplify it. Look for a subfile that
|
||||
|
@ -910,30 +939,20 @@ restart_symtab (CORE_ADDR start_addr)
|
|||
static void
|
||||
watch_main_source_file_lossage (void)
|
||||
{
|
||||
struct subfile *mainsub, *subfile;
|
||||
struct subfile *subfile;
|
||||
|
||||
/* Find the main source file.
|
||||
This loop could be eliminated if start_symtab saved it for us. */
|
||||
mainsub = NULL;
|
||||
for (subfile = subfiles; subfile; subfile = subfile->next)
|
||||
{
|
||||
/* The main subfile is guaranteed to be the last one. */
|
||||
if (subfile->next == NULL)
|
||||
mainsub = subfile;
|
||||
}
|
||||
/* We have to watch for mainsub == NULL here. It's a quirk of
|
||||
end_symtab, it can return NULL so there may not be a main subfile. */
|
||||
if (main_subfile == NULL)
|
||||
return;
|
||||
|
||||
/* If the main source file doesn't have any line number or symbol
|
||||
info, look for an alias in another subfile.
|
||||
info, look for an alias in another subfile. */
|
||||
|
||||
We have to watch for mainsub == NULL here. It's a quirk of
|
||||
end_symtab, it can return NULL so there may not be a main
|
||||
subfile. */
|
||||
|
||||
if (mainsub
|
||||
&& mainsub->line_vector == NULL
|
||||
&& mainsub->symtab == NULL)
|
||||
if (main_subfile->line_vector == NULL
|
||||
&& main_subfile->symtab == NULL)
|
||||
{
|
||||
const char *mainbase = lbasename (mainsub->name);
|
||||
const char *mainbase = lbasename (main_subfile->name);
|
||||
int nr_matches = 0;
|
||||
struct subfile *prevsub;
|
||||
struct subfile *mainsub_alias = NULL;
|
||||
|
@ -956,15 +975,15 @@ watch_main_source_file_lossage (void)
|
|||
|
||||
if (nr_matches == 1)
|
||||
{
|
||||
gdb_assert (mainsub_alias != NULL && mainsub_alias != mainsub);
|
||||
gdb_assert (mainsub_alias != NULL && mainsub_alias != main_subfile);
|
||||
|
||||
/* Found a match for the main source file.
|
||||
Copy its line_vector and symtab to the main subfile
|
||||
and then discard it. */
|
||||
|
||||
mainsub->line_vector = mainsub_alias->line_vector;
|
||||
mainsub->line_vector_length = mainsub_alias->line_vector_length;
|
||||
mainsub->symtab = mainsub_alias->symtab;
|
||||
main_subfile->line_vector = mainsub_alias->line_vector;
|
||||
main_subfile->line_vector_length = mainsub_alias->line_vector_length;
|
||||
main_subfile->symtab = mainsub_alias->symtab;
|
||||
|
||||
if (prev_mainsub_alias == NULL)
|
||||
subfiles = mainsub_alias->next;
|
||||
|
@ -994,7 +1013,7 @@ static void
|
|||
reset_symtab_globals (void)
|
||||
{
|
||||
set_last_source_file (NULL);
|
||||
current_subfile = NULL;
|
||||
free_subfiles_list ();
|
||||
pending_macros = NULL;
|
||||
if (pending_addrmap)
|
||||
{
|
||||
|
@ -1106,6 +1125,191 @@ end_symtab_get_static_block (CORE_ADDR end_addr, struct objfile *objfile,
|
|||
}
|
||||
}
|
||||
|
||||
/* Subroutine of end_symtab_from_static_block to simplify it.
|
||||
Handle the "no blockvector" case.
|
||||
When this happens there is nothing to record, so just free up
|
||||
any memory we allocated while reading debug info. */
|
||||
|
||||
static void
|
||||
end_symtab_without_blockvector (struct objfile *objfile)
|
||||
{
|
||||
struct subfile *subfile;
|
||||
|
||||
/* Since we are ignoring these subfiles, we also need
|
||||
to unlink the associated empty symtab that we created.
|
||||
Otherwise, we can run into trouble because various parts
|
||||
such as the block-vector are uninitialized whereas
|
||||
the rest of the code assumes that they are.
|
||||
|
||||
We can only unlink the symtab. We can't free it because
|
||||
it was allocated on the objfile obstack. */
|
||||
|
||||
for (subfile = subfiles; subfile != NULL; subfile = subfile->next)
|
||||
{
|
||||
if (subfile->symtab)
|
||||
{
|
||||
struct symtab *s;
|
||||
|
||||
if (objfile->symtabs == subfile->symtab)
|
||||
objfile->symtabs = objfile->symtabs->next;
|
||||
else
|
||||
ALL_OBJFILE_SYMTABS (objfile, s)
|
||||
if (s->next == subfile->symtab)
|
||||
{
|
||||
s->next = s->next->next;
|
||||
break;
|
||||
}
|
||||
subfile->symtab = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Subroutine of end_symtab_from_static_block to simplify it.
|
||||
Handle the "have blockvector" case.
|
||||
See end_symtab_from_static_block for a description of the arguments. */
|
||||
|
||||
static struct symtab *
|
||||
end_symtab_with_blockvector (struct block *static_block,
|
||||
struct objfile *objfile, int section,
|
||||
int expandable)
|
||||
{
|
||||
struct symtab *symtab;
|
||||
struct blockvector *blockvector;
|
||||
struct subfile *subfile;
|
||||
CORE_ADDR end_addr;
|
||||
|
||||
gdb_assert (static_block != NULL);
|
||||
gdb_assert (subfiles != NULL);
|
||||
|
||||
end_addr = BLOCK_END (static_block);
|
||||
|
||||
/* Create the GLOBAL_BLOCK and build the blockvector. */
|
||||
finish_block_internal (NULL, &global_symbols, NULL,
|
||||
last_source_start_addr, end_addr, objfile,
|
||||
1, expandable);
|
||||
blockvector = make_blockvector (objfile);
|
||||
|
||||
/* Read the line table if it has to be read separately.
|
||||
This is only used by xcoffread.c. */
|
||||
if (objfile->sf->sym_read_linetable != NULL)
|
||||
objfile->sf->sym_read_linetable (objfile);
|
||||
|
||||
/* Handle the case where the debug info specifies a different path
|
||||
for the main source file. It can cause us to lose track of its
|
||||
line number information. */
|
||||
watch_main_source_file_lossage ();
|
||||
|
||||
/* Now create the symtab objects proper, one for each subfile. */
|
||||
|
||||
for (subfile = subfiles; subfile != NULL; subfile = subfile->next)
|
||||
{
|
||||
int linetablesize = 0;
|
||||
|
||||
if (subfile->line_vector)
|
||||
{
|
||||
linetablesize = sizeof (struct linetable) +
|
||||
subfile->line_vector->nitems * sizeof (struct linetable_entry);
|
||||
|
||||
/* Like the pending blocks, the line table may be
|
||||
scrambled in reordered executables. Sort it if
|
||||
OBJF_REORDERED is true. */
|
||||
if (objfile->flags & OBJF_REORDERED)
|
||||
qsort (subfile->line_vector->item,
|
||||
subfile->line_vector->nitems,
|
||||
sizeof (struct linetable_entry), compare_line_numbers);
|
||||
}
|
||||
|
||||
/* Allocate a symbol table if necessary. */
|
||||
if (subfile->symtab == NULL)
|
||||
subfile->symtab = allocate_symtab (subfile->name, objfile);
|
||||
symtab = subfile->symtab;
|
||||
|
||||
/* Fill in its components. */
|
||||
symtab->blockvector = blockvector;
|
||||
symtab->macro_table = pending_macros;
|
||||
if (subfile->line_vector)
|
||||
{
|
||||
/* Reallocate the line table on the symbol obstack. */
|
||||
symtab->linetable = (struct linetable *)
|
||||
obstack_alloc (&objfile->objfile_obstack, linetablesize);
|
||||
memcpy (symtab->linetable, subfile->line_vector, linetablesize);
|
||||
}
|
||||
else
|
||||
{
|
||||
symtab->linetable = NULL;
|
||||
}
|
||||
symtab->block_line_section = section;
|
||||
if (subfile->dirname)
|
||||
{
|
||||
/* Reallocate the dirname on the symbol obstack. */
|
||||
symtab->dirname =
|
||||
obstack_copy0 (&objfile->objfile_obstack,
|
||||
subfile->dirname,
|
||||
strlen (subfile->dirname));
|
||||
}
|
||||
else
|
||||
{
|
||||
symtab->dirname = NULL;
|
||||
}
|
||||
|
||||
/* Use whatever language we have been using for this
|
||||
subfile, not the one that was deduced in allocate_symtab
|
||||
from the filename. We already did our own deducing when
|
||||
we created the subfile, and we may have altered our
|
||||
opinion of what language it is from things we found in
|
||||
the symbols. */
|
||||
symtab->language = subfile->language;
|
||||
|
||||
/* Save the debug format string (if any) in the symtab. */
|
||||
symtab->debugformat = subfile->debugformat;
|
||||
|
||||
/* Similarly for the producer. */
|
||||
symtab->producer = subfile->producer;
|
||||
|
||||
/* All symtabs for the main file and the subfiles share a
|
||||
blockvector, so we need to clear primary for everything
|
||||
but the main file. */
|
||||
set_symtab_primary (symtab, 0);
|
||||
}
|
||||
|
||||
/* The main source file is the primary symtab. */
|
||||
gdb_assert (main_subfile->symtab != NULL);
|
||||
symtab = main_subfile->symtab;
|
||||
set_symtab_primary (symtab, 1);
|
||||
{
|
||||
struct block *b = BLOCKVECTOR_BLOCK (symtab->blockvector, GLOBAL_BLOCK);
|
||||
|
||||
set_block_symtab (b, symtab);
|
||||
}
|
||||
|
||||
/* Default any symbols without a specified symtab to the primary symtab. */
|
||||
{
|
||||
int block_i;
|
||||
|
||||
for (block_i = 0; block_i < BLOCKVECTOR_NBLOCKS (blockvector); block_i++)
|
||||
{
|
||||
struct block *block = BLOCKVECTOR_BLOCK (blockvector, block_i);
|
||||
struct symbol *sym;
|
||||
struct dict_iterator iter;
|
||||
|
||||
/* Inlined functions may have symbols not in the global or
|
||||
static symbol lists. */
|
||||
if (BLOCK_FUNCTION (block) != NULL)
|
||||
if (SYMBOL_SYMTAB (BLOCK_FUNCTION (block)) == NULL)
|
||||
SYMBOL_SYMTAB (BLOCK_FUNCTION (block)) = symtab;
|
||||
|
||||
/* Note that we only want to fix up symbols from the local
|
||||
blocks, not blocks coming from included symtabs. That is why
|
||||
we use ALL_DICT_SYMBOLS here and not ALL_BLOCK_SYMBOLS. */
|
||||
ALL_DICT_SYMBOLS (BLOCK_DICT (block), iter, sym)
|
||||
if (SYMBOL_SYMTAB (sym) == NULL)
|
||||
SYMBOL_SYMTAB (sym) = symtab;
|
||||
}
|
||||
}
|
||||
|
||||
return symtab;
|
||||
}
|
||||
|
||||
/* Implementation of the second part of end_symtab. Pass STATIC_BLOCK
|
||||
as value returned by end_symtab_get_static_block.
|
||||
|
||||
|
@ -1120,204 +1324,22 @@ end_symtab_from_static_block (struct block *static_block,
|
|||
struct objfile *objfile, int section,
|
||||
int expandable)
|
||||
{
|
||||
struct symtab *symtab = NULL;
|
||||
struct blockvector *blockvector;
|
||||
struct subfile *subfile;
|
||||
struct subfile *nextsub;
|
||||
struct symtab *s;
|
||||
|
||||
if (static_block == NULL)
|
||||
{
|
||||
/* Ignore symtabs that have no functions with real debugging info. */
|
||||
blockvector = NULL;
|
||||
end_symtab_without_blockvector (objfile);
|
||||
s = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
CORE_ADDR end_addr = BLOCK_END (static_block);
|
||||
|
||||
/* Define after STATIC_BLOCK also GLOBAL_BLOCK, and build the
|
||||
blockvector. */
|
||||
finish_block_internal (NULL, &global_symbols, NULL,
|
||||
last_source_start_addr, end_addr, objfile,
|
||||
1, expandable);
|
||||
blockvector = make_blockvector (objfile);
|
||||
}
|
||||
|
||||
/* Read the line table if it has to be read separately.
|
||||
This is only used by xcoffread.c. */
|
||||
if (objfile->sf->sym_read_linetable != NULL)
|
||||
objfile->sf->sym_read_linetable (objfile);
|
||||
|
||||
/* Handle the case where the debug info specifies a different path
|
||||
for the main source file. It can cause us to lose track of its
|
||||
line number information. */
|
||||
watch_main_source_file_lossage ();
|
||||
|
||||
/* Now create the symtab objects proper, one for each subfile. */
|
||||
/* (The main file is the last one on the chain.) */
|
||||
|
||||
for (subfile = subfiles; subfile; subfile = nextsub)
|
||||
{
|
||||
int linetablesize = 0;
|
||||
symtab = NULL;
|
||||
|
||||
/* If we have blocks of symbols, make a symtab. Otherwise, just
|
||||
ignore this file and any line number info in it. */
|
||||
if (blockvector)
|
||||
{
|
||||
if (subfile->line_vector)
|
||||
{
|
||||
linetablesize = sizeof (struct linetable) +
|
||||
subfile->line_vector->nitems * sizeof (struct linetable_entry);
|
||||
|
||||
/* Like the pending blocks, the line table may be
|
||||
scrambled in reordered executables. Sort it if
|
||||
OBJF_REORDERED is true. */
|
||||
if (objfile->flags & OBJF_REORDERED)
|
||||
qsort (subfile->line_vector->item,
|
||||
subfile->line_vector->nitems,
|
||||
sizeof (struct linetable_entry), compare_line_numbers);
|
||||
}
|
||||
|
||||
/* Now, allocate a symbol table. */
|
||||
if (subfile->symtab == NULL)
|
||||
symtab = allocate_symtab (subfile->name, objfile);
|
||||
else
|
||||
symtab = subfile->symtab;
|
||||
|
||||
/* Fill in its components. */
|
||||
symtab->blockvector = blockvector;
|
||||
symtab->macro_table = pending_macros;
|
||||
if (subfile->line_vector)
|
||||
{
|
||||
/* Reallocate the line table on the symbol obstack. */
|
||||
symtab->linetable = (struct linetable *)
|
||||
obstack_alloc (&objfile->objfile_obstack, linetablesize);
|
||||
memcpy (symtab->linetable, subfile->line_vector, linetablesize);
|
||||
}
|
||||
else
|
||||
{
|
||||
symtab->linetable = NULL;
|
||||
}
|
||||
symtab->block_line_section = section;
|
||||
if (subfile->dirname)
|
||||
{
|
||||
/* Reallocate the dirname on the symbol obstack. */
|
||||
symtab->dirname =
|
||||
obstack_copy0 (&objfile->objfile_obstack,
|
||||
subfile->dirname,
|
||||
strlen (subfile->dirname));
|
||||
}
|
||||
else
|
||||
{
|
||||
symtab->dirname = NULL;
|
||||
}
|
||||
|
||||
/* Use whatever language we have been using for this
|
||||
subfile, not the one that was deduced in allocate_symtab
|
||||
from the filename. We already did our own deducing when
|
||||
we created the subfile, and we may have altered our
|
||||
opinion of what language it is from things we found in
|
||||
the symbols. */
|
||||
symtab->language = subfile->language;
|
||||
|
||||
/* Save the debug format string (if any) in the symtab. */
|
||||
symtab->debugformat = subfile->debugformat;
|
||||
|
||||
/* Similarly for the producer. */
|
||||
symtab->producer = subfile->producer;
|
||||
|
||||
/* All symtabs for the main file and the subfiles share a
|
||||
blockvector, so we need to clear primary for everything
|
||||
but the main file. */
|
||||
set_symtab_primary (symtab, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (subfile->symtab)
|
||||
{
|
||||
/* Since we are ignoring that subfile, we also need
|
||||
to unlink the associated empty symtab that we created.
|
||||
Otherwise, we can run into trouble because various parts
|
||||
such as the block-vector are uninitialized whereas
|
||||
the rest of the code assumes that they are.
|
||||
|
||||
We can only unlink the symtab because it was allocated
|
||||
on the objfile obstack. */
|
||||
struct symtab *s;
|
||||
|
||||
if (objfile->symtabs == subfile->symtab)
|
||||
objfile->symtabs = objfile->symtabs->next;
|
||||
else
|
||||
ALL_OBJFILE_SYMTABS (objfile, s)
|
||||
if (s->next == subfile->symtab)
|
||||
{
|
||||
s->next = s->next->next;
|
||||
break;
|
||||
}
|
||||
subfile->symtab = NULL;
|
||||
}
|
||||
}
|
||||
if (subfile->name != NULL)
|
||||
{
|
||||
xfree ((void *) subfile->name);
|
||||
}
|
||||
if (subfile->dirname != NULL)
|
||||
{
|
||||
xfree ((void *) subfile->dirname);
|
||||
}
|
||||
if (subfile->line_vector != NULL)
|
||||
{
|
||||
xfree ((void *) subfile->line_vector);
|
||||
}
|
||||
|
||||
nextsub = subfile->next;
|
||||
xfree ((void *) subfile);
|
||||
}
|
||||
|
||||
/* Set this for the main source file. */
|
||||
if (symtab)
|
||||
{
|
||||
set_symtab_primary (symtab, 1);
|
||||
|
||||
if (symtab->blockvector)
|
||||
{
|
||||
struct block *b = BLOCKVECTOR_BLOCK (symtab->blockvector,
|
||||
GLOBAL_BLOCK);
|
||||
|
||||
set_block_symtab (b, symtab);
|
||||
}
|
||||
}
|
||||
|
||||
/* Default any symbols without a specified symtab to the primary
|
||||
symtab. */
|
||||
if (blockvector)
|
||||
{
|
||||
int block_i;
|
||||
|
||||
for (block_i = 0; block_i < BLOCKVECTOR_NBLOCKS (blockvector); block_i++)
|
||||
{
|
||||
struct block *block = BLOCKVECTOR_BLOCK (blockvector, block_i);
|
||||
struct symbol *sym;
|
||||
struct dict_iterator iter;
|
||||
|
||||
/* Inlined functions may have symbols not in the global or
|
||||
static symbol lists. */
|
||||
if (BLOCK_FUNCTION (block) != NULL)
|
||||
if (SYMBOL_SYMTAB (BLOCK_FUNCTION (block)) == NULL)
|
||||
SYMBOL_SYMTAB (BLOCK_FUNCTION (block)) = symtab;
|
||||
|
||||
/* Note that we only want to fix up symbols from the local
|
||||
blocks, not blocks coming from included symtabs. That is why
|
||||
we use ALL_DICT_SYMBOLS here and not ALL_BLOCK_SYMBOLS. */
|
||||
ALL_DICT_SYMBOLS (BLOCK_DICT (block), iter, sym)
|
||||
if (SYMBOL_SYMTAB (sym) == NULL)
|
||||
SYMBOL_SYMTAB (sym) = symtab;
|
||||
}
|
||||
s = end_symtab_with_blockvector (static_block, objfile, section,
|
||||
expandable);
|
||||
}
|
||||
|
||||
reset_symtab_globals ();
|
||||
|
||||
return symtab;
|
||||
return s;
|
||||
}
|
||||
|
||||
/* Finish the symbol definitions for one main source file, close off
|
||||
|
|
Loading…
Add table
Reference in a new issue