# Copyright (C) 1992 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 was written by Fred Fish. (fnf@cygnus.com)
# Rob Savoye changed it to use gdb_test (rob@cygnus.com)

if $tracelevel then {
	strace $tracelevel
}

set prms_id 0
set bug_id 0

# FIXME: The configure.in for this test should look for --with-targets
# and deal accordingly.  Until that has been done, skip the whole thing.
# With a minimal bfd (the default), few if any of these tests work.

verbose "FIXME: all the crossload tests ignored"
continue

# FIXME: These tests don't work for the i960, because
# bfd/config/i960-bout.mt sets SELECT_VECS.  I could use setup_xfail
# for each test, but rebooting the board between each one takes a long
# time so I'm just punting the whole file.
if [istarget "i960-*-*"] then {
    if $verbose>1 then {
	warning "FIXME: crossload test case doesn't run on the i960."
    }
    continue
}

# FIXME: These tests don't work for the a29k, because SELECT_VECS is
# used when compiling bfd.  It would be nice if there were some better
# way of detecting this case.
if [istarget "a29k-*-*"] then {
    if $verbose>1 then {
	warning "FIXME: crossload test case doesn't run on the a29k."
    }
    continue
}

# Test if gdb can automatically determine the bfd format of an
# executable and read it's symbols.

proc bfddefault {} {
    global GDB
    global GDBFLAGS
    global prompt
    global objdir
    global subdir
    global binfile
    global bfdformat
    global file_loaded

    gdb_unload
    set file_loaded 0
    send "file $objdir/$subdir/$binfile\n"
    expect {
	-re "A program is being debugged already.  Kill it.*y or n." {
	    send "y\n"
	    exp_continue
	}
	-re "Reading symbols from $objdir/$subdir/$binfile\[.\]+done\..*$prompt $" {
	    pass "$binfile ($bfdformat) auto format"
	}
	-re "Reading symbols from $objdir/$subdir/$binfile\[.\]+.no debugging symbols found.\[.\]+done\..*$prompt $" {
	    pass "$binfile ($bfdformat) auto format (but no symbols found)"
	}
	-re "File format not recognized.*$prompt $" {
	    fail "$binfile ($bfdformat) auto format (format not recognized)"
	    return
	}
	-re "File format is ambiguous.*$prompt $" {
	    fail "$binfile ($bfdformat) auto format (format is ambiguous)"
	    return
	}
	-re "$prompt $" {
	    fail "$binfile ($bfdformat) auto format"
	    return
	}
	timeout {
	    fail "(timeout) $binfile ($bfdformat) auto format"
	    return
	}	
    }

    if [gdb_test "info target" ".*file type $bfdformat" ""]==0 then {
	set file_loaded 1
    } else {
	fail "$binfile ($bfdformat) wrong format found"
    }
}

# Test if gdb can read symbols from an executable when the bfd format
# is explicitly set via the environment variable GNUTARGET.

proc bfdexplicit {} {
    global GDB
    global GDBFLAGS
    global prompt
    global subdir
    global objdir
    global det_file
    global binfile
    global bfdformat
    global file_loaded

    gdb_unload
    set file_loaded 0

    # Once GDB 4.10 (the last to lack `set gnutarget') is forgotten,
    # change this to use set gnutarget.
   if [gdb_test "set env GNUTARGET=$bfdformat" "" ""]!=0 then {
       fail "setting GNUTARGET=$bfdformat in environment"
       return
    }

    send "file $objdir/$subdir/$binfile\n"
    expect {
	-re "A program is being debugged already.  Kill it.*y or n." {
	    send "y\n"
	    exp_continue
	}
	-re "Reading symbols from $objdir/$subdir/$binfile\[.\]+done\..*$prompt $" {
	    pass "$binfile ($bfdformat) explicit format"
	}
	-re "Invalid target.*$prompt $" {
	    fail "$binfile ($bfdformat) explicit format (invalid target)"
	    return
	}
	-re "$prompt $" {
	    fail "$binfile ($bfdformat) explicit format"
	    return
	}
	timeout {
	    fail "(timeout) $binfile ($bfdformat) explicit format"
	    return
	}	
    }

    set file_loaded 1
}

