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