Index: gdb/parse.c |
diff --git a/gdb/parse.c b/gdb/parse.c |
index b0fa2379fd186ba67961c0f6d22bf873f9364d35..529c517c25e612486575390ba4da5b113095f214 100644 |
--- a/gdb/parse.c |
+++ b/gdb/parse.c |
@@ -75,8 +75,7 @@ struct block *expression_context_block; |
CORE_ADDR expression_context_pc; |
struct block *innermost_block; |
int arglist_len; |
-union type_stack_elt *type_stack; |
-int type_stack_depth, type_stack_size; |
+static struct type_stack type_stack; |
char *lexptr; |
char *prev_lexptr; |
int paren_depth; |
@@ -90,16 +89,6 @@ int in_parse_field; |
'->'. This is set when parsing and is only used when completing a |
field name. It is -1 if no dereference operation was found. */ |
static int expout_last_struct = -1; |
- |
-/* A temporary buffer for identifiers, so we can null-terminate them. |
- |
- We allocate this with xrealloc. parse_exp_1 used to allocate with |
- alloca, using the size of the whole expression as a conservative |
- estimate of the space needed. However, macro expansion can |
- introduce names longer than the original expression; there's no |
- practical way to know beforehand how large that might be. */ |
-char *namecopy; |
-size_t namecopy_size; |
static int expressiondebug = 0; |
static void |
@@ -123,12 +112,11 @@ show_parserdebug (struct ui_file *file, int from_tty, |
static void free_funcalls (void *ignore); |
-static int prefixify_expression (struct expression *); |
- |
static int prefixify_subexp (struct expression *, struct expression *, int, |
int); |
-static struct expression *parse_exp_in_context (char **, struct block *, int, |
+static struct expression *parse_exp_in_context (char **, CORE_ADDR, |
+ struct block *, int, |
int, int *); |
void _initialize_parse (void); |
@@ -192,6 +180,35 @@ free_funcalls (void *ignore) |
/* This page contains the functions for adding data to the struct expression |
being constructed. */ |
+/* See definition in parser-defs.h. */ |
+ |
+void |
+initialize_expout (int initial_size, const struct language_defn *lang, |
+ struct gdbarch *gdbarch) |
+{ |
+ expout_size = initial_size; |
+ expout_ptr = 0; |
+ expout = xmalloc (sizeof (struct expression) |
+ + EXP_ELEM_TO_BYTES (expout_size)); |
+ expout->language_defn = lang; |
+ expout->gdbarch = gdbarch; |
+} |
+ |
+/* See definition in parser-defs.h. */ |
+ |
+void |
+reallocate_expout (void) |
+{ |
+ /* Record the actual number of expression elements, and then |
+ reallocate the expression memory so that we free up any |
+ excess elements. */ |
+ |
+ expout->nelts = expout_ptr; |
+ expout = xrealloc ((char *) expout, |
+ sizeof (struct expression) |
+ + EXP_ELEM_TO_BYTES (expout_ptr)); |
+} |
+ |
/* Add one element to the end of the expression. */ |
/* To avoid a bug in the Sun 4 compiler, we pass things that can fit into |
@@ -744,13 +761,28 @@ find_template_name_end (char *p) |
} |
+/* Return a null-terminated temporary copy of the name of a string token. |
+ |
+ Tokens that refer to names do so with explicit pointer and length, |
+ so they can share the storage that lexptr is parsing. |
+ When it is necessary to pass a name to a function that expects |
+ a null-terminated string, the substring is copied out |
+ into a separate block of storage. |
-/* Return a null-terminated temporary copy of the name |
- of a string token. */ |
+ N.B. A single buffer is reused on each call. */ |
char * |
copy_name (struct stoken token) |
{ |
+ /* A temporary buffer for identifiers, so we can null-terminate them. |
+ We allocate this with xrealloc. parse_exp_1 used to allocate with |
+ alloca, using the size of the whole expression as a conservative |
+ estimate of the space needed. However, macro expansion can |
+ introduce names longer than the original expression; there's no |
+ practical way to know beforehand how large that might be. */ |
+ static char *namecopy; |
+ static size_t namecopy_size; |
+ |
/* Make sure there's enough space for the token. */ |
if (namecopy_size < token.length + 1) |
{ |
@@ -764,14 +796,10 @@ copy_name (struct stoken token) |
return namecopy; |
} |
-/* Reverse an expression from suffix form (in which it is constructed) |
- to prefix form (in which we can conveniently print or execute it). |
- Ordinarily this always returns -1. However, if EXPOUT_LAST_STRUCT |
- is not -1 (i.e., we are trying to complete a field name), it will |
- return the index of the subexpression which is the left-hand-side |
- of the struct operation at EXPOUT_LAST_STRUCT. */ |
-static int |
+/* See comments on parser-defs.h. */ |
+ |
+int |
prefixify_expression (struct expression *expr) |
{ |
int len = sizeof (struct expression) + EXP_ELEM_TO_BYTES (expr->nelts); |
@@ -1069,9 +1097,9 @@ prefixify_subexp (struct expression *inexpr, |
If COMMA is nonzero, stop if a comma is reached. */ |
struct expression * |
-parse_exp_1 (char **stringptr, struct block *block, int comma) |
+parse_exp_1 (char **stringptr, CORE_ADDR pc, struct block *block, int comma) |
{ |
- return parse_exp_in_context (stringptr, block, comma, 0, NULL); |
+ return parse_exp_in_context (stringptr, pc, block, comma, 0, NULL); |
} |
/* As for parse_exp_1, except that if VOID_CONTEXT_P, then |
@@ -1082,8 +1110,8 @@ parse_exp_1 (char **stringptr, struct block *block, int comma) |
is left untouched. */ |
static struct expression * |
-parse_exp_in_context (char **stringptr, struct block *block, int comma, |
- int void_context_p, int *out_subexp) |
+parse_exp_in_context (char **stringptr, CORE_ADDR pc, struct block *block, |
+ int comma, int void_context_p, int *out_subexp) |
{ |
volatile struct gdb_exception except; |
struct cleanup *old_chain; |
@@ -1094,7 +1122,7 @@ parse_exp_in_context (char **stringptr, struct block *block, int comma, |
prev_lexptr = NULL; |
paren_depth = 0; |
- type_stack_depth = 0; |
+ type_stack.depth = 0; |
expout_last_struct = -1; |
comma_terminates = comma; |
@@ -1110,8 +1138,10 @@ parse_exp_in_context (char **stringptr, struct block *block, int comma, |
/* If no context specified, try using the current frame, if any. */ |
if (!expression_context_block) |
expression_context_block = get_selected_block (&expression_context_pc); |
- else |
+ else if (pc == 0) |
expression_context_pc = BLOCK_START (expression_context_block); |
+ else |
+ expression_context_pc = pc; |
/* Fall back to using the current source static context, if any. */ |
@@ -1151,12 +1181,7 @@ parse_exp_in_context (char **stringptr, struct block *block, int comma, |
else |
lang = current_language; |
- expout_size = 10; |
- expout_ptr = 0; |
- expout = (struct expression *) |
- xmalloc (sizeof (struct expression) + EXP_ELEM_TO_BYTES (expout_size)); |
- expout->language_defn = lang; |
- expout->gdbarch = get_current_arch (); |
+ initialize_expout (10, lang, get_current_arch ()); |
TRY_CATCH (except, RETURN_MASK_ALL) |
{ |
@@ -1174,14 +1199,7 @@ parse_exp_in_context (char **stringptr, struct block *block, int comma, |
discard_cleanups (old_chain); |
- /* Record the actual number of expression elements, and then |
- reallocate the expression memory so that we free up any |
- excess elements. */ |
- |
- expout->nelts = expout_ptr; |
- expout = (struct expression *) |
- xrealloc ((char *) expout, |
- sizeof (struct expression) + EXP_ELEM_TO_BYTES (expout_ptr)); |
+ reallocate_expout (); |
/* Convert expression from postfix form as generated by yacc |
parser, to a prefix form. */ |
@@ -1211,7 +1229,7 @@ parse_expression (char *string) |
{ |
struct expression *exp; |
- exp = parse_exp_1 (&string, 0, 0); |
+ exp = parse_exp_1 (&string, 0, 0, 0); |
if (*string) |
error (_("Junk after end of expression.")); |
return exp; |
@@ -1236,7 +1254,7 @@ parse_field_expression (char *string, char **name) |
TRY_CATCH (except, RETURN_MASK_ERROR) |
{ |
in_parse_field = 1; |
- exp = parse_exp_in_context (&string, 0, 0, 0, &subexp); |
+ exp = parse_exp_in_context (&string, 0, 0, 0, 0, &subexp); |
} |
in_parse_field = 0; |
if (except.reason < 0 || ! exp) |
@@ -1282,7 +1300,6 @@ int |
parse_float (const char *p, int len, DOUBLEST *d, const char **suffix) |
{ |
char *copy; |
- char *s; |
int n, num; |
copy = xmalloc (len + 1); |
@@ -1341,54 +1358,214 @@ 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 = (union type_stack_elt *) |
- xrealloc ((char *) type_stack, type_stack_size * sizeof (*type_stack)); |
+ 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. */ |
+ |
+static void |
+insert_into_type_stack (int slot, union type_stack_elt element) |
+{ |
+ check_type_stack_depth (); |
+ |
+ if (slot < type_stack.depth) |
+ memmove (&type_stack.elements[slot + 1], &type_stack.elements[slot], |
+ (type_stack.depth - slot) * sizeof (union type_stack_elt)); |
+ type_stack.elements[slot] = element; |
+ ++type_stack.depth; |
+} |
+ |
+/* Insert a new type, TP, at the bottom of the type stack. If TP is |
+ tp_pointer or tp_reference, it is inserted at the bottom. If TP is |
+ a qualifier, it is inserted at slot 1 (just above a previous |
+ tp_pointer) if there is anything on the stack, or simply pushed if |
+ the stack is empty. Other values for TP are invalid. */ |
+ |
+void |
+insert_type (enum type_pieces tp) |
+{ |
+ union type_stack_elt element; |
+ int slot; |
+ |
+ gdb_assert (tp == tp_pointer || tp == tp_reference |
+ || tp == tp_const || tp == tp_volatile); |
+ |
+ /* If there is anything on the stack (we know it will be a |
+ tp_pointer), insert the qualifier above it. Otherwise, simply |
+ push this on the top of the stack. */ |
+ if (type_stack.depth && (tp == tp_const || tp == tp_volatile)) |
+ slot = 1; |
+ else |
+ slot = 0; |
+ |
+ element.piece = tp; |
+ insert_into_type_stack (slot, element); |
+} |
+ |
void |
push_type (enum type_pieces tp) |
{ |
check_type_stack_depth (); |
- type_stack[type_stack_depth++].piece = tp; |
+ type_stack.elements[type_stack.depth++].piece = tp; |
} |
void |
push_type_int (int n) |
{ |
check_type_stack_depth (); |
- type_stack[type_stack_depth++].int_val = n; |
+ type_stack.elements[type_stack.depth++].int_val = n; |
} |
+/* Insert a tp_space_identifier and the corresponding address space |
+ value into the stack. STRING is the name of an address space, as |
+ recognized by address_space_name_to_int. If the stack is empty, |
+ the new elements are simply pushed. If the stack is not empty, |
+ this function assumes that the first item on the stack is a |
+ tp_pointer, and the new values are inserted above the first |
+ item. */ |
+ |
void |
-push_type_address_space (char *string) |
+insert_type_address_space (char *string) |
{ |
- push_type_int (address_space_name_to_int (parse_gdbarch, string)); |
+ union type_stack_elt element; |
+ int slot; |
+ |
+ /* If there is anything on the stack (we know it will be a |
+ tp_pointer), insert the address space qualifier above it. |
+ Otherwise, simply push this on the top of the stack. */ |
+ if (type_stack.depth) |
+ slot = 1; |
+ else |
+ slot = 0; |
+ |
+ element.piece = tp_space_identifier; |
+ insert_into_type_stack (slot, element); |
+ element.int_val = address_space_name_to_int (parse_gdbarch, string); |
+ insert_into_type_stack (slot, element); |
} |
enum type_pieces |
pop_type (void) |
{ |
- if (type_stack_depth) |
- return type_stack[--type_stack_depth].piece; |
+ if (type_stack.depth) |
+ return type_stack.elements[--type_stack.depth].piece; |
return tp_end; |
} |
int |
pop_type_int (void) |
{ |
- if (type_stack_depth) |
- return type_stack[--type_stack_depth].int_val; |
+ if (type_stack.depth) |
+ return type_stack.elements[--type_stack.depth].int_val; |
/* "Can't happen". */ |
return 0; |
} |
+/* Pop a type list element from the global type stack. */ |
+ |
+static VEC (type_ptr) * |
+pop_typelist (void) |
+{ |
+ gdb_assert (type_stack.depth); |
+ return type_stack.elements[--type_stack.depth].typelist_val; |
+} |
+ |
+/* 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); |
+} |
+ |
+/* Push a function type with arguments onto the global type stack. |
+ LIST holds the argument types. If the final item in LIST is NULL, |
+ then the function will be varargs. */ |
+ |
+void |
+push_typelist (VEC (type_ptr) *list) |
+{ |
+ check_type_stack_depth (); |
+ type_stack.elements[type_stack.depth++].typelist_val = list; |
+ push_type (tp_function_with_arguments); |
+} |
+ |
/* Pop the type stack and return the type which corresponds to FOLLOW_TYPE |
as modified by all the stuff on the stack. */ |
struct type * |
@@ -1475,6 +1652,36 @@ follow_types (struct type *follow_type) |
done with it. */ |
follow_type = lookup_function_type (follow_type); |
break; |
+ |
+ case tp_function_with_arguments: |
+ { |
+ VEC (type_ptr) *args = pop_typelist (); |
+ |
+ follow_type |
+ = lookup_function_type_with_arguments (follow_type, |
+ VEC_length (type_ptr, args), |
+ VEC_address (type_ptr, |
+ args)); |
+ VEC_free (type_ptr, args); |
+ } |
+ 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; |
} |
@@ -1642,10 +1849,9 @@ exp_uses_objfile (struct expression *exp, struct objfile *objfile) |
void |
_initialize_parse (void) |
{ |
- type_stack_size = 80; |
- type_stack_depth = 0; |
- type_stack = (union type_stack_elt *) |
- xmalloc (type_stack_size * sizeof (*type_stack)); |
+ type_stack.size = 0; |
+ type_stack.depth = 0; |
+ type_stack.elements = NULL; |
add_setshow_zinteger_cmd ("expression", class_maintenance, |
&expressiondebug, |