aboutsummaryrefslogtreecommitdiff
path: root/gdb/testsuite/gdb.base/list-multi-source.exp
blob: 887ff961933e2d3f981fad1d43249f8ae0941017 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# Copyright 2025 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 3 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, see <http://www.gnu.org/licenses/>.

# Test that 'list FILE:LINE' can print multiple results if FILE
# matches multiple files from the source tree.
#
# Then test that we can use 'list DIR/FILE:LINE' to restrict the
# results to a single source file.

# With a remote host, source files are automatically copied to the
# host by dejagnu, and this drops the directory structure that is
# needed for this test to work, i.e. we need a/foo.c and b/foo.c, but
# dejagnu's automatic copying just gives us a single foo.c.  Instead
# of trying to fix this, for now at least, just skip remote host
# testing.
require {!is_remote host}

# This test uses a single source file that is copied into the build
# tree 3 times.  The three copies are then copied with different
# defines set so that we see different functions in each copy.
standard_testfile .c

# Create the source tree within the build directory.
set src_root [standard_output_file "src"]
set src_a "$src_root/a"
set src_b "$src_root/b"
set file_a "$src_a/foo.c"
set file_b "$src_b/foo.c"
set file_main "$src_root/main.c"
file mkdir "$src_root"
file mkdir "$src_a"
file mkdir "$src_b"

# Helper proc.  Copy global SRCFILE to DEST, replacing
# 'value_to_return' with VALUE during the copy.
proc copy_and_update_source_file { dest value } {
    # Open the source file for reading.
    set in [open "$::srcdir/$::subdir/$::srcfile" r]

    # Read in the entire contents of the file.  This should be fine as
    # the input file is not large.
    set file_content [read $in]

    # Close the input file.
    close $in

    # Perform the replacement over the entire file contents.
    set updated_content [string map \
			     [list "value_to_return" $value] \
			     $file_content]

    # Open the destination file for writing.
    set out [open $dest w]

    # Write the modified content to the destination file.
    puts -nonewline $out $updated_content

    # Close the output file.
    close $out
}

# Make three copies of the single source file in the build directory
# based source tree.  Two of the source files are modified slighly to
# make the output of 'list' unique for each copy.
file copy "$srcdir/$subdir/$srcfile" "$file_main"
copy_and_update_source_file $file_a "3"
copy_and_update_source_file $file_b "-3"

# Build the executable.  Use defines to make the source files
# different.
if { [prepare_for_testing_full "failed to prepare" \
	  [list $testfile debug \
	       $file_main [list debug additional_flags=-DMAIN] \
	       $file_a [list debug additional_flags=-DFILE_A] \
	       $file_b [list debug additional_flags=-DFILE_B]]]} {
    return
}

# The LINENUM we should list, and the first and last lines that should
# appear in the list output.
set linenum [gdb_get_line_number "List this line"]
set first_linenum [expr {$linenum - 5}]
set last_linenum [expr {$linenum + 4}]

# List using FILE:LINE for a filename that is ambiguous.
gdb_test "list foo.c:$linenum" \
    [multi_line \
	 "file: \"\[^\r\n\]+/a/foo.c\", line number: $linenum, symbol: \"get_value_common\"" \
	 "$first_linenum\\s+\[^\r\n\]+" \
	 ".*" \
	 "$linenum\\s+[string_to_regexp {return 3;	/* List this line.  */}]" \
	 ".*" \
	 "$last_linenum\\s+\[^\r\n\]+" \
	 "file: \"\[^\r\n\]+/b/foo.c\", line number: $linenum, symbol: \"get_value_common\"" \
	 "$first_linenum\\s+\[^\r\n\]+" \
	 ".*" \
	 "$linenum\\s+[string_to_regexp {return -3;	/* List this line.  */}]" \
	 ".*" \
	 "$last_linenum\\s+\[^\r\n\]+"]

# Now list using a more acurate filename, we should only get a single
# result.
gdb_test "list a/foo.c:$linenum" \
    [multi_line \
	 "^$first_linenum\\s+\[^\r\n\]+" \
	 ".*" \
	 "$linenum\\s+[string_to_regexp {return 3;	/* List this line.  */}]" \
	 ".*" \
	 "$last_linenum\\s+\[^\r\n\]+"]

gdb_test "list b/foo.c:$linenum" \
    [multi_line \
	 "^$first_linenum\\s+\[^\r\n\]+" \
	 ".*" \
	 "$linenum\\s+[string_to_regexp {return -3;	/* List this line.  */}]" \
	 ".*" \
	 "$last_linenum\\s+\[^\r\n\]+"]