summaryrefslogtreecommitdiff
path: root/gdb/block.c
blob: 1c928b4629f1f99a6447d664581b7fee13a31c43 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
/* 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;
}