gdb:
[external/binutils.git] / gdb / testsuite / gdb.base / charset.exp
1 # This testcase is part of GDB, the GNU debugger.
2
3 # Copyright 2001, 2004, 2007, 2008, 2009 Free Software Foundation, Inc.
4
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18 # Please email any bugs, comments, and/or additions to this file to:
19 # bug-gdb@gnu.org
20
21 # Test GDB's character set support.
22
23 if $tracelevel then {
24         strace $tracelevel
25 }
26
27 set prms_id 0
28 set bug_id 0
29
30 set testfile "charset"
31 set srcfile ${testfile}.c
32 set binfile ${objdir}/${subdir}/${testfile}
33 if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
34     untested "couldn't compile ${srcdir}/${subdir}/${srcfile}"
35     return -1
36 }
37
38 # Start with a fresh gdb.
39 gdb_exit
40 gdb_start
41 gdb_reinitialize_dir $srcdir/$subdir
42 gdb_load ${binfile}
43
44 # Parse the output from a `show charset' command.  Return the host
45 # and target charset as a two-element list.
46 proc parse_show_charset_output {testname} {
47     global gdb_prompt
48
49     gdb_expect {
50         -re "The host character set is \"(.*)\"\\.\[\r\n\]+The target character set is \"(.*)\"\\.\[\r\n\]+The target wide character set is \"(.*)\"\\.\[\r\n\]+$gdb_prompt $" {
51             set host_charset $expect_out(1,string)
52             set target_charset $expect_out(2,string)
53             set retlist [list $host_charset $target_charset]
54             pass $testname
55         }
56         -re "The host character set is \"(.*)\"\\.\[\r\n\]+$gdb_prompt $" {
57             set host_charset $expect_out(1,string)
58             set retlist [list $host_charset]
59             pass $testname
60         }
61         -re "The target character set is \"(.*)\"\\.\[\r\n\]+$gdb_prompt $" {
62             set target_charset $expect_out(1,string)
63             set retlist [list $target_charset]
64             pass $testname
65         }
66         -re ".*$gdb_prompt $" {
67             fail $testname
68         }
69         timeout {
70             fail "$testname (timeout)"
71         }
72     }
73
74     return $retlist
75 }
76
77
78 # Try the various `show charset' commands.
79
80 send_gdb "show charset\n"
81 set show_charset [parse_show_charset_output "show charset"]
82
83 send_gdb "show target-charset\n"
84 set show_target_charset \
85   [lindex [parse_show_charset_output "show target-charset"] 0]
86
87 if {[lsearch -exact $show_charset $show_target_charset] >= 0} {
88     pass "check `show target-charset' against `show charset'"
89 } else {
90     fail "check `show target-charset' against `show charset'"
91 }
92
93 send_gdb "show host-charset\n"
94 set show_host_charset \
95   [lindex [parse_show_charset_output "show host-charset"] 0]
96
97 if {[lsearch -exact $show_charset $show_host_charset] >= 0} {
98     pass "check `show host-charset' against `show charset'"
99 } else {
100     fail "check `show host-charset' against `show charset'"
101 }
102
103 # Try a malformed `set charset'.
104 gdb_test "set charset" \
105          "Requires an argument. Valid arguments are.*" \
106          "try malformed `set charset'"
107
108 # Try using `set host-charset' on an invalid character set.
109 gdb_test "set host-charset my_grandma_bonnie" \
110          "Undefined item: \"my_grandma_bonnie\"." \
111          "try `set host-charset' with invalid charset"
112
113 # Try using `set target-charset' on an invalid character set.
114 gdb_test "set target-charset my_grandma_bonnie" \
115          "Undefined item: \"my_grandma_bonnie\"." \
116          "try `set target-charset' with invalid charset"
117
118 # A Tcl array mapping the names of all the character sets we've seen
119 # to "1" if the character set can be used as a host character set, or
120 # "0" otherwise.  We can use `array names charsets' just to get a list
121 # of all character sets.
122 array set charsets {}
123
124 proc all_charset_names {} {
125     global charsets
126     return [array names charsets]
127 }
128
129 proc valid_host_charset {charset} {
130     global charsets
131     return [expr {[info exists charsets($charset)] && $charsets($charset)}]
132 }
133
134 send_gdb "set host-charset\n"
135 gdb_expect {
136     -re "Requires an argument. Valid arguments are (\[^ \t\n\r,.\]*)" {
137         #set host_charset_list $expect_out(1,string)
138         set charsets($expect_out(1,string)) 1
139         exp_continue
140         #pass "capture valid host charsets"
141     }
142
143     -re ", (\[^ \t\n\r,.\]*)" {
144         #set host_charset_list $expect_out(1,string)
145         set charsets($expect_out(1,string)) 1
146         exp_continue
147         #pass "capture valid host charsets"
148     }
149
150     -re "\\.\r\n$gdb_prompt $" {
151         #set host_charset_list $expect_out(1,string)
152         pass "capture valid host charsets"
153     }
154
155     -re ".*$gdb_prompt $" {
156         fail "capture valid host charsets"
157     }
158     timeout {
159         fail "(timeout) capture valid host charsets"
160     }
161 }
162
163 # If gdb was built with a phony iconv, it will only have two character
164 # sets: "auto" and the default.  In this situation, this set of tests
165 # is pointless.
166 if {[llength [array names charsets]] < 3} {
167     untested charset.exp
168     return -1
169 }
170
171 send_gdb "set target-charset\n"
172 gdb_expect {
173     -re "Requires an argument. Valid arguments are (\[^ \t\n\r,.\]*)" {
174         set target_charset $expect_out(1,string)
175         if {! [info exists charsets($target_charset)]} {
176             set charsets($target_charset) 0
177         }
178         exp_continue
179     }
180
181     -re ", (\[^ \t\n\r,.\]*)" {
182         set target_charset $expect_out(1,string)
183         if {! [info exists charsets($target_charset)]} {
184             set charsets($target_charset) 0
185         }
186         exp_continue
187     }
188
189     -re "\\.\r\n$gdb_prompt $" {
190         pass "capture valid target charsets"
191
192     }
193
194     -re ".*$gdb_prompt $" {
195         fail "capture valid target charsets"
196     }
197
198     timeout {
199         fail "(timeout) capture valid target charsets"
200     }
201 }
202
203 # We don't want to test all the charset names here, since that would
204 # be too many combinations.  We we pick a subset.
205 set charset_subset {ASCII ISO-8859-1 EBCDIC-US IBM1047}
206 foreach host_charset $charset_subset {
207     if {[valid_host_charset $host_charset]} {
208
209         set testname "try `set host-charset $host_charset'"
210         send_gdb "set host-charset $host_charset\n"
211         gdb_expect {
212             -re "GDB doesn't know of any character set named.*\[\r\n]+${gdb_prompt} $" {
213                 # How did it get into `charsets' then?
214                 fail "$testname (didn't recognize name)"
215             }
216             -re "GDB can't use `.*' as its host character set\\.\[\r\n]+${gdb_prompt} $" {
217                 # Well, then why does its `charsets' entry say it can?
218                 fail $testname
219             }
220             -re "${gdb_prompt} $" {
221                 pass $testname
222             }
223             timeout {
224                 fail "$testname (timeout)"
225             }
226         }
227
228         # Check that the command actually had its intended effect:
229         # $host_charset should now be the host character set.
230         send_gdb "show charset\n"
231         set result [parse_show_charset_output "parse `show charset' after `set host-charset $host_charset'"]
232         if {! [string compare [lindex $result 0] $host_charset]} {
233             pass "check effect of `set host-charset $host_charset'"
234         } else {
235             fail "check effect of `set host-charset $host_charset'"
236         }
237
238         # Now try setting every possible target character set,
239         # given that host charset.
240         foreach target_charset $charset_subset {
241             set testname "try `set target-charset $target_charset'"
242             send_gdb "set target-charset $target_charset\n"
243             gdb_expect {
244                 -re "GDB doesn't know of any character set named.*\[\r\n]+${gdb_prompt} $" {
245                     fail "$testname (didn't recognize name)"
246                 }
247                 -re "GDB can't convert from the .* character set to .*\\.\[\r\n\]+${gdb_prompt} $" {
248                     # This is a serious problem.  GDB should be able to convert
249                     # between any arbitrary pair of character sets.
250                     fail "$testname (can't convert)"
251                 }
252                 -re "${gdb_prompt} $" {
253                     pass $testname
254                 }
255                 timeout {
256                     fail "$testname (timeout)"
257                 }
258             }
259
260             # Check that the command actually had its intended effect:
261             # $target_charset should now be the target charset.
262             send_gdb "show charset\n"
263             set result [parse_show_charset_output "parse `show charset' after `set target-charset $target_charset'"]
264             if {! [string compare $result [list $host_charset $target_charset]]} {
265                 pass "check effect of `set target-charset $target_charset'"
266             } else {
267                 fail "check effect of `set target-charset $target_charset'"
268             }
269
270             # Test handling of characters in the host charset which
271             # can't be translated into the target charset.  \xA2 is
272             # `cent' in ISO-8859-1, which has no equivalent in ASCII.
273             #
274             # On some systems, the pseudo-tty through which we
275             # communicate with GDB insists on stripping the high bit
276             # from input characters, meaning that `cent' turns into
277             # `"'.  Since ISO-8859-1 and ASCII are identical in the
278             # lower 128 characters, it's tough to see how we can test
279             # this behavior on such systems, so we just xfail it.
280             #
281             # Note: the \x16 (Control-V) is an escape to allow \xA2 to
282             # get past readline.
283             if {! [string compare $host_charset iso-8859-1] && ! [string compare $target_charset ascii]} {
284
285                 set testname "untranslatable character in character literal"
286                 send_gdb "print '\x16\xA2'\n"
287                 gdb_expect {
288                     -re "There is no character corresponding to .* in the target character set .*\\.\[\r\n\]+$gdb_prompt $" {
289                         pass $testname
290                     }
291                     -re " = 34 '\"'\[\r\n\]+$gdb_prompt $" {
292                         xfail "$testname (DejaGNU's pseudo-tty strips eighth bit)"
293                     }
294                     -re "$gdb_prompt $" {
295                         fail $testname
296                     }
297                     timeout {
298                         fail "$testname (timeout)"
299                     }
300                 }
301
302                 set testname "untranslatable character in string literal"
303                 # If the PTTY zeros bit seven, then this turns into
304                 #   print """
305                 # which gets us a syntax error.  We don't care.
306                 send_gdb "print \"\x16\xA2\"\n"
307                 gdb_expect {
308                     -re "There is no character corresponding to .* in the target character set .*\\.\[\r\n\]+$gdb_prompt $" {
309                         pass $testname
310                     }
311                     -re "Unterminated string in expression.\[\r\n\]+$gdb_prompt $" {
312                         xfail "$testname (DejaGNU's pseudo-tty strips eighth bit)"
313                     }
314                     -re "$gdb_prompt $" {
315                         fail $testname
316                     }
317                     timeout {
318                         fail "$testname (timeout)"
319                     }
320                 }
321
322                 set testname "untranslatable characters in backslash escape"
323                 send_gdb "print '\\\x16\xA2'\n"
324                 gdb_expect {
325                     -re "The escape sequence .* is equivalent to plain .*, which has no equivalent\[\r\n\]+in the .* character set\\.\[\r\n\]+$gdb_prompt $" {
326                         pass $testname
327                     }
328                     -re " = 34 '\"'\[\r\n\]+$gdb_prompt $" {
329                         xfail "$testname (DejaGNU's pseudo-tty strips eighth bit)"
330                     }
331                     -re "$gdb_prompt $" {
332                         fail $testname
333                     }
334                     timeout {
335                         fail "$testname (timeout)"
336                     }
337                 }
338             }
339         }
340     }
341 }
342
343
344 # Set the host character set to plain ASCII, and try actually printing
345 # some strings in various target character sets.  We need to run the
346 # test program to the point at which the strings have been
347 # initialized.
348 gdb_test "break ${srcfile}:[gdb_get_line_number "all strings initialized"]" \
349          ".*Breakpoint.* at .*" \
350          "set breakpoint after all strings have been initialized"
351 gdb_run_cmd
352 gdb_expect {
353     -re "Breakpoint.*all strings initialized.*$gdb_prompt $" {
354         pass "run until all strings have been initialized"
355     }
356     -re "$gdb_prompt $" {
357         fail "run until all strings have been initialized"
358     }
359     timeout {
360         fail "run until all strings have been initialized (timeout)"
361     }
362 }
363
364
365 # We only try the wide character tests on machines where the wchar_t
366 # typedef in the test case has the right size.
367 set wchar_size [get_sizeof wchar_t 99]
368 set wchar_ok 0
369 if {$wchar_size == 2} {
370     lappend charset_subset UCS-2
371     set wchar_ok 1
372 } elseif {$wchar_size == 4} {
373     lappend charset_subset UCS-4
374     set wchar_ok 1
375 }
376
377 gdb_test "set host-charset ASCII" ""
378 foreach target_charset $charset_subset {
379     if {$target_charset == "UCS-4" || $target_charset == "UCS-2"} {
380         set param target-wide-charset
381         set L L
382     } else {
383         set param target-charset
384         set L ""
385     }
386     send_gdb "set $param $target_charset\n" 
387     gdb_expect {
388         -re "$gdb_prompt $" {
389             pass "set $param $target_charset"
390         }
391         timeout {
392             fail "set $param $target_charset (timeout)"
393         }
394     }
395
396     # Try printing the null character.  There seems to be a bug in
397     # gdb_test that requires us to use gdb_expect here.
398     send_gdb "print $L'\\0'\n"
399     gdb_expect {
400         -re "\\\$${decimal} = 0 $L'\\\\0'\[\r\n\]+$gdb_prompt $" {
401             pass "print the null character in ${target_charset}"
402         }
403         -re "$gdb_prompt $" {
404             fail "print the null character in ${target_charset}"
405         }
406         timeout {
407             fail "print the null character in ${target_charset} (timeout)"
408         }
409     }
410
411     # Compute the name of the variable in the test program that holds
412     # a string in $target_charset.  The variable's name is the
413     # character set's name, in lower-case, with all non-identifier
414     # characters replaced with '_', with "_string" stuck on the end.
415     if {$target_charset == "UCS-2"} {
416         # We still use the ucs_4_string variable -- but the size is
417         # correct for UCS-2.
418         set var_name ucs_4_string
419     } else {
420         set var_name [string tolower "${target_charset}_string"]
421         regsub -all -- "\[^a-z0-9_\]" $var_name "_" var_name
422     }
423     
424     # Compute a regexp matching the results we expect.  This is static,
425     # but it's easier than writing it out.
426     regsub -all "." "abfnrtv" "(\\\\&|x)" escapes
427     set uppercase "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
428     set lowercase "abcdefghijklmnopqrstuvwxyz"
429     set digits "0123456789"
430     set octal_escape "\\\\\[0-9\]+"
431
432     send_gdb "print $var_name\n"
433     # ${escapes}${uppercase}${lowercase}${digits}${octal}${octal}
434     gdb_expect {
435         -re ".* = $L\"(\\\\a|x)(\\\\b|x)(\\\\f|x)(\\\\n|x)(\\\\r|x)(\\\\t|x)(\\\\v|x)${uppercase}${lowercase}${digits}(${octal_escape}|x)+\"\[\r\n\]+$gdb_prompt $" {
436             pass "print string in $target_charset"
437         }
438         -re "$gdb_prompt $" {
439             fail "print string in $target_charset"
440         }
441         timeout {
442             fail "print string in $target_charset (timeout)"
443         }
444     }
445
446     # Try entering a character literal, and see if it comes back unchanged.
447     gdb_test "print $L'A'" \
448              " = \[0-9-\]+ $L'A'" \
449              "parse character literal in ${target_charset}"
450
451     # Check that the character literal was encoded correctly.
452     gdb_test "print $L'A' == $var_name\[7\]" \
453              " = 1" \
454              "check value of parsed character literal in ${target_charset}"
455
456     # Try entering a string literal, and see if it comes back unchanged.
457     gdb_test "print $L\"abcdefABCDEF012345\"" \
458              " = $L\"abcdefABCDEF012345\"" \
459              "parse string literal in ${target_charset}"
460
461     # Check that the string literal was encoded correctly.
462     gdb_test "print $L\"q\"\[0\] == $var_name\[49\]" \
463              " = 1" \
464              "check value of parsed string literal in ${target_charset}"
465
466     # Test handling of characters in the target charset which
467     # can't be translated into the host charset.
468     if {! [string compare $target_charset iso-8859-1]} {
469         gdb_test "print iso_8859_1_string\[69\]" \
470                  " = \[0-9-\]+ '\\\\242'" \
471                  "print character with no equivalent in host character set"
472         gdb_test "print iso_8859_1_string + 70" \
473                  " = ${hex} \"\\\\242.*\"" \
474                  "print string with no equivalent in host character set"
475     }
476
477     # Make sure that we don't apply the ISO-8859-1 `print_literally'
478     # function to ASCII.
479     if {! [string compare $target_charset ascii]} {
480         gdb_test "print iso_8859_1_string\[69\]" \
481                  " = \[0-9-\]+ '\\\\242'" \
482                  "print ASCII unprintable character"
483         gdb_test "print iso_8859_1_string + 70" \
484                  " = ${hex} \"\\\\242.*\"" \
485                  "print ASCII unprintable string"
486     }
487
488     # Try printing characters with backslash escape equivalents.
489     set escapees {a b f n r t v}
490     for {set i 0} {$i < [llength $escapees]} {incr i} {
491         set escape [lindex $escapees $i]
492         send_gdb "print $var_name\[$i\]\n"
493         set have_escape 1
494         gdb_expect {
495             -re "= \[0-9-\]+ $L'\\\\${escape}'\[\r\n\]+$gdb_prompt $" {
496                 pass "try printing '\\${escape}' in ${target_charset}"
497             }
498             -re "= \[0-9-\]+ 'x'\[\r\n\]+$gdb_prompt $" {
499                 xfail "try printing '\\${escape}' in ${target_charset} (no such escape)"
500                 set have_escape 0
501             }
502             -re "$gdb_prompt $" {
503                 fail "try printing '\\${escape}' in ${target_charset}"
504             }
505             timeout {
506                 fail "try printing '\\${escape}' in ${target_charset} (timeout)"
507             }
508         }
509
510         if {$have_escape} {
511
512             # Try parsing a backslash escape in a character literal.
513             gdb_test "print $L'\\${escape}' == $var_name\[$i\]" \
514                      " = 1" \
515                      "check value of '\\${escape}' in ${target_charset}"
516
517             # Try parsing a backslash escape in a string literal.
518             gdb_test "print $L\"\\${escape}\"\[0\] == $var_name\[$i\]" \
519                      " = 1" \
520                      "check value of \"\\${escape}\" in ${target_charset}"
521         }
522     }
523
524     # Try printing a character escape that doesn't exist.  We should 
525     # get the unescaped character, in the target character set.
526     gdb_test "print $L'\\q'" " = \[0-9-\]+ $L'q'" \
527              "print escape that doesn't exist in $target_charset"
528     gdb_test "print $L'\\q' == $var_name\[49\]" " = 1" \
529              "check value of escape that doesn't exist in $target_charset"
530 }
531
532 # Reset the target charset.
533 gdb_test "set target-charset UTF-8" ""
534
535 # \242 is not a valid UTF-8 character.
536 gdb_test "print \"\\242\"" " = \"\\\\242\"" \
537   "non-representable target character"
538
539 gdb_test "print '\\x'" "\\\\x escape without a following hex digit."
540 gdb_test "print '\\u'" "\\\\u escape without a following hex digit."
541 gdb_test "print '\\9'" " = \[0-9\]+ '9'"
542
543 # Tests for wide- or unicode- strings.  L is the prefix letter to use,
544 # either "L" (for wide strings), "u" (for UCS-2), or "U" (for UCS-4).
545 # NAME is used in the test names and should be related to the prefix
546 # letter in some easy-to-undestand way.
547 proc test_wide_or_unicode {L name} {
548     gdb_test "print $L\"ab\" $L\"c\"" " = $L\"abc\"" \
549       "basic $name string concatenation"
550     gdb_test "print $L\"ab\" \"c\"" " = $L\"abc\"" \
551       "narrow and $name string concatenation"
552     gdb_test "print \"ab\" $L\"c\"" " = $L\"abc\"" \
553       "$name and narrow string concatenation"
554     gdb_test "print $L\"\\xe\" $L\"c\"" " = $L\"\\\\16c\"" \
555       "$name string concatenation with escape"
556     gdb_test "print $L\"\" \"abcdef\" \"g\"" \
557       "$L\"abcdefg\"" \
558       "concatenate three strings with empty $name string"
559
560     gdb_test "print $L'a'" "= \[0-9\]+ $L'a'" \
561       "basic $name character"
562 }
563
564 if {$wchar_ok} {
565     test_wide_or_unicode L wide
566 }
567
568 set ucs2_ok [expr {[get_sizeof char16_t 99] == 2}]
569 if {$ucs2_ok} {
570     test_wide_or_unicode u UCS-2
571 }
572
573 set ucs4_ok [expr {[get_sizeof char32_t 99] == 4}]
574 if {$ucs4_ok} {
575     test_wide_or_unicode U UCS-4
576 }
577
578 # Test an invalid string combination.
579 proc test_combination {L1 name1 L2 name2} {
580     gdb_test "print $L1\"abc\" $L2\"def\"" \
581       "Undefined string concatenation." \
582       "undefined concatenation of $name1 and $name2"
583 }
584
585 if {$wchar_ok && $ucs2_ok} {
586     test_combination L wide u UCS-2
587 }
588 if {$wchar_ok && $ucs4_ok} {
589     test_combination L wide U UCS-4
590 }
591 if {$ucs2_ok && $ucs4_ok} {
592     test_combination u UCS-2 U UCS-4
593 }
594
595 gdb_exit