Add new tests for charset support.
[external/binutils.git] / gdb / testsuite / gdb.base / charset.exp
1 # Copyright 2001 Free Software Foundation, Inc.
2
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2 of the License, or
6 # (at your option) any later version.
7
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 # GNU General Public License for more details.
12
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software
15 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  
16
17 # Please email any bugs, comments, and/or additions to this file to:
18 # bug-gdb@prep.ai.mit.edu
19
20 # Test GDB's character set support.
21
22 if $tracelevel then {
23         strace $tracelevel
24 }
25
26 set prms_id 0
27 set bug_id 0
28
29 set testfile "charset"
30 set srcfile ${testfile}.c
31 set binfile ${objdir}/${subdir}/${testfile}
32 if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
33      gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
34 }
35
36 # Start with a fresh gdb.
37 gdb_exit
38 gdb_start
39 gdb_reinitialize_dir $srcdir/$subdir
40 gdb_load ${binfile}
41
42 # Parse the output from a `show charset' command.  Return the host
43 # and target charset as a two-element list.
44 proc parse_show_charset_output {testname} {
45     global gdb_prompt
46
47     gdb_expect {
48         -re "The current host and target character set is `(.*)'\\.\[\r\n\]+$gdb_prompt $" {
49             set host_charset $expect_out(1,string)
50             set target_charset $expect_out(1,string)
51             pass $testname
52         }
53         -re "The current host character set is `(.*)'\\.\[\r\n\]+The current target character set is `(.*)'\\.\[\r\n\]+$gdb_prompt $" {
54             set host_charset $expect_out(1,string)
55             set target_charset $expect_out(2,string)
56             pass $testname
57         }
58         -re ".*$gdb_prompt $" {
59             fail $testname
60         }
61         timeout {
62             fail "$testname (timeout)"
63         }
64     }
65
66     return [list $host_charset $target_charset]
67 }
68
69
70 # Try the various `show charset' commands.  These are all aliases of each
71 # other; `show target-charset' and `show host-charset' actually print
72 # both the host and target charsets.
73
74 send_gdb "show charset\n"
75 set show_charset [parse_show_charset_output "show charset"]
76
77 send_gdb "show target-charset\n"
78 set show_target_charset [parse_show_charset_output "show target-charset"]
79
80 if {! [string compare $show_charset $show_target_charset]} {
81     pass "check `show target-charset' against `show charset'"
82 } else {
83     fail "check `show target-charset' against `show charset'"
84 }
85
86 send_gdb "show host-charset\n"
87 set show_host_charset [parse_show_charset_output "show host-charset"]
88
89 if {! [string compare $show_charset $show_host_charset]} {
90     pass "check `show host-charset' against `show charset'"
91 } else {
92     fail "check `show host-charset' against `show charset'"
93 }
94
95
96 # Get the list of supported charsets.
97 send_gdb "set charset\n"
98
99 # True iff we've seen the "Valid character sets are:" message.
100 set seen_valid 0
101
102 # True iff we've seen the "can be used as a host character set" message.
103 set seen_can_host 0
104
105 # A Tcl array mapping the names of all the character sets we've seen
106 # to "1" if the character set can be used as a host character set, or
107 # "0" otherwise.  We can use `array names charsets' just to get a list
108 # of all character sets.
109 array set charsets {}
110
111 proc all_charset_names {} {
112     global charsets
113     return [array names charsets]
114 }
115
116 proc charset_exists {charset} {
117     global charsets
118     return [info exists charsets($charset)]
119 }
120
121 proc valid_host_charset {charset} {
122     global charsets
123     return $charsets($charset)
124 }
125
126 gdb_expect {
127     -re "Valid character sets are:\[\r\n\]+" {
128         # There's no ^ at the beginning of the pattern above, so that
129         # expect can skip the echoed `set charset' command.
130         set seen_valid 1
131         exp_continue
132     }
133     -re "^  (\[^ \t\n\]*) \\*\[\r\n\]+" {
134         set charsets($expect_out(1,string)) 1
135         exp_continue
136     }
137     -re "^  (\[^ \t\n\]*)\[ \t\]*\[\r\n\]+" {
138         set charsets($expect_out(1,string)) 0
139         exp_continue
140     }
141     -re "^\\* - can be used as a host character set\[\r\n\]+" {
142         set seen_can_host 1
143         exp_continue
144     }
145     -re ".*${gdb_prompt} $" {
146         # We don't do an exp_continue here.
147     }
148     timeout {
149         fail "get valid character sets (timeout)"
150     }
151 }
152
153
154 # Check that we've seen all the right pieces of the output, and that
155 # we can at least use ASCII as a host character set.
156 if {$seen_valid && $seen_can_host && [charset_exists ascii]} {
157     # We can't do the below as part of the test above, since all the
158     # [] substitution takes place before any expression evaluation
159     # takes place; && doesn't really short circuit things the way
160     # you'd like.  We'd get an "can't read $charsets(ascii)" error
161     # even when `info exists' had returned zero.
162     if {[valid_host_charset ascii]} {
163         pass "get valid character sets"
164     } else {
165         fail "get valid character sets"
166     }
167 } else {
168     fail "get valid character sets (no ascii charset)"
169 }
170
171
172 # Try using `set host-charset' on an invalid character set.
173 gdb_test "set host-charset my_grandma_bonnie" \
174          "GDB doesn't know of any character set named `my_grandma_bonnie'." \
175          "try `set host-charset' with invalid charset"
176
177
178 # Try using `set target-charset' on an invalid character set.
179 gdb_test "set target-charset my_grandma_bonnie" \
180          "GDB doesn't know of any character set named `my_grandma_bonnie'." \
181          "try `set target-charset' with invalid charset"
182
183
184 # Make sure that GDB supports every host/target charset combination.
185 foreach host_charset [all_charset_names] {
186     if {[valid_host_charset $host_charset]} {
187
188         set testname "try `set host-charset $host_charset'"
189         send_gdb "set host-charset $host_charset\n"
190         gdb_expect {
191             -re "GDB doesn't know of any character set named.*\[\r\n]+${gdb_prompt} $" {
192                 # How did it get into `charsets' then?
193                 fail "$testname (didn't recognize name)"
194             }
195             -re "GDB can't use `.*' as its host character set\\.\[\r\n]+${gdb_prompt} $" {
196                 # Well, then why does its `charsets' entry say it can?
197                 fail $testname
198             }
199             -re "${gdb_prompt} $" {
200                 pass $testname
201             }
202             timeout {
203                 fail "$testname (timeout)"
204             }
205         }
206
207         # Check that the command actually had its intended effect:
208         # $host_charset should now be the host character set.
209         send_gdb "show charset\n"
210         set result [parse_show_charset_output "parse `show charset' after `set host-charset $host_charset'"]
211         if {! [string compare [lindex $result 0] $host_charset]} {
212             pass "check effect of `set host-charset $host_charset'"
213         } else {
214             fail "check effect of `set host-charset $host_charset'"
215         }
216
217         # Now try setting every possible target character set,
218         # given that host charset.
219         foreach target_charset [all_charset_names] {
220             set testname "try `set target-charset $target_charset'"
221             send_gdb "set target-charset $target_charset\n"
222             gdb_expect {
223                 -re "GDB doesn't know of any character set named.*\[\r\n]+${gdb_prompt} $" {
224                     fail "$testname (didn't recognize name)"
225                 }
226                 -re "GDB can't convert from the .* character set to .*\\.\[\r\n\]+${gdb_prompt} $" {
227                     # This is a serious problem.  GDB should be able to convert
228                     # between any arbitrary pair of character sets.
229                     fail "$testname (can't convert)"
230                 }
231                 -re "${gdb_prompt} $" {
232                     pass $testname
233                 }
234                 timeout {
235                     fail "$testname (timeout)"
236                 }
237             }
238
239             # Check that the command actually had its intended effect:
240             # $target_charset should now be the target charset.
241             send_gdb "show charset\n"
242             set result [parse_show_charset_output "parse `show charset' after `set target-charset $target_charset'"]
243             if {! [string compare $result [list $host_charset $target_charset]]} {
244                 pass "check effect of `set target-charset $target_charset'"
245             } else {
246                 fail "check effect of `set target-charset $target_charset'"
247             }
248
249             # Test handling of characters in the host charset which
250             # can't be translated into the target charset.  \xA2 is
251             # `cent' in ISO-8859-1, which has no equivalent in ASCII.
252             #
253             # On some systems, the pseudo-tty through which we
254             # communicate with GDB insists on stripping the high bit
255             # from input characters, meaning that `cent' turns into
256             # `"'.  Since ISO-8859-1 and ASCII are identical in the
257             # lower 128 characters, it's tough to see how we can test
258             # this behavior on such systems, so we just xfail it.
259             #
260             # Note: the \x16 (Control-V) is an escape to allow \xA2 to
261             # get past readline.
262             if {! [string compare $host_charset iso-8859-1] && ! [string compare $target_charset ascii]} {
263
264                 set testname "untranslatable character in character literal"
265                 send_gdb "print '\x16\xA2'\n"
266                 gdb_expect {
267                     -re "There is no character corresponding to .* in the target character set .*\\.\[\r\n\]+$gdb_prompt $" {
268                         pass $testname
269                     }
270                     -re " = 34 '\"'\[\r\n\]+$gdb_prompt $" {
271                         xfail "$testname (DejaGNU's pseudo-tty strips eighth bit)"
272                     }
273                     -re "$gdb_prompt $" {
274                         fail $testname
275                     }
276                     timeout {
277                         fail "$testname (timeout)"
278                     }
279                 }
280
281                 set testname "untranslatable character in string literal"
282                 # If the PTTY zeros bit seven, then this turns into
283                 #   print """
284                 # which gets us a syntax error.  We don't care.
285                 send_gdb "print \"\x16\xA2\"\n"
286                 gdb_expect {
287                     -re "There is no character corresponding to .* in the target character set .*\\.\[\r\n\]+$gdb_prompt $" {
288                         pass $testname
289                     }
290                     -re "Unterminated string in expression.\[\r\n\]+$gdb_prompt $" {
291                         xfail "$testname (DejaGNU's pseudo-tty strips eighth bit)"
292                     }
293                     -re "$gdb_prompt $" {
294                         fail $testname
295                     }
296                     timeout {
297                         fail "$testname (timeout)"
298                     }
299                 }
300
301                 set testname "untranslatable characters in backslash escape"
302                 send_gdb "print '\\\x16\xA2'\n"
303                 gdb_expect {
304                     -re "The escape sequence .* is equivalent to plain .*, which has no equivalent\[\r\n\]+in the .* character set\\.\[\r\n\]+$gdb_prompt $" {
305                         pass $testname
306                     }
307                     -re " = 34 '\"'\[\r\n\]+$gdb_prompt $" {
308                         xfail "$testname (DejaGNU's pseudo-tty strips eighth bit)"
309                     }
310                     -re "$gdb_prompt $" {
311                         fail $testname
312                     }
313                     timeout {
314                         fail "$testname (timeout)"
315                     }
316                 }
317             }
318         }
319     }
320 }
321
322
323 # Set the host character set to plain ASCII, and try actually printing
324 # some strings in various target character sets.  We need to run the
325 # test program to the point at which the strings have been
326 # initialized.
327 gdb_test "break [gdb_get_line_number "all strings initialized"]" \
328          ".*Breakpoint.* at .*" \
329          "set breakpoint after all strings have been initialized"
330 gdb_run_cmd
331 gdb_expect {
332     -re "Breakpoint.*all strings initialized.*$gdb_prompt $" {
333         pass "run until all strings have been initialized"
334     }
335     -re "$gdb_prompt $" {
336         fail "run until all strings have been initialized"
337     }
338     timeout {
339         fail "run until all strings have been initialized (timeout)"
340     }
341 }
342
343
344 gdb_test "set host-charset ascii" ""
345 foreach target_charset [all_charset_names] {
346     send_gdb "set target-charset $target_charset\n" 
347     gdb_expect {
348         -re "$gdb_prompt $" {
349             pass "set target-charset $target_charset"
350         }
351         timeout {
352             fail "set target-charset $target_charset (timeout)"
353         }
354     }
355
356     # Try printing the null character.  There seems to be a bug in
357     # gdb_test that requires us to use gdb_expect here.
358     send_gdb "print '\\0'\n"
359     gdb_expect {
360         -re "\\\$${decimal} = 0 '\\\\0'\[\r\n\]+$gdb_prompt $" {
361             pass "print the null character in ${target_charset}"
362         }
363         -re "$gdb_prompt $" {
364             fail "print the null character in ${target_charset}"
365         }
366         timeout {
367             fail "print the null character in ${target_charset} (timeout)"
368         }
369     }
370
371     # Compute the name of the variable in the test program that holds
372     # a string in $target_charset.  The variable's name is the
373     # character set's name, in lower-case, with all non-identifier
374     # characters replaced with '_', with "_string" stuck on the end.
375     set var_name [string tolower "${target_charset}_string"]
376     regsub -all -- "\[^a-z0-9_\]" $var_name "_" var_name
377     
378     # Compute a regexp matching the results we expect.  This is static,
379     # but it's easier than writing it out.
380     regsub -all "." "abefnrtv" "(\\\\&|x)" escapes
381     set uppercase "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
382     set lowercase "abcdefghijklmnopqrstuvwxyz"
383     set digits "0123456789"
384     set octal_escape "\\\\\[0-9\]\[0-9\]\[0-9\]"
385
386     send_gdb "print $var_name\n"
387     # ${escapes}${uppercase}${lowercase}${digits}${octal}${octal}
388     gdb_expect {
389         -re ".* = \"(\\\\a|x)(\\\\b|x)(\\\\e|x)(\\\\f|x)(\\\\n|x)(\\\\r|x)(\\\\t|x)(\\\\v|x)${uppercase}${lowercase}${digits}(\\\\\[0-9\]\[0-9\]\[0-9\]|x)(\\\\\[0-9\]\[0-9\]\[0-9\]|x).*\"\[\r\n\]+$gdb_prompt $" {
390             pass "print string in $target_charset"
391         }
392         -re "$gdb_prompt $" {
393             fail "print string in $target_charset"
394         }
395         timeout {
396             fail "print string in $target_charset (timeout)"
397         }
398     }
399
400     # Try entering a character literal, and see if it comes back unchanged.
401     gdb_test "print 'A'" \
402              " = \[0-9-\]+ 'A'" \
403              "parse character literal in ${target_charset}"
404
405     # Check that the character literal was encoded correctly.
406     gdb_test "print 'A' == $var_name\[8\]" \
407              " = 1" \
408              "check value of parsed character literal in ${target_charset}"
409
410     # Try entering a string literal, and see if it comes back unchanged.
411     gdb_test "print \"abcdefABCDEF012345\"" \
412              " = \"abcdefABCDEF012345\"" \
413              "parse string literal in ${target_charset}"
414
415     # Check that the string literal was encoded correctly.
416     gdb_test "print \"q\"\[0\] == $var_name\[50\]" \
417              " = 1" \
418              "check value of parsed string literal in ${target_charset}"
419
420     # Test handling of characters in the target charset which
421     # can't be translated into the host charset.
422     if {! [string compare $target_charset iso-8859-1]} {
423         gdb_test "print iso_8859_1_string\[70\]" \
424                  " = \[0-9-\]+ '\\\\242'" \
425                  "print character with no equivalent in host character set"
426         gdb_test "print iso_8859_1_string + 70" \
427                  " = ${hex} \"\\\\242.*\"" \
428                  "print string with no equivalent in host character set"
429     }
430
431     # Make sure that we don't apply the ISO-8859-1 `print_literally'
432     # function to ASCII.
433     if {! [string compare $target_charset ascii]} {
434         gdb_test "print iso_8859_1_string\[70\]" \
435                  " = \[0-9-\]+ '\\\\242'" \
436                  "print ASCII unprintable character"
437         gdb_test "print iso_8859_1_string + 70" \
438                  " = ${hex} \"\\\\242.*\"" \
439                  "print ASCII unprintable string"
440     }
441
442     # Try printing characters with backslash escape equivalents.
443     set escapees {a b e f n r t v}
444     for {set i 0} {$i < [llength $escapees]} {incr i} {
445         set escape [lindex $escapees $i]
446         send_gdb "print $var_name\[$i\]\n"
447         set have_escape 1
448         gdb_expect {
449             -re "= \[0-9-\]+ '\\\\${escape}'\[\r\n\]+$gdb_prompt $" {
450                 pass "try printing '\\${escape}' in ${target_charset}"
451             }
452             -re "= \[0-9-\]+ 'x'\[\r\n\]+$gdb_prompt $" {
453                 xfail "try printing '\\${escape}' in ${target_charset} (no such escape)"
454                 set have_escape 0
455             }
456             -re "$gdb_prompt $" {
457                 fail "try printing '\\${escape}' in ${target_charset}"
458             }
459             timeout {
460                 fail "try printing '\\${escape}' in ${target_charset} (timeout)"
461             }
462         }
463
464         if {$have_escape} {
465
466             # Try parsing a backslash escape in a character literal.
467             gdb_test "print '\\${escape}' == $var_name\[$i\]" \
468                      " = 1" \
469                      "check value of '\\${escape}' in ${target_charset}"
470
471             # Try parsing a backslash escape in a string literal.
472             gdb_test "print \"\\${escape}\"\[0\] == $var_name\[$i\]" \
473                      " = 1" \
474                      "check value of \"\\${escape}\" in ${target_charset}"
475         }
476     }
477
478     # Try printing a character escape that doesn't exist.  We should 
479     # get the unescaped character, in the target character set.
480     gdb_test "print '\\q'" " = \[0-9-\]+ 'q'" \
481              "print escape that doesn't exist in $target_charset"
482     gdb_test "print '\\q' == $var_name\[50\]" " = 1" \
483              "check value of escape that doesn't exist in $target_charset"
484 }
485
486 gdb_exit