proc test_ptype_functions {} {
    global prompt
    global binfile
    global bfdformat
    global det_file
    send "ptype main\n"
    expect {
	-re "type = int \[)(\]+\r\n$prompt $" {}
	timeout { fail "$binfile ($bfdformat) function main" ; return }
    }

    # set up a list of lists of command and patterns
    set command [list { "ptype v_char_func" "type =(\ unsigned\ |\ signed\ |\ )char \[)(\]+" }\
	        { "ptype v_short_func" "type = (short|short int) \[)(\]+" } \
                { "ptype v_int_func" "type = int \[)(\]+" } \
                { "ptype v_long_func" "type = (long|long int|int) \[)(\]+" } \
                { "ptype v_float_func" "type = float \[)(\]+" } \
                { "ptype v_double_func" "type = double \[)(\]+" } ]

    foreach i $command {
	if [gdb_test [lindex $i 0] [lindex $i 1] ""] then {
	    fail "$binfile ($bfdformat) \"[lindex $i 0]\" function types"
	    return
	}
    }
    pass "$binfile ($bfdformat) ptype function types"
}

# Note that plain chars can be either signed or unsigned.

proc test_ptype_plain_types {} {
    global prompt
    global binfile
    global bfdformat

    # set up a list of lists of command and patterns
    set command [list { "ptype v_char" "type =(\ unsigned\ |\ signed\ |\ )char" }\
	        { "ptype v_short" "type = short" } \
                { "ptype v_int" "type = int" } \
                { "ptype v_long" "type = long" } \
                { "ptype v_float" "type = float" } \
                { "ptype v_double" "type = double" } ]

    foreach i $command {
	if [gdb_test [lindex $i 0] [lindex $i 1] ""] then {
	    fail "$binfile ($bfdformat) \"[lindex $i 0]\" plain C types"
	    return
    }
    }
    pass "$binfile ($bfdformat) ptype plain C types"
}

# Note that if compiled with pre-ANSI compilers, the "signed" keywords are
# defined away and the variables default to plain types.  So accept either.

proc test_ptype_signed_types {} {
    global prompt
    global binfile
    global bfdformat
    global det_file

    # set up a list of lists of command and patterns
    set command [list { "ptype v_signed_char" "type =(\ signed\ |\ )char" }\
	        { "ptype v_signed_short"  "type =(\ signed\ |\ )short" } \
                { "ptype v_signed_int" "type =(\ signed\ |\ )int" } \
                { "ptype v_signed_long" "type =(\ signed\ |\ )long" } ]

    foreach i $command {
	if [gdb_test [lindex $i 0] [lindex $i 1] ""] then {
	    if [expr [string match "ecoff-bigmips" $bfdformat]+[string match "ptype v_signed_char" [lindex $i 0]]]==2 then {
		setup_xfail "*-*-*"
	    }
	    fail "$binfile ($bfdformat) \"[lindex $i 0]\" signed C types"
	    return
	}
    }
    pass "$binfile ($bfdformat) ptype signed C types"
}

proc test_ptype_unsigned_types {} {
    global prompt
    global binfile
    global bfdformat
    global det_file

    # set up a list of lists of command and patterns
    set command [list { "ptype v_unsigned_char" "type = unsigned char" }\
	        { "ptype v_unsigned_short" \
		  "type = (unsigned short|short unsigned int)" } \
                { "ptype v_unsigned_int" "type = unsigned int" } \
                { "ptype v_unsigned_long" \
		  "type = (unsigned long|long unsigned int)" } ]

    foreach i $command {
	if [gdb_test [lindex $i 0] [lindex $i 1] ""] then {
	    fail "$binfile ($bfdformat) \"[lindex $i 0]\" unsigned C types"
	    return
	}
    }
    pass "$binfile ($bfdformat) ptype unsigned C types"
}

# Note that plain chars can be either signed or unsigned.

