mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2025-02-16 07:27:56 +00:00
2006-09-21 Nathan Sidwell <nathan@codesourcery.com>
gdb/ * vec.h: New file. * vec.c: New file. * Makefile.in (SFILES): Add vec.c. (vec_h): New. (COMMON_OBJS): Add vec.o. (vec.o): New target. gdb/doc/ * gdbint.texinfo (Array Containers): New section.
This commit is contained in:
parent
5bd4b6af45
commit
350da6eece
@ -1,3 +1,12 @@
|
||||
2006-09-21 Nathan Sidwell <nathan@codesourcery.com>
|
||||
|
||||
* vec.h: New file.
|
||||
* vec.c: New file.
|
||||
* Makefile.in (SFILES): Add vec.c.
|
||||
(vec_h): New.
|
||||
(COMMON_OBJS): Add vec.o.
|
||||
(vec.o): New target.
|
||||
|
||||
2006-09-20 Daniel Jacobowitz <dan@codesourcery.com>
|
||||
|
||||
PR remote/2154
|
||||
|
@ -560,7 +560,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c \
|
||||
typeprint.c \
|
||||
ui-out.c utils.c ui-file.h ui-file.c \
|
||||
user-regs.c \
|
||||
valarith.c valops.c valprint.c value.c varobj.c \
|
||||
valarith.c valops.c valprint.c value.c varobj.c vec.c \
|
||||
wrapper.c
|
||||
|
||||
LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c
|
||||
@ -816,6 +816,7 @@ value_h = value.h $(doublest_h) $(frame_h) $(symtab_h) $(gdbtypes_h) \
|
||||
$(expression_h)
|
||||
varobj_h = varobj.h $(symtab_h) $(gdbtypes_h)
|
||||
vax_tdep_h = vax-tdep.h
|
||||
vec_h = vec.h $(gdb_assert_h) $(gdb_string_h)
|
||||
version_h = version.h
|
||||
wince_stub_h = wince-stub.h
|
||||
wrapper_h = wrapper.h $(gdb_h)
|
||||
@ -941,7 +942,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
|
||||
dwarf2expr.o dwarf2loc.o dwarf2-frame.o \
|
||||
ada-lang.o c-lang.o f-lang.o objc-lang.o \
|
||||
ui-out.o cli-out.o \
|
||||
varobj.o wrapper.o \
|
||||
varobj.o vec.o wrapper.o \
|
||||
jv-lang.o jv-valprint.o jv-typeprint.o \
|
||||
m2-lang.o p-lang.o p-typeprint.o p-valprint.o \
|
||||
scm-exp.o scm-lang.o scm-valprint.o \
|
||||
@ -2826,6 +2827,7 @@ vax-tdep.o: vax-tdep.c $(defs_h) $(arch_utils_h) $(dis_asm_h) \
|
||||
$(float_format_h) $(frame_h) $(frame_base_h) $(frame_unwind_h) \
|
||||
$(gdbcore_h) $(gdbtypes_h) $(osabi_h) $(regcache_h) $(regset_h) \
|
||||
$(trad_frame_h) $(value_h) $(gdb_string_h) $(vax_tdep_h)
|
||||
vec.o: vec.c $(defs_h) $(vec_h)
|
||||
win32-nat.o: win32-nat.c $(defs_h) $(frame_h) $(inferior_h) $(target_h) \
|
||||
$(exceptions_h) $(gdbcore_h) $(command_h) $(completer_h) \
|
||||
$(regcache_h) $(top_h) $(buildsym_h) $(symfile_h) $(objfiles_h) \
|
||||
|
@ -1,3 +1,7 @@
|
||||
2006-09-21 Nathan Sidwell <nathan@codesourcery.com>
|
||||
|
||||
* gdbint.texinfo (Array Containers): New section.
|
||||
|
||||
2006-09-17 Vladimir Prus <vladimir@codesourcery.com>
|
||||
|
||||
* gdb.texinfo (GDB/MI Stack Manipulation): Mention that
|
||||
|
@ -4913,6 +4913,181 @@ Regex conditionals.
|
||||
@item sparc
|
||||
@end table
|
||||
|
||||
@section Array Containers
|
||||
@cindex Array Containers
|
||||
@cindex VEC
|
||||
|
||||
Often it is necessary to manipulate a dynamic array of a set of
|
||||
objects. C forces some bookkeeping on this, which can get cumbersome
|
||||
and repetative. The @file{vec.h} file contains macros for defining
|
||||
and using a typesafe vector type. The functions defined will be
|
||||
inlined when compiling, and so the abstraction cost should be zero.
|
||||
Domain checks are added to detect programming errors.
|
||||
|
||||
An example use would be an array of symbols or section information.
|
||||
The array can be grown as symbols are read in (or preallocated), and
|
||||
the accessor macros provided keep care of all the necessary
|
||||
bookkeeping. Because the arrays are type safe, there is no danger of
|
||||
accidentally mixing up the contents. Think of these as C++ templates,
|
||||
but implemented in C.
|
||||
|
||||
Because of the different behavior of structure objects, scalar objects
|
||||
and of pointers, there are three flavors of vector, one for each of
|
||||
these variants. Both the structure object and pointer variants pass
|
||||
pointers to objects around --- in the former case the pointers are
|
||||
stored into the vector and in the latter case the pointers are
|
||||
dereferenced and the objects copied into the vector. The scalar
|
||||
object variant is suitable for @code{int}-like objects, and the vector
|
||||
elements are returned by value.
|
||||
|
||||
There are both @code{index} and @code{iterate} accessors. The iterator
|
||||
returns a boolean iteration condition and updates the iteration
|
||||
variable passed by reference. Because the iterator will be inlined,
|
||||
the address-of can be optimized away.
|
||||
|
||||
The vectors are implemented using the trailing array idiom, thus they
|
||||
are not resizeable without changing the address of the vector object
|
||||
itself. This means you cannot have variables or fields of vector type
|
||||
--- always use a pointer to a vector. The one exception is the final
|
||||
field of a structure, which could be a vector type. You will have to
|
||||
use the @code{embedded_size} & @code{embedded_init} calls to create
|
||||
such objects, and they will probably not be resizeable (so don't use
|
||||
the @dfn{safe} allocation variants). The trailing array idiom is used
|
||||
(rather than a pointer to an array of data), because, if we allow
|
||||
@code{NULL} to also represent an empty vector, empty vectors occupy
|
||||
minimal space in the structure containing them.
|
||||
|
||||
Each operation that increases the number of active elements is
|
||||
available in @dfn{quick} and @dfn{safe} variants. The former presumes
|
||||
that there is sufficient allocated space for the operation to succeed
|
||||
(it dies if there is not). The latter will reallocate the vector, if
|
||||
needed. Reallocation causes an exponential increase in vector size.
|
||||
If you know you will be adding N elements, it would be more efficient
|
||||
to use the reserve operation before adding the elements with the
|
||||
@dfn{quick} operation. This will ensure there are at least as many
|
||||
elements as you ask for, it will exponentially increase if there are
|
||||
too few spare slots. If you want reserve a specific number of slots,
|
||||
but do not want the exponential increase (for instance, you know this
|
||||
is the last allocation), use a negative number for reservation. You
|
||||
can also create a vector of a specific size from the get go.
|
||||
|
||||
You should prefer the push and pop operations, as they append and
|
||||
remove from the end of the vector. If you need to remove several items
|
||||
in one go, use the truncate operation. The insert and remove
|
||||
operations allow you to change elements in the middle of the vector.
|
||||
There are two remove operations, one which preserves the element
|
||||
ordering @code{ordered_remove}, and one which does not
|
||||
@code{unordered_remove}. The latter function copies the end element
|
||||
into the removed slot, rather than invoke a memmove operation. The
|
||||
@code{lower_bound} function will determine where to place an item in
|
||||
the array using insert that will maintain sorted order.
|
||||
|
||||
If you need to directly manipulate a vector, then the @code{address}
|
||||
accessor will return the address of the start of the vector. Also the
|
||||
@code{space} predicate will tell you whether there is spare capacity in the
|
||||
vector. You will not normally need to use these two functions.
|
||||
|
||||
Vector types are defined using a
|
||||
@code{DEF_VEC_@{O,P,I@}(@var{typename})} macro. Variables of vector
|
||||
type are declared using a @code{VEC(@var{typename})} macro. The
|
||||
characters @code{O}, @code{P} and @code{I} indicate whether
|
||||
@var{typename} is an object (@code{O}), pointer (@code{P}) or integral
|
||||
(@code{I}) type. Be careful to pick the correct one, as you'll get an
|
||||
awkward and inefficient API if you use the wrong one. There is a
|
||||
check, which results in a compile-time warning, for the @code{P} and
|
||||
@code{I} versions, but there is no check for the @code{O} versions, as
|
||||
that is not possible in plain C.
|
||||
|
||||
An example of their use would be,
|
||||
|
||||
@smallexample
|
||||
DEF_VEC_P(tree); // non-managed tree vector.
|
||||
|
||||
struct my_struct @{
|
||||
VEC(tree) *v; // A (pointer to) a vector of tree pointers.
|
||||
@};
|
||||
|
||||
struct my_struct *s;
|
||||
|
||||
if (VEC_length(tree, s->v)) @{ we have some contents @}
|
||||
VEC_safe_push(tree, s->v, decl); // append some decl onto the end
|
||||
for (ix = 0; VEC_iterate(tree, s->v, ix, elt); ix++)
|
||||
@{ do something with elt @}
|
||||
|
||||
@end smallexample
|
||||
|
||||
The @file{vec.h} file provides details on how to invoke the various
|
||||
accessors provided. They are enumerated here:
|
||||
|
||||
@table @code
|
||||
@item VEC_length
|
||||
Return the number of items in the array,
|
||||
|
||||
@item VEC_empty
|
||||
Return true if the array has no elements.
|
||||
|
||||
@item VEC_last
|
||||
@itemx VEC_index
|
||||
Return the last or arbitrary item in the array.
|
||||
|
||||
@item VEC_iterate
|
||||
Access an array element and indicate whether the array has been
|
||||
traversed.
|
||||
|
||||
@item VEC_alloc
|
||||
@itemx VEC_free
|
||||
Create and destroy an array.
|
||||
|
||||
@item VEC_embedded_size
|
||||
@itemx VEC_embedded_init
|
||||
Helpers for embedding an array as the final element of another struct.
|
||||
|
||||
@item VEC_copy
|
||||
Duplicate an array.
|
||||
|
||||
@item VEC_space
|
||||
Return the amount of free space in an array.
|
||||
|
||||
@item VEC_reserve
|
||||
Ensure a certain amount of free space.
|
||||
|
||||
@item VEC_quick_push
|
||||
@itemx VEC_safe_push
|
||||
Append to an array, either assuming the space is available, or making
|
||||
sure that it is.
|
||||
|
||||
@item VEC_pop
|
||||
Remove the last item from an array.
|
||||
|
||||
@item VEC_truncate
|
||||
Remove several items from the end of an array.
|
||||
|
||||
@item VEC_safe_grow
|
||||
Add several items to the end of an array.
|
||||
|
||||
@item VEC_replace
|
||||
Overwrite an item in the array.
|
||||
|
||||
@item VEC_quick_insert
|
||||
@itemx VEC_safe_insert
|
||||
Insert an item into the middle of the array. Either the space must
|
||||
already exist, or the space is created.
|
||||
|
||||
@item VEC_ordered_remove
|
||||
@itemx VEC_unordered_remove
|
||||
Remove an item from the array, preserving order or not.
|
||||
|
||||
@item VEC_block_remove
|
||||
Remove a set of items from the array.
|
||||
|
||||
@item VEC_address
|
||||
Provide the address of the first element.
|
||||
|
||||
@item VEC_lower_bound
|
||||
Binary search the array.
|
||||
|
||||
@end table
|
||||
|
||||
@section include
|
||||
|
||||
@node Coding
|
||||
|
120
gdb/vec.c
Normal file
120
gdb/vec.c
Normal file
@ -0,0 +1,120 @@
|
||||
/* Vector API for GDB.
|
||||
Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
Contributed by Nathan Sidwell <nathan@codesourcery.com>
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "vec.h"
|
||||
#include "defs.h"
|
||||
|
||||
struct vec_prefix
|
||||
{
|
||||
unsigned num;
|
||||
unsigned alloc;
|
||||
void *vec[1];
|
||||
};
|
||||
|
||||
/* Calculate the new ALLOC value, making sure that abs(RESERVE) slots
|
||||
are free. If RESERVE < 0 grow exactly, otherwise grow
|
||||
exponentially. */
|
||||
|
||||
static inline unsigned
|
||||
calculate_allocation (const struct vec_prefix *pfx, int reserve)
|
||||
{
|
||||
unsigned alloc = 0;
|
||||
unsigned num = 0;
|
||||
|
||||
if (pfx)
|
||||
{
|
||||
alloc = pfx->alloc;
|
||||
num = pfx->num;
|
||||
}
|
||||
else if (!reserve)
|
||||
/* If there's no prefix, and we've not requested anything, then we
|
||||
will create a NULL vector. */
|
||||
return 0;
|
||||
|
||||
/* We must have run out of room. */
|
||||
gdb_assert (alloc - num < (unsigned)(reserve < 0 ? -reserve : reserve));
|
||||
|
||||
if (reserve < 0)
|
||||
/* Exact size. */
|
||||
alloc = num + -reserve;
|
||||
else
|
||||
{
|
||||
/* Exponential growth. */
|
||||
if (!alloc)
|
||||
alloc = 4;
|
||||
else if (alloc < 16)
|
||||
/* Double when small. */
|
||||
alloc = alloc * 2;
|
||||
else
|
||||
/* Grow slower when large. */
|
||||
alloc = (alloc * 3 / 2);
|
||||
|
||||
/* If this is still too small, set it to the right size. */
|
||||
if (alloc < num + reserve)
|
||||
alloc = num + reserve;
|
||||
}
|
||||
return alloc;
|
||||
}
|
||||
|
||||
/* Ensure there are at least abs(RESERVE) free slots in VEC. If
|
||||
RESERVE < 0 grow exactly, else grow exponentially. As a special
|
||||
case, if VEC is NULL, and RESERVE is 0, no vector will be created. */
|
||||
|
||||
void *
|
||||
vec_p_reserve (void *vec, int reserve)
|
||||
{
|
||||
return vec_o_reserve (vec, reserve,
|
||||
offsetof (struct vec_prefix, vec), sizeof (void *));
|
||||
}
|
||||
|
||||
/* As vec_p_reserve, but for object vectors. The vector's trailing
|
||||
array is at VEC_OFFSET offset and consists of ELT_SIZE sized
|
||||
elements. */
|
||||
|
||||
void *
|
||||
vec_o_reserve (void *vec, int reserve, size_t vec_offset, size_t elt_size)
|
||||
{
|
||||
struct vec_prefix *pfx = vec;
|
||||
unsigned alloc = calculate_allocation (pfx, reserve);
|
||||
|
||||
if (!alloc)
|
||||
return NULL;
|
||||
|
||||
vec = xrealloc (vec, vec_offset + alloc * elt_size);
|
||||
((struct vec_prefix *)vec)->alloc = alloc;
|
||||
if (!pfx)
|
||||
((struct vec_prefix *)vec)->num = 0;
|
||||
|
||||
return vec;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Example uses. */
|
||||
DEF_VEC_I (int);
|
||||
typedef struct X
|
||||
{
|
||||
int i;
|
||||
} obj_t;
|
||||
typedef obj_t *ptr_t;
|
||||
|
||||
DEF_VEC_P (ptr_t);
|
||||
DEF_VEC_O (obj_t);
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user