tagged release 0.7.1
[parrot.git] / t / op / string.t
blob56f2824b5ee43b33d7b7d55341e3e04d3babdeb4
1 #!perl
2 # Copyright (C) 2001-2007, The Perl Foundation.
3 # $Id$
5 use strict;
6 use warnings;
7 use lib qw( . lib ../lib ../../lib );
9 use Test::More;
10 use Parrot::Test tests => 160;
11 use Parrot::Config;
13 =head1 NAME
15 t/op/string.t - Parrot Strings
17 =head1 SYNOPSIS
19      % prove t/op/string.t
21 =head1 DESCRIPTION
23 Tests Parrot string registers and operations.
25 =cut
27 pasm_output_is( <<'CODE', <<'OUTPUT', 'set_s_s|sc' );
28     set S4, "JAPH\n"
29     set     S5, S4
30     print   S4
31     print   S5
32     end
33 CODE
34 JAPH
35 JAPH
36 OUTPUT
38 pasm_output_is( <<'CODE', <<'OUTPUT', 'clone' );
39         set     S0, "Foo\n"
40     clone   S1, S0
41         print   S0
42     print   S1
44     clone   S1, "Bar\n"
45     print   S1
46         chopn   S1, 1   # Check that the contents of S1 are no longer constant
47     print   S1
48         print   "\n"
50     end
51 CODE
52 Foo
53 Foo
54 Bar
55 Bar
56 OUTPUT
58 pasm_output_is( <<'CODE', '4', 'length_i_s' );
59     set I4, 0
60     set S4, "JAPH"
61     length  I4, S4
62     print   I4
63     end
64 CODE
66 pasm_output_is( <<'CODE', '0', '0 length substr' );
67     set I4, 0
68     set S4, "JAPH"
69         substr  S3, S4, 1, 0
70     length  I4, S3
71         print   I4
72     end
73 CODE
75 pasm_output_is( <<'CODE', <<'OUTPUT', 'chopn with clone' );
76     set S4, "JAPHxyzw"
77     set S5, "japhXYZW"
78         clone   S3, S4
79     set S1, "\n"
80     set I1, 4
81     chopn   S4, 3
82     chopn   S4, 1
83         chopn   S5, I1
84     print   S4
85         print   S1
86     print   S5
87         print   S1
88     print   S3
89         print   S1
90     end
91 CODE
92 JAPH
93 japh
94 JAPHxyzw
95 OUTPUT
97 pasm_output_is( <<'CODE', <<'OUTPUT', 'chopn with set' );
98     set S4, "JAPHxyzw"
99     set S5, "japhXYZW"
100         set     S3, S4
101     set S1, "\n"
102     set I1, 4
103     chopn   S4, 3
104     chopn   S4, 1
105         chopn   S5, I1
106     print   S4
107         print   S1
108     print   S5
109         print   S1
110     print   S3
111         print   S1
112     end
113 CODE
114 JAPH
115 japh
116 JAPH
117 OUTPUT
119 pasm_output_is( <<'CODE', <<'OUTPUT', 'chopn, OOB values' );
120     set S1, "A string of length 21"
121     chopn   S1, 0
122     print   S1
123     print   "\n"
124     chopn   S1, 4
125     print   S1
126     print   "\n"
127     # -length cuts now
128     chopn   S1, -4
129     print   S1
130     print   "\n"
131     chopn   S1, 1000
132     print   S1
133     print   "** nothing **\n"
134     end
135 CODE
136 A string of length 21
137 A string of lengt
138 A st
139 ** nothing **
140 OUTPUT
142 pasm_output_is( <<'CODE', <<'OUTPUT', 'Three argument chopn' );
143     set S1, "Parrot"
145     chopn   S2, S1, 0
146     print   S1
147     print   "\n"
148     print   S2
149     print   "\n"
151     chopn   S2, S1, 1
152     print   S1
153     print   "\n"
154     print   S2
155     print   "\n"
157         set     I0, 2
158     chopn   S2, S1, I0
159     print   S1
160     print   "\n"
161     print   S2
162     print   "\n"
164     chopn   S2, "Parrot", 3
165     print   S2
166     print   "\n"
168     chopn   S1, S1, 5
169     print   S1
170     print   "\n"
172         set     S1, "Parrot"
173         set     S3, S1
174         chopn   S2, S1, 3
175         print   S3
176     print   "\n"
178         set     S3, S1
179         chopn   S1, 3
180         print   S3
181     print   "\n"
183     end
184 CODE
185 Parrot
186 Parrot
187 Parrot
188 Parro
189 Parrot
190 Parr
193 Parrot
195 OUTPUT
197 pasm_output_is( <<'CODE', <<'OUTPUT', 'Three argument chopn, OOB values' );
198     set S1, "Parrot"
200     chopn   S2, S1, 7
201     print   S1
202     print   "\n"
203     print   S2
204     print   "\n"
206     chopn   S2, S1, -1
207     print   S1
208     print   "\n"
209     print   S2
210     print   "\n"
212     end
213 CODE
214 Parrot
216 Parrot
218 OUTPUT
220 pasm_output_is( <<'CODE', <<'OUTPUT', 'substr_s_s|sc_i|ic_i|ic' );
221     set S4, "12345JAPH01"
222     set I4, 5
223     set I5, 4
224     substr  S5, S4, I4, I5
225     print   S5
226     substr S5, S4, I4, 4
227     print  S5
228     substr S5, S4, 5, I5
229     print  S5
230     substr S5, S4, 5, 4
231     print  S5
232     substr S5, "12345JAPH01", I4, I5
233     print  S5
234     substr S5, "12345JAPH01", I4, 4
235     print  S5
236     substr S5, "12345JAPH01", 5, I5
237     print  S5
238     substr S5, "12345JAPH01", 5, 4
239     print  S5
240     print  "\n"
241     end
242 CODE
243 JAPHJAPHJAPHJAPHJAPHJAPHJAPHJAPH
244 OUTPUT
246 # negative offsets
247 pasm_output_is( <<'CODE', <<'OUTPUT', 'neg substr offset' );
248     set S0, "A string of length 21"
249     set I0, -9
250     set I1, 6
251     substr S1, S0, I0, I1
252     print S0
253     print "\n"
254     print S1
255     print "\n"
256     end
257 CODE
258 A string of length 21
259 length
260 OUTPUT
262 # This asks for substring that shouldn't be allowed...
263 pasm_error_output_like( <<'CODE', <<'OUTPUT', 'substr OOB' );
264     set S0, "A string of length 21"
265     set I0, -99
266     set I1, 6
267     substr S1, S0, I0, I1
268     end
269 CODE
270 /^Cannot take substr outside string/
271 OUTPUT
273 # This asks for substring that shouldn't be allowed...
274 pasm_error_output_like( <<'CODE', <<'OUTPUT', 'substr OOB' );
275     set S0, "A string of length 21"
276     set I0, 99
277     set I1, 6
278     substr S1, S0, I0, I1
279     end
280 CODE
281 /^Cannot take substr outside string/
282 OUTPUT
284 # This asks for substring much greater than length of original string
285 pasm_output_is( <<'CODE', <<'OUTPUT', 'len>strlen' );
286     set S0, "A string of length 21"
287     set I0, 12
288     set I1, 1000
289     substr S1, S0, I0, I1
290     print  S0
291     print "\n"
292     print S1
293     print "\n"
294     end
295 CODE
296 A string of length 21
297 length 21
298 OUTPUT
300 # The same, with a negative offset
301 pasm_output_is( <<'CODE', <<'OUTPUT', 'len>strlen, -ve os' );
302     set S0, "A string of length 21"
303     set I0, -9
304     set I1, 1000
305     substr S1, S0, I0, I1
306     print S0
307     print "\n"
308     print S1
309     print "\n"
310     end
311 CODE
312 A string of length 21
313 length 21
314 OUTPUT
316 pasm_output_is( <<'CODE', <<'OUTPUT', '5 arg substr, replacement = length' );
317   set S0, "abcdefghijk"
318   set S1, "xyz"
319   substr S2, S0, 4, 3, S1
320   print S0
321   print "\n"
322   print S1
323   print "\n"
324   print S2
325   print "\n"
326   end
327 CODE
328 abcdxyzhijk
331 OUTPUT
333 pasm_output_is( <<'CODE', <<'OUTPUT', '5 arg substr, replacement > length' );
334   set S0, "abcdefghijk"
335   set S1, "xyz0123"
336   substr S2, S0, 4, 3, S1
337   print S0
338   print "\n"
339   print S1
340   print "\n"
341   print S2
342   print "\n"
343   end
344 CODE
345 abcdxyz0123hijk
346 xyz0123
348 OUTPUT
350 pasm_output_is( <<'CODE', <<'OUTPUT', '5 arg substr, replacement < length' );
351   set S0, "abcdefghijk"
352   set S1, "x"
353   substr S2, S0, 4, 3, S1
354   print S0
355   print "\n"
356   print S1
357   print "\n"
358   print S2
359   print "\n"
360   end
361 CODE
362 abcdxhijk
365 OUTPUT
367 pasm_output_is( <<'CODE', <<'OUTPUT', '5 arg substr, offset at end of string' );
368   set S0, "abcdefghijk"
369   set S1, "xyz"
370   substr S2, S0, 11, 3, S1
371   print S0
372   print "\n"
373   print S1
374   print "\n"
375   print S2
376   print "\n"
377   end
378 CODE
379 abcdefghijkxyz
382 OUTPUT
384 pasm_error_output_like( <<'CODE', <<'OUTPUT', '5 arg substr, offset past end of string' );
385   set S0, "abcdefghijk"
386   set S1, "xyz"
387   substr S2, S0, 12, 3, S1
388   print S0
389   print "\n"
390   print S1
391   print "\n"
392   print S2
393   print "\n"
394   end
395 CODE
396 /^Can only replace inside string or index after end of string/
397 OUTPUT
399 pasm_output_is( <<'CODE', <<'OUTPUT', '5 arg substr, -ve offset, repl=length' );
400   set S0, "abcdefghijk"
401   set S1, "xyz"
402   substr S2, S0, -3, 3, S1
403   print S0
404   print "\n"
405   print S1
406   print "\n"
407   print S2
408   print "\n"
409   end
410 CODE
411 abcdefghxyz
414 OUTPUT
416 pasm_output_is( <<'CODE', <<'OUTPUT', '5 arg substr, -ve offset, repl>length' );
417   set S0, "abcdefghijk"
418   set S1, "xyz"
419   substr S2, S0, -6, 2, S1
420   print S0
421   print "\n"
422   print S1
423   print "\n"
424   print S2
425   print "\n"
426   end
427 CODE
428 abcdexyzhijk
431 OUTPUT
433 pasm_output_is( <<'CODE', <<'OUTPUT', '5 arg substr, -ve offset, repl<length' );
434   set S0, "abcdefghijk"
435   set S1, "xyz"
436   substr S2, S0, -6, 4, S1
437   print S0
438   print "\n"
439   print S1
440   print "\n"
441   print S2
442   print "\n"
443   end
444 CODE
445 abcdexyzjk
447 fghi
448 OUTPUT
450 pasm_error_output_like( <<'CODE', <<'OUTPUT', '5 arg substr, -ve offset out of string' );
451   set S0, "abcdefghijk"
452   set S1, "xyz"
453   substr S2, S0, -12, 4, S1
454   print S0
455   print "\n"
456   print S1
457   print "\n"
458   print S2
459   print "\n"
460   end
461 CODE
462 /^Can only replace inside string or index after end of string/
463 OUTPUT
465 pasm_output_is( <<'CODE', <<'OUTPUT', '5 arg substr, length > strlen ' );
466   set S0, "abcdefghijk"
467   set S1, "xyz"
468   substr S2, S0, 3, 11, S1
469   print S0
470   print "\n"
471   print S1
472   print "\n"
473   print S2
474   print "\n"
475   end
476 CODE
477 abcxyz
479 defghijk
480 OUTPUT
482 pasm_output_is( <<'CODE', <<'OUTPUT', '5 arg substr, length > strlen, -ve offset' );
483   set S0, "abcdefghijk"
484   set S1, "xyz"
485   substr S2, S0, -3, 11, S1
486   print S0
487   print "\n"
488   print S1
489   print "\n"
490   print S2
491   print "\n"
492   end
493 CODE
494 abcdefghxyz
497 OUTPUT
499 pasm_output_is( <<'CODE', <<'OUTPUT', '4-arg, replacement-only substr' );
500   set S0, "abcdefghijk"
501   set S1, "xyz"
502   substr S0, 3, 3, S1
503   print S0
504   print "\n"
505   print S1
506   print "\n"
507   end
508 CODE
509 abcxyzghijk
511 OUTPUT
513 pasm_output_is( <<'CODE', 'PH', '3-arg substr' );
514   set S0, "JAPH"
515   substr S1, S0, 2
516   print S1
517   end
518 CODE
520 pasm_error_output_like( <<'CODE', <<'OUTPUT', "substr, +ve offset, zero-length string" );
521   set S0, ""
522   substr S1, S0, 10, 3
523   print S1
524   end
525 CODE
526 /Cannot take substr outside string/
527 OUTPUT
529 pasm_output_is( <<'CODE', <<'OUTPUT', 'substr, offset 0, zero-length string' );
530   set S0, ""
531   substr S1, S0, 0, 1
532   print S1
533   print "_\n"
534   end
535 CODE
537 OUTPUT
539 pasm_error_output_like( <<'CODE', <<'OUTPUT', "substr, offset -1, zero-length string" );
540   set S0, ""
541   substr S1, S0, -1, 1
542   print S1
543   end
544 CODE
545 /Cannot take substr outside string/
546 OUTPUT
548 pasm_error_output_like( <<'CODE', <<'OUTPUT', "substr, -ve offset, zero-length string" );
549   set S0, ""
550   substr S1, S0, -10, 5
551   print S1
552   end
553 CODE
554 /Cannot take substr outside string/
555 OUTPUT
557 pasm_output_is( <<'CODE', <<'OUTPUT', 'zero-length substr, zero-length string' );
558   set S0, ""
559   substr S1, S0, 10, 0
560   print S1
561   print "_\n"
562   end
563 CODE
565 OUTPUT
567 pasm_output_is( <<'CODE', <<'OUTPUT', 'zero-length substr, zero-length string' );
568   set S0, ""
569   substr S1, S0, -10, 0
570   print S1
571   print "_\n"
572   end
573 CODE
575 OUTPUT
577 pasm_output_is( <<'CODE', <<'OUTPUT', '3-arg substr, zero-length string' );
578   set S0, ""
579   substr S1, S0, 2
580   print S1
581   print "_\n"
582   end
583 CODE
585 OUTPUT
587 pasm_output_is( <<'CODE', <<'OUTPUT', '5 arg substr, zero-length string' );
588   set S0, ""
589   set S1, "xyz"
590   substr S2, S0, 0, 3, S1
591   print S0
592   print "\n"
593   print S1
594   print "\n"
595   print S2
596   print "\n"
598   set S3, ""
599   set S4, "abcde"
600   substr S5, S3, 0, 0, S4
601   print S3
602   print "\n"
603   print S4
604   print "\n"
605   print S5
606   print "\n"
607   end
608 CODE
612 abcde
613 abcde
615 OUTPUT
617 pasm_output_is( <<'CODE', <<'OUTPUT', '4 arg substr replace, zero-length string' );
618   set S0, ""
619   set S1, "xyz"
620   substr S0, 0, 3, S1
621   print S0
622   print "\n"
623   print S1
624   print "\n"
626   set S2, ""
627   set S3, "abcde"
628   substr S2, 0, 0, S3
629   print S2
630   print "\n"
631   print S3
632   print "\n"
633   end
634 CODE
637 abcde
638 abcde
639 OUTPUT
641 pasm_output_is( <<'CODE', '<><', 'concat_s_s|sc, null onto null' );
642  print "<>"
643  concat S0, S0
644  concat S1, ""
645  print "<"
646  end
647 CODE
649 pasm_output_is( <<'CODE', <<'OUTPUT', 'concat_s_sc, repeated two-arg concats' );
650   set S12, ""
651   set I0, 0
652 WHILE:
653   concat S12, "hi"
654   add I0, 1
655   lt I0, 10, WHILE
656   print S12
657   print "\n"
658   end
659 CODE
660 hihihihihihihihihihi
661 OUTPUT
663 pasm_output_is( <<'CODE', <<'OUTPUT', 'concat_s_s|sc, "foo1" onto null' );
664  concat S0, "foo1"
665  set S1, "foo2"
666  concat S2, S1
667  print S0
668  print "\n"
669  print S2
670  print "\n"
671  end
672 CODE
673 foo1
674 foo2
675 OUTPUT
677 pasm_output_is( <<'CODE', <<'OUTPUT', 'concat_s_s|sc' );
678     set S1, "fish"
679     set S2, "bone"
680     concat S1, S2
681     print S1
682     concat S1, "\n"
683     print S1
684     end
685 CODE
686 fishbonefishbone
687 OUTPUT
689 pasm_output_is( <<'CODE', <<'OUTPUT', 'concat_s_s|sc_s|sc' );
690     set S1, "japh"
691     set S2, "JAPH"
692     concat S0, "japh", "JAPH"
693     print S0
694     print "\n"
695     concat S0, S1, "JAPH"
696     print S0
697     print "\n"
698     concat S0, "japh", S2
699     print S0
700     print "\n"
701     concat S0, S1, S2
702     print S0
703     print "\n"
704     end
705 CODE
706 japhJAPH
707 japhJAPH
708 japhJAPH
709 japhJAPH
710 OUTPUT
712 pasm_output_is( <<'CODE', <<'OUTPUT', 'concat - ensure copy is made' );
713     set S2, "JAPH"
714     concat S0, S2, ""
715     concat S1, "", S2
716     chopn S0, 1
717     chopn S1, 1
718     print S2
719     print "\n"
720     end
721 CODE
722 JAPH
723 OUTPUT
725 pasm_output_is( <<"CODE", <<'OUTPUT', 'clears' );
726 @{[ set_str_regs( sub {"BOO $_[0]\\n"} ) ]}
727     clears
728 @{[ print_str_regs() ]}
729     print "done\\n"
730     end
731 CODE
732 done
733 OUTPUT
735 my @strings = (
736     "hello",   "hello", "hello", "world", "world", "hello", "hello", "hellooo",
737     "hellooo", "hello", "hello", "hella", "hella", "hello", "hella", "hellooo",
738     "hellooo", "hella", "hElLo", "HeLlO", "hElLo", "hElLo"
741 pasm_output_is( <<"CODE", <<'OUTPUT', 'eq_s_s_ic' );
742 @{[ compare_strings( 0, "eq", @strings ) ]}
743     print "ok\\n"
744     end
745 ERROR:
746     print "bad\\n"
747     end
748 CODE
750 OUTPUT
752 pasm_output_is( <<"CODE", <<'OUTPUT', 'eq_sc_s_ic' );
753 @{[ compare_strings( 1, "eq", @strings ) ]}
754     print "ok\\n"
755     end
756 ERROR:
757     print "bad\\n"
758     end
759 CODE
761 OUTPUT
763 pasm_output_is( <<"CODE", <<'OUTPUT', 'eq_s_sc_ic' );
764 @{[ compare_strings( 2, "eq", @strings ) ]}
765     print "ok\\n"
766     end
767 ERROR:
768     print "bad\\n"
769     end
770 CODE
772 OUTPUT
774 pasm_output_is( <<"CODE", <<'OUTPUT', 'eq_sc_sc_ic' );
775 @{[ compare_strings( 3, "eq", @strings ) ]}
776     print "ok\\n"
777     end
778 ERROR:
779     print "bad\\n"
780     end
781 CODE
783 OUTPUT
785 pasm_output_is( <<"CODE", <<'OUTPUT', 'ne_s_s_ic' );
786 @{[ compare_strings( 0, "ne", @strings ) ]}
787     print "ok\\n"
788     end
789 ERROR:
790     print "bad\\n"
791     end
792 CODE
794 OUTPUT
796 pasm_output_is( <<"CODE", <<'OUTPUT', 'ne_sc_s_ic' );
797 @{[ compare_strings( 1, "ne", @strings ) ]}
798     print "ok\\n"
799     end
800 ERROR:
801     print "bad\\n"
802     end
803 CODE
805 OUTPUT
807 pasm_output_is( <<"CODE", <<'OUTPUT', 'ne_s_sc_ic' );
808 @{[ compare_strings( 2, "ne", @strings ) ]}
809     print "ok\\n"
810     end
811 ERROR:
812     print "bad\\n"
813     end
814 CODE
816 OUTPUT
818 pasm_output_is( <<"CODE", <<'OUTPUT', 'ne_sc_sc_ic' );
819 @{[ compare_strings( 3, "ne", @strings ) ]}
820     print "ok\\n"
821     end
822 ERROR:
823     print "bad\\n"
824     end
825 CODE
827 OUTPUT
829 pasm_output_is( <<"CODE", <<'OUTPUT', 'lt_s_s_ic' );
830 @{[ compare_strings( 0, "lt", @strings ) ]}
831     print "ok\\n"
832     end
833 ERROR:
834     print "bad\\n"
835     end
836 CODE
838 OUTPUT
840 pasm_output_is( <<"CODE", <<'OUTPUT', 'lt_sc_s_ic' );
841 @{[ compare_strings( 1, "lt", @strings ) ]}
842     print "ok\\n"
843     end
844 ERROR:
845     print "bad\\n"
846     end
847 CODE
849 OUTPUT
851 pasm_output_is( <<"CODE", <<'OUTPUT', 'lt_s_sc_ic' );
852 @{[ compare_strings( 2, "lt", @strings ) ]}
853     print "ok\\n"
854     end
855 ERROR:
856     print "bad\\n"
857     end
858 CODE
860 OUTPUT
862 pasm_output_is( <<"CODE", <<'OUTPUT', 'lt_sc_sc_ic' );
863 @{[ compare_strings( 3, "lt", @strings ) ]}
864     print "ok\\n"
865     end
866 ERROR:
867     print "bad\\n"
868     end
869 CODE
871 OUTPUT
873 pasm_output_is( <<"CODE", <<'OUTPUT', 'le_s_s_ic' );
874 @{[ compare_strings( 0, "le", @strings ) ]}
875     print "ok\\n"
876     end
877 ERROR:
878     print "bad\\n"
879     end
880 CODE
882 OUTPUT
884 pasm_output_is( <<"CODE", <<'OUTPUT', 'le_sc_s_ic' );
885 @{[ compare_strings( 1, "le", @strings ) ]}
886     print "ok\\n"
887     end
888 ERROR:
889     print "bad\\n"
890     end
891 CODE
893 OUTPUT
895 pasm_output_is( <<"CODE", <<'OUTPUT', 'le_s_sc_ic' );
896 @{[ compare_strings( 2, "le", @strings ) ]}
897     print "ok\\n"
898     end
899 ERROR:
900     print "bad\\n"
901     end
902 CODE
904 OUTPUT
906 pasm_output_is( <<"CODE", <<'OUTPUT', 'le_sc_sc_ic' );
907 @{[ compare_strings( 3, "le", @strings ) ]}
908     print "ok\\n"
909     end
910 ERROR:
911     print "bad\\n"
912     end
913 CODE
915 OUTPUT
917 pasm_output_is( <<"CODE", <<'OUTPUT', 'gt_s_s_ic' );
918 @{[ compare_strings( 0, "gt", @strings ) ]}
919     print "ok\\n"
920     end
921 ERROR:
922     print "bad\\n"
923     end
924 CODE
926 OUTPUT
928 pasm_output_is( <<"CODE", <<'OUTPUT', 'gt_sc_s_ic' );
929 @{[ compare_strings( 1, "gt", @strings ) ]}
930     print "ok\\n"
931     end
932 ERROR:
933     print "bad\\n"
934     end
935 CODE
937 OUTPUT
939 pasm_output_is( <<"CODE", <<'OUTPUT', 'gt_s_sc_ic' );
940 @{[ compare_strings( 2, "gt", @strings ) ]}
941     print "ok\\n"
942     end
943 ERROR:
944     print "bad\\n"
945     end
946 CODE
948 OUTPUT
950 pasm_output_is( <<"CODE", <<'OUTPUT', 'gt_sc_sc_ic' );
951 @{[ compare_strings( 3, "gt", @strings ) ]}
952     print "ok\\n"
953     end
954 ERROR:
955     print "bad\\n"
956     end
957 CODE
959 OUTPUT
961 pasm_output_is( <<"CODE", <<'OUTPUT', 'ge_s_s_ic' );
962 @{[ compare_strings( 0, "ge", @strings ) ]}
963     print "ok\\n"
964     end
965 ERROR:
966     print "bad\\n"
967     end
968 CODE
970 OUTPUT
972 pasm_output_is( <<"CODE", <<'OUTPUT', 'ge_sc_s_ic' );
973 @{[ compare_strings( 1, "ge", @strings ) ]}
974     print "ok\\n"
975     end
976 ERROR:
977     print "bad\\n"
978     end
979 CODE
981 OUTPUT
983 pasm_output_is( <<"CODE", <<'OUTPUT', 'ge_s_sc_ic' );
984 @{[ compare_strings( 2, "ge", @strings ) ]}
985     print "ok\\n"
986     end
987 ERROR:
988     print "bad\\n"
989     end
990 CODE
992 OUTPUT
994 pasm_output_is( <<"CODE", <<'OUTPUT', 'ge_sc_sc_ic' );
995 @{[ compare_strings( 3, "ge", @strings ) ]}
996     print "ok\\n"
997     end
998 ERROR:
999     print "bad\\n"
1000     end
1001 CODE
1003 OUTPUT
1005 pasm_output_is( <<'CODE', <<'OUTPUT', 'same constant twice bug' );
1006        set     S0, ""
1007        set     S1, ""
1008        set     S2, "foo"
1009        concat  S1,S1,S2
1010        print   S1
1011        print   S0
1012        print   "\n"
1013        end
1014 CODE
1016 OUTPUT
1018 pasm_error_output_like( <<'CODE', <<'OUTPUT', '2-param ord, empty string' );
1019     ord I0,""
1020     print I0
1021     end
1022 CODE
1023 /^Cannot get character of empty string/
1024 OUTPUT
1026 pasm_error_output_like( <<'CODE', <<'OUTPUT', '2-param ord, empty string register' );
1027     ord I0,S0
1028     print I0
1029     end
1030 CODE
1031 /^Cannot get character of empty string/
1032 OUTPUT
1034 pasm_error_output_like( <<'CODE', <<'OUTPUT', '3-param ord, empty string' );
1035     ord I0,"",0
1036     print I0
1037     end
1038 CODE
1039 /^Cannot get character of empty string/
1040 OUTPUT
1042 pasm_error_output_like( <<'CODE', <<'OUTPUT', '3-param ord, empty string register' );
1043     ord I0,S0,0
1044     print I0
1045     end
1046 CODE
1047 /^Cannot get character of empty string/
1048 OUTPUT
1050 pasm_output_is( <<'CODE', ord('a'), '2-param ord, one-character string' );
1051     ord I0,"a"
1052     print I0
1053     end
1054 CODE
1056 pasm_output_is( <<'CODE', ord('a'), '2-param ord, multi-character string' );
1057     ord I0,"abc"
1058     print I0
1059     end
1060 CODE
1062 pasm_output_is( <<'CODE', ord('a'), '2-param ord, one-character string register' );
1063     set S0,"a"
1064     ord I0,S0
1065     print I0
1066     end
1067 CODE
1069 pasm_output_is( <<'CODE', ord('a'), '3-param ord, one-character string' );
1070     ord I0,"a",0
1071     print I0
1072     end
1073 CODE
1075 pasm_output_is( <<'CODE', ord('a'), '3-param ord, one-character string register' );
1076     set S0,"a"
1077     ord I0,S0,0
1078     print I0
1079     end
1080 CODE
1082 pasm_output_is( <<'CODE', ord('b'), '3-param ord, multi-character string' );
1083     ord I0,"ab",1
1084     print I0
1085     end
1086 CODE
1088 pasm_output_is( <<'CODE', ord('b'), '3-param ord, multi-character string register' );
1089     set S0,"ab"
1090     ord I0,S0,1
1091     print I0
1092     end
1093 CODE
1095 pasm_error_output_like( <<'CODE', <<'OUTPUT', '3-param ord, multi-character string' );
1096     ord I0,"ab",2
1097     print I0
1098     end
1099 CODE
1100 /^Cannot get character past end of string/
1101 OUTPUT
1103 pasm_error_output_like( <<'CODE', <<'OUTPUT', '3-param ord, multi-character string' );
1104     set S0,"ab"
1105     ord I0,S0,2
1106     print I0
1107     end
1108 CODE
1109 /^Cannot get character past end of string/
1110 OUTPUT
1112 pasm_output_is( <<'CODE', ord('a'), '3-param ord, one-character string, from end' );
1113     ord I0,"a",-1
1114     print I0
1115     end
1116 CODE
1118 pasm_output_is( <<'CODE', ord('a'), '3-param ord, one-character string register, from end' );
1119     set S0,"a"
1120     ord I0,S0,-1
1121     print I0
1122     end
1123 CODE
1125 pasm_output_is( <<'CODE', ord('b'), '3-param ord, multi-character string, from end' );
1126     ord I0,"ab",-1
1127     print I0
1128     end
1129 CODE
1131 pasm_output_is( <<'CODE', ord('b'), '3-param ord, multi-character string register, from end' );
1132     set S0,"ab"
1133     ord I0,S0,-1
1134     print I0
1135     end
1136 CODE
1138 pasm_error_output_like(
1139     <<'CODE', <<'OUTPUT', '3-param ord, multi-character string register, from end, OOB' );
1140     set S0,"ab"
1141     ord I0,S0,-3
1142     print I0
1143         end
1144 CODE
1145 /^Cannot get character before beginning of string/
1146 OUTPUT
1148 pasm_output_is( <<'CODE', chr(32), 'chr of 32 is space in ASCII' );
1149         chr S0, 32
1150         print S0
1151         end
1152 CODE
1154 pasm_output_is( <<'CODE', chr(65), 'chr of 65 is A in ASCII' );
1155         chr S0, 65
1156         print S0
1157         end
1158 CODE
1160 pasm_output_is( <<'CODE', chr(122), 'chr of 122 is z in ASCII' );
1161         chr S0, 122
1162         print S0
1163     end
1164 CODE
1166 pasm_output_is( <<'CODE', <<'OUTPUT', 'if_s_ic' );
1167     set S0, "I've told you once, I've told you twice..."
1168     if  S0, OK1
1169     print   "not "
1170 OK1:    print   "ok 1\n"
1172     set S0, "0.0"
1173     if  S0, OK2
1174     print   "not "
1175 OK2:    print   "ok 2\n"
1177     set S0, ""
1178     if  S0, BAD3
1179     branch OK3
1180 BAD3:   print   "not "
1181 OK3:    print   "ok 3\n"
1183     set S0, "0"
1184     if  S0, BAD4
1185     branch OK4
1186 BAD4:   print   "not "
1187 OK4:    print   "ok 4\n"
1189     set S0, "0e0"
1190     if  S0, OK5
1191     print   "not "
1192 OK5:    print   "ok 5\n"
1194     set S0, "x"
1195     if  S0, OK6
1196     print   "not "
1197 OK6:    print   "ok 6\n"
1199     set S0, "\\x0"
1200     if  S0, OK7
1201     print   "not "
1202 OK7:    print   "ok 7\n"
1204     set S0, "\n"
1205     if  S0, OK8
1206     print   "not "
1207 OK8:    print   "ok 8\n"
1209     set S0, " "
1210     if  S0, OK9
1211     print   "not "
1212 OK9:    print   "ok 9\n"
1214 # An empty register should be false...
1215         clears
1216         if      S1, BAD10
1217         branch  OK10
1218 BAD10:  print   "not "
1219 OK10:   print   "ok 10\n"
1221     end
1222 CODE
1223 ok 1
1224 ok 2
1225 ok 3
1226 ok 4
1227 ok 5
1228 ok 6
1229 ok 7
1230 ok 8
1231 ok 9
1232 ok 10
1233 OUTPUT
1235 pasm_output_is( <<'CODE', <<'OUTPUT', 'repeat_s_s|sc_i|ic' );
1236     set S0, "x"
1238     repeat S1, S0, 12
1239     print S0
1240     print "\n"
1241     print S1
1242     print "\n"
1244     set I0, 12
1245     set S2, "X"
1247     repeat S3, S2, I0
1248     print S2
1249     print "\n"
1250     print S3
1251     print "\n"
1253     repeat S4, "~", 12
1254     print S4
1255     print "\n"
1257     repeat S5, "~", I0
1258     print S5
1259     print "\n"
1261     print ">"
1262     repeat S6, "***", 0
1263     print S6
1264     print "< done\n"
1266     end
1267 CODE
1269 xxxxxxxxxxxx
1271 XXXXXXXXXXXX
1272 ~~~~~~~~~~~~
1273 ~~~~~~~~~~~~
1274 >< done
1275 OUTPUT
1277 pasm_error_output_like( <<'CODE', qr/Cannot repeat with negative arg\n/, 'repeat OOB' );
1278     repeat S0, "japh", -1
1279     end
1280 CODE
1282 pasm_output_is( <<'CODE', <<'OUTPUT', 'index, 3-arg form' );
1283       set S0, "Parrot"
1284       set S1, "Par"
1285       index I1, S0, S1
1286       print I1
1287       print "\n"
1289       set S1, "rot"
1290       index I1, S0, S1
1291       print I1
1292       print "\n"
1294       set S1, "bar"
1295       index I1, S0, S1
1296       print I1
1297       print "\n"
1299       end
1300 CODE
1304 OUTPUT
1306 pasm_output_is( <<'CODE', <<'OUTPUT', 'index, 4-arg form' );
1307       set S0, "Barbarian"
1308       set S1, "ar"
1309       index I1, S0, S1, 0
1310       print I1
1311       print "\n"
1313       index I1, S0, S1, 2
1314       print I1
1315       print "\n"
1317       set S1, "qwx"
1318       index I1, S0, S1, 0
1319       print I1
1320       print "\n"
1322       end
1323 CODE
1327 OUTPUT
1329 pasm_output_is( <<'CODE', <<'OUTPUT', 'index, 4-arg form, bug 22718' );
1330     set S1, "This is not quite right"
1331     set S0, " is "
1332     index I0, S1, S0, 0
1333     print I0
1334     set S0, "is"
1335     index I0, S1, S0, 0
1336     print I0
1337     print "\n"
1338     end
1339 CODE
1341 OUTPUT
1343 pasm_output_is( <<'CODE', <<'OUTPUT', 'index, null strings' );
1344       set S0, "Parrot"
1345       set S1, ""
1346       index I1, S0, S1
1347       print I1
1348       print "\n"
1350       index I1, S0, S1, 0
1351       print I1
1352       print "\n"
1354       index I1, S0, S1, 5
1355       print I1
1356       print "\n"
1358       index I1, S0, S1, 6
1359       print I1
1360       print "\n"
1362       set S0, ""
1363       set S1, "a"
1364       index I1, S0, S1
1365       print I1
1366       print "\n"
1368       index I1, S0, S1, 0
1369       print I1
1370       print "\n"
1372       set S0, "Parrot"
1373       null S1
1374       index I1, S0, S1
1375       print I1
1376       print "\n"
1378       null S0
1379       null S1
1380       index I1, S0, S1
1381       print I1
1382       print "\n"
1383       end
1384 CODE
1393 OUTPUT
1395 pasm_output_is( <<'CODE', <<'OUTPUT', 'index, embedded nulls' );
1396       set S0, "Par\0\0rot"
1397       set S1, "\0"
1398       index I1, S0, S1
1399       print I1
1400       print "\n"
1402       index I1, S0, S1, 4
1403       print I1
1404       print "\n"
1406       end
1407 CODE
1410 OUTPUT
1412 pasm_output_is( <<'CODE', <<'OUTPUT', 'index, big strings' );
1413       set S0, "a"
1414       repeat S0, S0, 10000
1415       set S1, "a"
1416       repeat S1, S1, 500
1417       index I1, S0, S1
1418       print I1
1419       print "\n"
1421       index I1, S0, S1, 1234
1422       print I1
1423       print "\n"
1425       index I1, S0, S1, 9501
1426       print I1
1427       print "\n"
1429       end
1430 CODE
1432 1234
1434 OUTPUT
1436 pasm_output_is( <<'CODE', <<'OUTPUT', 'index, big, hard to match strings' );
1437 # Builds a 24th iteration fibonacci string (approx. 100K)
1438       set S1, "a"
1439       set S2, "b"
1440       set I0, 0
1441 LOOP:
1442       set S3, S1
1443       concat S1, S2, S3
1444       set S2, S3
1445       inc I0
1446       lt I0, 24, LOOP
1448       index I1, S1, S2
1449       print I1
1450       print "\n"
1452       index I1, S1, S2, 50000
1453       print I1
1454       print "\n"
1455       end
1456 CODE
1457 46368
1459 OUTPUT
1461 pir_output_is( << 'CODE', << 'OUTPUT', 'index with different charsets' );
1463 .sub test :main
1465     print "default - default:\n"
1466     set S0, "Parrot"
1467     set S1, "rot"
1468     index I1, S0, S1
1469     print I1
1470     print "\n"
1472     print "ascii - ascii:\n"
1473     set S0, ascii:"Parrot"
1474     set S1, ascii:"rot"
1475     index I1, S0, S1
1476     print I1
1477     print "\n"
1479     print "default - ascii:\n"
1480     set S0, "Parrot"
1481     set S1, ascii:"rot"
1482     index I1, S0, S1
1483     print I1
1484     print "\n"
1486     print "ascii - default:\n"
1487     set S0, ascii:"Parrot"
1488     set S1, "rot"
1489     index I1, S0, S1
1490     print I1
1491     print "\n"
1493     print "binary - binary:\n"
1494     set S0, binary:"Parrot"
1495     set S1, binary:"rot"
1496     index I1, S0, S1
1497     print I1
1498     print "\n"
1500 .end
1501 CODE
1502 default - default:
1504 ascii - ascii:
1506 default - ascii:
1508 ascii - default:
1510 binary - binary:
1512 OUTPUT
1514 pasm_output_is( <<'CODE', <<'OUTPUT', 'negative index #35959' );
1515     index I1, "u", "t", -123456
1516     print I1
1517     print "\n"
1518     index I1, "u", "t", -123456789
1519     print I1
1520     print "\n"
1521     end
1522 CODE
1525 OUTPUT
1527 SKIP: {
1528     skip( "Pending rework of creating non-ascii literals", 2 );
1529     pasm_output_is( <<'CODE', <<'OUTPUT', 'index, multibyte matching' );
1530     set S0, "\xAB"
1531     find_chartype I0, "8859-1"
1532     set_chartype S0, I0
1533     find_encoding I0, "singlebyte"
1534     set_encoding S0, I0
1536     find_encoding I0, "utf8"
1537     find_chartype I1, "unicode"
1538     transcode S1, S0, I0, I1
1540     eq S0, S1, equal
1541     print "not "
1542 equal:
1543     print "equal\n"
1545     index I0, S0, S1
1546     print I0
1547     print "\n"
1548     index I0, S1, S0
1549     print I0
1550     print "\n"
1551     end
1552 CODE
1553 equal
1556 OUTPUT
1558     pasm_output_is( <<'CODE', <<'OUTPUT', 'index, multibyte matching 2' );
1559     set S0, "\xAB\xBA"
1560     set S1, "foo\xAB\xAB\xBAbar"
1561     find_chartype I0, "8859-1"
1562     set_chartype S0, I0
1563     find_encoding I0, "singlebyte"
1564     set_encoding S0, I0
1566     find_chartype I0, "unicode"
1567     find_encoding I1, "utf8"
1568     transcode S1, S1, I1, I0
1570     index I0, S0, S1
1571     print I0
1572     print "\n"
1573     index I0, S1, S0
1574     print I0
1575     print "\n"
1576     end
1577 CODE
1580 OUTPUT
1583 pasm_output_is( <<'CODE', <<'OUTPUT', 'num to string' );
1584     set N0, 80.43
1585     set S0, N0
1586     print S0
1587     print "\n"
1589     set N0, -1.111111
1590     set S0, N0
1591     print S0
1592     print "\n"
1593     end
1594 CODE
1595 80.43
1596 -1.11111
1597 OUTPUT
1599 pasm_output_is( <<'CODE', <<'OUTPUT', 'string to int' );
1600     set S0, "123"
1601     set I0, S0
1602     print   I0
1603     print   "\n"
1605     set S0, " 1"
1606     set I0, S0
1607     print   I0
1608     print   "\n"
1610     set S0, "-1"
1611     set I0, S0
1612     print   I0
1613     print   "\n"
1615         set     S0, "Not a number"
1616     set I0, S0
1617     print   I0
1618     print   "\n"
1620     set S0, ""
1621     set I0, S0
1622     print   I0
1623     print   "\n"
1625     end
1626 CODE
1632 OUTPUT
1634 pasm_output_is( <<'CODE', <<'OUTPUT', 'concat/substr (COW)' );
1635     set S0, "<JA"
1636     set S1, "PH>"
1637     set S2, ""
1638     concat S2, S2, S0
1639     concat S2, S2, S1
1640     print S2
1641     print "\n"
1642     substr S0, S2, 1, 4
1643     print S0
1644     print "\n"
1645     end
1646 CODE
1647 <JAPH>
1648 JAPH
1649 OUTPUT
1651 pasm_output_is( <<'CODE', <<'OUTPUT', 'constant to cstring' );
1652   stringinfo I0, "\n", 2
1653   stringinfo I1, "\n", 2
1654   eq I1, I0, ok1
1655   print "N"
1656 ok1:
1657   print "OK"
1658   print "\n"
1659   stringinfo I2, "\n", 2
1660   eq I2, I0, ok2
1661   print "N"
1662 ok2:
1663   print "OK\n"
1664   end
1665 CODE
1668 OUTPUT
1670 pasm_output_is( <<'CODE', <<'OUTPUT', 'COW with chopn leaving original untouched' );
1671   set S0, "ABCD"
1672   clone S1, S0
1673   chopn S0, 1
1674   print S0
1675   print "\n"
1676   print S1
1677   print "\n"
1678   end
1679 CODE
1681 ABCD
1682 OUTPUT
1684 pasm_output_is( <<'CODE', <<'OUTPUT', 'Check that bug #16874 was fixed' );
1685   set S0,  "foo     "
1686   set S1,  "bar     "
1687   set S2,  "quux    "
1688   set S15, ""
1689   concat S15, S0
1690   concat S15, S1
1691   concat S15, S2
1692   print "["
1693   print S15
1694   print "]\n"
1695   end
1696 CODE
1697 [foo     bar     quux    ]
1698 OUTPUT
1700 pasm_output_is( <<'CODE', "all ok\n", 'stress concat' );
1701  set I0, 1000
1702  set S0, "michael"
1703 LOOP:
1704  set S2, I0
1705  concat S1, S0, S2
1706  concat S3, "mic", "hael"
1707  concat S3, S3, S2
1708  eq S1, S3, BOTTOM
1709  print "Failed: "
1710  print S1
1711  print " ne "
1712  print S3
1713  print "\n"
1714  end
1715 BOTTOM:
1716  sub I0, I0, 1
1717  ne I0, 0, LOOP
1718  print "all ok\n"
1719  end
1720 CODE
1722 pasm_output_is( <<'CODE', <<'OUTPUT', 'ord and substring (see #17035)' );
1723   set S0, "abcdef"
1724   substr S1, S0, 2, 3
1725   ord I0, S0, 2
1726   ord I1, S1, 0
1727   ne I0, I1, fail
1728   ord I0, S0, 3
1729   ord I1, S1, 1
1730   ne I0, I1, fail
1731   ord I0, S0, 4
1732   ord I1, S1, 2
1733   ne I0, I1, fail
1734   print "It's all good\n"
1735   end
1736 fail:
1737   print "Not good: original string="
1738   print I0
1739   print ", substring="
1740   print I1
1741   print "\n"
1742   end
1743 CODE
1744 It's all good
1745 OUTPUT
1747 pasm_output_is( <<'CODE', <<'OUTPUT', 'sprintf' );
1748     branch MAIN
1750 NEWARYP:
1751     new P1, 'ResizablePMCArray'
1752     set P1[0], P0
1753     ret
1754 NEWARYS:
1755     new P1, 'ResizablePMCArray'
1756     set P1[0], S0
1757     ret
1758 NEWARYI:
1759     new P1, 'ResizablePMCArray'
1760     set P1[0], I0
1761     ret
1762 NEWARYN:
1763     new P1, 'ResizablePMCArray'
1764     set P1[0], N0
1765     ret
1766 PRINTF:
1767     sprintf S2, S1, P1
1768     print S2
1769     ret
1771 MAIN:
1772     set S1, "Hello, %s\n"
1773     set S0, "Parrot!"
1774     bsr NEWARYS
1775     bsr PRINTF
1777     set S1, "Hash[0x%x]\n"
1778     set I0, 256
1779     bsr NEWARYI
1780     bsr PRINTF
1782     set S1, "Hash[0x%lx]\n"
1783     set I0, 256
1784     bsr NEWARYI
1785     bsr PRINTF
1787     set S1, "Hello, %.2s!\n"
1788     set S0, "Parrot"
1789     bsr NEWARYS
1790     bsr PRINTF
1792     set S1, "Hello, %Ss"
1793     set S0, S2
1794     bsr NEWARYS
1795     bsr PRINTF
1797     set S1, "1 == %Pd\n"
1798     new P0, 'Integer'
1799     set P0, 1
1800     bsr NEWARYP
1801     bsr PRINTF
1803     set S1, "-255 == %vd\n"
1804     set I0, -255
1805     bsr NEWARYI
1806     bsr PRINTF
1808     set S1, "+123 == %+vd\n"
1809     set I0, 123
1810     bsr NEWARYI
1811     bsr PRINTF
1813     set S1, "256 == %vu\n"
1814     set I0, 256
1815     bsr NEWARYI
1816     bsr PRINTF
1818     set S1, "1 == %+vu\n"
1819     set I0, 1
1820     bsr NEWARYI
1821     bsr PRINTF
1823     set S1, "001 == %0.3u\n"
1824     set I0, 1
1825     bsr NEWARYI
1826     bsr PRINTF
1828     set S1, "001 == %+0.3u\n"
1829     set I0, 1
1830     bsr NEWARYI
1831     bsr PRINTF
1833     set S1, "0.500000 == %f\n"
1834     set N0, 0.5
1835     bsr NEWARYN
1836     bsr PRINTF
1838     set S1, "0.500 == %5.3f\n"
1839     set N0, 0.5
1840     bsr NEWARYN
1841     bsr PRINTF
1843     set S1, "0.001 == %g\n"
1844     set N0, 0.001
1845     bsr NEWARYN
1846     bsr PRINTF
1848     set S1, "1e+06 == %g\n"
1849     set N0, 1.0e6
1850     bsr NEWARYN
1851     bsr PRINTF
1853     set S1, "0.5 == %3.3g\n"
1854     set N0, 0.5
1855     bsr NEWARYN
1856     bsr PRINTF
1858     set S1, "%% == %%\n"
1859     set I0, 0
1860     bsr NEWARYI
1861     bsr PRINTF
1863     set S1, "That's all, %s\n"
1864     set S0, "folks!"
1865     bsr NEWARYS
1866     bsr PRINTF
1868     end
1869 CODE
1870 Hello, Parrot!
1871 Hash[0x100]
1872 Hash[0x100]
1873 Hello, Pa!
1874 Hello, Hello, Pa!
1875 1 == 1
1876 -255 == -255
1877 +123 == +123
1878 256 == 256
1879 1 == 1
1880 001 == 001
1881 001 == 001
1882 0.500000 == 0.500000
1883 0.500 == 0.500
1884 0.001 == 0.001
1885 1e+06 == 1e+06
1886 0.5 == 0.5
1887 % == %
1888 That's all, folks!
1889 OUTPUT
1891 pasm_output_is( <<'CODE', <<'OUTPUT', 'other form of sprintf op' );
1892     branch MAIN
1894 PRINTF:
1895     sprintf P3, P2, P1
1896     print P3
1897     ret
1899 MAIN:
1900     new P3, 'String'
1902     new P2, 'String'
1903     set P2, "15 is %b\n"
1904     new P1, 'ResizablePMCArray'
1905     set P1[0], 15
1906     bsr PRINTF
1908     new P2, 'String'
1909     set P2, "128 is %o\n"
1910     new P1, 'ResizablePMCArray'
1911     set P1[0], 128
1912     bsr PRINTF
1914     end
1915 CODE
1916 15 is 1111
1917 128 is 200
1918 OUTPUT
1920 pir_output_is( <<'CODE', <<'OUTPUT', 'sprintf - left justify' );
1921 .sub main :main
1922   $P0 = new 'ResizablePMCArray'
1923   $P1 = new 'Integer'
1924   $P1 = 10
1925   $P0[0] = $P1
1926   $P1 = new 'String'
1927   $P1 = "foo"
1928   $P0[1] = $P1
1929   $P1 = new 'String'
1930   $P1 = "bar"
1931   $P0[2] = $P1
1932   $S0 = sprintf "%-*s - %s\n", $P0
1933   print $S0
1934   end
1935 .end
1936 CODE
1937 foo        - bar
1938 OUTPUT
1941     my $output = substr( ( 'f' x ( $PConfig{intvalsize} * 2 ) ) . ( ' ' x 20 ), 0, 20 );
1942     pir_output_is( <<'CODE', $output, 'Correct precision for %x' ); }
1943 .sub main :main
1944   $P0 = new 'ResizablePMCArray'
1945   $P0[0] = -1
1946   $S0 = sprintf "%-20x", $P0
1947   print $S0
1948   end
1949 .end
1950 CODE
1952 pasm_output_is( <<'CODE', <<'OUTPUT', 'exchange' );
1953     set S0, "String #0\n"
1954     set S1, "String #1\n"
1955     exchange S0, S1
1956     print S0
1957     print S1
1959     set S2, "String #2\n"
1960     exchange S2, S2
1961     print S2
1963     end
1964 CODE
1965 String #1
1966 String #0
1967 String #2
1968 OUTPUT
1970 SKIP: {
1971     skip( "Peding reimplementation of find_encoding", 1 );
1972     pasm_output_is( <<'CODE', <<'OUTPUT', 'find_encoding' );
1973       find_encoding I0, "singlebyte"
1974       print I0
1975       print "\n"
1976       find_encoding I0, "utf8"
1977       print I0
1978       print "\n"
1979       find_encoding I0, "utf16"
1980       print I0
1981       print "\n"
1982       find_encoding I0, "utf32"
1983       print I0
1984       print "\n"
1985       end
1986 CODE
1991 OUTPUT
1994 SKIP: {
1995     skip( "no more visible encoding", 1 );
1996     pasm_output_is( <<'CODE', <<'OUTPUT', 'string_encoding' );
1997       set I0, 0
1998       new S0, 0, I0
1999       string_encoding I1, S0
2000       eq I0, I1, OK1
2001       print "not "
2002 OK1:  print "ok 1\n"
2004       set I0, 1
2005       new S0, 0, I0
2006       string_encoding I1, S0
2007       eq I0, I1, OK2
2008       print "not "
2009 OK2:  print "ok 2\n"
2011       set I0, 2
2012       new S0, 0, I0
2013       string_encoding I1, S0
2014       eq I0, I1, OK3
2015       print "not "
2016 OK3:  print "ok 3\n"
2018       set I0, 3
2019       new S0, 0, I0
2020       string_encoding I1, S0
2021       eq I0, I1, OK4
2022       print "not "
2023 OK4:  print "ok 4\n"
2025       end
2026 CODE
2027 ok 1
2028 ok 2
2029 ok 3
2030 ok 4
2031 OUTPUT
2034 pasm_output_is( <<'CODE', <<'OUTPUT', 'experimental opcode substr_r_s_s|sc_i|ic_i|ic' );
2035     set S4, "12345JAPH01"
2036     set I4, 5
2037     set I5, 4
2038     substr_r    S5, S4, I4, I5
2039     print   S5
2040     substr_r S5, S4, I4, 4
2041     print  S5
2042     substr_r S5, S4, 5, I5
2043     print  S5
2044     substr_r S5, S4, 5, 4
2045     print  S5
2046     substr_r S5, "12345JAPH01", I4, I5
2047     print  S5
2048     substr_r S5, "12345JAPH01", I4, 4
2049     print  S5
2050     substr_r S5, "12345JAPH01", 5, I5
2051     print  S5
2052     substr_r S5, "12345JAPH01", 5, 4
2053     print  S5
2054     print  "\n"
2055     end
2056 CODE
2057 JAPHJAPHJAPHJAPHJAPHJAPHJAPHJAPH
2058 OUTPUT
2060 pasm_output_is( <<'CODE', <<'OUTPUT', 'assign' );
2061     set S4, "JAPH\n"
2062     assign  S5, S4
2063     print   S4
2064     print   S5
2065     end
2066 CODE
2067 JAPH
2068 JAPH
2069 OUTPUT
2071 pasm_output_is( <<'CODE', <<'OUTPUT', 'assign & globber' );
2072     set S4, "JAPH\n"
2073     assign  S5, S4
2074     assign  S4, "Parrot\n"
2075     print   S4
2076     print   S5
2077     end
2078 CODE
2079 Parrot
2080 JAPH
2081 OUTPUT
2083 pasm_output_is( <<'CODE', <<'OUTPUT', 'assign & globber 2' );
2084     set S4, "JAPH\n"
2085     set     S5, S4
2086     assign  S4, "Parrot\n"
2087     print   S4
2088     print   S5
2089     end
2090 CODE
2091 Parrot
2092 Parrot
2093 OUTPUT
2095 pasm_output_is( <<'CODE', <<'OUTPUT', 'bands NULL string' );
2096     null S1
2097     set S2, "abc"
2098     bands S1, S2
2099     null S3
2100     eq S1, S3, ok1
2101     print "not "
2102 ok1:    print "ok 1\n"
2103     set S1, ""
2104     bands S1, S2
2105     unless S1, ok2
2106     print "not "
2107 ok2:    print "ok 2\n"
2109     null S2
2110     set S1, "abc"
2111     bands S1, S2
2112     null S3
2113     eq S1, S3, ok3
2114     print "not "
2115 ok3:    print "ok 3\n"
2116     set S2, ""
2117     bands S1, S2
2118     unless S1, ok4
2119     print "not "
2120 ok4:    print "ok 4\n"
2121     end
2122 CODE
2123 ok 1
2124 ok 2
2125 ok 3
2126 ok 4
2127 OUTPUT
2129 pasm_output_is( <<'CODE', <<'OUTPUT', 'bands 2' );
2130     set S1, "abc"
2131     set S2, "EE"
2132     bands S1, S2
2133     print S1
2134     print "\n"
2135     print S2
2136     print "\n"
2137     end
2138 CODE
2141 OUTPUT
2143 pasm_output_is( <<'CODE', <<'OUTPUT', 'bands 3' );
2144     set S1, "abc"
2145     set S2, "EE"
2146     bands S0, S1, S2
2147     print S0
2148     print "\n"
2149     print S1
2150     print "\n"
2151     print S2
2152     print "\n"
2153     end
2154 CODE
2158 OUTPUT
2160 pasm_output_is( <<'CODE', <<'OUTPUT', 'bands COW' );
2161   set S1, "foo"
2162   substr S2, S1, 0, 3
2163   bands S1, "bar"
2164   print S2
2165   print "\n"
2166   end
2167 CODE
2169 OUTPUT
2171 pasm_output_is( <<'CODE', <<'OUTPUT', 'bors NULL string' );
2172      null S1
2173      null S2
2174      bors S1, S2
2175      null S3
2176      eq S1, S3, OK1
2177      print "not "
2178 OK1: print "ok 1\n"
2180      null S1
2181      set S2, ""
2182      bors S1, S2
2183      null S3
2184      eq S1, S3, OK2
2185      print "not "
2186 OK2: print "ok 2\n"
2187      bors S2, S1
2188      eq S2, S3, OK3
2189      print "not "
2190 OK3: print "ok 3\n"
2192      null S1
2193      set S2, "def"
2194      bors S1, S2
2195      eq S1, "def", OK4
2196      print "not "
2197 OK4: print "ok 4\n"
2198      null S2
2199      bors S1, S2
2200      eq S1, "def", OK5
2201      print "not "
2202 OK5: print "ok 5\n"
2204      null S1
2205      null S2
2206      bors S3, S1, S2
2207      null S4
2208      eq S3, S4, OK6
2209      print "not "
2210 OK6: print "ok 6\n"
2212      set S1, ""
2213      bors S3, S1, S2
2214      eq S3, S4, OK7
2215      print "not "
2216 OK7: print "ok 7\n"
2217      bors S3, S2, S1
2218      eq S3, S4, OK8
2219      print "not "
2220 OK8: print "ok 8\n"
2222      set S1, "def"
2223      bors S3, S1, S2
2224      eq S3, "def", OK9
2225      print "not "
2226 OK9: print "ok 9\n"
2227      bors S3, S2, S1
2228      eq S3, "def", OK10
2229      print "not "
2230 OK10: print "ok 10\n"
2231      end
2232 CODE
2233 ok 1
2234 ok 2
2235 ok 3
2236 ok 4
2237 ok 5
2238 ok 6
2239 ok 7
2240 ok 8
2241 ok 9
2242 ok 10
2243 OUTPUT
2245 pasm_output_is( <<'CODE', <<'OUTPUT', 'bors 2' );
2246     set S1, "abc"
2247     set S2, "EE"
2248     bors S1, S2
2249     print S1
2250     print "\n"
2251     print S2
2252     print "\n"
2253     end
2254 CODE
2257 OUTPUT
2259 pasm_output_is( <<'CODE', <<'OUTPUT', 'bors 3' );
2260     set S1, "abc"
2261     set S2, "EE"
2262     bors S0, S1, S2
2263     print S0
2264     print "\n"
2265     print S1
2266     print "\n"
2267     print S2
2268     print "\n"
2269     end
2270 CODE
2274 OUTPUT
2276 pasm_output_is( <<'CODE', <<'OUTPUT', 'bors COW' );
2277   set S1, "foo"
2278   substr S2, S1, 0, 3
2279   bors S1, "bar"
2280   print S2
2281   print "\n"
2282   end
2283 CODE
2285 OUTPUT
2287 pasm_output_is( <<'CODE', <<'OUTPUT', 'bxors NULL string' );
2288      null S1
2289      null S2
2290      bxors S1, S2
2291      null S3
2292      eq S1, S3, OK1
2293      print "not "
2294 OK1: print "ok 1\n"
2296      null S1
2297      set S2, ""
2298      bxors S1, S2
2299      null S3
2300      eq S1, S3, OK2
2301      print "not "
2302 OK2: print "ok 2\n"
2303      bxors S2, S1
2304      eq S2, S3, OK3
2305      print "not "
2306 OK3: print "ok 3\n"
2308      null S1
2309      set S2, "abc"
2310      bxors S1, S2
2311      eq S1, "abc", OK4
2312      print "not "
2313 OK4: print "ok 4\n"
2314      null S2
2315      bxors S1, S2
2316      eq S1, "abc", OK5
2317      print "not "
2318 OK5: print "ok 5\n"
2320      null S1
2321      null S2
2322      bxors S3, S1, S2
2323      null S4
2324      eq S3, S4, OK6
2325      print "not "
2326 OK6: print "ok 6\n"
2328      set S1, ""
2329      bxors S3, S1, S2
2330      eq S3, S4, OK7
2331      print "not "
2332 OK7: print "ok 7\n"
2333      bxors S3, S2, S1
2334      eq S3, S4, OK8
2335      print "not "
2336 OK8: print "ok 8\n"
2338      set S1, "abc"
2339      bxors S3, S1, S2
2340      eq S3, "abc", OK9
2341      print "not "
2342 OK9: print "ok 9\n"
2343      bxors S3, S2, S1
2344      eq S3, "abc", OK10
2345      print "not "
2346 OK10: print "ok 10\n"
2347      end
2348 CODE
2349 ok 1
2350 ok 2
2351 ok 3
2352 ok 4
2353 ok 5
2354 ok 6
2355 ok 7
2356 ok 8
2357 ok 9
2358 ok 10
2359 OUTPUT
2361 pasm_output_is( <<'CODE', <<'OUTPUT', 'bxors 2' );
2362  set S1, "a2c"
2363  set S2, "Dw"
2364  bxors S1, S2
2365  print S1
2366  print "\n"
2367  print S2
2368  print "\n"
2369     set S1, "abc"
2370     set S2, "   X"
2371     bxors S1, S2
2372     print S1
2373  print "\n"
2374  print S2
2375  print "\n"
2376  end
2377 CODE
2380 ABCX
2381    X
2382 OUTPUT
2384 pasm_output_is( <<'CODE', <<'OUTPUT', 'bxors 3' );
2385  set S1, "a2c"
2386  set S2, "Dw"
2387  bxors S0, S1, S2
2388  print S0
2389  print "\n"
2390  print S1
2391  print "\n"
2392  print S2
2393  print "\n"
2394     set S1, "abc"
2395     set S2, "   Y"
2396     bxors S0, S1, S2
2397  print S0
2398  print "\n"
2399     print S1
2400  print "\n"
2401  print S2
2402  print "\n"
2403  end
2404 CODE
2408 ABCY
2410    Y
2411 OUTPUT
2413 pasm_output_is( <<'CODE', <<'OUTPUT', 'bxors COW' );
2414   set S1, "foo"
2415   substr S2, S1, 0, 3
2416   bxors S1, "bar"
2417   print S2
2418   print "\n"
2419   end
2420 CODE
2422 OUTPUT
2424 pasm_output_is( <<'CODE', <<'OUTPUT', 'bnots NULL string' );
2425      null S1
2426      null S2
2427      bnots S1, S2
2428      null S3
2429      eq S1, S3, OK1
2430      print "not "
2431 OK1: print "ok 1\n"
2433      null S1
2434      set S2, ""
2435      bnots S1, S2
2436      null S3
2437      eq S1, S3, OK2
2438      print "not "
2439 OK2: print "ok 2\n"
2440      bnots S2, S1
2441      eq S2, S3, OK3
2442      print "not "
2443 OK3: print "ok 3\n"
2444      end
2445 CODE
2446 ok 1
2447 ok 2
2448 ok 3
2449 OUTPUT
2451 SKIP: {
2452     skip( "No unicode yet", 1 );
2453     pasm_output_is( <<'CODE', <<'OUTPUT', 'bnots 2' );
2454  getstdout P0
2455  push P0, "utf8"
2456  set S1, "a2c"
2457  bnots S2, S1
2458  print S1
2459  print "\n"
2460  print S2
2461  print "\n"
2462  bnots S1, S1
2463  print S1
2464  print "\n"
2465  bnots S1, S1
2466  print S1
2467  print "\n"
2468  end
2469 CODE
2471 \xC2\x9E\xC3\x8D\xC2\x9C
2472 \xC2\x9E\xC3\x8D\xC2\x9C
2474 OUTPUT
2477 pasm_output_is( <<'CODE', <<'OUTPUT', 'bnots COW' );
2478   set S1, "foo"
2479   substr S2, S1, 0, 3
2480   bnots S1, S1
2481   print S2
2482   print "\n"
2483   end
2484 CODE
2486 OUTPUT
2488 SKIP: {
2489     skip( "no more transcode", 1 );
2490     pasm_output_is( <<'CODE', <<'OUTPUT', 'transcode to utf8' );
2491   set S1, "ASCII is the same as UTF8\n"
2492   find_encoding I1, "utf8"
2493   transcode S2, S1, I1
2494   print S1
2495   print S2
2496   end
2497 CODE
2498 ASCII is the same as UTF8
2499 ASCII is the same as UTF8
2500 OUTPUT
2503 SKIP: {
2504     skip( "no more chartype", 1 );
2505     pasm_output_is( <<'CODE', <<'OUTPUT', 'string_chartype' );
2506     set S0, "Test String"
2507     find_chartype I0, "usascii"
2508     set_chartype S0, I0
2509     string_chartype I1, S0
2510     eq I1, I0, OK
2511     print I0
2512     print "\n"
2513     print I1
2514     print "\n"
2515     print "not "
2516 OK: print "ok\n"
2517     end
2518 CODE
2520 OUTPUT
2523 # Set all string registers to values given by &$_[0](reg num)
2524 sub set_str_regs {
2525     my $code = shift;
2526     my $rt;
2527     for ( 0 .. 31 ) {
2528         $rt .= "\tset S$_, \"" . &$code($_) . "\"\n";
2529     }
2530     return $rt;
2533 # print string registers, no additional prints
2534 sub print_str_regs {
2535     my $rt;
2536     for ( 0 .. 31 ) {
2537         $rt .= "\tprint S$_\n";
2538     }
2539     return $rt;
2542 # Generate code to compare each pair of strings in a list
2543 sub compare_strings {
2544     my $const   = shift;
2545     my $op      = shift;
2546     my @strings = @_;
2547     my $i       = 1;
2548     my $rt;
2549     while (@strings) {
2550         my $s1 = shift @strings;
2551         my $s2 = shift @strings;
2552         my $arg1;
2553         my $arg2;
2554         if ( $const == 3 ) {
2555             $arg1 = "\"$s1\"";
2556             $arg2 = "\"$s2\"";
2557         }
2558         elsif ( $const == 2 ) {
2559             $rt .= "    set S0, \"$s1\"\n";
2560             $arg1 = "S0";
2561             $arg2 = "\"$s2\"";
2562         }
2563         elsif ( $const == 1 ) {
2564             $rt .= "    set S0, \"$s2\"\n";
2565             $arg1 = "\"$s1\"";
2566             $arg2 = "S0";
2567         }
2568         else {
2569             $rt .= "    set S0, \"$s1\"\n";
2570             $rt .= "    set S1, \"$s2\"\n";
2571             $arg1 = "S0";
2572             $arg2 = "S1";
2573         }
2574         if ( eval "\"$s1\" $op \"$s2\"" ) {
2575             $rt .= "    $op $arg1, $arg2, OK$i\n";
2576             $rt .= "    branch ERROR\n";
2577         }
2578         else {
2579             $rt .= "    $op $arg1, $arg2, ERROR\n";
2580         }
2581         $rt .= "OK$i:\n";
2582         $i++;
2583     }
2584     return $rt;
2587 pasm_output_is( <<'CODE', <<'OUTPUT', 'split on empty string' );
2588 _main:
2589     split P1, "", ""
2590     set I1, P1
2591     print I1
2592     print "\n"
2593     split P0, "", "ab"
2594     set I0, P0
2595     print I0
2596     print "\n"
2597     set S0, P0[0]
2598     print S0
2599     set S0, P0[1]
2600     print S0
2601     print "\n"
2602     end
2603 CODE
2607 OUTPUT
2609 pasm_output_is( <<'CODE', <<'OUTPUT', 'split on non-empty string' );
2610 _main:
2611     split P0, "a", "afooabara"
2612     set I0, P0
2613     print I0
2614     print "\n"
2615     set I1, 0
2616 loop:
2617     set S0, P0[I1]
2618     print S0
2619     print "\n"
2620     inc I1
2621     sub I2, I1, I0
2622     if I2, loop
2623     end
2624 CODE
2631 OUTPUT
2633 pasm_output_is( <<'CODE', <<'OUTPUT', 'join' );
2634 _main:
2635     new P0, 'ResizablePMCArray'
2636     join S0, "--", P0
2637     print S0
2638     print "\n"
2639     push P0, "a"
2640     join S0, "--", P0
2641     print S0
2642     print "\n"
2643     new P0, 'ResizablePMCArray'
2644     push P0, "a"
2645     push P0, "b"
2646     join S0, "--", P0
2647     print S0
2648     print "\n"
2649     end
2650 CODE
2653 a--b
2654 OUTPUT
2656 pir_output_is( <<'CODE', <<'OUTPUT', 'join: get_string returns a null string' );
2658 .sub _main
2659     newclass P0, "Foo"
2661     new P0, 'ResizablePMCArray'
2663     P1 = new "Foo"
2665     push P0, P1
2667     print "a"
2668     join S0, "", P0
2669     print "b"
2670     print S0
2671     print "c\n"
2672     end
2673 .end
2675 .namespace ["Foo"]
2677 .sub get_string :vtable :method
2678     .local string ret
2680     null ret
2681     .begin_return
2682     .return ret
2683     .end_return
2684 .end
2685 CODE
2687 OUTPUT
2689 pasm_output_is( <<'CODE', <<'OUTPUT', 'eq_addr/ne_addr' );
2690         set S0, "Test"
2691         set S1, S0
2692         eq_addr S1, S0, OK1
2693         print "not "
2694 OK1:    print "ok 1\n"
2695         set S1, "Test"
2696         eq_addr S1, S0, BAD2
2697         branch OK2
2698 BAD2:   print "not "
2699 OK2:    print "ok 2\n"
2701         ne_addr S1, S0, OK3
2702         print "not "
2703 OK3:    print "ok 3\n"
2704         set S0, S1
2705         ne_addr S1, S0, BAD4
2706         branch OK4
2707 BAD4:   print "not "
2708 OK4:    print "ok 4\n"
2709         end
2710 CODE
2711 ok 1
2712 ok 2
2713 ok 3
2714 ok 4
2715 OUTPUT
2717 pasm_output_is( <<'CODE', <<'OUTPUT', 'if_null_s_ic' );
2718     set S0, "foo"
2719     if_null S0, ERROR
2720     print "ok 1\n"
2721     null S0
2722     if_null S0, OK
2723 ERROR:  print "error\n"
2724     end
2725 OK: print "ok 2\n"
2726     end
2727 CODE
2728 ok 1
2729 ok 2
2730 OUTPUT
2732 pasm_output_is( <<'CODE', <<'OUTPUT', 'upcase' );
2733   set S0, "abCD012yz\n"
2734   upcase S1, S0
2735   print S1
2736   upcase S0
2737   print S0
2738   end
2739 CODE
2740 ABCD012YZ
2741 ABCD012YZ
2742 OUTPUT
2744 pasm_output_is( <<'CODE', <<'OUTPUT', 'downcase' );
2745   set S0, "ABcd012YZ\n"
2746   downcase S1, S0
2747   print S1
2748   downcase S0
2749   print S0
2750   end
2751 CODE
2752 abcd012yz
2753 abcd012yz
2754 OUTPUT
2756 pasm_output_is( <<'CODE', <<'OUTPUT', 'titlecase' );
2757   set S0, "aBcd012YZ\n"
2758   titlecase S1, S0
2759   print S1
2760   titlecase S0
2761   print S0
2762   end
2763 CODE
2764 Abcd012yz
2765 Abcd012yz
2766 OUTPUT
2768 pasm_output_is( <<'CODE', ord('a'), '3-param ord, one-character string register, I' );
2769     set S0,"a"
2770     set I1, 0
2771     ord I0,S0,I1
2772     print I0
2773     end
2774 CODE
2776 pasm_output_is( <<'CODE', ord('b'), '3-param ord, multi-character string, I' );
2777     set I1, 1
2778     ord I0,"ab",I1
2779     print I0
2780     end
2781 CODE
2783 pasm_output_is( <<'CODE', ord('b'), '3-param ord, multi-character string register, I' );
2784     set I1, 1
2785     set S0,"ab"
2786     ord I0,S0,I1
2787     print I0
2788     end
2789 CODE
2791 pasm_error_output_like( <<'CODE', <<'OUTPUT', '3-param ord, multi-character string, I' );
2792     set I1, 2
2793     ord I0,"ab",I1
2794     print I0
2795     end
2796 CODE
2797 /^Cannot get character past end of string/
2798 OUTPUT
2800 pasm_error_output_like( <<'CODE', <<'OUTPUT', '3-param ord, multi-character string, I' );
2801     set I1, 2
2802     set S0,"ab"
2803     ord I0,S0,I1
2804     print I0
2805     end
2806 CODE
2807 /^Cannot get character past end of string/
2808 OUTPUT
2810 pasm_output_is( <<'CODE', ord('a'), '3-param ord, one-character string, from end, I' );
2811     set I1, -1
2812     ord I0,"a",I1
2813     print I0
2814     end
2815 CODE
2817 pasm_output_is( <<'CODE', ord('a'), '3-param ord, one-character string register, from end, I' );
2818     set I1, -1
2819     set S0,"a"
2820     ord I0,S0,I1
2821     print I0
2822     end
2823 CODE
2825 pasm_output_is( <<'CODE', ord('b'), '3-param ord, multi-character string, from end, I' );
2826     set I1, -1
2827     ord I0,"ab",I1
2828     print I0
2829     end
2830 CODE
2832 pasm_output_is( <<'CODE', ord('b'), '3-param ord, multi-character string register, from end, I' );
2833     set I1, -1
2834     set S0,"ab"
2835     ord I0,S0,I1
2836     print I0
2837     end
2838 CODE
2840 pasm_error_output_like(
2841     <<'CODE', <<'OUTPUT', '3-param ord, multi-character string register, from end, OOB, I' );
2842     set I1, -3
2843     set S0,"ab"
2844     ord I0,S0,I1
2845     print I0
2846         end
2847 CODE
2848 /^Cannot get character before beginning of string/
2849 OUTPUT
2851 pir_output_is( <<'CODE', <<'OUT', 'more string_to_int' );
2852    .sub 'main' :main
2853       print_as_integer('-4')
2854       print_as_integer('X-4')
2855       print_as_integer('--4')
2856       print_as_integer('+')
2857       print_as_integer('++')
2858       print_as_integer('+2')
2859       print_as_integer(' +3')
2860       print_as_integer('++4')
2861       print_as_integer('+ 5')
2862       print_as_integer('-')
2863       print_as_integer('--56')
2864       print_as_integer('  -+67')
2865       print_as_integer('+-78')
2866       print_as_integer('  -089xyz')
2867       print_as_integer('- 89')
2868    .end
2870    .sub 'print_as_integer'
2871       .param string s
2872       $I0 = s
2873       print $I0
2874       print "\n"
2875    .end
2876 CODE
2894 # Local Variables:
2895 #   mode: cperl
2896 #   cperl-indent-level: 4
2897 #   fill-column: 100
2898 # End:
2899 # vim: expandtab shiftwidth=4: