From 73a93a3251211bf8c5774282e41dbc023820404a Mon Sep 17 00:00:00 2001 From: Jim Ingham Date: Mon, 13 Mar 2000 21:51:46 +0000 Subject: [PATCH] 2000-03-13 James Ingham 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. * 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. * lib/gdb.exp: Fix the gdbtk_start routine to correctly find all the library directories. * gdbtk-varobj.c (variable_create): Pass the correct "how_specified" flag to the varobj_create routine. --- gdb/ChangeLog | 24 ++++ gdb/mi/ChangeLog-mi | 7 + gdb/mi/mi-cmd-var.c | 65 ++++++--- gdb/testsuite/ChangeLog | 5 + gdb/testsuite/gdb.mi/ChangeLog-mi | 8 ++ gdb/testsuite/gdb.mi/mi-var-block.exp | 4 +- gdb/testsuite/gdb.mi/mi-var-child.exp | 33 +++-- gdb/testsuite/gdb.mi/mi-var-cmd.exp | 34 +++-- gdb/testsuite/lib/gdb.exp | 22 +-- gdb/varobj.c | 195 ++++++++++++++++++++------ gdb/varobj.h | 10 +- gdb/wrapper.c | 41 ++++++ gdb/wrapper.h | 4 + 13 files changed, 351 insertions(+), 101 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index d00e17462d5..7097e66bdc1 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,27 @@ +2000-03-13 James Ingham + + 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 * go32-nat.c (struct env387): Remove declaration. diff --git a/gdb/mi/ChangeLog-mi b/gdb/mi/ChangeLog-mi index 6abbfa2b564..eae7d381694 100644 --- a/gdb/mi/ChangeLog-mi +++ b/gdb/mi/ChangeLog-mi @@ -1,3 +1,10 @@ +2000-03-13 James Ingham + + * 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 * mi-cmds.h: Export mi_cmd_data_write_register_values. diff --git a/gdb/mi/mi-cmd-var.c b/gdb/mi/mi-cmd-var.c index 568cb7e2586..a20f4f1bbee 100644 --- a/gdb/mi/mi-cmd-var.c +++ b/gdb/mi/mi-cmd-var.c @@ -34,20 +34,21 @@ 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) { @@ -77,16 +78,21 @@ mi_cmd_var_create (char *command, char **argv, int argc) 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"); @@ -443,12 +449,14 @@ mi_cmd_var_update (char *command, char **argv, int argc) 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; @@ -457,16 +465,41 @@ varobj_update_one (struct varobj *var) 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: */ diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index fc372fd6e11..caf80beceae 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2000-03-13 James Ingham + + * lib/gdb.exp: Fix the gdbtk_start routine to correctly find all + the library directories. + Mon Feb 21 13:05:36 2000 Andrew Cagney * configure.in (configdirs): Add sub directory gdb.mi. diff --git a/gdb/testsuite/gdb.mi/ChangeLog-mi b/gdb/testsuite/gdb.mi/ChangeLog-mi index 54cd191ce0f..b54deaab28f 100644 --- a/gdb/testsuite/gdb.mi/ChangeLog-mi +++ b/gdb/testsuite/gdb.mi/ChangeLog-mi @@ -1,3 +1,11 @@ +2000-03-13 James Ingham + + * 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 * mi-disassemble.exp: Don't assume numbers for the offset diff --git a/gdb/testsuite/gdb.mi/mi-var-block.exp b/gdb/testsuite/gdb.mi/mi-var-block.exp index 7eb473d5950..539a58def6a 100644 --- a/gdb/testsuite/gdb.mi/mi-var-block.exp +++ b/gdb/testsuite/gdb.mi/mi-var-block.exp @@ -62,7 +62,7 @@ mi_gdb_test "-var-create cb * cb" \ "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;" @@ -103,7 +103,7 @@ gdb_expect { # 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;" diff --git a/gdb/testsuite/gdb.mi/mi-var-child.exp b/gdb/testsuite/gdb.mi/mi-var-child.exp index 21a7cba0b22..9aafcedef34 100644 --- a/gdb/testsuite/gdb.mi/mi-var-child.exp +++ b/gdb/testsuite/gdb.mi/mi-var-child.exp @@ -784,7 +784,7 @@ gdb_expect { # 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: @@ -805,7 +805,7 @@ gdb_expect { # 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;" @@ -822,7 +822,7 @@ gdb_expect { # 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;" @@ -839,7 +839,7 @@ gdb_expect { # 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;" @@ -856,7 +856,7 @@ gdb_expect { # 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;" @@ -873,7 +873,7 @@ gdb_expect { # 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: @@ -897,7 +897,7 @@ gdb_expect { # 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" @@ -915,7 +915,7 @@ gdb_expect { # 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 @@ -1185,7 +1185,7 @@ gdb_expect { # 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;" @@ -1203,7 +1203,7 @@ gdb_expect { # 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" @@ -1222,7 +1222,7 @@ gdb_expect { # 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" @@ -1240,7 +1240,7 @@ gdb_expect { # 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" @@ -1258,12 +1258,15 @@ gdb_expect { # 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;" @@ -1281,7 +1284,7 @@ gdb_expect { # 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" diff --git a/gdb/testsuite/gdb.mi/mi-var-cmd.exp b/gdb/testsuite/gdb.mi/mi-var-cmd.exp index 7b4ebcc5eae..f1fcedd26f4 100644 --- a/gdb/testsuite/gdb.mi/mi-var-cmd.exp +++ b/gdb/testsuite/gdb.mi/mi-var-cmd.exp @@ -59,14 +59,14 @@ mi_gdb_test "111-var-create global_simple * global_simple" \ # 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" \ @@ -192,7 +192,7 @@ gdb_expect { # 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;" @@ -209,7 +209,7 @@ gdb_expect { # 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';" @@ -226,7 +226,7 @@ gdb_expect { # 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;" @@ -243,7 +243,7 @@ gdb_expect { # 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" @@ -272,7 +272,7 @@ gdb_expect { # 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: @@ -294,7 +294,7 @@ gdb_expect { # 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 @@ -323,7 +323,7 @@ gdb_expect { # 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" @@ -454,7 +454,7 @@ mi_gdb_test "-var-create l * l" \ # 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" @@ -471,10 +471,14 @@ gdb_expect { # 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 { @@ -487,7 +491,7 @@ 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" @@ -501,7 +505,7 @@ gdb_expect { # 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" @@ -515,8 +519,8 @@ gdb_expect { # 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 diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp index 1a5ecc88e90..191bf1866f8 100644 --- a/gdb/testsuite/lib/gdb.exp +++ b/gdb/testsuite/lib/gdb.exp @@ -1617,29 +1617,31 @@ proc gdbtk_start {test} { } } + 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 diff --git a/gdb/varobj.c b/gdb/varobj.c index f0740c69672..e2a241982ee 100644 --- a/gdb/varobj.c +++ b/gdb/varobj.c @@ -56,6 +56,10 @@ struct varobj_root /* 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; @@ -204,7 +208,8 @@ static char *name_of_variable PARAMS ((struct varobj *)); 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)); @@ -224,7 +229,7 @@ static char *c_name_of_variable PARAMS ((struct varobj * parent)); 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)); @@ -244,7 +249,7 @@ static char *cplus_name_of_variable PARAMS ((struct varobj * parent)); 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)); @@ -262,7 +267,7 @@ static char *java_name_of_variable PARAMS ((struct varobj * parent)); 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)); @@ -290,7 +295,7 @@ struct language_specific 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)); @@ -401,7 +406,8 @@ static struct vlist **varobj_table; 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; @@ -421,19 +427,28 @@ varobj_create (char *objname, 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) @@ -486,7 +501,10 @@ varobj_create (char *objname, 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)); @@ -845,6 +863,10 @@ varobj_list (struct varobj ***varlist) 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... */ @@ -852,6 +874,7 @@ int varobj_update (struct varobj *var, struct varobj ***changelist) { int changed = 0; + int type_changed; int i; int vleft; int error2; @@ -878,19 +901,27 @@ varobj_update (struct varobj *var, struct varobj ***changelist) /* 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++; @@ -984,7 +1015,10 @@ varobj_update (struct varobj *var, struct varobj ***changelist) /* Restore selected frame */ select_frame (old_fi, -1); - return changed; + if (type_changed) + return -2; + else + return changed; } @@ -1039,9 +1073,9 @@ delete_variable_1 (resultp, delcountp, var, 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; @@ -1057,8 +1091,9 @@ delete_variable_1 (resultp, delcountp, var, { 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); @@ -1315,6 +1350,7 @@ new_root_variable (void) 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; @@ -1578,12 +1614,74 @@ name_of_child (var, index) 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? */ @@ -1790,38 +1888,51 @@ c_name_of_child (parent, index) } 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 @@ -1830,7 +1941,7 @@ c_value_of_root (var) } else var->error = 1; - + release_value (new_val); return new_val; } @@ -2194,10 +2305,10 @@ cplus_name_of_child (parent, index) } 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 @@ -2367,10 +2478,10 @@ java_name_of_child (parent, index) } 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 diff --git a/gdb/varobj.h b/gdb/varobj.h index 28c5fac4d16..e5e325498ff 100644 --- a/gdb/varobj.h +++ b/gdb/varobj.h @@ -32,6 +32,13 @@ enum varobj_display_formats 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[]; @@ -50,7 +57,8 @@ struct varobj; /* 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); diff --git a/gdb/wrapper.c b/gdb/wrapper.c index be7d4e27391..ea43fd92b8f 100644 --- a/gdb/wrapper.c +++ b/gdb/wrapper.c @@ -33,6 +33,10 @@ struct gdb_wrapper_arguments 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 *)); @@ -45,6 +49,42 @@ int wrap_value_equal 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; @@ -163,3 +203,4 @@ wrap_value_ind (opaque_arg) (args)->result = (char *) value_ind (val); return 1; } + diff --git a/gdb/wrapper.h b/gdb/wrapper.h index f4303b2264b..401cad8a0c5 100644 --- a/gdb/wrapper.h +++ b/gdb/wrapper.h @@ -22,6 +22,10 @@ /* 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 *)); -- 2.30.2