+2000-03-13 James Ingham <jingham@leda.cygnus.com>
+
+ Add support for a variable object that tries to evaluate itself in
+ the currently selected frame, rather than in a fixed frame.
+
+ * wrapper.c,h (gdb_parse_exp_1): Added a wrapper for
+ gdb_parse_exp_1.
+ * varobj.h: Added USE_CURRENT_FRAME to varobj_type & changed def'n
+ of varobj_create.
+ * varobj.c (varobj_list): Return type indicates whether the
+ variable's type has changed (for current frame variables).
+ (varobj_update): Handle the case where the variable's type has
+ changed.
+ (delete_variable_1): Allow for deletion of variables that have not
+ been installed yet.
+ (new_root_variable): Initialize use_selected_frame variable.
+ (value_of_root): This is where most of the work to handle "current
+ frame" variables was added. Most of the complexity involves
+ handling the case where the type of the variable has changed.
+ (varobj_create): Add a "type" argument, to tell if the
+ variable is one of these "current frame" variables. Also protect
+ call to parse_exp_1 from long jumping.
+
+
2000-03-13 Eli Zaretskii <eliz@is.elta.co.il>
* go32-nat.c (struct env387): Remove declaration.
+2000-03-13 James Ingham <jingham@leda.cygnus.com>
+
+ * mi-cmd-var.c (mi_cmd_var_create): Add special frame cookie "@"
+ to indicate an "USE_CURRENT_FRAME" variable.
+ (varobj_update_one): Add "in_scope" and "type_changed" to the
+ result.
+
2000-03-06 Elena Zannoni <ezannoni@kwikemart.cygnus.com>
* mi-cmds.h: Export mi_cmd_data_write_register_values.
extern int varobjdebug; /* defined in varobj.c */
-static void varobj_update_one (struct varobj *var);
+static int varobj_update_one (struct varobj *var);
/* VAROBJ operations */
enum mi_cmd_result
mi_cmd_var_create (char *command, char **argv, int argc)
{
- CORE_ADDR frameaddr;
+ CORE_ADDR frameaddr = 0;
struct varobj *var;
char *name;
char *frame;
char *expr;
char *type;
struct cleanup *old_cleanups;
+ enum varobj_type var_type;
if (argc != 3)
{
error ("mi_cmd_var_create: name of object must begin with a letter");
if (strcmp (frame, "*") == 0)
- frameaddr = -1;
+ var_type = USE_CURRENT_FRAME;
+ else if (strcmp (frame, "@") == 0)
+ var_type = USE_SELECTED_FRAME;
else
- frameaddr = parse_and_eval_address (frame);
+ {
+ var_type = USE_SPECIFIED_FRAME;
+ frameaddr = parse_and_eval_address (frame);
+ }
if (varobjdebug)
fprintf_unfiltered (gdb_stdlog,
"Name=\"%s\", Frame=\"%s\" (0x%s), Expression=\"%s\"\n",
name, frame, paddr (frameaddr), expr);
- var = varobj_create (name, expr, frameaddr);
+ var = varobj_create (name, expr, frameaddr, var_type);
if (var == NULL)
error ("mi_cmd_var_create: unable to create variable object");
varobj_update_one (var);
ui_out_list_end (uiout);
}
- return MI_CMD_DONE;
+ return MI_CMD_DONE;
}
-/* Helper for mi_cmd_var_update() */
+/* Helper for mi_cmd_var_update() Returns 0 if the update for
+ the variable fails (usually because the variable is out of
+ scope), and 1 if it succeeds. */
-static void
+static int
varobj_update_one (struct varobj *var)
{
struct varobj **changelist;
nc = varobj_update (var, &changelist);
- if (nc <= 0)
- return;
-
- cc = changelist;
- while (*cc != NULL)
+ /* nc == 0 means that nothing has changed.
+ nc == -1 means that an error occured in updating the variable.
+ nc == -2 means the variable has changed type. */
+
+ if (nc == 0)
+ return 1;
+ else if (nc == -1)
{
- ui_out_field_string (uiout, "name", varobj_get_objname (*cc));
- cc++;
+ ui_out_field_string (uiout, "name", varobj_get_objname(var));
+ ui_out_field_string (uiout, "in_scope", "false");
+ return -1;
+ }
+ else if (nc == -2)
+ {
+ ui_out_field_string (uiout, "name", varobj_get_objname (var));
+ ui_out_field_string (uiout, "in_scope", "true");
+ ui_out_field_string (uiout, "new_type", varobj_get_type(var));
+ ui_out_field_int (uiout, "new_num_children",
+ varobj_get_num_children(var));
+ }
+ else
+ {
+
+ cc = changelist;
+ while (*cc != NULL)
+ {
+ ui_out_field_string (uiout, "name", varobj_get_objname (*cc));
+ ui_out_field_string (uiout, "in_scope", "true");
+ ui_out_field_string (uiout, "type_changed", "false");
+ cc++;
+ }
+ free (changelist);
+ return 1;
}
- free (changelist);
+ return 1;
}
/* Local variables: */
+2000-03-13 James Ingham <jingham@leda.cygnus.com>
+
+ * lib/gdb.exp: Fix the gdbtk_start routine to correctly find all
+ the library directories.
+
Mon Feb 21 13:05:36 2000 Andrew Cagney <cagney@b1.cygnus.com>
* configure.in (configdirs): Add sub directory gdb.mi.
+2000-03-13 James Ingham <jingham@leda.cygnus.com>
+
+ * mi-var-block.exp: The error report from varobj_create changed
+ since I am now trapping parse_exp_1 errors. Change the tests to
+ match the new error message.
+ * mi-var-child.exp: Ditto.
+ * mi-var-cmd.exp: Ditto.
+
2000-03-06 Elena Zannoni <ezannoni@kwikemart.cygnus.com>
* mi-disassemble.exp: Don't assume numbers for the offset
"create local variable cb"
mi_gdb_test "-var-create foo * foo" \
- "&\"No symbol \\\\\"foo\\\\\" in current context.\\\\n\".*\\^error,msg=\"No symbol \\\\\"foo\\\\\" in current context.\"" \
+ "&\"mi_cmd_var_create: unable to create variable object\\\\n\".*\\^error,msg=\"mi_cmd_var_create: unable to create variable object\"" \
"create local variable foo"
# step to "foo = 123;"
# Test: c_variable-3.4
# Desc: check foo, cb changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\{name=\"foo\",name=\"cb\"\}" \
+ "\\^done,changelist=\{name=\"foo\",in_scope=\"true\",type_changed=\"false\",name=\"cb\",in_scope=\"true\",type_changed=\"false\"\}" \
"update all vars: cb foo changed"
# step to "foo = 321;"
# Test: c_variable-5.2
# Desc: check that integer changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\{name=\"struct_declarations.integer\"\}" \
+ "\\^done,changelist=\{name=\"struct_declarations.integer\",in_scope=\"true\",type_changed=\"false\"\}" \
"update all vars struct_declarations.integer"
# Step over:
# Test: c_variable-5.3
# Desc: check that char_ptr changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\{name=\"struct_declarations.char_ptr\"\}" \
+ "\\^done,changelist=\{name=\"struct_declarations.char_ptr\",in_scope=\"true\",type_changed=\"false\"\}" \
"update all vars struct_declarations.char_ptr"
# Step over "struct_declarations.int_ptr_ptr = &foo;"
# Test: c_variable-5.4
# Desc: check that int_ptr_ptr and children changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\{name=\"weird->int_ptr_ptr\",name=\"weird->int_ptr_ptr.\\*weird->int_ptr_ptr\",name=\"weird->int_ptr_ptr.\\*weird->int_ptr_ptr.\\*\\*weird->int_ptr_ptr\",name=\"struct_declarations.int_ptr_ptr\",name=\"struct_declarations.int_ptr_ptr.\\*int_ptr_ptr\",name=\"struct_declarations.int_ptr_ptr.\\*int_ptr_ptr.\\*\\*int_ptr_ptr\"\}" \
+ "\\^done,changelist=\{name=\"weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",name=\"weird->int_ptr_ptr.\\*weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",name=\"weird->int_ptr_ptr.\\*weird->int_ptr_ptr.\\*\\*weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",name=\"struct_declarations.int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",name=\"struct_declarations.int_ptr_ptr.\\*int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",name=\"struct_declarations.int_ptr_ptr.\\*int_ptr_ptr.\\*\\*int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\}" \
"update all vars int_ptr_ptr and children changed"
# Step over "weird->long_array[0] = 1234;"
# Test: c_variable-5.5
# Desc: check that long_array[0] changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\{name=\"struct_declarations.long_array.0\"\}" \
+ "\\^done,changelist=\{name=\"struct_declarations.long_array.0\",in_scope=\"true\",type_changed=\"false\"\}" \
"update all vars struct_declarations.long_array.0 changed"
# Step over "struct_declarations.long_array[1] = 2345;"
# Test: c_variable-5.6
# Desc: check that long_array[1] changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\{name=\"struct_declarations.long_array.1\"\}" \
+ "\\^done,changelist=\{name=\"struct_declarations.long_array.1\",in_scope=\"true\",type_changed=\"false\"\}" \
"update all vars struct_declarations.long_array.1 changed"
# Step over "weird->long_array[2] = 3456;"
# Test: c_variable-5.7
# Desc: check that long_array[2] changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\{name=\"struct_declarations.long_array.2\"\}" \
+ "\\^done,changelist=\{name=\"struct_declarations.long_array.2\",in_scope=\"true\",type_changed=\"false\"\}" \
"update all vars struct_declarations.long_array.2 changed"
# Step over:
# Test: c_variable-5.8
# Desc: check that long_array[3-9] changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\{name=\"struct_declarations.long_array.3\",name=\"struct_declarations.long_array.4\",name=\"struct_declarations.long_array.5\",name=\"struct_declarations.long_array.6\",name=\"struct_declarations.long_array.7\",name=\"struct_declarations.long_array.8\",name=\"struct_declarations.long_array.9\"\}" \
+ "\\^done,changelist=\{name=\"struct_declarations.long_array.3\",in_scope=\"true\",type_changed=\"false\",name=\"struct_declarations.long_array.4\",in_scope=\"true\",type_changed=\"false\",name=\"struct_declarations.long_array.5\",in_scope=\"true\",type_changed=\"false\",name=\"struct_declarations.long_array.6\",in_scope=\"true\",type_changed=\"false\",name=\"struct_declarations.long_array.7\",in_scope=\"true\",type_changed=\"false\",name=\"struct_declarations.long_array.8\",in_scope=\"true\",type_changed=\"false\",name=\"struct_declarations.long_array.9\",in_scope=\"true\",type_changed=\"false\"\}" \
"update all vars struct_declarations.long_array.3-9 changed"
# Test: c_variable-5.9
# Desc: check that func_ptr changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\{name=\"struct_declarations.func_ptr\"\}" \
+ "\\^done,changelist=\{name=\"struct_declarations.func_ptr\",in_scope=\"true\",type_changed=\"false\"\}" \
"update all vars struct_declarations.func_ptr changed"
# Delete all variables
# Test: c_variable-5.47
# Desc: check that psnp->char_ptr (and [0].char_ptr) changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\{name=\"psnp->ptrs.0.char_ptr\",name=\"psnp->char_ptr\",name=\"psnp->char_ptr.\\*psnp->char_ptr\",name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr\",name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr.\\*\\*\\*psnp->char_ptr\"\}" \
+ "\\^done,changelist=\{name=\"psnp->ptrs.0.char_ptr\",in_scope=\"true\",type_changed=\"false\",name=\"psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\",name=\"psnp->char_ptr.\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\",name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\",name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr.\\*\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\"\}" \
"update all vars psnp->char_ptr (and 0.char_ptr) changed"
# Step over "snp1.char_ptr = &c3;"
# Test: c_variable-5.48
# Desc: check that psnp->next->char_ptr (and [1].char_ptr) changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\{name=\"psnp->ptrs.0.next.char_ptr\",name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr\",name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr\",name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr.\\*\\*\\*char_ptr\"\}" \
+ "\\^done,changelist=\{name=\"psnp->ptrs.0.next.char_ptr\",in_scope=\"true\",type_changed=\"false\",name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr\",in_scope=\"true\",type_changed=\"false\",name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\",name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr.\\*\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\"\}" \
"update all vars psnp->next->char_ptr (and 1.char_ptr) changed"
# Test: c_variable-5.49
# Desc: check that psnp->next->next->char_ptr (and [2].char_ptr) changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\{name=\"psnp->ptrs.0.next.next.char_ptr\"\}" \
+ "\\^done,changelist=\{name=\"psnp->ptrs.0.next.next.char_ptr\",in_scope=\"true\",type_changed=\"false\"\}" \
"update all vars psnp->next->next->char_ptr (and 2.char_ptr) changed"
# Test: c_variable-5.50
# Desc: check that psnp->long_ptr (and [0].long_ptr) changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\{name=\"psnp->ptrs.0.long_ptr\",name=\"psnp->long_ptr\",name=\"psnp->long_ptr.\\*psnp->long_ptr\",name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr\",name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr.\\*\\*\\*psnp->long_ptr\",name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr.\\*\\*\\*psnp->long_ptr.\\*\\*\\*\\*psnp->long_ptr\"\}" \
+ "\\^done,changelist=\{name=\"psnp->ptrs.0.long_ptr\",in_scope=\"true\",type_changed=\"false\",name=\"psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\",name=\"psnp->long_ptr.\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\",name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\",name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr.\\*\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\",name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr.\\*\\*\\*psnp->long_ptr.\\*\\*\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\"\}" \
"update all vars psnp->long_ptr (and 0.long_ptr) changed"
# Test: c_variable-5.51
# Desc: check that psnp->next->long_ptr (and [1].long_ptr) changed
+# Why does this have a FIXME?
+setup_xfail *-*-*
mi_gdb_test "-var-update *" \
- "FIXME\\^done,changelist=\{name=\"psnp->ptrs.0.next.long_ptr\"\}" \
+ "FIXME\\^done,changelist=\{name=\"psnp->ptrs.0.next.long_ptr\",in_scope=\"true\",type_changed=\"false\"\}" \
"update all vars psnp->next->long_ptr (and 1.long_ptr) changed"
+clear_xfail *-*-*
# This command produces this error message:
-# &"warning: varobj_list: assertion failed - mycount <> 0\n"^M
+# &"warning: varobj_list: assertion failed - mycount <> 0\n"
#
# Step over "snp2.long_ptr = &z3;"
# Test: c_variable-5.52
# Desc: check that psnp->next->next->long_ptr (and [2].long_ptr) changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\{name=\"psnp->ptrs.0.next.next.long_ptr\"\}" \
+ "\\^done,changelist=\{name=\"psnp->ptrs.0.next.next.long_ptr\",in_scope=\"true\",type_changed=\"false\"\}" \
"update all vars psnp->next->next->long_ptr (and 2.long_ptr) changed"
# Desc: Create non-existent variable
mi_gdb_test "112-var-create bogus_unknown_variable * bogus_unknown_variable" \
- "&\"No symbol \\\\\"bogus_unknown_variable\\\\\" in current context.\\\\n\".*112\\^error,msg=\"No symbol \\\\\"bogus_unknown_variable\\\\\" in current context.\"" \
+ "&\"mi_cmd_var_create: unable to create variable object\\\\n\".*112\\^error,msg=\"mi_cmd_var_create: unable to create variable object\"" \
"create non-existent variable"
# Test: c_variable-1.3
# Desc: Create out of scope variable
mi_gdb_test "113-var-create argc * argc" \
- "&\"No symbol \\\\\"argc\\\\\" in current context.\\\\n\".*113\\^error,msg=\"No symbol \\\\\"argc\\\\\" in current context.\"" \
+ "&\"mi_cmd_var_create: unable to create variable object\\\\n\".*113\\^error,msg=\"mi_cmd_var_create: unable to create variable object\"" \
"create out of scope variable"
mi_gdb_test "200-break-insert do_locals_tests" \
# Test: c_variable-2.2
# Desc: check whether only linteger changed values
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\{name=\"linteger\"\}" \
+ "\\^done,changelist=\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\"\}" \
"update all vars: linteger changed"
# Step over "lpinteger = &linteger;"
# Test: c_variable-2.3
# Desc: check whether only lpinteger changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\{name=\"lpinteger\"\}" \
+ "\\^done,changelist=\{name=\"lpinteger\",in_scope=\"true\",type_changed=\"false\"\}" \
"update all vars: lpinteger changed"
# Step over "lcharacter = 'a';"
# Test: c_variable-2.4
# Desc: check whether only lcharacter changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\{name=\"lcharacter\"\}" \
+ "\\^done,changelist=\{name=\"lcharacter\",in_scope=\"true\",type_changed=\"false\"\}" \
"update all vars: lcharacter changed"
# Step over "lpcharacter = &lcharacter;"
# Test: c_variable-2.5
# Desc: check whether only lpcharacter changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\{name=\"lpcharacter\"\}" \
+ "\\^done,changelist=\{name=\"lpcharacter\",in_scope=\"true\",type_changed=\"false\"\}" \
"update all vars: lpcharacter changed"
# Desc: check whether llong, lplong, lfloat, lpfloat, ldouble, lpdouble, lsimple.integer,
# lsimple.unsigned_character lsimple.integer lsimple.character changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\{name=\"lsimple.integer\",name=\"lsimple->integer\",name=\"lsimple.character\",name=\"lpdouble\",name=\"ldouble\",name=\"lpfloat\",name=\"lfloat\",name=\"lplong\",name=\"llong\"\}" \
+ "\\^done,changelist=\{name=\"lsimple.integer\",in_scope=\"true\",type_changed=\"false\",name=\"lsimple->integer\",in_scope=\"true\",type_changed=\"false\",name=\"lsimple.character\",in_scope=\"true\",type_changed=\"false\",name=\"lpdouble\",in_scope=\"true\",type_changed=\"false\",name=\"ldouble\",in_scope=\"true\",type_changed=\"false\",name=\"lpfloat\",in_scope=\"true\",type_changed=\"false\",name=\"lfloat\",in_scope=\"true\",type_changed=\"false\",name=\"lplong\",in_scope=\"true\",type_changed=\"false\",name=\"llong\",in_scope=\"true\",type_changed=\"false\"\}" \
"update all vars: many changed"
# Step over:
# Test: c_variable-2.7
# Desc: check whether (lsimple.signed_character, lsimple.char_ptr) lpsimple, func changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\{name=\"func\",name=\"lpsimple\"\}" \
+ "\\^done,changelist=\{name=\"func\",in_scope=\"true\",type_changed=\"false\",name=\"lpsimple\",in_scope=\"true\",type_changed=\"false\"\}" \
"update all vars: func and lpsimple changed"
# Step over
# Note: this test also checks that lpsimple->integer and lsimple.integer have
# changed (they are the same)
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\{name=\"lsimple.integer\",name=\"lsimple->integer\",name=\"lsimple.character\",name=\"ldouble\",name=\"lfloat\",name=\"llong\",name=\"lcharacter\",name=\"linteger\"\}" \
+ "\\^done,changelist=\{name=\"lsimple.integer\",in_scope=\"true\",type_changed=\"false\",name=\"lsimple->integer\",in_scope=\"true\",type_changed=\"false\",name=\"lsimple.character\",in_scope=\"true\",type_changed=\"false\",name=\"ldouble\",in_scope=\"true\",type_changed=\"false\",name=\"lfloat\",in_scope=\"true\",type_changed=\"false\",name=\"llong\",in_scope=\"true\",type_changed=\"false\",name=\"lcharacter\",in_scope=\"true\",type_changed=\"false\",name=\"linteger\",in_scope=\"true\",type_changed=\"false\"\}" \
"update all vars: func and lpsimple changed"
# Test: c_variable-2.11
# Desc: create do_locals_tests local in subroutine1
mi_gdb_test "-var-create linteger * linteger" \
- "&\"No symbol \\\\\"linteger\\\\\" in current context.\\\\n\".*\\^error,msg=\"No symbol \\\\\"linteger\\\\\" in current context.\"" \
+ "&\"mi_cmd_var_create: unable to create variable object\\\\n\".*\\^error,msg=\"mi_cmd_var_create: unable to create variable object\"" \
"create linteger"
send_gdb "-exec-step\n"
# Desc: change global_simple.integer
# Note: This also tests whether we are reporting changes in structs properly.
# gdb normally would say that global_simple has changed, but we
-# special case that, since it is not what a human expects to see.
+# special case that, since it is not what a human expects to
+# see.
+
+setup_xfail *-*-*
mi_gdb_test "-var-update *" \
"\\^done,changelist=\{FIXME: WHAT IS CORRECT HERE\}" \
"update all vars: changed FIXME"
+clear_xfail *-*-*
send_gdb "-exec-step\n"
gdb_expect {
# Test: c_variable-2.13
# Desc: change subroutine1 local i
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\{name=\"i\"\}" \
+ "\\^done,changelist=\{name=\"i\",in_scope=\"true\",type_changed=\"false\"\}" \
"update all vars: i changed"
send_gdb "-exec-step\n"
# Test: c_variable-2.14
# Desc: change do_locals_tests local llong
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\{name=\"llong\"\}" \
+ "\\^done,changelist=\{name=\"llong\",in_scope=\"true\",type_changed=\"false\"\}" \
"update all vars: llong changed"
send_gdb "-exec-next\n"
# Test: c_variable-2.15
# Desc: check for out of scope subroutine1 locals
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\{\}" \
- "update all vars: none changed"
+ "\\^done,changelist=\{name=\"l\",in_scope=\"false\",name=\"i\",in_scope=\"false\"\}" \
+ "update all vars: all now out of scope"
# Done with locals/globals tests. Erase all variables
#delete_all_variables
}
}
+
set wd [pwd]
- cd [file join $srcdir .. gdbtk library]
+ cd $srcdir
+ set abs_srcdir [pwd]
+ cd [file join $abs_srcdir .. gdbtk library]
set env(GDBTK_LIBRARY) [pwd]
- cd [file join $srcdir .. .. tcl library]
+ cd [file join $abs_srcdir .. .. tcl library]
set env(TCL_LIBRARY) [pwd]
- cd [file join $srcdir .. .. tk library]
+ cd [file join $abs_srcdir .. .. tk library]
set env(TK_LIBRARY) [pwd]
- cd [file join $srcdir .. .. tix library]
+ cd [file join $abs_srcdir .. .. tix library]
set env(TIX_LIBRARY) [pwd]
- cd [file join $srcdir .. .. itcl itcl library]
+ cd [file join $abs_srcdir .. .. itcl itcl library]
set env(ITCL_LIBRARY) [pwd]
- cd [file join .. $srcdir .. .. libgui library]
+ cd [file join .. $abs_srcdir .. .. libgui library]
set env(CYGNUS_GUI_LIBRARY) [pwd]
cd $wd
- cd [file join $srcdir $subdir]
+ cd [file join $abs_srcdir $subdir]
set env(DEFS) [file join [pwd] defs]
cd $wd
cd [file join $objdir $subdir]
set env(OBJDIR) [pwd]
cd $wd
- cd $srcdir
- set env(SRCDIR) [pwd]
- cd $wd
+
+ set env(SRCDIR) $abs_srcdir
set env(GDBTK_VERBOSE) 1
set env(GDBTK_LOGFILE) [file join $objdir gdb.log]
set env(GDBTK_TEST_RUNNING) 1
/* The frame for this expression */
CORE_ADDR frame;
+ /* If 1, "update" always recomputes the frame & valid block
+ using the currently selected frame. */
+ int use_selected_frame;
+
/* Language info for this variable and its children */
struct language_specific *lang;
static char *name_of_child PARAMS ((struct varobj *, int));
-static value_ptr value_of_root PARAMS ((struct varobj * var));
+static value_ptr value_of_root PARAMS ((struct varobj ** var_handle,
+ int *));
static value_ptr value_of_child PARAMS ((struct varobj * parent, int index));
static char *c_name_of_child PARAMS ((struct varobj * parent, int index));
-static value_ptr c_value_of_root PARAMS ((struct varobj * var));
+static value_ptr c_value_of_root PARAMS ((struct varobj ** var_handle));
static value_ptr c_value_of_child PARAMS ((struct varobj * parent, int index));
static char *cplus_name_of_child PARAMS ((struct varobj * parent, int index));
-static value_ptr cplus_value_of_root PARAMS ((struct varobj * var));
+static value_ptr cplus_value_of_root PARAMS ((struct varobj ** var_handle));
static value_ptr cplus_value_of_child PARAMS ((struct varobj * parent, int index));
static char *java_name_of_child PARAMS ((struct varobj * parent, int index));
-static value_ptr java_value_of_root PARAMS ((struct varobj * var));
+static value_ptr java_value_of_root PARAMS ((struct varobj ** var_handle));
static value_ptr java_value_of_child PARAMS ((struct varobj * parent, int index));
char *(*name_of_child) PARAMS ((struct varobj * parent, int index));
/* The value_ptr of the root variable ROOT. */
- value_ptr (*value_of_root) PARAMS ((struct varobj * root));
+ value_ptr (*value_of_root) PARAMS ((struct varobj ** root_handle));
/* The value_ptr of the INDEX'th child of PARENT. */
value_ptr (*value_of_child) PARAMS ((struct varobj * parent, int index));
struct varobj *
varobj_create (char *objname,
- char *expression, CORE_ADDR frame)
+ char *expression, CORE_ADDR frame,
+ enum varobj_type type)
{
struct varobj *var;
struct frame_info *fi, *old_fi;
of the variable's data as possible */
/* Allow creator to specify context of variable */
- if (frame == (CORE_ADDR) -1)
+ if ((type == USE_CURRENT_FRAME)
+ || (type == USE_SELECTED_FRAME))
fi = selected_frame;
else
fi = find_frame_addr_in_frame_chain (frame);
+ /* frame = -2 means always use selected frame */
+ if (type == USE_SELECTED_FRAME)
+ var->root->use_selected_frame = 1;
+
block = NULL;
if (fi != NULL)
block = get_frame_block (fi);
p = expression;
innermost_block = NULL;
- /* Callee may longjump */
- var->root->exp = parse_exp_1 (&p, block, 0);
+ /* Wrap the call to parse expression, so we can
+ return a sensible error. */
+ if (!gdb_parse_exp_1 (&p, block, 0, &var->root->exp))
+ {
+ return NULL;
+ }
/* Don't allow variables to be created for types. */
if (var->root->exp->elts[0].opcode == OP_TYPE)
select_frame (old_fi, -1);
}
- if (var != NULL)
+ /* If the variable object name is null, that means this
+ is a temporary variable, so don't install it. */
+
+ if ((var != NULL) && (objname != NULL))
{
var->obj_name = savestring (objname, strlen (objname));
expression to see if it's changed. Then go all the way
through its children, reconstructing them and noting if they've
changed.
+ Return value:
+ -1 if there was an error updating the varobj
+ -2 if the type changed
+ Otherwise it is the number of children + parent changed
Only root variables can be updated... */
varobj_update (struct varobj *var, struct varobj ***changelist)
{
int changed = 0;
+ int type_changed;
int i;
int vleft;
int error2;
/* Update the root variable. value_of_root can return NULL
if the variable is no longer around, i.e. we stepped out of
- the frame in which a local existed. */
- new = value_of_root (var);
+ the frame in which a local existed. We are letting the
+ value_of_root variable dispose of the varobj if the type
+ has changed. */
+ type_changed = 1;
+ new = value_of_root (&var, &type_changed);
if (new == NULL)
- return -1;
+ {
+ var->error = 1;
+ return -1;
+ }
/* Initialize a stack for temporary results */
vpush (&result, NULL);
- if (!my_value_equal (var->value, new, &error2))
+ if (type_changed || !my_value_equal (var->value, new, &error2))
{
/* Note that it's changed There a couple of exceptions here,
- though. We don't want some types to be reported as "changed". */
- if (type_changeable (var))
+ though. We don't want some types to be reported as
+ "changed". The exception to this is if this is a
+ "use_selected_frame" varobj, and its type has changed. */
+ if (type_changed || type_changeable (var))
{
vpush (&result, var);
changed++;
/* Restore selected frame */
select_frame (old_fi, -1);
- return changed;
+ if (type_changed)
+ return -2;
+ else
+ return changed;
}
\f
return;
/* Otherwise, add it to the list of deleted ones and proceed to do so */
- if (var->obj_name == NULL)
- warning ("Assertion failed: NULL var->obj_name unexpectdly found");
- else
+ /* If the name is null, this is a temporary variable, that has not
+ yet been installed, don't report it, it belongs to the caller... */
+ if (var->obj_name != NULL)
{
cppush (resultp, strdup (var->obj_name));
*delcountp = *delcountp + 1;
{
remove_child_from_parent (var->parent, var);
}
-
- uninstall_variable (var);
+
+ if (var->obj_name != NULL)
+ uninstall_variable (var);
/* Free memory associated with this variable */
free_variable (var);
var->root->exp = NULL;
var->root->valid_block = NULL;
var->root->frame = (CORE_ADDR) -1;
+ var->root->use_selected_frame = 0;
var->root->rootvar = NULL;
return var;
return (*var->root->lang->name_of_child) (var, index);
}
-/* What is the value_ptr of the root variable VAR? */
+/* What is the value_ptr of the root variable VAR?
+ TYPE_CHANGED controls what to do if the type of a
+ use_selected_frame = 1 variable changes. On input,
+ TYPE_CHANGED = 1 means discard the old varobj, and replace
+ it with this one. TYPE_CHANGED = 0 means leave it around.
+ NB: In both cases, var_handle will point to the new varobj,
+ so if you use TYPE_CHANGED = 0, you will have to stash the
+ old varobj pointer away somewhere before calling this.
+ On return, TYPE_CHANGED will be 1 if the type has changed, and
+ 0 otherwise. */
static value_ptr
-value_of_root (var)
- struct varobj *var;
+value_of_root (var_handle, type_changed)
+ struct varobj ** var_handle;
+ int *type_changed;
{
- return (*var->root->lang->value_of_root) (var);
+ struct varobj *var;
+
+ if (var_handle == NULL)
+ return NULL;
+
+ var = *var_handle;
+
+ /* This should really be an exception, since this should
+ only get called with a root variable. */
+
+ if (var->root->rootvar != var)
+ return NULL;
+
+ if (var->root->use_selected_frame)
+ {
+ struct varobj *tmp_var;
+ char *old_type, *new_type;
+ old_type = varobj_get_type (var);
+ tmp_var = varobj_create (NULL, var->name, (CORE_ADDR) 0,
+ USE_SELECTED_FRAME);
+ if (tmp_var == NULL)
+ {
+ return NULL;
+ }
+ new_type = varobj_get_type (tmp_var);
+ if (strcmp(old_type, new_type) == 0)
+ {
+ varobj_delete (tmp_var, NULL, 0);
+ *type_changed = 0;
+ }
+ else
+ {
+ if (*type_changed)
+ {
+ tmp_var->obj_name =
+ savestring (var->obj_name, strlen (var->obj_name));
+ uninstall_variable (var);
+ }
+ else
+ {
+ tmp_var->obj_name = varobj_gen_name ();
+ }
+ install_variable (tmp_var);
+ *var_handle = tmp_var;
+ *type_changed = 1;
+ }
+ }
+ else
+ {
+ *type_changed = 0;
+ }
+
+ return (*var->root->lang->value_of_root) (var_handle);
}
/* What is the value_ptr for the INDEX'th child of PARENT? */
}
static value_ptr
-c_value_of_root (var)
- struct varobj *var;
+c_value_of_root (var_handle)
+ struct varobj **var_handle;
{
value_ptr new_val;
+ struct varobj *var = *var_handle;
struct frame_info *fi;
int within_scope;
+ /* Only root variables can be updated... */
+ if (var->root->rootvar != var)
+ /* Not a root var */
+ return NULL;
+
+
/* Determine whether the variable is still around. */
if (var->root->valid_block == NULL)
within_scope = 1;
else
{
reinit_frame_cache ();
+
+
fi = find_frame_addr_in_frame_chain (var->root->frame);
+
within_scope = fi != NULL;
/* FIXME: select_frame could fail */
if (within_scope)
select_frame (fi, -1);
}
-
+
if (within_scope)
{
- /* We need to catch errors here, because if evaluate expression fails
- we just want to make val->error = 1 and go on */
+ /* We need to catch errors here, because if evaluate
+ expression fails we just want to make val->error = 1 and
+ go on */
if (gdb_evaluate_expression (var->root->exp, &new_val))
{
if (VALUE_LAZY (new_val))
{
- /* We need to catch errors because if value_fetch_lazy fails we
- still want to continue (after making val->error = 1) */
- /* FIXME: Shouldn't be using VALUE_CONTENTS? The comment on
- value_fetch_lazy() says it is only called from the macro... */
+ /* We need to catch errors because if
+ value_fetch_lazy fails we still want to continue
+ (after making val->error = 1) */
+ /* FIXME: Shouldn't be using VALUE_CONTENTS? The
+ comment on value_fetch_lazy() says it is only
+ called from the macro... */
if (!gdb_value_fetch_lazy (new_val))
var->error = 1;
else
}
else
var->error = 1;
-
+
release_value (new_val);
return new_val;
}
}
static value_ptr
-cplus_value_of_root (var)
- struct varobj *var;
+cplus_value_of_root (var_handle)
+ struct varobj **var_handle;
{
- return c_value_of_root (var);
+ return c_value_of_root (var_handle);
}
static value_ptr
}
static value_ptr
-java_value_of_root (var)
- struct varobj *var;
+java_value_of_root (var_handle)
+ struct varobj **var_handle;
{
- return cplus_value_of_root (var);
+ return cplus_value_of_root (var_handle);
}
static value_ptr
FORMAT_OCTAL /* Octal display */
};
+enum varobj_type
+ {
+ USE_SPECIFIED_FRAME, /* Use the frame passed to varobj_create */
+ USE_CURRENT_FRAME, /* Use the current frame */
+ USE_SELECTED_FRAME /* Always reevaluate in selected frame */
+ };
+
/* String representations of gdb's format codes (defined in varobj.c) */
extern char *varobj_format_string[];
/* API functions */
extern struct varobj *varobj_create (char *objname,
- char *expression, CORE_ADDR frame);
+ char *expression, CORE_ADDR frame,
+ enum varobj_type type);
extern char *varobj_gen_name (void);
char *args[10];
};
+int gdb_parse_exp_1 PARAMS ((char **, struct block *,
+ int, struct expression **));
+int wrap_parse_exp_1 PARAMS ((char *));
+
int gdb_evaluate_expression PARAMS ((struct expression *, value_ptr *));
int wrap_evaluate_expression PARAMS ((char *));
int gdb_value_ind PARAMS ((value_ptr val, value_ptr * rval));
int wrap_value_ind PARAMS ((char *opaque_arg));
+int
+gdb_parse_exp_1 (stringptr, block, comma, expression)
+ char **stringptr;
+ struct block *block;
+ int comma;
+ struct expression **expression;
+{
+ struct gdb_wrapper_arguments args;
+ args.args[0] = (char *) stringptr;
+ args.args[1] = (char *) block;
+ args.args[2] = (char *) comma;
+
+ if (!catch_errors ((catch_errors_ftype *) wrap_parse_exp_1, &args,
+ "", RETURN_MASK_ERROR))
+ {
+ /* An error occurred */
+ return 0;
+ }
+
+ *expression = (struct expression *) args.result;
+ return 1;
+
+}
+
+int
+wrap_parse_exp_1 (argptr)
+ char *argptr;
+{
+ struct gdb_wrapper_arguments *args
+ = (struct gdb_wrapper_arguments *) argptr;
+ args->result = (char *) parse_exp_1((char **) args->args[0],
+ (struct block *) args->args[1],
+ (int) args->args[2]);
+ return 1;
+}
+
int
gdb_evaluate_expression (exp, value)
struct expression *exp;
(args)->result = (char *) value_ind (val);
return 1;
}
+
/* Use this struct used to pass arguments to wrapper routines. */
struct gdb_wrapper_arguments;
+extern int gdb_parse_exp_1 PARAMS ((char **, struct block *,
+ int, struct expression **));
+extern int wrap_parse_exp_1 PARAMS ((char *));
+
extern int gdb_evaluate_expression PARAMS ((struct expression *, value_ptr *));
extern int wrap_evaluate_expression PARAMS ((char *));