diff options
Diffstat (limited to 'gdb/parse.c')
-rw-r--r-- | gdb/parse.c | 107 |
1 files changed, 98 insertions, 9 deletions
diff --git a/gdb/parse.c b/gdb/parse.c index 83f7fec..b1ad832 100644 --- a/gdb/parse.c +++ b/gdb/parse.c @@ -1358,18 +1358,29 @@ parse_c_float (struct gdbarch *gdbarch, const char *p, int len, /* Stuff for maintaining a stack of types. Currently just used by C, but probably useful for any language which declares its types "backwards". */ +/* Ensure that there are HOWMUCH open slots on the type stack STACK. */ + static void -check_type_stack_depth (void) +type_stack_reserve (struct type_stack *stack, int howmuch) { - if (type_stack.depth == type_stack.size) + if (stack->depth + howmuch >= stack->size) { - type_stack.size *= 2; - type_stack.elements - = xrealloc (type_stack.elements, - type_stack.size * sizeof (union type_stack_elt)); + stack->size *= 2; + if (stack->size < howmuch) + stack->size = howmuch; + stack->elements = xrealloc (stack->elements, + stack->size * sizeof (union type_stack_elt)); } } +/* Ensure that there is a single open slot in the global type stack. */ + +static void +check_type_stack_depth (void) +{ + type_stack_reserve (&type_stack, 1); +} + /* A helper function for insert_type and insert_type_address_space. This does work of expanding the type stack and inserting the new element, ELEMENT, into the stack at location SLOT. */ @@ -1472,6 +1483,68 @@ pop_type_int (void) return 0; } +/* Pop a type_stack element from the global type stack. */ + +static struct type_stack * +pop_type_stack (void) +{ + gdb_assert (type_stack.depth); + return type_stack.elements[--type_stack.depth].stack_val; +} + +/* Append the elements of the type stack FROM to the type stack TO. + Always returns TO. */ + +struct type_stack * +append_type_stack (struct type_stack *to, struct type_stack *from) +{ + type_stack_reserve (to, from->depth); + + memcpy (&to->elements[to->depth], &from->elements[0], + from->depth * sizeof (union type_stack_elt)); + to->depth += from->depth; + + return to; +} + +/* Push the type stack STACK as an element on the global type stack. */ + +void +push_type_stack (struct type_stack *stack) +{ + check_type_stack_depth (); + type_stack.elements[type_stack.depth++].stack_val = stack; + push_type (tp_type_stack); +} + +/* Copy the global type stack into a newly allocated type stack and + return it. The global stack is cleared. The returned type stack + must be freed with type_stack_cleanup. */ + +struct type_stack * +get_type_stack (void) +{ + struct type_stack *result = XNEW (struct type_stack); + + *result = type_stack; + type_stack.depth = 0; + type_stack.size = 0; + type_stack.elements = NULL; + + return result; +} + +/* A cleanup function that destroys a single type stack. */ + +void +type_stack_cleanup (void *arg) +{ + struct type_stack *stack = arg; + + xfree (stack->elements); + xfree (stack); +} + /* Pop the type stack and return the type which corresponds to FOLLOW_TYPE as modified by all the stuff on the stack. */ struct type * @@ -1558,6 +1631,23 @@ follow_types (struct type *follow_type) done with it. */ follow_type = lookup_function_type (follow_type); break; + + case tp_type_stack: + { + struct type_stack *stack = pop_type_stack (); + /* Sort of ugly, but not really much worse than the + alternatives. */ + struct type_stack save = type_stack; + + type_stack = *stack; + follow_type = follow_types (follow_type); + gdb_assert (type_stack.depth == 0); + + type_stack = save; + } + break; + default: + gdb_assert_not_reached ("unrecognized tp_ value in follow_types"); } return follow_type; } @@ -1725,10 +1815,9 @@ exp_uses_objfile (struct expression *exp, struct objfile *objfile) void _initialize_parse (void) { - type_stack.size = 80; + type_stack.size = 0; type_stack.depth = 0; - type_stack.elements = xmalloc (type_stack.size - * sizeof (union type_stack_elt)); + type_stack.elements = NULL; add_setshow_zinteger_cmd ("expression", class_maintenance, &expressiondebug, |