Switch the license of all .exp files to GPLv3.
[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 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 current host and target character set is `(.*)'\\.\[\r\n\]+$gdb_prompt $" {
51             set host_charset $expect_out(1,string)
52             set target_charset $expect_out(1,string)
53             set retlist [list $host_charset $target_charset]
54             pass $testname
55         }
56         -re "The current host character set is `(.*)'\\.\[\r\n\]+The current target character set is `(.*)'\\.\[\r\n\]+$gdb_prompt $" {
57             set host_charset $expect_out(1,string)
58             set target_charset $expect_out(2,string)
59             set retlist [list $host_charset $target_charset]
60             pass $testname
61         }
62         -re "The host character set is \"(.*)\"\\.\[\r\n\]+$gdb_prompt $" {
63             set host_charset $expect_out(1,string)
64             set retlist [list $host_charset]
65             pass $testname
66         }
67         -re "The target character set is \"(.*)\"\\.\[\r\n\]+$gdb_prompt $" {
68             set target_charset $expect_out(1,string)
69             set retlist [list $target_charset]
70             pass $testname
71         }
72         -re ".*$gdb_prompt $" {
73             fail $testname
74         }
75         timeout {
76             fail "$testname (timeout)"
77         }
78     }
79
80     return $retlist
81 }
82
83
84 # Try the various `show charset' commands.  These are all aliases of each
85 # other; `show target-charset' and `show host-charset' actually print
86 # both the host and target charsets.
87
88 send_gdb "show charset\n"
89 set show_charset [parse_show_charset_output "show charset"]
90
91 send_gdb "show target-charset\n"
92 set show_target_charset [parse_show_charset_output "show target-charset"]
93
94 if {[lsearch $show_charset $show_target_charset] >= 0} {
95     pass "check `show target-charset' against `show charset'"
96 } else {
97     fail "check `show target-charset' against `show charset'"
98 }
99
100 send_gdb "show host-charset\n"
101 set show_host_charset [parse_show_charset_output "show host-charset"]
102
103 if {[lsearch $show_charset $show_host_charset] >= 0} {
104     pass "check `show host-charset' against `show charset'"
105 } else {
106     fail "check `show host-charset' against `show charset'"
107 }
108
109
110 # Get the list of supported (host) charsets as possible completions.
111 send_gdb "set charset \t\t"
112
113 # Check that we can at least use ASCII as a host character set.
114 sleep 1
115 gdb_expect {
116     -re "^set charset .*\r\nASCII.*\r\n$gdb_prompt set charset " {
117         # We got the output that we wanted, including ASCII as possible
118         # charset. Send a newline to get us back to the prompt. This will
119         # also generate an error message. Let's not check here that the error
120         # message makes sense, we do that below, as a separate testcase.
121         send_gdb "\n"
122         gdb_expect {
123             -re ".*Requires an argument.*$gdb_prompt $" {
124                 pass "get valid character sets"
125             }
126             -re ".*$gdb_prompt $" {
127                 send_gdb "\n"
128                 gdb_expect {
129                     -re ".*$gdb_prompt $" {
130                         fail "get valid character sets"
131                     }
132                 }
133             }
134             timeout {
135                 fail "(timeout) get valid character sets"
136             }
137         }
138     }
139     -re ".*$gdb_prompt $" {
140         # We got some output that ended with a regular prompt
141         fail "get valid character sets"
142     }
143     -re ".*$gdb_prompt set charset.*$" {
144         # We got some other output, send a cntrl-c to gdb to get us back
145         # to the prompt.
146         send_gdb "\003"
147         fail "get valid character sets"
148     }
149     timeout {
150         fail "get valid character sets (timeout)"
151     }
152 }
153
154 # Try a malformed `set charset'.
155 gdb_test "set charset" \
156          "Requires an argument. Valid arguments are.*" \
157          "try malformed `set charset'"
158
159 # Try using `set host-charset' on an invalid character set.
160 gdb_test "set host-charset my_grandma_bonnie" \
161          "Undefined item: \"my_grandma_bonnie\"." \
162          "try `set host-charset' with invalid charset"
163
164 # Try using `set target-charset' on an invalid character set.
165 gdb_test "set target-charset my_grandma_bonnie" \
166          "Undefined item: \"my_grandma_bonnie\"." \
167          "try `set target-charset' with invalid charset"
168
169 # A Tcl array mapping the names of all the character sets we've seen
170 # to "1" if the character set can be used as a host character set, or
171 # "0" otherwise.  We can use `array names charsets' just to get a list
172 # of all character sets.
173 array set charsets {}
174
175 proc all_charset_names {} {
176     global charsets
177     return [array names charsets]
178 }
179
180 proc valid_host_charset {charset} {
181     global charsets
182     return $charsets($charset)
183 }
184
185 send_gdb "set host-charset\n"
186 gdb_expect {
187     -re "Requires an argument. Valid arguments are (\[^ \t\n\r,.\]*)" {
188         #set host_charset_list $expect_out(1,string)
189         set charsets($expect_out(1,string)) 1
190         exp_continue
191         #pass "capture valid host charsets"
192     }
193
194     -re ", (\[^ \t\n\r,.\]*)" {
195         #set host_charset_list $expect_out(1,string)
196         set charsets($expect_out(1,string)) 1
197         exp_continue
198         #pass "capture valid host charsets"
199     }
200
201     -re "\\.\r\n$gdb_prompt $" {
202         #set host_charset_list $expect_out(1,string)
203         pass "capture valid host charsets"
204     }
205
206     -re ".*$gdb_prompt $" {
207         fail "capture valid host charsets"
208     }
209     timeout {
210         fail "(timeout) capture valid host charsets"
211     }
212 }
213
214
215 send_gdb "set target-charset\n"
216 gdb_expect {
217     -re "Requires an argument. Valid arguments are (\[^ \t\n\r,.\]*)" {
218         set target_charset $expect_out(1,string)
219         if {! [info exists charsets($target_charset)]} {
220             set charsets($target_charset) 0
221         }
222         exp_continue
223     }
224
225     -re ", (\[^ \t\n\r,.\]*)" {
226         set target_charset $expect_out(1,string)
227         if {! [info exists charsets($target_charset)]} {
228             set charsets($target_charset) 0
229         }
230         exp_continue
231     }
232
233     -re "\\.\r\n$gdb_prompt $" {
234         pass "capture valid target charsets"
235
236     }
237
238     -re ".*$gdb_prompt $" {
239         fail "capture valid target charsets"
240     }
241
242     timeout {
243         fail "(timeout) capture valid target charsets"
244     }
245 }
246
247 # Make sure that GDB supports every host/target charset combination.
248 foreach host_charset [all_charset_names] {
249     if {[valid_host_charset $host_charset]} {
250
251         set testname "try `set host-charset $host_charset'"
252         send_gdb "set host-charset $host_charset\n"
253         gdb_expect {
254             -re "GDB doesn't know of any character set named.*\[\r\n]+${gdb_prompt} $" {
255                 # How did it get into `charsets' then?
256                 fail "$testname (didn't recognize name)"
257             }
258             -re "GDB can't use `.*' as its host character set\\.\[\r\n]+${gdb_prompt} $" {
259                 # Well, then why does its `charsets' entry say it can?
260                 fail $testname
261             }
262             -re "${gdb_prompt} $" {
263                 pass $testname
264             }
265             timeout {
266                 fail "$testname (timeout)"
267             }
268         }
269
270         # Check that the command actually had its intended effect:
271         # $host_charset should now be the host character set.
272         send_gdb "show charset\n"
273         set result [parse_show_charset_output "parse `show charset' after `set host-charset $host_charset'"]
274         if {! [string compare [lindex $result 0] $host_charset]} {
275             pass "check effect of `set host-charset $host_charset'"
276         } else {
277             fail "check effect of `set host-charset $host_charset'"
278         }
279
280         # Now try setting every possible target character set,
281         # given that host charset.
282         foreach target_charset [all_charset_names] {
283             set testname "try `set target-charset $target_charset'"
284             send_gdb "set target-charset $target_charset\n"
285             gdb_expect {
286                 -re "GDB doesn't know of any character set named.*\[\r\n]+${gdb_prompt} $" {
287                     fail "$testname (didn't recognize name)"
288                 }
289                 -re "GDB can't convert from the .* character set to .*\\.\[\r\n\]+${gdb_prompt} $" {
290                     # This is a serious problem.  GDB should be able to convert
291                     # between any arbitrary pair of character sets.
292                     fail "$testname (can't convert)"
293                 }
294                 -re "${gdb_prompt} $" {
295                     pass $testname
296                 }
297                 timeout {
298                     fail "$testname (timeout)"
299                 }
300             }
301
302             # Check that the command actually had its intended effect:
303             # $target_charset should now be the target charset.
304             send_gdb "show charset\n"
305             set result [parse_show_charset_output "parse `show charset' after `set target-charset $target_charset'"]
306             if {! [string compare $result [list $host_charset $target_charset]]} {
307                 pass "check effect of `set target-charset $target_charset'"
308             } else {
309                 fail "check effect of `set target-charset $target_charset'"
310             }
311
312             # Test handling of characters in the host charset which
313             # can't be translated into the target charset.  \xA2 is
314             # `cent' in ISO-8859-1, which has no equivalent in ASCII.
315             #
316             # On some systems, the pseudo-tty through which we
317             # communicate with GDB insists on stripping the high bit
318             # from input characters, meaning that `cent' turns into
319             # `"'.  Since ISO-8859-1 and ASCII are identical in the
320             # lower 128 characters, it's tough to see how we can test
321             # this behavior on such systems, so we just xfail it.
322             #
323             # Note: the \x16 (Control-V) is an escape to allow \xA2 to
324             # get past readline.
325             if {! [string compare $host_charset iso-8859-1] && ! [string compare $target_charset ascii]} {
326
327                 set testname "untranslatable character in character literal"
328                 send_gdb "print '\x16\xA2'\n"
329                 gdb_expect {
330                     -re "There is no character corresponding to .* in the target character set .*\\.\[\r\n\]+$gdb_prompt $" {
331                         pass $testname
332                     }
333                     -re " = 34 '\"'\[\r\n\]+$gdb_prompt $" {
334                         xfail "$testname (DejaGNU's pseudo-tty strips eighth bit)"
335                     }
336                     -re "$gdb_prompt $" {
337                         fail $testname
338                     }
339                     timeout {
340                         fail "$testname (timeout)"
341                     }
342                 }
343
344                 set testname "untranslatable character in string literal"
345                 # If the PTTY zeros bit seven, then this turns into
346                 #   print """
347                 # which gets us a syntax error.  We don't care.
348                 send_gdb "print \"\x16\xA2\"\n"
349                 gdb_expect {
350                     -re "There is no character corresponding to .* in the target character set .*\\.\[\r\n\]+$gdb_prompt $" {
351                         pass $testname
352                     }
353                     -re "Unterminated string in expression.\[\r\n\]+$gdb_prompt $" {
354                         xfail "$testname (DejaGNU's pseudo-tty strips eighth bit)"
355                     }
356                     -re "$gdb_prompt $" {
357                         fail $testname
358                     }
359                     timeout {
360                         fail "$testname (timeout)"
361                     }
362                 }
363
364                 set testname "untranslatable characters in backslash escape"
365                 send_gdb "print '\\\x16\xA2'\n"
366                 gdb_expect {
367                     -re "The escape sequence .* is equivalent to plain .*, which has no equivalent\[\r\n\]+in the .* character set\\.\[\r\n\]+$gdb_prompt $" {
368                         pass $testname
369                     }
370                     -re " = 34 '\"'\[\r\n\]+$gdb_prompt $" {
371                         xfail "$testname (DejaGNU's pseudo-tty strips eighth bit)"
372                     }
373                     -re "$gdb_prompt $" {
374                         fail $testname
375                     }
376                     timeout {
377                         fail "$testname (timeout)"
378                     }
379                 }
380             }
381         }
382     }
383 }
384
385
386 # Set the host character set to plain ASCII, and try actually printing
387 # some strings in various target character sets.  We need to run the
388 # test program to the point at which the strings have been
389 # initialized.
390 gdb_test "break ${srcfile}:[gdb_get_line_number "all strings initialized"]" \
391          ".*Breakpoint.* at .*" \
392          "set breakpoint after all strings have been initialized"
393 gdb_run_cmd
394 gdb_expect {
395     -re "Breakpoint.*all strings initialized.*$gdb_prompt $" {
396         pass "run until all strings have been initialized"
397     }
398     -re "$gdb_prompt $" {
399         fail "run until all strings have been initialized"
400     }
401     timeout {
402         fail "run until all strings have been initialized (timeout)"
403     }
404 }
405
406
407 gdb_test "set host-charset ASCII" ""
408 foreach target_charset [all_charset_names] {
409     send_gdb "set target-charset $target_charset\n" 
410     gdb_expect {
411         -re "$gdb_prompt $" {
412             pass "set target-charset $target_charset"
413         }
414         timeout {
415             fail "set target-charset $target_charset (timeout)"
416         }
417     }
418
419     # Try printing the null character.  There seems to be a bug in
420     # gdb_test that requires us to use gdb_expect here.
421     send_gdb "print '\\0'\n"
422     gdb_expect {
423         -re "\\\$${decimal} = 0 '\\\\0'\[\r\n\]+$gdb_prompt $" {
424             pass "print the null character in ${target_charset}"
425         }
426         -re "$gdb_prompt $" {
427             fail "print the null character in ${target_charset}"
428         }
429         timeout {
430             fail "print the null character in ${target_charset} (timeout)"
431         }
432     }
433
434     # Compute the name of the variable in the test program that holds
435     # a string in $target_charset.  The variable's name is the
436     # character set's name, in lower-case, with all non-identifier
437     # characters replaced with '_', with "_string" stuck on the end.
438     set var_name [string tolower "${target_charset}_string"]
439     regsub -all -- "\[^a-z0-9_\]" $var_name "_" var_name
440     
441     # Compute a regexp matching the results we expect.  This is static,
442     # but it's easier than writing it out.
443     regsub -all "." "abfnrtv" "(\\\\&|x)" escapes
444     set uppercase "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
445     set lowercase "abcdefghijklmnopqrstuvwxyz"
446     set digits "0123456789"
447     set octal_escape "\\\\\[0-9\]\[0-9\]\[0-9\]"
448
449     send_gdb "print $var_name\n"
450     # ${escapes}${uppercase}${lowercase}${digits}${octal}${octal}
451     gdb_expect {
452         -re ".* = \"(\\\\a|x)(\\\\b|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 $" {
453             pass "print string in $target_charset"
454         }
455         -re "$gdb_prompt $" {
456             fail "print string in $target_charset"
457         }
458         timeout {
459             fail "print string in $target_charset (timeout)"
460         }
461     }
462
463     # Try entering a character literal, and see if it comes back unchanged.
464     gdb_test "print 'A'" \
465              " = \[0-9-\]+ 'A'" \
466              "parse character literal in ${target_charset}"
467
468     # Check that the character literal was encoded correctly.
469     gdb_test "print 'A' == $var_name\[7\]" \
470              " = 1" \
471              "check value of parsed character literal in ${target_charset}"
472
473     # Try entering a string literal, and see if it comes back unchanged.
474     gdb_test "print \"abcdefABCDEF012345\"" \
475              " = \"abcdefABCDEF012345\"" \
476              "parse string literal in ${target_charset}"
477
478     # Check that the string literal was encoded correctly.
479     gdb_test "print \"q\"\[0\] == $var_name\[49\]" \
480              " = 1" \
481              "check value of parsed string literal in ${target_charset}"
482
483     # Test handling of characters in the target charset which
484     # can't be translated into the host charset.
485     if {! [string compare $target_charset iso-8859-1]} {
486         gdb_test "print iso_8859_1_string\[69\]" \
487                  " = \[0-9-\]+ '\\\\242'" \
488                  "print character with no equivalent in host character set"
489         gdb_test "print iso_8859_1_string + 70" \
490                  " = ${hex} \"\\\\242.*\"" \
491                  "print string with no equivalent in host character set"
492     }
493
494     # Make sure that we don't apply the ISO-8859-1 `print_literally'
495     # function to ASCII.
496     if {! [string compare $target_charset ascii]} {
497         gdb_test "print iso_8859_1_string\[69\]" \
498                  " = \[0-9-\]+ '\\\\242'" \
499                  "print ASCII unprintable character"
500         gdb_test "print iso_8859_1_string + 70" \
501                  " = ${hex} \"\\\\242.*\"" \
502                  "print ASCII unprintable string"
503     }
504
505     # Try printing characters with backslash escape equivalents.
506     set escapees {a b f n r t v}
507     for {set i 0} {$i < [llength $escapees]} {incr i} {
508         set escape [lindex $escapees $i]
509         send_gdb "print $var_name\[$i\]\n"
510         set have_escape 1
511         gdb_expect {
512             -re "= \[0-9-\]+ '\\\\${escape}'\[\r\n\]+$gdb_prompt $" {
513                 pass "try printing '\\${escape}' in ${target_charset}"
514             }
515             -re "= \[0-9-\]+ 'x'\[\r\n\]+$gdb_prompt $" {
516                 xfail "try printing '\\${escape}' in ${target_charset} (no such escape)"
517                 set have_escape 0
518             }
519             -re "$gdb_prompt $" {
520                 fail "try printing '\\${escape}' in ${target_charset}"
521             }
522             timeout {
523                 fail "try printing '\\${escape}' in ${target_charset} (timeout)"
524             }
525         }
526
527         if {$have_escape} {
528
529             # Try parsing a backslash escape in a character literal.
530             gdb_test "print '\\${escape}' == $var_name\[$i\]" \
531                      " = 1" \
532                      "check value of '\\${escape}' in ${target_charset}"
533
534             # Try parsing a backslash escape in a string literal.
535             gdb_test "print \"\\${escape}\"\[0\] == $var_name\[$i\]" \
536                      " = 1" \
537                      "check value of \"\\${escape}\" in ${target_charset}"
538         }
539     }
540
541     # Try printing a character escape that doesn't exist.  We should 
542     # get the unescaped character, in the target character set.
543     gdb_test "print '\\q'" " = \[0-9-\]+ 'q'" \
544              "print escape that doesn't exist in $target_charset"
545     gdb_test "print '\\q' == $var_name\[49\]" " = 1" \
546              "check value of escape that doesn't exist in $target_charset"
547 }
548
549 gdb_exit