Introduce save_vars, a testsuite proc for safely manipulating globals
authorPatrick Palka <patrick@parcs.ath.cx>
Fri, 19 Jun 2015 01:33:26 +0000 (21:33 -0400)
committerPatrick Palka <patrick@parcs.ath.cx>
Wed, 12 Aug 2015 12:39:18 +0000 (08:39 -0400)
gdb/testsuite/ChangeLog:

* lib/gdb.exp (save_vars): New proc.

gdb/testsuite/ChangeLog
gdb/testsuite/lib/gdb.exp

index 7af0868552f5854b8818891e898718a96dca60a2..2bfa192139e56ea114f4a582fe683fd3953f1ef1 100644 (file)
@@ -1,3 +1,7 @@
+2015-08-12  Patrick Palka  <patrick@parcs.ath.cx>
+
+       * lib/gdb.exp (save_vars): New proc.
+
 2015-08-11  Keith Seitz  <keiths@redhat.com>
 
        * gdb.base/help.exp: Update help_breakpoint_text.
index 5ecef1a81752ef7e97976df59e3308dc7d570698..c5b7a06cfbb0352fe457e7d7cd6b2c9fd80c44de 100644 (file)
@@ -1897,6 +1897,73 @@ proc with_test_prefix { prefix body } {
   }
 }
 
+# Run BODY in the context of the caller.  After BODY is run, the variables
+# listed in VARS will be reset to the values they had before BODY was run.
+#
+# This is useful for providing a scope in which it is safe to temporarily
+# modify global variables, e.g.
+#
+#   global INTERNAL_GDBFLAGS
+#   global env
+#
+#   set foo GDBHISTSIZE
+#
+#   save_vars { INTERNAL_GDBFLAGS env($foo) env(HOME) } {
+#       append INTERNAL_GDBFLAGS " -nx"
+#       unset -nocomplain env(GDBHISTSIZE)
+#       gdb_start
+#       gdb_test ...
+#   }
+#
+# Here, although INTERNAL_GDBFLAGS, env(GDBHISTSIZE) and env(HOME) may be
+# modified inside BODY, this proc guarantees that the modifications will be
+# undone after BODY finishes executing.
+
+proc save_vars { vars body } {
+    array set saved_scalars { }
+    array set saved_arrays { }
+    set unset_vars { }
+
+    foreach var $vars {
+       # First evaluate VAR in the context of the caller in case the variable
+       # name may be a not-yet-interpolated string like env($foo)
+       set var [uplevel 1 list $var]
+
+       if [uplevel 1 [list info exists $var]] {
+           if [uplevel 1 [list array exists $var]] {
+               set saved_arrays($var) [uplevel 1 [list array get $var]]
+           } else {
+               set saved_scalars($var) [uplevel 1 [list set $var]]
+           }
+       } else {
+           lappend unset_vars $var
+       }
+    }
+
+    set code [catch {uplevel 1 $body} result]
+
+    foreach {var value} [array get saved_scalars] {
+       uplevel 1 [list set $var $value]
+    }
+
+    foreach {var value} [array get saved_arrays] {
+       uplevel 1 [list unset $var]
+       uplevel 1 [list array set $var $value]
+    }
+
+    foreach var $unset_vars {
+       uplevel 1 [list unset -nocomplain $var]
+    }
+
+    if {$code == 1} {
+       global errorInfo errorCode
+       return -code $code -errorinfo $errorInfo -errorcode $errorCode $result
+    } else {
+       return -code $code $result
+    }
+}
+
+
 # Run tests in BODY with GDB prompt and variable $gdb_prompt set to
 # PROMPT.  When BODY is finished, restore GDB prompt and variable
 # $gdb_prompt.