blob: 1c928b4629f1f99a6447d664581b7fee13a31c43 [file] [log] [blame]
/* Block support for the GNU debugger, GDB.
Copyright 2002 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "block.h"
#include "gdb_obstack.h"
#include "cp-support.h"
static void block_initialize_namespace (struct block *block,
struct obstack *obstack);
/* Return the symbol for the function which contains a specified
lexical block, described by a struct block BL. */
struct symbol *
block_function (const struct block *bl)
{
while (BLOCK_FUNCTION (bl) == 0 && BLOCK_SUPERBLOCK (bl) != 0)
bl = BLOCK_SUPERBLOCK (bl);
return BLOCK_FUNCTION (bl);
}
/* Return Nonzero if block A is lexically nested within block B,
or if A and B have the same pc range.
Return zero otherwise. */
int
contained_in (const struct block *a, const struct block *b)
{
if (!a || !b)
return 0;
return BLOCK_START (a) >= BLOCK_START (b) && BLOCK_END (a) <= BLOCK_END (b);
}
/* Now come some functions designed to deal with C++ namespace issues.
The accessors are safe to use even in the non-C++ case. */
/* This returns the using directives associated to BLOCK (but _not_
its parents), if any. */
struct using_direct_node *
block_using (const struct block *block)
{
if (BLOCK_NAMESPACE (block) == NULL)
return NULL;
else
return BLOCK_NAMESPACE (block)->using;
}
/* This returns the using directives associated to BLOCK and its
parents, if any. The resulting structure must be freed by calling
cp_free_usings on it. */
struct using_direct_node *
block_all_usings (const struct block *block)
{
struct using_direct_node *using = NULL;
while (block != NULL)
{
using = cp_copy_usings (block_using (block), using);
block = BLOCK_SUPERBLOCK (block);
}
return using;
}
/* Set block_using (BLOCK) to USING; if needed, allocate memory via
OBSTACK. */
void
block_set_using (struct block *block, struct using_direct_node *using,
struct obstack *obstack)
{
block_initialize_namespace (block, obstack);
BLOCK_NAMESPACE (block)->using = using;
}
/* This returns the namespace that BLOCK is enclosed in, or "" if it
isn't enclosed in a namespace at all. This travels the chain of
superblocks looking for a scope, if necessary. */
const char *
block_scope (const struct block *block)
{
for (; block != NULL; block = BLOCK_SUPERBLOCK (block))
{
if (BLOCK_NAMESPACE (block) != NULL
&& BLOCK_NAMESPACE (block)->scope != NULL)
return BLOCK_NAMESPACE (block)->scope;
}
return "";
}
/* Set block_scope (BLOCK) to SCOPE; if needed, allocate memory via
OBSTACK. (It won't make a copy of SCOPE, however, so that already
has to be allocated correctly.) */
void
block_set_scope (struct block *block, const char *scope,
struct obstack *obstack)
{
block_initialize_namespace (block, obstack);
BLOCK_NAMESPACE (block)->scope = scope;
}
/* If BLOCK_NAMESPACE (block) is NULL, allocate it via OBSTACK and
ititialize its members to zero. */
static void
block_initialize_namespace (struct block *block, struct obstack *obstack)
{
if (BLOCK_NAMESPACE (block) == NULL)
{
BLOCK_NAMESPACE (block)
= obstack_alloc (obstack, sizeof (struct namespace_info));
BLOCK_NAMESPACE (block)->using = NULL;
}
}
/* Return the static block associated to BLOCK. Return NULL if block
is NULL or if block is a global block. */
const struct block *
block_static_block (const struct block *block)
{
if (block == NULL || BLOCK_SUPERBLOCK (block) == NULL)
return NULL;
while (BLOCK_SUPERBLOCK (BLOCK_SUPERBLOCK (block)) != NULL)
block = BLOCK_SUPERBLOCK (block);
return block;
}
/* Initialize ITERATOR to point at the first using directive valid for
BLOCK, and return that using directive, or NULL if there aren't
any. */
struct using_direct *
block_using_iterator_first (const struct block *block,
struct block_using_iterator *iterator)
{
if (block == NULL)
return NULL;
iterator->current_block = block;
iterator->next_node = block_using (block);
return block_using_iterator_next (iterator);
}
/* Advance ITERATOR, and return the next using directive, or NULL if
there aren't any more. Don't call this if you've previously
received NULL from block_using_iterator_first or
block_using_iterator_next during this iteration. */
struct using_direct *
block_using_iterator_next (struct block_using_iterator *iterator)
{
if (iterator->next_node != NULL)
{
struct using_direct *retval = iterator->next_node->current;
iterator->next_node = iterator->next_node->next;
return retval;
}
else
{
while (BLOCK_SUPERBLOCK (iterator->current_block) != NULL)
{
iterator->current_block
= BLOCK_SUPERBLOCK (iterator->current_block);
iterator->next_node = block_using (iterator->current_block);
if (iterator->next_node != NULL)
{
struct using_direct *retval = iterator->next_node->current;
iterator->next_node = iterator->next_node->next;
return retval;
}
}
/* We didn't find any superblocks with using directives. */
return NULL;
}
}
/* This allocates a block on OBSTACK, and initializes its elements to
zero/NULL. This is useful for creating "dummy" blocks that don't
correspond to actual source files.
Warning: it sets the block's BLOCK_DICT to NULL, which isn't a
valid value. If you don't want the block to have a dictiionary,
then you should subsequently set its BLOCK_DICT to
dict_create_linear (obstack, NULL). */
struct block *
allocate_block (struct obstack *obstack)
{
struct block *bl = obstack_alloc (obstack, sizeof (struct block));
BLOCK_START (bl) = 0;
BLOCK_END (bl) = 0;
BLOCK_FUNCTION (bl) = NULL;
BLOCK_SUPERBLOCK (bl) = NULL;
BLOCK_DICT (bl) = NULL;
BLOCK_NAMESPACE (bl) = NULL;
BLOCK_GCC_COMPILED (bl) = 0;
return bl;
}