OSDN Git Service

* configure.in: Add config header.
authorKeith Seitz <keiths@redhat.com>
Tue, 24 Sep 2002 19:36:06 +0000 (19:36 +0000)
committerKeith Seitz <keiths@redhat.com>
Tue, 24 Sep 2002 19:36:06 +0000 (19:36 +0000)
        Check for pthread.h.
        * configure: Regenerate.
        * config.in: New file.
        * pthreads.c: New file.
        * mi-pthreads.exp: New file to test thread functionality.
        * gdb669.exp: New file.

gdb/testsuite/gdb.mi/ChangeLog
gdb/testsuite/gdb.mi/config.in [new file with mode: 0644]
gdb/testsuite/gdb.mi/configure
gdb/testsuite/gdb.mi/configure.in
gdb/testsuite/gdb.mi/gdb669.exp [new file with mode: 0644]
gdb/testsuite/gdb.mi/mi-pthreads.exp [new file with mode: 0644]
gdb/testsuite/gdb.mi/pthreads.c [new file with mode: 0644]

index 5feba8d..3deddd7 100644 (file)
@@ -1,3 +1,13 @@
+2002-09-24  Keith Seitz  <keiths@redhat.com>
+
+       * configure.in: Add config header.
+       Check for pthread.h.
+       * configure: Regenerate.
+       * config.in: New file.
+       * pthreads.c: New file.
+       * mi-pthreads.exp: New file to test thread functionality.
+       * gdb669.exp: New file.
+
 2002-09-17  Keith Seitz  <keiths@redhat.com>
 
        * mi-var-cmd.exp: Add tests to check when varobj pinned to a
diff --git a/gdb/testsuite/gdb.mi/config.in b/gdb/testsuite/gdb.mi/config.in
new file mode 100644 (file)
index 0000000..d8418ba
--- /dev/null
@@ -0,0 +1,4 @@
+/* config.h.in.  Generated automatically from configure.in by autoheader.  */
+
+/* Define if you have the <pthread.h> header file.  */
+#undef HAVE_PTHREAD_H
index fd5d146..48628f5 100755 (executable)
@@ -522,6 +522,7 @@ fi
 
 
 
+
 CC=${CC-cc}
 
 ac_aux_dir=
@@ -571,7 +572,7 @@ else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
 fi
 
 echo $ac_n "checking host system type""... $ac_c" 1>&6
-echo "configure:575: checking host system type" >&5
+echo "configure:576: checking host system type" >&5
 
 host_alias=$host
 case "$host_alias" in
@@ -592,7 +593,7 @@ host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
 echo "$ac_t""$host" 1>&6
 
 echo $ac_n "checking target system type""... $ac_c" 1>&6
-echo "configure:596: checking target system type" >&5
+echo "configure:597: checking target system type" >&5
 
 target_alias=$target
 case "$target_alias" in
@@ -610,7 +611,7 @@ target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
 echo "$ac_t""$target" 1>&6
 
 echo $ac_n "checking build system type""... $ac_c" 1>&6
-echo "configure:614: checking build system type" >&5
+echo "configure:615: checking build system type" >&5
 
 build_alias=$build
 case "$build_alias" in
@@ -633,6 +634,128 @@ test "$host_alias" != "$target_alias" &&
   program_prefix=${target_alias}-
 
 
+# Check for pthread.h
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:640: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+    # This must be in double quotes, not single quotes, because CPP may get
+  # substituted into the Makefile and "${CC-cc}" will confuse make.
+  CPP="${CC-cc} -E"
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp.
+  cat > conftest.$ac_ext <<EOF
+#line 655 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:661: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP="${CC-cc} -E -traditional-cpp"
+  cat > conftest.$ac_ext <<EOF
+#line 672 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:678: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP="${CC-cc} -nologo -E"
+  cat > conftest.$ac_ext <<EOF
+#line 689 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:695: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+  ac_cv_prog_CPP="$CPP"
+fi
+  CPP="$ac_cv_prog_CPP"
+else
+  ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+for ac_hdr in pthread.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:723: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 728 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:733: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+
 trap '' 1 2 15
 cat > confcache <<\EOF
 # This file is a shell script that caches the results of configure
@@ -696,19 +819,7 @@ fi
 
 trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
 
