* gdb.c++/classes.exp, gdb.c++/cplusfuncs.exp,
[deliverable/binutils-gdb.git] / gdb / testsuite / lib / gdb.exp
index 1518c26e320d3a9904af588b7473eee64829f885..a3e0fac75d1c36bb189d5ce3b1c6151c83818ab6 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (C) 1992 Free Software Foundation, Inc.
+# Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc.
 
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # need to be modified for any target, it can be done with a variable
 # or by passing arguments.
 
+global GDB
+if ![info exists GDB] then {
+    set GDB [findfile $base_dir/../gdb $base_dir/../gdb [transform gdb ]]
+}
+
+global GDBFLAGS
+if ![info exists GDBFLAGS] then {
+    set GDBFLAGS ""
+}
+
+# set the prompt if it doesn't exist
+global prompt
+if ![info exists prompt] then {
+    set prompt "\[(\]gdb\[)\]"
+}
+
 #
-# gdb_version -- extract and print the version number of gcc
+# gdb_version -- extract and print the version number of GDB
 #
 proc default_gdb_version {} {
     global GDB
     global GDBFLAGS
     if {[which $GDB] != 0} then {
-       set tmp [exec echo "q" | $GDB]
-       set version "[lindex $tmp [lsearch $tmp "\[0-9\]*"]]"
-       set version "[string range $version 0 [expr [string length $version]-2]]"
-       clone_output "[which $GDB] version $version $GDBFLAGS\n"
+       set tmp [exec echo "q" | $GDB -nw]
+       regexp " \[0-9\.\]+" $tmp version
+       clone_output "[which $GDB] version$version -nw $GDBFLAGS \n"
     } else {
        warning "$GDB does not exist"
     }
@@ -49,22 +64,20 @@ proc gdb_unload {} {
     global prompt
     send "file\n"
     expect {
-       -re "No exec file now\.\r" { continue -expect }
-       -re "No symbol file now\.\r" { continue -expect }
-       -re "A program is being debugged already..*Kill it\? \(y or n\) $"\
+       -re "No exec file now.*\r" { exp_continue }
+       -re "No symbol file now.*\r" { exp_continue }
+       -re "A program is being debugged already..*Kill it.*y or n. $"\
            { send "y\n"
-               if $verbose>1 then {
-                   send_user "\t\tKilling previous program being debugged\n"
-               }
-           continue -expect
+               verbose "\t\tKilling previous program being debugged"
+           exp_continue
        }
-       -re "Discard symbol table from .*\? \(y or n\) $" {
+       -re "Discard symbol table from .*y or n. $" {
            send "y\n"
-           continue -expect
+           exp_continue
        }
        -re "$prompt $" {}
        timeout {
-           error "couldn't unload file in $GDB (timed out)."
+           perror "couldn't unload file in $GDB (timed out)."
            return -1
        }
     }
@@ -81,30 +94,48 @@ proc delete_breakpoints {} {
 
     send "delete breakpoints\n"
     expect {
-       -re "Delete all breakpoints\? \(y or n\) $" {
+       -re "Delete all breakpoints.*y or n. $" {
            send "y\n"
-           continue -expect
+           exp_continue
        }
        -re "y\r\n$prompt $" {}
-       -re ".*$prompt $" { fail "Delete all breakpoints" ; return }
-       timeout { fail "Delete all breakpoints (timeout)" ; return }
+       -re ".*$prompt $" { # This happens if there were no breakpoints
+           }
+       timeout { perror "Delete all breakpoints (timeout)" ; return }
     }
     send "info breakpoints\n"
     expect {
        -re "No breakpoints or watchpoints..*$prompt $" {}
-       -re ".*$prompt $" { fail "breakpoints not deleted" ; return }
-       timeout { fail "info breakpoints (timeout)" ; return }
+       -re ".*$prompt $" { perror "breakpoints not deleted" ; return }
+       timeout { perror "info breakpoints (timeout)" ; return }
     }
 }
 
 
 #
+# Generic run command.
+#
+# The second pattern below matches up to the first newline *only*.
+# Using ``.*$'' could swallow up output that we attempt to match
+# elsewhere.
+#
+proc gdb_run_cmd {} {
+    send "run\n"
+    expect {
+       -re "The program .* has been started already.*y or n. $" {
+           send "y\n"
+           exp_continue
+       }
+       -re "Starting program: \[^\n\]*" {}
+    }
+}
+
+
 # Set breakpoint at function and run gdb until it breaks there.
 # Since this is the only breakpoint that will be set, if it stops
 # at a breakpoint, we will assume it is the one we want.  We can't
 # just compare to "function" because it might be a fully qualified,
 # single quoted C++ function specifier.
-#
 
 proc runto { function } {
     global prompt
@@ -112,7 +143,7 @@ proc runto { function } {
 
     send "delete\n"
     expect {
-       -re "Delete all breakpoints\? \(y or n\) $" {
+       -re "delete.*Delete all breakpoints.*y or n. $" {
            send "y\n"
            expect {
                -re "$prompt $" {}
@@ -124,28 +155,34 @@ proc runto { function } {
     }
 
     send "break $function\n"
-    # The first regexp is what we get with -g, the second without -g.
+    # The first two regexps are what we get with -g, the third is without -g.
     expect {
-       -re "Break.* at .*: file .*, line $decimal.\r\n$prompt $" {}
-       -re "Breakpoint \[0-9\]* at 0x\[0-9a-f\]*.*$prompt $" {}
+       -re "Breakpoint \[0-9\]* at .*: file .*, line $decimal.\r\n$prompt $" {}
+       -re "Breakpoint \[0-9\]*: file .*, line $decimal.\r\n$prompt $" {}
+       -re "Breakpoint \[0-9\]* at .*$prompt $" {}
        -re "$prompt $" { fail "setting breakpoint at $function" ; return 0 }
        timeout { fail "setting breakpoint at $function (timeout)" ; return 0 }
     }
 
-    send "run\n"
+    gdb_run_cmd
+    
     # the "at foo.c:36" output we get with -g.
     # the "in func" output we get without -g.
     expect {
-       -re "The program .* has been started already.* \(y or n\) $" {
-           send "y\n"
-           continue -expect
+       -re "Break.* at .*:$decimal.*$prompt $" {
+           return 1
        }
-       -re "Starting.*Break.* at .*:$decimal.*$prompt $" { return 1 }
        -re "Breakpoint \[0-9\]*, \[0-9xa-f\]* in $function.*$prompt $" { 
            return 1
        }
-       -re "$prompt $" { fail "running to $function" ; return 0 }
-       timeout { fail "running to $function (timeout)" ; return 0 }
+       -re "$prompt $" { 
+           fail "running to $function"
+           return 0
+       }
+       timeout { 
+           fail "running to $function (timeout)"
+           return 0
+       }
     }
 }
 
@@ -184,13 +221,15 @@ proc gdb_test { args } {
 
     set result -1
     set errmess ""
-    # trap the send so any problems don't crash things
-    catch "send \"$command\n\"" errmess
-    if [string match "write\(spawn_id=\[0-9\]+\):" $errmess] then {
-       error "sent \"$command\" got expect error \"$errmess\""
-       catch "close"
-       gdb_start
-       return -1
+    if ![string match $command ""] {
+       # trap the send so any problems don't crash things
+       catch "send \"$command\n\"" errmess
+       if [string match "write.spawn_id=\[0-9\]+.:" $errmess] then {
+           perror "sent \"$command\" got expect error \"$errmess\""
+           catch "close"
+           gdb_start
+           return -1
+       }
     }
 
     expect {
@@ -209,11 +248,11 @@ proc gdb_test { args } {
            set result 0
        }
        -re "Undefined command:.*$prompt" {
-           error "Undefined command \"$command\"."
+           perror "Undefined command \"$command\"."
            set result 1
        }
        -re "Ambiguous command.*$prompt $" {
-           error "\"$command\" is not a unique command name."
+           perror "\"$command\" is not a unique command name."
            set result 1
        }
        -re ".*$prompt $" {
@@ -224,32 +263,180 @@ proc gdb_test { args } {
        }
        "<return>" {
            send "\n"
-           error "Window too small."
+           perror "Window too small."
        }
-       -re "\(y or n\) " {
+       -re "\[(\]+y or n\[)\]+ " {
            send "n\n"
-           error "Got interactive prompt."
+           perror "Got interactive prompt."
        }
        eof {
-           error "Process no longer exists"
+           perror "Process no longer exists"
            return -1
        }
        buffer_full {
-           error "internal buffer is full."
+           perror "internal buffer is full."
        }
        timeout {
-           fail "(timeout) $message"
+           if ![string match "" $message] then {
+               fail "(timeout) $message"
+           }
            set result 1
        }
     }
     return $result
 }
+\f
+# Testing printing of a specific value.  For passes and fails, return
+# a 1 to indicate that more tests can proceed.  However a timeout
+# is a serious error, generates a special fail message, and causes
+# a 0 to be returned to indicate that more tests are likely to fail
+# as well.
+#
+# Args are:
+#
+#      First one is string to send to gdb
+#      Second one is string to match gdb result to
+#      Third one is an optional message to be printed
+#
+# This differs from gdb_test in a few ways: (1) no catch on the send (there is
+# no reason for this to be different from gdb_test but I think the lack of 
+# catch is correct), (2) it tests for the " =" (that could easily be moved
+# to the callers, (3) the pattern must be followed by \r\n and the prompt,
+# not other garbage as in gdb_test (this feature seems kind of worthwhile).
 
-proc gdb_reinitialize_dir { subdir } {
+proc test_print_accept { args } {
     global prompt
     global verbose
 
-    send "dir\n"
+    if [llength $args]==3 then {
+       set message [lindex $args 2]
+    } else {
+       set message [lindex $args 0]
+    }
+    set sendthis [lindex $args 0]
+    set expectthis [lindex $args 1]
+    if $verbose>2 then {
+       send_user "Sending \"$sendthis\" to gdb\n"
+       send_user "Looking to match \"$expectthis\"\n"
+       send_user "Message is \"$message\"\n"
+    }
+    send "$sendthis\n"
+    expect {
+       -re ".* = $expectthis\r\n$prompt $" {
+           if ![string match "" $message] then {
+               pass "$sendthis ($message)"
+           } else {
+               pass "$sendthis"
+           }
+           return 1
+       }
+       -re ".*$prompt $" {
+           if ![string match "" $message] then {
+               fail "$sendthis ($message)"
+           } else {
+               fail "$sendthis"
+           }
+           return 1
+       }
+       timeout {
+           fail "$sendthis (timeout)"
+           return 0
+       }
+    }
+}
+
+# Testing printing of a specific value.  For pass or fail, return
+# a 1 to indicate that more tests can proceed.  However a timeout
+# is a serious error, generates a special fail message, and causes
+# a 0 to be returned to indicate that more tests are likely to fail
+# as well.
+
+proc test_print_reject { args } {
+    global prompt
+    global verbose
+
+    if [llength $args]==2 then {
+       set expectthis [lindex $args 1]
+    } else {
+       set expectthis "should never match this bogus string"
+    }
+    set sendthis [lindex $args 0]
+    if $verbose>2 then {
+       send_user "Sending \"$sendthis\" to gdb\n"
+       send_user "Looking to match \"$expectthis\"\n"
+    }
+    send "$sendthis\n"
+    expect {
+       -re ".*A .* in expression.*\\.*$prompt $" {
+           pass "reject $sendthis"
+           return 1
+       }
+       -re ".*Invalid syntax in expression.*$prompt $" {
+           pass "reject $sendthis"
+           return 1
+       }
+       -re ".*Junk after end of expression.*$prompt $" {
+           pass "reject $sendthis"
+           return 1
+       }
+       -re ".*Invalid number.*$prompt $" {
+           pass "reject $sendthis"
+           return 1
+       }
+       -re ".*Invalid character constant.*$prompt $" {
+           pass "reject $sendthis"
+           return 1
+       }
+       -re ".*No symbol table is loaded.*$prompt $" {
+           pass "reject $sendthis"
+           return 1
+       }
+       -re ".*No symbol .* in current context.*$prompt $" {
+           pass "reject $sendthis"
+           return 1
+       }
+       -re ".*$expectthis.*$prompt $" {
+           pass "reject $sendthis"
+           return 1
+       }
+       -re ".*$prompt $" {
+           fail "reject $sendthis"
+           return 1
+       }
+       default {
+           fail "reject $sendthis (eof or timeout)"
+           return 0
+       }
+    }
+}
+\f
+# Given an input string, adds backslashes as needed to create a
+# regexp that will match the string.
+
+proc string_to_regexp {str} {
+    set result $str
+    regsub -all {[]*+.|()^$\[]} $str {\\&} result
+    return $result
+}
+
+# Same as gdb_test, but the second parameter is not a regexp,
+# but a string that must match exactly.
+
+proc gdb_test_exact { args } {
+    set command [lindex $args 0]
+    set pattern [string_to_regexp [lindex $args 1]]
+    if [llength $args]==3 then {
+       set message [lindex $args 2]
+    } else {
+       set message $command
+    }
+    return [gdb_test $command $pattern $message]
+}
+\f
+proc gdb_reinitialize_dir { subdir } {
+    global prompt
+
+   send "dir\n"
     expect {
        -re "Reinitialize source path to empty.*" {
            send "y\n"
@@ -258,27 +445,24 @@ proc gdb_reinitialize_dir { subdir } {
                    send "dir $subdir\n"
                    expect {
                        -re "Source directories searched.*$prompt $" {
-                           if $verbose>1 then {
-                               send_user "Dir set to $subdir\n"
-                           }
+                           verbose "Dir set to $subdir"
                        }
                        -re ".*$prompt $" {
-                           error "Dir \"$subdir\" failed."
+                           perror "Dir \"$subdir\" failed."
                        }
                    }
                }
                -re ".*$prompt $" {
-                   error "Dir \"$subdir\" failed."
+                   perror "Dir \"$subdir\" failed."
                }
            }
        }
        -re ".*$prompt $" {
-           error "Dir \"$subdir\" failed."
+           perror "Dir \"$subdir\" failed."
        }
     }
 }
 
-
 #
 # gdb_exit -- exit the GDB, killing the target program if necessary
 #
@@ -287,48 +471,149 @@ proc default_gdb_exit {} {
     global GDBFLAGS
     global verbose
 
-    verbose "Quitting $GDB $GDBFLAGS" 1
+    verbose "Quitting $GDB $GDBFLAGS"
 
     # This used to be 1 for unix-gdb.exp
     set timeout 5
 
-    catch "send \"quit\n\"" result
-    # If the process has gone away (e.g. gdb dumped core), deal with it.
-    if [string match "write\(spawn_id=\[0-9\]+\):" $result] then {
-       catch "close"
-       # FIXME:  Shouldn't we call "wait" too?
-       return -1
+    # We used to try to send "quit" to GDB, and wait for it to die.
+    # Dealing with all the cases and errors got pretty hairy.  Just close it, 
+    # that is simpler.
+    close
+
+    # Omitting this probably would cause strange timing-dependent failures.
+    wait
+}
+
+#
+# gdb_load -- load a file into the debugger.
+#             return a -1 if anything goes wrong.
+#
+proc gdb_file_cmd { arg } {
+    global verbose
+    global loadpath
+    global loadfile
+    global GDB
+    global prompt
+    global spawn_id
+
+    send "file $arg\n"
+    expect {
+        -re "Reading symbols from.*done.*$prompt $" {
+            verbose "\t\tLoaded $arg into the $GDB"
+            return 0
+        }
+        -re "has no symbol-table.*$prompt $" {
+            perror "$arg wasn't compiled with \"-g\""
+            return -1
+        }
+        -re "A program is being debugged already.*Kill it.*y or n. $" {
+            send "y\n"
+                verbose "\t\tKilling previous program being debugged"
+            exp_continue
+        }
+        -re "Load new symbol table from \".*\".*y or n. $" {
+            send "y\n"
+            expect {
+                -re "Reading symbols from.*done.*$prompt $" {
+                    verbose "\t\tLoaded $arg with new symbol table into $GDB"
+                    return 0
+                }
+                timeout {
+                    perror "(timeout) Couldn't load $arg, other program already l
+oaded."
+                    return -1
+                }
+            }
+       }
+        -re ".*No such file or directory.*$prompt $" {
+            perror "($arg) No such file or directory\n"
+            return -1
+        }
+        -re "$prompt $" {
+            perror "couldn't load $arg into $GDB."
+            return -1
+            }
+        timeout {
+            perror "couldn't load $arg into $GDB (timed out)."
+            return -1
+        }
+        eof {
+            # This is an attempt to detect a core dump, but seems not to
+            # work.  Perhaps we need to match .* followed by eof, in which
+            # expect does not seem to have a way to do that.
+            perror "couldn't load $arg into $GDB (end of file)."
+            return -1
+        }
     }
-    # FIXME: What is this catch statement doing here?  Won't it prevent us
-    # from getting errors that we'd rather see?
-    catch {
+}
+
+#
+# start gdb -- start gdb running, default procedure
+#
+proc default_gdb_start { } {
+    global verbose
+    global GDB
+    global GDBFLAGS
+    global prompt
+    global spawn_id
+    global timeout
+    verbose "Spawning $GDB -nw $GDBFLAGS"
+
+    if { [which $GDB] == 0 } then {
+       perror "$GDB does not exist."
+       exit 1
+    }
+    
+    set oldtimeout $timeout
+    set timeout [expr "$timeout + 60"]
+    eval "spawn $GDB -nw $GDBFLAGS"
     expect {
-       eof { 
-           verbose "Got EOF from $GDB" 2
+       -re ".*\r\n$prompt $" {
+           verbose "GDB initialized."
        }
-       timeout { 
-           verbose "Got TIMEOUT from $GDB" 2
+       -re "$prompt $" {
+           perror "GDB never initialized."
+           return -1
        }
-       -re "The program is running.  Quit anyway.*(y or n) $" {
-           send "y\n"
-           verbose "Killing program being debugged" 2
+       timeout         {
+           perror "(timeout) GDB never initialized."
+           return -1
        }
     }
+    set timeout $oldtimeout
+    # force the height to "unlimited", so no pagers get used
+    send "set height 0\n"
+    expect {
+       -re ".*$prompt $" { 
+           verbose "Setting height to 0." 2
+       }
+       timeout {
+           warning "Couldn't set the height to 0."
+       }
+    }
+    # force the width to "unlimited", so no wraparound occurs
+    send "set width 0\n"
+    expect {
+       -re ".*$prompt $" {
+           verbose "Seting width to 0." 2
+       }
+       timeout {
+           warning "Couldn't set the width to 0."
+       }
     }
-
-    # FIXME: Does the catch prevent us from getting errors that we'd rather
-    # see?  the old gdb_exit in unix-gdb.exp had "close" without catch
-    # in the above expect statement (for the timeout and -re "The
-    # program... cases) (as well as a catch "close" here).
-    catch "close"
-
-    # Before this was here sometimes "uit" would get sent to the next GDB
-    # (assuming this is immediately followed by gdb_start), which would
-    # cause a loss of syncronization (i.e. all the stuff that swallows a
-    # prompt would swallow the wrong one).
-    wait
 }
 
-
+#
+# FIXME: this is a copy of the new library procedure, but it's here too
+# till the new dejagnu gets installed everywhere. I'd hate to break the
+# gdb tests suite.
+#
+global argv0
+if ![info exists argv0] then {
+    proc exp_continue { } {
+       continue -expect
+    }
+}
 
 
This page took 0.032134 seconds and 4 git commands to generate.