proc test_ptype_array_types {} {
    global prompt
    global binfile
    global bfdformat
    global det_file

    # set up a list of lists of command and patterns
    set command [list { "ptype v_char_array" "type =(\ unsigned\ |\ signed\ |\ )char \\\[2\\\]" }\
	        { "ptype v_short_array"  \
		  "type = (short|short int) \\\[2\\\]" } \
                { "ptype v_int_array" "type = int \\\[2\\\]" } \
                { "ptype v_long_array" "type = (long|long int) \\\[2\\\]" } \
                { "ptype v_float_array" "type = float \\\[2\\\]" } \
                { "ptype v_double_array" "type = double \\\[2\\\]" } ]

    foreach i $command {
	if [gdb_test [lindex $i 0] [lindex $i 1] ""] then {
	    fail "$binfile ($bfdformat) \"[lindex $i 0]\" C array types"
	    return
	}
    }
    pass "$binfile ($bfdformat) ptype C array types"
}

proc test_ptype_pointer_types {} {
    global prompt
    global binfile
    global bfdformat
    global det_file

    # set up a list of lists of command and patterns
    set command [list { "ptype v_char_pointer" "type =(\ unsigned\ |\ signed\ |\ )char \*" }\
	        { "ptype v_short_pointer"  "type = (short|short int) \*" } \
                { "ptype v_int_pointer" "type = int \*" } \
                { "ptype v_long_pointer" "type = (long|long int) \*" } \
                { "ptype v_float_pointer" "type = float \*" } \
                { "ptype v_double_pointer" "type = double \*" } ]

    foreach i $command {
	if [gdb_test [lindex $i 0] [lindex $i 1] ""] then {
	    fail "$binfile ($bfdformat) \"[lindex $i 0]\" C pointer types"
	    return
	}
    }
    pass "$binfile ($bfdformat) ptype C pointer types"
}

proc loadandtest { args } {
    global verbose
    global GDB
    global GDBFLAGS
    global prompt
    global subdir
    global objdir
    global binfile
    global bfdformat
    global file_loaded

    set binfile [ lindex $args 0 ]
    set bfdformat [ lindex $args 1 ]
    set fixme [ lindex $args 2 ]

    if ![file exists $objdir/$subdir/$binfile] then {
        perror "$objdir/$subdir/$binfile does not exist"
	return 0
    }
    gdb_exit
    gdb_start
    if $fixme then { setup_xfail "*-*-*" }
    bfddefault
    if $fixme then { setup_xfail "*-*-*" }
    if [string match $bfdformat "elf-big"] then {
	if [string match $binfile "i860-elf"] then {
	    setup_xfail "*-*-*"
	}
    }
    bfdexplicit
    if $file_loaded==1 then {
	test_ptype_functions
        if $fixme then { setup_xfail "*-*-*" }
	test_ptype_plain_types
        if $fixme then { setup_xfail "*-*-*" }
	test_ptype_signed_types
        if $fixme then { setup_xfail "*-*-*" }
	test_ptype_unsigned_types
        if $fixme then { setup_xfail "*-*-*" }
	test_ptype_array_types
        if $fixme then { setup_xfail "*-*-*" }
	test_ptype_pointer_types
    }
}

# Run tests for each of the test executables.
# If the third argument is 1, the tests will be expected to fail.
# We should extract the information about available tests and bfd formats
# from the makefile or some other control file (FIXME).

loadandtest m68k-elf	"elf32-m68k"		0

# I'm getting an XPASS for explicit format on this one
loadandtest m68k-aout	"a.out-newsos3"		1

loadandtest m68k-aout2	"a.out-sunos-big"	0
loadandtest mips-ecoff	"ecoff-bigmips"		0
loadandtest i486-elf	"elf32-i386"		0
loadandtest sparc-aout	"a.out-sunos-big"	0
loadandtest sparc-elf	"elf32-sparc"		0

#FIXME:  i860 support is unlikely to be working in the near future
# so suppress this test until it is working.  -fnf
#loadandtest i860-elf	"elf32-i860"		0

gdb_test "set gnutarget auto" ""