-# Transform confdefs.h into DEFS.
-# Protect against shell expansion while executing Makefile rules.
-# Protect against Makefile macro expansion.
-cat > conftest.defs <<\EOF
-s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
-s%[    `~#$^&*(){}\\|;'"<>?]%\\&%g
-s%\[%\\&%g
-s%\]%\\&%g
-s%\$%$$%g
-EOF
-DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
-rm -f conftest.defs
-
+DEFS=-DHAVE_CONFIG_H
 
 # Without the "./", some shells look in PATH for config.status.
 : ${CONFIG_STATUS=./config.status}
@@ -745,7 +856,7 @@ done
 
 ac_given_srcdir=$srcdir
 
-trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+trap 'rm -fr `echo "Makefile config.h:config.in" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
 EOF
 cat >> $CONFIG_STATUS <<EOF
 
@@ -793,6 +904,7 @@ s%@build_alias@%$build_alias%g
 s%@build_cpu@%$build_cpu%g
 s%@build_vendor@%$build_vendor%g
 s%@build_os@%$build_os%g
+s%@CPP@%$CPP%g
 
 CEOF
 EOF
@@ -888,6 +1000,113 @@ s%@top_srcdir@%$top_srcdir%g
 fi; done
 rm -f conftest.s*
 
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s%^\([  ]*\)#\([        ]*define[       ][      ]*\)'
+ac_dB='\([     ][      ]*\)[^  ]*%\1#\2'
+ac_dC='\3'
+ac_dD='%g'
+# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
+ac_uA='s%^\([  ]*\)#\([        ]*\)undef\([    ][      ]*\)'
+ac_uB='\([     ]\)%\1#\2define\3'
+ac_uC=' '
+ac_uD='\4%g'
+# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_eA='s%^\([  ]*\)#\([        ]*\)undef\([    ][      ]*\)'
+ac_eB='$%\1#\2define\3'
+ac_eC=' '
+ac_eD='%g'
+
+if test "${CONFIG_HEADERS+set}" != set; then
+EOF
+cat >> $CONFIG_STATUS <<EOF
+  CONFIG_HEADERS="config.h:config.in"
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+fi
+for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case "$ac_file" in
+  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+  *) ac_file_in="${ac_file}.in" ;;
+  esac
+
+  echo creating $ac_file
+
+  rm -f conftest.frag conftest.in conftest.out
+  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+  cat $ac_file_inputs > conftest.in
+
+EOF
+
+# Transform confdefs.h into a sed script conftest.vals that substitutes
+# the proper values into config.h.in to produce config.h.  And first:
+# Protect against being on the right side of a sed subst in config.status.
+# Protect against being in an unquoted here document in config.status.
+rm -f conftest.vals
+cat > conftest.hdr <<\EOF
+s/[\\&%]/\\&/g
+s%[\\$`]%\\&%g
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
+s%ac_d%ac_u%gp
+s%ac_u%ac_e%gp
+EOF
+sed -n -f conftest.hdr confdefs.h > conftest.vals
+rm -f conftest.hdr
+
+# This sed command replaces #undef with comments.  This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >> conftest.vals <<\EOF
+s%^[   ]*#[    ]*undef[        ][      ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
+EOF
+
+# Break up conftest.vals because some shells have a limit on
+# the size of here documents, and old seds have small limits too.
+
+rm -f conftest.tail
+while :
+do
+  ac_lines=`grep -c . conftest.vals`
+  # grep -c gives empty output for an empty file on some AIX systems.
+  if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
+  # Write a limited-size here document to conftest.frag.
+  echo '  cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
+  echo 'CEOF
+  sed -f conftest.frag conftest.in > conftest.out
+  rm -f conftest.in
+  mv conftest.out conftest.in
+' >> $CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
+  rm -f conftest.vals
+  mv conftest.tail conftest.vals
+done
+rm -f conftest.vals
+
+cat >> $CONFIG_STATUS <<\EOF
+  rm -f conftest.frag conftest.h
+  echo "/* $ac_file.  Generated automatically by configure.  */" > conftest.h
+  cat conftest.in >> conftest.h
+  rm -f conftest.in
+  if cmp -s $ac_file conftest.h 2>/dev/null; then
+    echo "$ac_file is unchanged"
+    rm -f conftest.h
+  else
+    # Remove last slash and all that follows it.  Not all systems have dirname.
+      ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+      if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+      # The file is in a subdirectory.
+      test ! -d "$ac_dir" && mkdir "$ac_dir"
+    fi
+    rm -f $ac_file
+    mv conftest.h $ac_file
+  fi
+fi; done
+
 EOF
 cat >> $CONFIG_STATUS <<EOF
 
index 9427827..3204867 100644 (file)
@@ -6,10 +6,14 @@ dnl any existing configure script.
 
 AC_PREREQ(2.5)
 AC_INIT(mi-basics.exp)
+AC_CONFIG_HEADER(config.h:config.in)
 
 CC=${CC-cc}
 AC_SUBST(CC)
 AC_CONFIG_AUX_DIR(`cd $srcdir;pwd`/../../..)
 AC_CANONICAL_SYSTEM
 
+# Check for pthread.h
+AC_CHECK_HEADERS(pthread.h)
+
 AC_OUTPUT(Makefile)
diff --git a/gdb/testsuite/gdb.mi/gdb669.exp b/gdb/testsuite/gdb.mi/gdb669.exp
new file mode 100644 (file)
index 0000000..e8c6481
--- /dev/null
@@ -0,0 +1,190 @@
+# Copyright 2002 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
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file checks for the bug gdb/669, where the console
+# command "info threads" and the MI command "-thread-list-ids"
+# return different threads in the system.
+
+# This only works with native configurations
+if {![isnative]} {
+  return
+}
+
+load_lib mi-support.exp
+set MIFLAGS "-i=mi"
+
+gdb_exit
+if {[mi_gdb_start]} {
+    continue
+}
+
+# The procs below are all stolen from mi-pthreads.exp. Any updates
+# should also be made to the procs there.
+
+proc get_mi_thread_list {name} {
+  global expect_out
+
+  # MI will return a list of thread ids:
+  #
+  # -thread-list-ids
+  # ^done,thread-ids=[thread-id="1",thread-id="2",...],number-of-threads="N"
+  # (gdb)
+  mi_gdb_test "-thread-list-ids" \
+    {\^done,thread-ids={(thread-id="[0-9]+"(,)?)+},number-of-threads="[0-9]+"} \
+    "-thread_list_ids ($name)"
+
+  set thread_list {}
+  if {![regexp {thread-ids=\{(thread-id="[0-9]+"(,)?)*\}} $expect_out(buffer) threads]} {
+    fail "finding threads in MI output ($name)"
+  } else {
+    pass "finding threads in MI output ($name)"
+
+    # Make list of console threads
+    set start [expr {[string first \{ $threads] + 1}]
+    set end   [expr {[string first \} $threads] - 1}]
+    set threads [string range $threads $start $end]
+    foreach thread [split $threads ,] {
+      if {[scan $thread {thread-id="%d"} num]} {
+       lappend thread_list $num
+      }
+    }
+  }
+
+  return $thread_list
+}
+
+# Check that MI and the console know of the same threads.
+# Appends NAME to all test names.
+proc check_mi_and_console_threads {name} {
+  global expect_out
+
+  mi_gdb_test "-thread-list-ids" \
+    {\^done,thread-ids={(thread-id="[0-9]+"(,)*)+},number-of-threads="[0-9]+"} \
+    "-thread-list-ids ($name)"
+  set mi_output $expect_out(buffer)
+
+  # GDB will return a list of thread ids and some more info:
+  #
+  # (gdb) 
+  # -interpreter-exec console "info threads"
+  # ~"  4 Thread 2051 (LWP 7734)  0x401166b1 in __libc_nanosleep () at __libc_nanosleep:-1"
+  # ~"  3 Thread 1026 (LWP 7733)   () at __libc_nanosleep:-1"
+  # ~"  2 Thread 2049 (LWP 7732)  0x401411f8 in __poll (fds=0x804bb24, nfds=1, timeout=2000) at ../sysdeps/unix/sysv/linux/poll.c:63"
+  # ~"* 1 Thread 1024 (LWP 7731)  main (argc=1, argv=0xbfffdd94) at ../../../src/gdb/testsuite/gdb.mi/pthreads.c:160"
+  # FIXME: kseitz/2002-09-05: Don't use the hack-cli method.
+  mi_gdb_test "info threads" \
+    {.*(~".*"[\r\n]*)+.*} \
+    "info threads ($name)"
+  set console_output $expect_out(buffer)
+
+  # Make a list of all known threads to console (gdb's thread IDs)
+  set console_thread_list {}
+  foreach line [split $console_output \n] {
+    if {[string index $line 0] == "~"} {
+      # This is a line from the console; trim off "~", " ", "*", and "\""
+      set line [string trim $line ~\ \"\*]
+      if {[scan $line "%d" id] == 1} {
+       lappend console_thread_list $id
+      }
+    }
+  }
+
+  # Now find the result string from MI
+  set mi_result ""
+  foreach line [split $mi_output \n] {
+    if {[string range $line 0 4] == "^done"} {
+      set mi_result $line
+    }
+  }
+  if {$mi_result == ""} {
+    fail "finding MI result string ($name)"
+  } else {
+    pass "finding MI result string ($name)"
+  }
+
+  # Finally, extract the thread ids and compare them to the console
+  set num_mi_threads_str ""
+  if {![regexp {number-of-threads="[0-9]+"} $mi_result num_mi_threads_str]} {
+    fail "finding number of threads in MI output ($name)"
+  } else {
+    pass "finding number of threads in MI output ($name)"
+
+    # Extract the number of threads from the MI result
+    if {![scan $num_mi_threads_str {number-of-threads="%d"} num_mi_threads]} {
+      fail "got number of threads from MI ($name)"
+    } else {
+      pass "got number of threads from MI ($name)"
+
+      # Check if MI and console have same number of threads
+      if {$num_mi_threads != [llength $console_thread_list]} {
+       fail "console and MI have same number of threads ($name)"
+      } else {
+       pass "console and MI have same number of threads ($name)"
+
+       # Get MI thread list
+       set mi_thread_list [get_mi_thread_list $name]
+
+       # Check if MI and console have the same threads
+       set fails 0
+       foreach ct [lsort $console_thread_list] mt [lsort $mi_thread_list] {
+         if {$ct != $mt} {
+           incr fails
+         }
+       }
+       if {$fails > 0} {
+         fail "MI and console have same threads ($name)"
+
+         # Send a list of failures to the log
+         send_log "Console has thread ids: $console_thread_list\n"
+         send_log "MI has thread ids: $mi_thread_list\n"
+       } else {
+         pass "MI and console have same threads ($name)"
+       }
+      }
+    }
+  }
+}
+
+#
+# Start here
+#
+set testfile "pthreads"
+set srcfile "$testfile.c"
+set binfile "$objdir/$subdir/$testfile"
+
+set options [list debug incdir=$subdir]
+if  {[gdb_compile_pthreads "$srcdir/$subdir/$srcfile" $binfile executable $options]
+     != "" } {
+  gdb_suppress_entire_file \
+    "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+mi_gdb_reinitialize_dir $srcdir/$subdir
+mi_gdb_load $binfile
+
+mi_run_to_main
+check_mi_and_console_threads "at main"
+
+for {set i 0} {$i < 4} {incr i} {
+  mi_next "next, try $i"
+  check_mi_and_console_threads "try $i"
+}
+
+mi_gdb_exit
+
diff --git a/gdb/testsuite/gdb.mi/mi-pthreads.exp b/gdb/testsuite/gdb.mi/mi-pthreads.exp
new file mode 100644 (file)
index 0000000..900df9b
--- /dev/null
@@ -0,0 +1,209 @@
+# Copyright 2002 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
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file tests MI thread commands.
+# Specifically, we are testing the MI command set and the console (in MI)
+# command set ("interpreter-exec") and that the commands that are executed
+# via these command pathways are properly executed. Console commands
+# executed via MI should use MI output wrappers, MI event handlers, etc.
+
+# This only works with native configurations
+if {![isnative]} {
+  return
+}
+
+load_lib mi-support.exp
+set MIFLAGS "-i=mi"
+
+gdb_exit
+if {[mi_gdb_start]} {
+    continue
+}
+
+# The procs below dealing with parsing cli/mi output for the threadlist
+# is duplicated in gdb669.exp. Any changes here will probably need to
+# be made there as well.
+
+proc get_mi_thread_list {name} {
+  global expect_out
+
+  # MI will return a list of thread ids:
+  #
+  # -thread-list-ids
+  # ^done,thread-ids=[thread-id="1",thread-id="2",...],number-of-threads="N"
+  # (gdb)
+  mi_gdb_test "-thread-list-ids" \
+    {\^done,thread-ids={(thread-id="[0-9]+"(,)?)+},number-of-threads="[0-9]+"} \
+    "-thread_list_ids ($name)"
+
+  set thread_list {}
+  if {![regexp {thread-ids=\{(thread-id="[0-9]+"(,)?)*\}} $expect_out(buffer) threads]} {
+    fail "finding threads in MI output ($name)"
+  } else {
+    pass "finding threads in MI output ($name)"
+
+    # Make list of console threads
+    set start [expr {[string first \{ $threads] + 1}]
+    set end   [expr {[string first \} $threads] - 1}]
+    set threads [string range $threads $start $end]
+    foreach thread [split $threads ,] {
+      if {[scan $thread {thread-id="%d"} num]} {
+       lappend thread_list $num
+      }
+    }
+  }
+
+  return $thread_list
+}
+
+# Check that MI and the console know of the same threads.
+# Appends NAME to all test names.
+proc check_mi_and_console_threads {name} {
+  global expect_out
+
+  mi_gdb_test "-thread-list-ids" \
+    {\^done,thread-ids={(thread-id="[0-9]+"(,)*)+},number-of-threads="[0-9]+"} \
+    "-thread-list-ids ($name)"
+  set mi_output $expect_out(buffer)
+
+  # GDB will return a list of thread ids and some more info:
+  #
+  # (gdb) 
+  # -interpreter-exec console "info threads"
+  # ~"  4 Thread 2051 (LWP 7734)  0x401166b1 in __libc_nanosleep () at __libc_nanosleep:-1"
+  # ~"  3 Thread 1026 (LWP 7733)   () at __libc_nanosleep:-1"
+  # ~"  2 Thread 2049 (LWP 7732)  0x401411f8 in __poll (fds=0x804bb24, nfds=1, timeout=2000) at ../sysdeps/unix/sysv/linux/poll.c:63"
+  # ~"* 1 Thread 1024 (LWP 7731)  main (argc=1, argv=0xbfffdd94) at ../../../src/gdb/testsuite/gdb.mi/pthreads.c:160"
+  # FIXME: kseitz/2002-09-05: Don't use the hack-cli method.
+  mi_gdb_test "info threads" \
+    {.*(~".*"[\r\n]*)+.*} \
+    "info threads ($name)"
+  set console_output $expect_out(buffer)
+
+  # Make a list of all known threads to console (gdb's thread IDs)
+  set console_thread_list {}
+  foreach line [split $console_output \n] {
+    if {[string index $line 0] == "~"} {
+      # This is a line from the console; trim off "~", " ", "*", and "\""
+      set line [string trim $line ~\ \"\*]
+      if {[scan $line "%d" id] == 1} {
+       lappend console_thread_list $id
+      }
+    }
+  }
+
+  # Now find the result string from MI
+  set mi_result ""
+  foreach line [split $mi_output \n] {
+    if {[string range $line 0 4] == "^done"} {
+      set mi_result $line
+    }
+  }
+  if {$mi_result == ""} {
+    fail "finding MI result string ($name)"
+  } else {
+    pass "finding MI result string ($name)"
+  }
+
+  # Finally, extract the thread ids and compare them to the console
+  set num_mi_threads_str ""
+  if {![regexp {number-of-threads="[0-9]+"} $mi_result num_mi_threads_str]} {
+    fail "finding number of threads in MI output ($name)"
+  } else {
+    pass "finding number of threads in MI output ($name)"
+
+    # Extract the number of threads from the MI result
+    if {![scan $num_mi_threads_str {number-of-threads="%d"} num_mi_threads]} {
+      fail "got number of threads from MI ($name)"
+    } else {
+      pass "got number of threads from MI ($name)"
+
+      # Check if MI and console have same number of threads
+      if {$num_mi_threads != [llength $console_thread_list]} {
+       fail "console and MI have same number of threads ($name)"
+      } else {
+       pass "console and MI have same number of threads ($name)"
+
+       # Get MI thread list
+       set mi_thread_list [get_mi_thread_list $name]
+
+       # Check if MI and console have the same threads
+       set fails 0
+       foreach ct [lsort $console_thread_list] mt [lsort $mi_thread_list] {
+         if {$ct != $mt} {
+           incr fails
+         }
+       }
+       if {$fails > 0} {
+         fail "MI and console have same threads ($name)"
+
+         # Send a list of failures to the log
+         send_log "Console has thread ids: $console_thread_list\n"
+         send_log "MI has thread ids: $mi_thread_list\n"
+       } else {
+         pass "MI and console have same threads ($name)"
+       }
+      }
+    }
+  }
+}
+
+# This procedure tests the various thread commands in MI.
+proc check_mi_thread_command_set {} {
+
+  mi_runto done_making_threads
+
+  set thread_list [get_mi_thread_list "in check_mi_thread_command_set"]
+  
+  mi_gdb_test "-thread-select" \
+    {\^error,msg="mi_cmd_thread_select: USAGE: threadnum."} \
+    "check_mi_thread_command_set: -thread-select"
+
+  mi_gdb_test "-thread-select 123456789" \
+    {\^error,msg="Thread ID 123456789 not known\."} \
+    "check_mi_thread_command_set: -thread-select 123456789"
+
+  foreach thread $thread_list {
+    mi_gdb_test "-thread-select $thread" \
+      "\\^done,new-thread-id=\"$thread\",frame={.*},line=\"(-)?\[0-9\]+\",file=\".*\"" \
+      "check_mi_thread_command_set: -thread-select $thread"
+  }
+}
+
+#
+# Start here
+#
+set testfile "pthreads"
+set srcfile "$testfile.c"
+set binfile "$objdir/$subdir/$testfile"
+
+set options [list debug incdir=$subdir]
+if  {[gdb_compile_pthreads "$srcdir/$subdir/$srcfile" $binfile executable $options]
+     != "" } {
+  gdb_suppress_entire_file \
+    "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+mi_gdb_reinitialize_dir $srcdir/$subdir
+mi_gdb_load $binfile
+
+check_mi_thread_command_set
+
+mi_gdb_exit
+
diff --git a/gdb/testsuite/gdb.mi/pthreads.c b/gdb/testsuite/gdb.mi/pthreads.c
new file mode 100644 (file)
index 0000000..c3e17bc
--- /dev/null
@@ -0,0 +1,80 @@
+#include <stdio.h>
+
+#include "config.h"
+
+#ifndef HAVE_PTHREAD_H
+
+/* Don't even try to compile.  In fact, cause a syntax error that we can
+   look for as a compiler error message and know that we have no pthread
+   support.  In that case we can just suppress the test completely. */
+
+#error "no posix threads support"
+
+#else
+
+/* OK.  We have the right header.  If we try to compile this and fail, then
+   there is something wrong and the user should know about it so the testsuite
+   should issue an ERROR result.. */
+
+#ifdef __linux__
+#define  _MIT_POSIX_THREADS 1  /* GNU/Linux (or at least RedHat 4.0)
+                                   needs this */
+#endif
+
+#include <pthread.h>
+
+/* Under OSF 2.0 & 3.0 and HPUX 10, the second arg of pthread_create
+   is prototyped to be just a "pthread_attr_t", while under Solaris it
+   is a "pthread_attr_t *".  Arg! */
+
+#if defined (__osf__) || defined (__hpux__)
+#define PTHREAD_CREATE_ARG2(arg) arg
+#define PTHREAD_CREATE_NULL_ARG2 null_attr
+static pthread_attr_t null_attr;
+#else
+#define PTHREAD_CREATE_ARG2(arg) &arg
+#define PTHREAD_CREATE_NULL_ARG2 NULL
+#endif
+
+void *
+routine (void *arg)
+{
+  sleep (9);
+  printf ("hello thread\n");
+}
+
+/* Marker function for the testsuite */
+void
+done_making_threads (void)
+{
+  /* Nothing */
+};
+
+void
+create_thread (void)
+{
+  pthread_t tid;
+
+  if (pthread_create (&tid, PTHREAD_CREATE_NULL_ARG2, routine, (void *) 0xfeedface))
+    {
+      perror ("pthread_create 1");
+      exit (1);
+    }
+}
+
+int
+main (int argc, char *argv[])
+{
+  int i;
+
+  /* Create a few threads */
+  for (i = 0; i < 5; i++)
+    create_thread ();
+  done_making_threads ();
+
+  printf ("hello\n");
+  printf ("hello\n");
+  return 0;
+}
+
+#endif /* ifndef HAVE_PTHREAD_H */