* src/pmc/scalar.pmc:
[parrot.git] / t / op / string_cs.t
blob7fe0ab288e247a61c3c90afea543ebc32e79f87e
1 #!perl
2 # Copyright (C) 2001-2005, The Perl Foundation.
3 # $Id$
5 use strict;
6 use warnings;
7 use lib qw( . lib ../lib ../../lib );
8 use Test::More;
9 use Parrot::Test tests => 50;
10 use Parrot::Config;
12 =head1 NAME
14 t/op/string_cs.t - String Charset Tests
16 =head1 SYNOPSIS
18         % prove t/op/string_cs.t
20 =head1 DESCRIPTION
22 Tests charset support.
24 =cut
26 pasm_output_is( <<'CODE', <<OUTPUT, "basic syntax" );
27     set S0, ascii:"ok 1\n"
28     print S0
29     set S0, binary:"ok 2\n"
30     print S0
31     set S0, iso-8859-1:"ok 3\n"
32     print S0
33     end
34 CODE
35 ok 1
36 ok 2
37 ok 3
38 OUTPUT
40 pasm_output_is( <<'CODE', <<OUTPUT, "charset name" );
41     set S0, "ok 1\n"
42     charset I0, S0
43     charsetname S1, I0
44     print S1
45     print "\n"
46     end
47 CODE
48 ascii
49 OUTPUT
51 pasm_output_is( <<'CODE', <<OUTPUT, "find_charset" );
52     find_charset I0, "iso-8859-1"
53     print "ok 1\n"
54     find_charset I0, "ascii"
55     print "ok 2\n"
56     find_charset I0, "binary"
57     print "ok 3\n"
58     end
59 CODE
60 ok 1
61 ok 2
62 ok 3
63 OUTPUT
65 pasm_output_like( <<'CODE', <<OUTPUT, "find_charset - not existing" );
66     find_charset I0, "no_such"
67     end
68 CODE
69 /charset 'no_such' not found/
70 OUTPUT
72 pasm_output_is( <<'CODE', <<OUTPUT, "downcase" );
73     set S0, iso-8859-1:"AEIOU_ÄÖÜ\n"
74     downcase S1, S0
75     print S1
76     end
77 CODE
78 aeiou_äöü
79 OUTPUT
81 pasm_output_is( <<'CODE', <<OUTPUT, "upcase" );
82     set S0, iso-8859-1:"aeiou_äöüß\n"
83     upcase S1, S0
84     print S1
85     end
86 CODE
87 AEIOU_ÄÖÜß
88 OUTPUT
90 pasm_output_is( <<'CODE', <<OUTPUT, "titlecase" );
91     set S0, iso-8859-1:"zAEIOU_ÄÖÜ\n"
92     titlecase S1, S0
93     print S1
94     end
95 CODE
96 Zaeiou_äöü
97 OUTPUT
99 pasm_output_is( <<'CODE', <<OUTPUT, "is_whitespace" );
100     set S0, iso-8859-1:"a\t\n \xa0" # is 0xa0 a whitespace in iso-8859-1??
101     .include "cclass.pasm"
102     is_cclass I0, .CCLASS_WHITESPACE, S0, 0
103     is_cclass I1, .CCLASS_WHITESPACE, S0, 1
104     is_cclass I2, .CCLASS_WHITESPACE, S0, 2
105     is_cclass I3, .CCLASS_WHITESPACE, S0, 3
106     set I4, 4
107     is_cclass I4, .CCLASS_WHITESPACE, S0, I4
108     print I0
109     print I1
110     print I2
111     print I3
112     print I4
113     print "\n"
114     set S0, ascii:"a\t\n "
115     is_cclass I0, .CCLASS_WHITESPACE, S0, 0
116     is_cclass I1, .CCLASS_WHITESPACE, S0, 1
117     is_cclass I2, .CCLASS_WHITESPACE, S0, 2
118     is_cclass I3, .CCLASS_WHITESPACE, S0, 3
119     is_cclass I4, .CCLASS_WHITESPACE, S0, 4 # access past string boundary: not a whitespace
120     print I0
121     print I1
122     print I2
123     print I3
124     print I4
125     print "\n"
126     end
127 CODE
128 01111
129 01110
130 OUTPUT
132 pasm_output_is( <<'CODE', <<OUTPUT, "is_wordchar" );
133     .include "cclass.pasm"
134     set S0, "az019-,._"
135     length I1, S0
136     set I2, 0
138     is_cclass I0, .CCLASS_WORD, S0, I2
139     print I0
140     inc I2
141     lt I2, I1, lp
142     print "\n"
143     end
144 CODE
145 111110001
146 OUTPUT
148 pasm_output_is( <<'CODE', <<OUTPUT, "is_digit" );
149     .include "cclass.pasm"
150     set S0, "az019-,._"
151     length I1, S0
152     set I2, 0
154     is_cclass I0, .CCLASS_NUMERIC, S0, I2
155     print I0
156     inc I2
157     lt I2, I1, lp
158     print "\n"
159     end
160 CODE
161 001110000
162 OUTPUT
164 pasm_output_is( <<'CODE', <<OUTPUT, "is_punctuation" );
165     .include "cclass.pasm"
166     set S0, "az019-,._"
167     length I1, S0
168     set I2, 0
170     is_cclass I0, .CCLASS_PUNCTUATION, S0, I2
171     print I0
172     inc I2
173     lt I2, I1, lp
174     print "\n"
175     end
176 CODE
177 000001111
178 OUTPUT
180 pasm_output_is( <<'CODE', <<OUTPUT, "is_newline" );
181     .include "cclass.pasm"
182     set S0, "a\n"
183     is_cclass I0, .CCLASS_NEWLINE, S0, 0
184     print I0
185     is_cclass I0, .CCLASS_NEWLINE, S0, 1
186     print I0
187     print "\n"
188     end
189 CODE
191 OUTPUT
193 pasm_output_is( <<'CODE', <<OUTPUT, "find_wordchar" );
194     .include "cclass.pasm"
195     set S0, "_ ab 09"
196     set I0, 0
197     length I1, S0
199     find_cclass I0, .CCLASS_WORD, S0, I0, I1
200     print I0
201     print " "
202     eq I0, I1, done
203     inc I0
204     branch lp
205 done:
206     print "ok\n"
207     end
208 CODE
209 0 2 3 5 6 7 ok
210 OUTPUT
212 pasm_output_is( <<'CODE', <<OUTPUT, "find_digit" );
213     .include "cclass.pasm"
214     set S0, "_ ab 09"
215     set I0, 0
216     length I1, S0
218     find_cclass I0, .CCLASS_NUMERIC, S0, I0, I1
219     print I0
220     print " "
221     eq I0, I1, done
222     inc I0
223     branch lp
224 done:
225     print "ok\n"
226     end
227 CODE
228 5 6 7 ok
229 OUTPUT
231 pasm_output_is( <<'CODE', <<OUTPUT, "find_punctuation" );
232     .include "cclass.pasm"
233     set S0, "_ .b ,9"
234     set I0, 0
235     length I1, S0
237     find_cclass I0, .CCLASS_PUNCTUATION, S0, I0, I1
238     print I0
239     print " "
240     eq I0, I1, done
241     inc I0
242     branch lp
243 done:
244     print "ok\n"
245     end
246 CODE
247 0 2 5 7 ok
248 OUTPUT
250 pasm_output_is( <<'CODE', <<OUTPUT, "trans_charset_s_s_i" );
251     set S0, "abc"
252     find_charset I0, "iso-8859-1"
253     trans_charset S1, S0, I0
254     print S1
255     print "\n"
256     charset I0, S1
257     charsetname S2, I0
258     print S2
259     print "\n"
260     end
261 CODE
263 iso-8859-1
264 OUTPUT
266 pasm_output_is( <<'CODE', <<OUTPUT, "trans_charset_s_i" );
267     set S1, "abc"
268     find_charset I0, "iso-8859-1"
269     trans_charset S1, I0
270     print S1
271     print "\n"
272     charset I0, S1
273     charsetname S2, I0
274     print S2
275     print "\n"
276     end
277 CODE
279 iso-8859-1
280 OUTPUT
282 pasm_output_like( <<'CODE', <<OUTPUT, "trans_charset_s_i - lossy" );
283     set S1, iso-8859-1:"abcä"
284     find_charset I0, "ascii"
285     trans_charset S1, I0
286     print "never\n"
287     end
288 CODE
289 /lossy conversion to ascii/
290 OUTPUT
292 pasm_output_is( <<'CODE', <<OUTPUT, "trans_charset_s_i - same" );
293     set S1, ascii:"abc"
294     find_charset I0, "ascii"
295     trans_charset S1, I0
296     print S1
297     print "\n"
298     charset I0, S1
299     charsetname S2, I0
300     print S2
301     print "\n"
302     end
303 CODE
305 ascii
306 OUTPUT
308 pasm_output_is( <<'CODE', <<OUTPUT, "trans_charset_s_s_i iso-8859-1 to binary" );
309     set S0, iso-8859-1:"abc"
310     find_charset I0, "binary"
311     trans_charset S1, S0, I0
312     print S1
313     print "\n"
314     charset I0, S1
315     charsetname S2, I0
316     print S2
317     print "\n"
318     end
319 CODE
321 binary
322 OUTPUT
324 pasm_output_is( <<'CODE', <<OUTPUT, "trans_charset_s_i iso-8859-1 to binary" );
325     set S1, iso-8859-1:"abc"
326     find_charset I0, "binary"
327     trans_charset S1, I0
328     print S1
329     print "\n"
330     charset I0, S1
331     charsetname S2, I0
332     print S2
333     print "\n"
334     end
335 CODE
337 binary
338 OUTPUT
340 pasm_output_is( <<'CODE', <<OUTPUT, "trans_charset_s_s_i ascii to binary" );
341     set S0, ascii:"abc"
342     find_charset I0, "binary"
343     trans_charset S1, S0, I0
344     print S1
345     print "\n"
346     charset I0, S1
347     charsetname S2, I0
348     print S2
349     print "\n"
350     end
351 CODE
353 binary
354 OUTPUT
356 pasm_output_is( <<'CODE', <<OUTPUT, "trans_charset_s_i ascii to binary" );
357     set S1, ascii:"abc"
358     find_charset I0, "binary"
359     trans_charset S1, I0
360     print S1
361     print "\n"
362     charset I0, S1
363     charsetname S2, I0
364     print S2
365     print "\n"
366     end
367 CODE
369 binary
370 OUTPUT
372 pasm_output_is( <<'CODE', <<OUTPUT, "trans_charset_s_s_i ascii to iso-8859-1" );
373     set S0, ascii:"abc"
374     find_charset I0, "iso-8859-1"
375     trans_charset S1, S0, I0
376     print S1
377     print "\n"
378     charset I0, S1
379     charsetname S2, I0
380     print S2
381     print "\n"
382     end
383 CODE
385 iso-8859-1
386 OUTPUT
388 pasm_output_is( <<'CODE', <<OUTPUT, "trans_charset_s_i ascii to iso-8859-1" );
389     set S1, ascii:"abc"
390     find_charset I0, "iso-8859-1"
391     trans_charset S1, I0
392     print S1
393     print "\n"
394     charset I0, S1
395     charsetname S2, I0
396     print S2
397     print "\n"
398     end
399 CODE
401 iso-8859-1
402 OUTPUT
404 pasm_output_is( <<'CODE', <<OUTPUT, "trans_charset_s_s_i iso-8859-1 to unicode" );
405     set S0, iso-8859-1:"abc_ä_"
406     find_charset I0, "unicode"
407     trans_charset S1, S0, I0
408     print S1
409     print "\n"
410     charset I0, S1
411     charsetname S2, I0
412     print S2
413     print "\n"
414     length I2, S1
415     print I2
416     print "\n"
417     end
418 CODE
419 abc_\xc3\xa4_
420 unicode
422 OUTPUT
424 pasm_output_is( <<'CODE', <<OUTPUT, "trans_charset_s_s_i unicode to iso-8859-1" );
425     set S0, unicode:"abc_\xe4_"
426     bytelength I2, S0   # XXX its 7 for utf8 only
427     print I2
428     print "\n"
429     find_charset I0, "iso-8859-1"
430     trans_charset S1, S0, I0
431     print S1
432     print "\n"
433     charset I0, S1
434     charsetname S2, I0
435     print S2
436     print "\n"
437     length I2, S1
438     print I2
439     print "\n"
440     end
441 CODE
443 abc_ä_
444 iso-8859-1
446 OUTPUT
448 pir_output_is( <<'CODE', <<'OUTPUT', "bug #34661 literal" );
449 .sub main :main
450     $S0 = unicode:"\"]\nif I3 == "
451     print "ok 1\n"
452 .end
453 CODE
454 ok 1
455 OUTPUT
457 pir_output_is( <<'CODE', <<'OUTPUT', "todo #34660 hash" );
458 .sub main :main
459     $P0 = new Integer
460     $P0 = 42
461     store_global "Foo", unicode:"Bar", $P0
462     print "ok 1\n"
463     $P1 = find_global "Foo", "Bar"
464     print "ok 2\n"
465     print $P1
466     print "\n"
467 .end
468 CODE
469 ok 1
470 ok 2
472 OUTPUT
474 pir_output_is( <<'CODE', <<'OUTPUT', "concat ascii, utf8" );
475 .sub main
476     .local string s, t, u
477     s = "abcd"
478     t = unicode:"efg\n"
479     u = s . t
480     print u
481     s = unicode:"abcd"
482     t = "efg\n"
483     u = s . t
484     print u
485 .end
486 CODE
487 abcdefg
488 abcdefg
489 OUTPUT
491 SKIP: {
492     skip( 'no ICU lib', 16 ) unless $PConfig{has_icu};
493     pasm_output_is( <<'CODE', <<"OUTPUT", "unicode downcase" );
494     set S0, iso-8859-1:"TÖTSCH"
495     find_charset I0, "unicode"
496     trans_charset S1, S0, I0
497     downcase S1
498     getstdout P0          # need to convert back to utf8
499     push P0, "utf8"       # push utf8 output layer
500     print S1
501     print "\n"
502     end
503 CODE
504 t\xc3\xb6tsch
505 OUTPUT
507     pasm_output_is( <<'CODE', <<"OUTPUT", "unicode downcase, trans_charset_s_i" );
508     set S0, iso-8859-1:"TÖTSCH"
509     find_charset I0, "unicode"
510     trans_charset S1, S0, I0
511     downcase S1
512     find_charset I0, "iso-8859-1"
513     trans_charset S1, I0
514     print S1
515     print "\n"
516     end
517 CODE
518 t\xf6tsch
519 OUTPUT
520     pasm_output_is( <<'CODE', <<"OUTPUT", "unicode downcase - transcharset" );
521     set S0, iso-8859-1:"TÖTSCH"
522     find_charset I0, "unicode"
523     trans_charset S1, S0, I0
524     downcase S1
525     find_encoding I0, "utf8"
526     trans_encoding S2, S1, I0
527     print S2
528     print "\n"
529     end
530 CODE
531 t\xc3\xb6tsch
532 OUTPUT
534     pasm_output_is( <<'CODE', <<"OUTPUT", "utf16 ord, length" );
535     set S0, iso-8859-1:"TÖTSCH"
536     find_charset I0, "unicode"
537     trans_charset S1, S0, I0
538     find_encoding I0, "utf16"
539     trans_encoding S1, S1, I0
540     length I1, S1
541     print I1
542     print "\n"
543     null I0
544 loop:
545     ord I2, S1, I0
546     print I2
547     print '_'
548     inc I0
549     lt I0, I1, loop
550     print "\n"
551     end
552 CODE
554 84_214_84_83_67_72_
555 OUTPUT
557     pasm_output_is( <<'CODE', <<"OUTPUT", "chopn utf8" );
558     set S0, iso-8859-1:"TTÖÖ"
559     find_charset I0, "unicode"
560     trans_charset S1, S0, I0
561     chopn S1, 2
562     print S1
563     print ' '
564     length I0, S1
565     print I0
566     print ' '
567     .include "stringinfo.pasm"
568     stringinfo I0, S1, .STRINGINFO_BUFUSED
569     print I0
570     print_newline
571     end
572 CODE
573 TT 2 2
574 OUTPUT
576     pasm_output_is( <<'CODE', <<"OUTPUT", "utf16 append" );
577     set S0, iso-8859-1:"Tötsch"
578     find_charset I0, "unicode"
579     trans_charset S1, S0, I0
580     find_encoding I0, "utf16"
581     trans_encoding S1, S1, I0
582     concat S1, " Leo"
583     length I0, S1
584     print I0
585     print ' '
586     .include "stringinfo.pasm"
587     stringinfo I0, S1, .STRINGINFO_BUFUSED
588     print I0
589     print_newline
590     find_encoding I0, "utf8"
591     trans_encoding S2, S1, I0
592     print S2
593     print "\n"
594     end
595 CODE
596 10 20
597 T\xc3\xb6tsch Leo
598 OUTPUT
600     pasm_output_is( <<'CODE', <<"OUTPUT", "utf16 concat" );
601     set S0, iso-8859-1:"Tötsch"
602     find_charset I0, "unicode"
603     trans_charset S1, S0, I0
604     find_encoding I0, "utf16"
605     trans_encoding S1, S1, I0
606     concat S2, S1, " Leo"
607     length I0, S2
608     print I0
609     print ' '
610     .include "stringinfo.pasm"
611     stringinfo I0, S2, .STRINGINFO_BUFUSED
612     print I0
613     print_newline
614     find_encoding I0, "utf8"
615     trans_encoding S2, S2, I0
616     print S2
617     print "\n"
618     end
619 CODE
620 10 20
621 T\xc3\xb6tsch Leo
622 OUTPUT
624     pasm_output_is( <<'CODE', <<"OUTPUT", "utf16 substr" );
625     set S0, iso-8859-1:"Tötsch"
626     find_charset I0, "unicode"
627     trans_charset S1, S0, I0
628     find_encoding I0, "utf16"
629     trans_encoding S1, S1, I0
630     substr S2, S1, 1, 2
631     find_encoding I0, "utf8"
632     trans_encoding S2, S2, I0
633     print S2
634     print "\n"
635     end
636 CODE
637 \xc3\xb6t
638 OUTPUT
640     pasm_output_is( <<'CODE', <<"OUTPUT", "utf16 replace" );
641     set S0, iso-8859-1:"Tötsch"
642     find_charset I0, "unicode"
643     trans_charset S1, S0, I0
644     find_encoding I0, "utf16"
645     trans_encoding S1, S1, I0
646     substr S2, S1, 1, 1, "oe"
647     find_encoding I0, "utf8"
648     trans_encoding S2, S2, I0
649     trans_encoding S1, S1, I0
650     print S2
651     print "\n"
652     print S1
653     print "\n"
654     end
655 CODE
656 \xc3\xb6
657 Toetsch
658 OUTPUT
660     pasm_output_is( <<'CODE', <<"OUTPUT", "utf16 index, latin1 search" );
661     set S0, iso-8859-1:"TÖTSCH"
662     find_charset I0, "unicode"
663     trans_charset S1, S0, I0
664     downcase S1
665     set S2, iso-8859-1:"öt"
666     index I0, S1, S2
667     print I0
668     print "\n"
669     end
670 CODE
672 OUTPUT
674     pasm_output_is( <<'CODE', <<"OUTPUT", "utf16 index, latin1 search" );
675     set S0, iso-8859-1:"TÖTSCH"
676     find_charset I0, "unicode"
677     trans_charset S1, S0, I0
678     downcase S1
679     set S2, iso-8859-1:"öt"
680     index I0, S1, S2
681     print I0
682     print "\n"
683     concat S1, S2
684     index I0, S1, S2, 2
685     print I0
686     print "\n"
687     end
688 CODE
691 OUTPUT
693     pasm_output_is( <<'CODE', <<"OUTPUT", "unicode upcase" );
694     set S0, iso-8859-1:"tötsch"
695     find_charset I0, "unicode"
696     trans_charset S1, S0, I0
697     upcase S1
698     getstdout P0          # need to convert back to utf8
699     push P0, "utf8"       # push utf8 output layer
700     print S1
701     print "\n"
702     end
703 CODE
704 T\x{c3}\x{96}TSCH
705 OUTPUT
707     pasm_output_is( <<'CODE', <<"OUTPUT", "unicode upcase to combined char" );
708     set S1, unicode:"hacek j \u01f0"
709     upcase S1
710     getstdout P0          # need to convert back to utf8
711     push P0, "utf8"       # push utf8 output layer
712     print S1
713     print "\n"
714     end
715 CODE
716 HACEK J J\xcc\x8c
717 OUTPUT
719     # charset/unicode.c
720     #
721     # 106         dest_len = u_strToUpper(src->strstart, dest_len,
722     # (gdb) p src_len
723     # $17 = 7
724     # (gdb) p dest_len
725     # $18 = 7
726     # (gdb) x /8h src->strstart
727     # 0x844fb60:      0x005f  0x005f  0x005f  0x01f0  0x0031  0x0032  0x0033  0x0000
728     # (gdb) n
729     # 110         src->bufused = dest_len * sizeof(UChar);
730     # (gdb) p dest_len
731     # $19 = 8
732     # (gdb) x /8h src->strstart
733     # 0x844fb60:      0x005f  0x005f  0x005f  0x004a  0x030c  0x0031  0x0032  0x0000
735     pasm_output_is( <<'CODE', <<"OUTPUT", "unicode upcase to combined char 3.2 bug?" );
736     set S1, unicode:"___\u01f0123"
737     upcase S1
738     getstdout P0          # need to convert back to utf8
739     push P0, "utf8"       # push utf8 output layer
740     print S1
741     print "\n"
742     end
743 CODE
744 ___J\xcc\x8c123
745 OUTPUT
747     pasm_output_is( <<'CODE', <<"OUTPUT", "unicode titlecase" );
748     set S0, iso-8859-1:"tötsch leo"
749     find_charset I0, "unicode"
750     trans_charset S1, S0, I0
751     titlecase S1
752     getstdout P0          # need to convert back to utf8
753     push P0, "utf8"       # push utf8 output layer
754     print S1
755     print "\n"
756     end
757 CODE
758 T\x{c3}\x{b6}tsch Leo
759 OUTPUT
761     pasm_output_is( <<'CODE', <<OUTPUT, "combose combined char" );
762     set S1, unicode:"___\u01f0___"
763     length I0, S1
764     upcase S1        # decompose J+hacek
765     length I1, S1    # 1 longer
766     downcase S1      # j+hacek
767     length I2, S1
768     compose S1, S1
769     length I3, S1    # back at original string
770     getstdout P0          # need to convert back to utf8
771     push P0, "utf8"       # push utf8 output layer
772     print S1
773     print "\n"
774     print I0
775     print ' '
776     print I1
777     print ' '
778     print I2
779     print ' '
780     print I3
781     print_newline
782     end
783 CODE
784 ___\x{c7}\x{b0}___
785 7 8 8 7
786 OUTPUT
788 }    # SKIP
790 pasm_output_is( <<'CODE', <<'OUTPUT', "escape ascii" );
791     set S0, "abcdefghi\n"
792     escape S1, S0
793     print S1
794     print "\n"
795     end
796 CODE
797 abcdefghi\n
798 OUTPUT
800 pasm_output_is( <<'CODE', <<'OUTPUT', "escape ctrl" );
801     set S0, "\x00\x01\x1f\x7f"
802     escape S1, S0
803     print S1
804     print "\n"
805     end
806 CODE
807 \x{0}\x{1}\x{1f}\x{7f}
808 OUTPUT
810 pasm_output_is( <<'CODE', <<'OUTPUT', "escape latin1" );
811     set S0, iso-8859-1:"tötsch leo"
812     escape S1, S0
813     print S1
814     print "\n"
815     end
816 CODE
817 t\x{f6}tsch leo
818 OUTPUT
820 pasm_output_is( <<'CODE', <<'OUTPUT', "escape unicode" );
821     set S0, unicode:"\u2001\u2002\u2003\u2004\x{e01ef}\u0114"
822     escape S1, S0
823     print S1
824     print "\n"
825     end
826 CODE
827 \u2001\u2002\u2003\u2004\x{e01ef}\u0114
828 OUTPUT
830 # Local Variables:
831 #   mode: cperl
832 #   cperl-indent-level: 4
833 #   fill-column: 100
834 # End:
835 # vim: expandtab shiftwidth=4: