fix codetest failure - ASSERT_ARGS does not have a ; after and
[parrot.git] / t / pmc / nci.t
blobfc7853aeb8ab94c50de96f246064cd24a2457061
1 #! perl
2 # Copyright (C) 2001-2010, Parrot Foundation.
3 # $Id$
5 use strict;
6 use warnings;
7 use lib qw( . lib ../lib ../../lib );
8 use Test::More;
9 use Parrot::Test;
10 use Parrot::Config qw(%PConfig);
12 =head1 NAME
14 t/pmc/nci.t - test the Native Call Interface
16 =head1 SYNOPSIS
18     % prove t/pmc/nci.t
20 =head1 DESCRIPTION
22 This tests the Native Call Interface, that is the ParrotLibrary PMC.
23 Most tests are skipped when the F<libnci_test.so> shared library is not found.
25 =head1 SEE ALSO
27   F<docs/pdds/pdd16_native_call.pod>
28   F<config/gen/makefiles/root.in>
29   F<src/nci_test.c>
31 =cut
33 $ENV{TEST_PROG_ARGS} ||= '';
35 SKIP: {
36     unless ( -e "runtime/parrot/dynext/libnci_test$PConfig{load_ext}" ) {
37         plan skip_all => "Please make libnci_test$PConfig{load_ext}";
38     }
39     plan tests => 71;
41     pir_output_is( << 'CODE', << 'OUTPUT', 'load library fails' );
42 .sub test :main
43   .local pmc libnci_test
44   .local int lib_defined
45   libnci_test = loadlib "no_such_library"
46   lib_defined = defined libnci_test
47   if lib_defined goto LIB_DEFINED
48   branch LIB_UNDEFINED
50 LIB_DEFINED:
51   print "defined\n"
52   branch LIB_END
54 LIB_UNDEFINED:
55   print "undefined\n"
56   branch LIB_END
58 LIB_END:
59 .end
60 CODE
61 undefined
62 OUTPUT
64     pir_output_is( << 'CODE', << 'OUTPUT', 'dlfunc on undef' );
65 .sub test :main
66   .local pmc libnci_test
67   .local pmc func
68   .local int func_defined
69   libnci_test = loadlib "no_such_library"
70   dlfunc func, libnci_test, "no_such_function", "v"
71   func_defined = defined func
72   if func_defined goto FUNC_DEFINED
73   branch FUNC_UNDEFINED
74 FUNC_DEFINED:
75   print "defined\n"
76   branch FUNC_END
78 FUNC_UNDEFINED:
79   print "undefined\n"
80   branch FUNC_END
82 FUNC_END:
83 .end
84 CODE
85 undefined
86 OUTPUT
88     pir_output_is( << 'CODE', << 'OUTPUT', 'dlfunc function not found' );
89 .sub test :main
90   .local pmc libnci_test
91   .local pmc func
92   .local int func_defined
93   libnci_test = loadlib "libnci_test"
94   unless libnci_test goto NOT_LOADED
95   print "libnci_test was successfully loaded\n"
97   dlfunc func, libnci_test, "no_such_function", "v"
98   func_defined = defined func
99   if func_defined goto FUNC_DEFINED
100   branch FUNC_UNDEFINED
102 FUNC_DEFINED:
103   print "defined\n"
104   branch FUNC_END
106 FUNC_UNDEFINED:
107   print "undefined\n"
108   branch FUNC_END
110 NOT_LOADED:
111   print "Could not load libnci_test\n"
112   branch FUNC_END
114 FUNC_END:
115 .end
116 CODE
117 libnci_test was successfully loaded
118 undefined
119 OUTPUT
121     pir_output_is( << 'CODE', << "OUTPUT", "nci_c - return a char in an INTEGER register" );
123 .include "datatypes.pasm"
125 .sub test :main
127   # load library
128   .local pmc libnci_test
129   libnci_test = loadlib "libnci_test"
130   unless libnci_test goto NOT_LOADED
131   print "libnci_test was successfully loaded\n"
133   # calling a function in libnci_test
134   .local pmc nci_c
135   dlfunc nci_c, libnci_test, "nci_c", "c"
136   .local int nci_c_out
137   ( nci_c_out ) = nci_c( )
138   print nci_c_out
139   print "\n"
140 NOT_LOADED:
141 .end
142 CODE
143 libnci_test was successfully loaded
145 OUTPUT
147     pir_output_is( << 'CODE', << 'OUTPUT', "nci_d and nci_dlvar_double" );
149 .include "datatypes.pasm"
151 .sub test :main
153     # load libnci_test.so
154     .local string library_name
155     library_name = 'libnci_test'
156     .local pmc libnci_test
157     libnci_test = loadlib library_name
158     unless libnci_test goto NOT_LOADED
159     print library_name
160     print " was successfully loaded\n"
162     # address of nci_dlvar_double
163     .local pmc nci_dlvar_double
164     nci_dlvar_double = dlvar libnci_test, "nci_dlvar_double"
166     # the contained structure pointer
167     .local pmc nci_dlvar_double_decl
168     nci_dlvar_double_decl = new ['ResizablePMCArray']
169     push nci_dlvar_double_decl, .DATATYPE_DOUBLE
170     push nci_dlvar_double_decl, 0
171     push nci_dlvar_double_decl, 0
172     assign nci_dlvar_double, nci_dlvar_double_decl
174     $N2 = nci_dlvar_double[0]
175     print $N2
176     print "\n"
178     .local pmc nci_d
179     nci_d = dlfunc libnci_test, "nci_d", "d"
180     .local num nci_d_out
181     ( nci_d_out ) = nci_d( )
182     print nci_d_out
183     print "\n"
184     ( nci_d_out ) = nci_d( )
185     print nci_d_out
186     print "\n"
187     ( nci_d_out ) = nci_d( )
188     print nci_d_out
189     print "\n"
190     ( nci_d_out ) = nci_d( )
191     print nci_d_out
192     print "\n"
193     ( nci_d_out ) = nci_d( )
194     print nci_d_out
195     print "\n"
197 NOT_LOADED:
198 .end
199 CODE
200 libnci_test was successfully loaded
201 -55555.55555
202 -555555.5555
203 -5555555.555
204 -55555555.55
205 -555555555.5
206 -5555555555
207 OUTPUT
209     pir_output_is( << 'CODE', << 'OUTPUT', "nci_f and nci_dlvar_float" );
211 .include "datatypes.pasm"
213 .sub test :main
215     # load libnci_test.so
216     .local string library_name
217     library_name = 'libnci_test'
218     .local pmc libnci_test
219     libnci_test = loadlib library_name
220     unless libnci_test goto NOT_LOADED
221     print library_name
222     print " was successfully loaded\n"
224     # address of nci_dlvar_float
225     .local pmc nci_dlvar_float
226     nci_dlvar_float = dlvar libnci_test, "nci_dlvar_float"
228     # the contained structure pointer
229     .local pmc nci_dlvar_float_decl
230     nci_dlvar_float_decl = new ['ResizablePMCArray']
231     push nci_dlvar_float_decl, .DATATYPE_FLOAT
232     push nci_dlvar_float_decl, 0
233     push nci_dlvar_float_decl, 0
234     assign nci_dlvar_float, nci_dlvar_float_decl
236     $N2 = nci_dlvar_float[0]
237     print $N2
238     print "\n"
240     .local pmc nci_f
241     nci_f = dlfunc libnci_test, "nci_f", "f"
242     .local num nci_f_out
243     ( nci_f_out ) = nci_f( )
244     print nci_f_out
245     print "\n"
246     ( nci_f_out ) = nci_f( )
247     print nci_f_out
248     print "\n"
249     ( nci_f_out ) = nci_f( )
250     print nci_f_out
251     print "\n"
252     ( nci_f_out ) = nci_f( )
253     print nci_f_out
254     print "\n"
255     ( nci_f_out ) = nci_f( )
256     print nci_f_out
257     print "\n"
259 NOT_LOADED:
260 .end
261 CODE
262 libnci_test was successfully loaded
263 -333
264 -3330
265 -33300
266 -333000
267 -3330000
268 -33300000
269 OUTPUT
271     pir_output_is( << 'CODE', << "OUTPUT", "nci_l - return a long in an INTEGER register" );
273 .include "datatypes.pasm"
275 .sub test :main
277   # load library
278   .local pmc libnci_test
279   libnci_test = loadlib "libnci_test"
280   unless libnci_test goto NOT_LOADED
281   print "libnci_test was successfully loaded\n"
283   # calling a function in libnci_test
284   .local pmc nci_l
285   dlfunc nci_l, libnci_test, "nci_l", "l"
286   .local int nci_l_out
287   ( nci_l_out ) = nci_l( )
288   print nci_l_out
289   print "\n"
290 NOT_LOADED:
291 .end
292 CODE
293 libnci_test was successfully loaded
294 -7777777
295 OUTPUT
297     pir_output_is( << 'CODE', << "OUTPUT", "nci_p - return a pointer to int" );
299 .include "datatypes.pasm"
301 .sub test :main
303     # load library
304     .local pmc libnci_test
305     libnci_test = loadlib "libnci_test"
306     unless libnci_test goto NOT_LOADED
307     print "libnci_test was successfully loaded\n"
309     # calling a function in libnci_test
310     .local pmc nci_p
311     dlfunc nci_p, libnci_test, "nci_p", "p"
312     .local pmc nci_p_out
313     ( nci_p_out ) = nci_p( )
315     # the contained structure pointer
316     .local pmc nci_p_out_decl
317     nci_p_out_decl = new ['ResizablePMCArray']
318     push nci_p_out_decl, .DATATYPE_INT
319     push nci_p_out_decl, 0
320     push nci_p_out_decl, 0
321     assign nci_p_out, nci_p_out_decl
323     $I2 = nci_p_out[0]
324     print $I2
325     print "\n"
326 NOT_LOADED:
327 .end
328 CODE
329 libnci_test was successfully loaded
330 -4444
331 OUTPUT
333     pir_output_is( << 'CODE', << "OUTPUT", "nci_t - return a C-string" );
335 .include "datatypes.pasm"
337 .sub test :main
339     # load library
340     .local pmc libnci_test
341     libnci_test = loadlib "libnci_test"
342     unless libnci_test goto NOT_LOADED
343     print "libnci_test was successfully loaded\n"
345     # calling a function in libnci_test
346     .local pmc nci_t
347     dlfunc nci_t, libnci_test, "nci_t", "t"
348     .local string nci_t_out
349     ( nci_t_out ) = nci_t( )
350     print nci_t_out
351 NOT_LOADED:
352 .end
353 CODE
354 libnci_test was successfully loaded
355 This is a C-string.
356 OUTPUT
358     pir_output_is( << 'CODE', << "OUTPUT", "nci_s - return a short in an INTEGER register" );
360 .include "datatypes.pasm"
362 .sub test :main
364   # load library
365   .local pmc libnci_test
366   libnci_test = loadlib "libnci_test"
367   unless libnci_test goto NOT_LOADED
368   print "libnci_test was successfully loaded\n"
370   # calling a function in libnci_test
371   .local pmc nci_s
372   dlfunc nci_s, libnci_test, "nci_s", "s"
373   .local int nci_s_out
374   ( nci_s_out ) = nci_s( )
375   print nci_s_out
376   print "\n"
377 NOT_LOADED:
378 .end
379 CODE
380 libnci_test was successfully loaded
382 OUTPUT
384 SKIP:
385     {
387         skip( "nci_dlvar_int hangs on HP-UX", 1 ) if $^O eq 'hpux';
389         pir_output_is( << 'CODE', << 'OUTPUT', "nci_v and nci_dlvar_int" );
391 .include "datatypes.pasm"
393 .sub test :main
395     # load libnci_test.so
396     .local string library_name
397     library_name = 'libnci_test'
398     .local pmc libnci_test
399     libnci_test = loadlib library_name
400     unless libnci_test goto NOT_LOADED
401     print library_name
402     print " was successfully loaded\n"
404     # address of nci_dlvar_int
405     .local pmc nci_dlvar_int
406     nci_dlvar_int = dlvar libnci_test, "nci_dlvar_int"
408     # the contained structure pointer
409     .local pmc nci_dlvar_int_decl
410     nci_dlvar_int_decl = new ['ResizablePMCArray']
411     push nci_dlvar_int_decl, .DATATYPE_INT
412     push nci_dlvar_int_decl, 0
413     push nci_dlvar_int_decl, 0
414     assign nci_dlvar_int, nci_dlvar_int_decl
416     $I2 = nci_dlvar_int[0]
417     print $I2
418     print "\n"
420     .local pmc nci_v
421     nci_v = dlfunc libnci_test, "nci_v", "v"
422     nci_v()
423     $I1 = nci_dlvar_int[0]
424     print $I1
425     print "\n"
426     nci_v()
427     $I1 = nci_dlvar_int[0]
428     print $I1
429     print "\n"
430     nci_v()
431     $I1 = nci_dlvar_int[0]
432     print $I1
433     print "\n"
434     nci_v()
435     $I1 = nci_dlvar_int[0]
436     print $I1
437     print "\n"
438 NOT_LOADED:
439 .end
440 CODE
441 libnci_test was successfully loaded
442 -4444
443 -44440
444 -444400
445 -4444000
446 -44440000
447 OUTPUT
448     }
450     pasm_output_is( <<'CODE', <<'OUTPUT', "nci_dd - PASM" );
451   loadlib P1, "libnci_test"
452   print "loaded\n"
453   dlfunc P0, P1, "nci_dd", "dd"
454   print "dlfunced\n"
455   set_args "0", 4.0
456   invokecc P0
457   get_results "0", N5
458   ne N5, 8.0, nok_1
459   print "ok 1\n"
460   end
461 nok_1: print "nok 1\n"
462   print N5
463   print "\n"
464   end
465 CODE
466 loaded
467 dlfunced
468 ok 1
469 OUTPUT
471     pir_output_is( << 'CODE', << 'OUTPUT', "nci_dd - PIR" );
473 .sub test :main
474     .local string library_name
475     library_name = 'libnci_test'
476     .local pmc libnci_test
477     libnci_test = loadlib  library_name
478     unless libnci_test goto NOT_LOADED
479     print library_name
480     print " was successfully loaded\n"
481     .local pmc twice
482     twice = dlfunc libnci_test, "nci_dd", "dd"
483     .local num r
484     r = twice( -4.128 )
485     print r
486 NOT_LOADED:
487     print "\n"
488 .end
489 CODE
490 libnci_test was successfully loaded
491 -8.256
492 OUTPUT
494     pir_output_is( << 'CODE', << "OUTPUT", "get_string()" );
496 .sub test :main
497     .local string library_name
498     library_name = 'libnci_test'
499     .local pmc libnci_test
500     libnci_test = loadlib  library_name
501     unless libnci_test goto NOT_LOADED
502         .local string filename_with_path
503         filename_with_path = libnci_test
504         # depending on the platform, 'filename' has path info or not
505         .local int start_of_filename
506         start_of_filename = index filename_with_path, 'libnci_test'
507         if start_of_filename == -1 goto NOT_LOADED
508             .local string filename
509             filename = substr filename_with_path, start_of_filename
510             print filename
511             print " was successfully loaded"
512     NOT_LOADED:
513     print "\n"
514 .end
515 CODE
516 libnci_test was successfully loaded
517 OUTPUT
519     pasm_output_is( <<'CODE', <<'OUTPUT', "nci_fff" );
520   loadlib P1, "libnci_test"
521   print "loaded\n"
522   dlfunc P0, P1, "nci_fff", "fff"
523   print "dlfunced\n"
524   set N5, 12.0
525   set N6, 3.0
526   set_args "0,0", N5, N6
527   invokecc P0
528   get_results "0", N5
529   ne N5, 4.0, nok_1
530   print "ok 1\n"
531   end
532 nok_1: print "nok 1\n"
533   print N5
534   print "\n"
535   end
536 CODE
537 loaded
538 dlfunced
539 ok 1
540 OUTPUT
542     pasm_output_is( <<'CODE', <<'OUTPUT', "nci_isc" );
543   loadlib P1, "libnci_test"
544   print "loaded\n"
545   dlfunc P0, P1, "nci_isc", "isc"
546   print "dlfunced\n"
547   set I5, 2
548   set I6, 3
549   set_args "0,0", I5, I6
550   invokecc P0
551   get_results "0", I5
552   ne I5, 6, nok_1
553   print "ok 1\n"
554   end
555 nok_1: print "nok 1\n"
556   print I5
557   print "\n"
558   end
559 CODE
560 loaded
561 dlfunced
562 ok 1
563 OUTPUT
565     pasm_output_is( <<'CODE', <<'OUTPUT', "nci_ssc" );
566   loadlib P1, "libnci_test"
567   print "loaded\n"
568   dlfunc P0, P1, "nci_ssc", "ssc"
569   print "dlfunced\n"
570   set I5, -2
571   set I6, 3
572   set_args "0,0", I5, I6
573   invokecc P0
574   get_results "0", I5
575   ne I5, -6, nok_1
576   print "ok 1\n"
577   end
578 nok_1: print "nok 1\n"
579   print I5
580   print "\n"
581   end
582 CODE
583 loaded
584 dlfunced
585 ok 1
586 OUTPUT
588     pasm_output_is( <<'CODE', <<'OUTPUT', "nci_csc" );
589   loadlib P1, "libnci_test"
590   print "loaded\n"
591   dlfunc P0, P1, "nci_csc", "csc"
592   print "dlfunced\n"
593   set I5, 6
594   set I6, 7
595   set_args "0,0", I5, I6
596   invokecc P0
597   get_results "0", I5
598   ne I5, 42, nok_1
599   print "ok 1\n"
600   end
601 nok_1: print "nok 1\n"
602   print I5
603   print "\n"
604   end
605 CODE
606 loaded
607 dlfunced
608 ok 1
609 OUTPUT
611     pir_output_is( <<'CODE', <<'OUTPUT', "nci_it" );
612 .loadlib 'io_ops'
613 .sub 'main' :main
614   loadlib $P1, "libnci_test"
615   printerr "loaded\n"
616   dlfunc $P0, $P1, "nci_it", "it"
617   printerr "dlfunced\n"
618   set $S5, "ko\n"
619   set_args "0", $S5
620   invokecc $P0
621   get_results "0", $I5
622   ne $I5, 2, nok_1
623   printerr "ok 2\n"
624   end
625 nok_1: printerr "nok 1\n"
626   printerr $I5
627   printerr "\n"
628   end
629 nok_2: printerr "nok 2\n"
630 .end
631 CODE
632 loaded
633 dlfunced
635 ok 2
636 OUTPUT
638     pir_output_is( <<'CODE', <<'OUTPUT', "nci_it" );
640 .include "datatypes.pasm"
641 .loadlib 'io_ops'
643 .sub test :main
644   loadlib $P1, "libnci_test"
645   printerr "loaded\n"
646   .local pmc nci_it
647   nci_it = dlfunc $P1, "nci_it", "it"
648   printerr "dlfunced\n"
649   ( $I5 ) = nci_it( "ko" )
650   ne $I5, 2, nok_1
651   printerr "ok "
652   printerr $I5
653   printerr "\n"
654   end
655 nok_1: printerr "nok 1\n"
656   printerr $I5
657   printerr "\n"
658   end
659 nok_2: printerr "nok 2\n"
660 .end
662 CODE
663 loaded
664 dlfunced
666 ok 2
667 OUTPUT
669     pasm_output_is( <<'CODE', <<'OUTPUT', "nci_tt" );
670   loadlib P1, "libnci_test"
671   print "loaded\n"
672   dlfunc P0, P1, "nci_tt", "tt"
673   print "dlfunced\n"
674   set S5, "ko\n"
675   set_args "0", S5
676   invokecc P0
677   get_results "0", S5
678   print S5
679   end
680 nok_1: print "nok 1\n"
681   print I5
682   print "\n"
683   end
684 nok_2: print "nok 2\n"
685   end
686 CODE
687 loaded
688 dlfunced
689 ok worked
690 OUTPUT
692     pasm_output_is( <<'CODE', <<'OUTPUT', "nci_dd - stress test" );
693   loadlib P1, "libnci_test"
694   print "loaded\n"
695   set I10, 10000
696   print "dlfunced\n"
697 loop:
698   dlfunc P0, P1, "nci_dd", "dd"
699   set N5, 77.0
700   set_args "0", 4.0
701   invokecc P0
702   get_results "0", N5
703   ne N5, 8.0, nok_1
704   dec I10
705   gt I10, 0, loop
706   print "ok 1\n"
707   end
708 nok_1: print "nok 1\n"
709   print N5
710   print "\n"
711   end
712 nok_2: print "nok 2\n"
713   end
714 CODE
715 loaded
716 dlfunced
717 ok 1
718 OUTPUT
720     pasm_output_is( <<'CODE', <<'OUTPUT', "nci_dd - clone" );
721   loadlib P1, "libnci_test"
722   print "loaded\n"
723   dlfunc P0, P1, "nci_dd", "dd"
724   print "dlfunced\n"
725   clone P2, P0
726   print "ok 1\n"
727   set_args "0", 4.0
728   invokecc P0
729   get_results "0", N5
730   ne N5, 8.0, nok_1
731   print "ok 2\n"
732   set_args "0", 4.0
733   invokecc P2
734   get_results "0", N5
735   ne N5, 8.0, nok_1
736   end
737 nok_1: print "nok 1\n"
738   print N5
739   print "\n"
740   end
741 CODE
742 loaded
743 dlfunced
744 ok 1
745 ok 2
746 OUTPUT
748     pasm_output_is( <<'CODE', <<'OUTPUT', "nci_iiii" );
749   loadlib P1, "libnci_test"
750   dlfunc P0, P1, "nci_iiii", "iiii"
751   set I5, 10
752   set I6, 20
753   set I7, 30
754   set_args "0,0,0", I5,I6,I7
755   invokecc P0
756   get_results "0", I5
757   print I5
758   print "\n"
759   end
760 CODE
761 10 20 30
763 OUTPUT
765     pasm_output_is( <<'CODE', <<'OUTPUT', "nci_i4i" );
766   loadlib P1, "libnci_test"
767   dlfunc P0, P1, "nci_i4i", "i4i"
768   new P5, ['Integer']
769   set P5, -6
770   set I5, -7
771   set_args "0,0", P5,I5
772   invokecc P0
773   get_results "0", I5
774   print I5
775   print "\n"
776   end
777 CODE
779 OUTPUT
781     pasm_output_is( <<'CODE', <<'OUTPUT', "nci_ii3" );
782 .include "datatypes.pasm"
783   loadlib P1, "libnci_test"
784   dlfunc P0, P1, "nci_ii3", "ii3"
785   set I5, -6
787   new P5, ['Integer']
788   set P5, -7
790   set_args "0,0", I5,P5
791   invokecc P0
792   get_results "0", I5
794   print I5
795   print "\n"
796   print P5
797   print "\n"
798   end
799 CODE
801 4711
802 OUTPUT
804     pasm_output_is( <<'CODE', <<'OUTPUT', "nci_tb" );
805   loadlib P1, "libnci_test"
806   dlfunc P0, P1, "nci_tb", "tb"
807   set S5, "ko\n"
808   set_args "0", S5
809   invokecc P0
810   get_results "0", S5
811   print S5
812   end
813 CODE
814 ok worked
815 OUTPUT
817     pasm_output_is( <<'CODE', <<'OUTPUT', "nci_tB" );
818   loadlib P1, "libnci_test"
819   dlfunc P0, P1, "nci_tB", "tB"
820   set S5, "ko\n"
821   set_args "0", S5
822   invokecc P0
823   get_results "0", S5
824   print S5
825   end
826 CODE
827 ok done
828 OUTPUT
830     pasm_output_is( <<'CODE', <<'OUTPUT', "nci_pi - struct with ints" );
831   loadlib P1, "libnci_test"
832   dlfunc P0, P1, "nci_pi", "pi"
833   # this test function returns a struct { int[2]; char }
834   set I5, 0
835   set_args "0", I5
836   invokecc P0
837   get_results "0", P5
838   new P2, ['ResizablePMCArray']
839 .include "datatypes.pasm"
840   push P2, .DATATYPE_INT
841   push P2, 2    # 2 elem array
842   push P2, 0
843   push P2, .DATATYPE_CHAR
844   push P2, 0
845   push P2, 0
846   assign P5, P2
847   set I0, P5[0;0]
848   print I0
849   print "\n"
850   set I0, P5[0;1]
851   print I0
852   print "\n"
853   set I0, P5[1]
854   print I0
855   print "\n"
856   end
857 CODE
861 OUTPUT
863     pasm_output_is( <<'CODE', <<'OUTPUT', "nci_pi - struct with floats" );
864   loadlib P1, "libnci_test"
865   dlfunc P0, P1, "nci_pi", "pi"
866   # this test function returns a struct { float[2]; double }
867   set_args "0", 1
868   invokecc P0
869   get_results "0", P5
870   new P2, ['ResizablePMCArray']
871 .include "datatypes.pasm"
872   push P2, .DATATYPE_FLOAT
873   push P2, 2    # 2 elem array
874   push P2, 0
875   push P2, .DATATYPE_DOUBLE
876   push P2, 0
877   push P2, 0
878   assign P5, P2
879   set N0, P5[0;0]
880   print N0
881   print "\n"
882   set N0, P5[0;1]
883   print N0
884   print "\n"
885   set N0, P5[1]
886   print N0
887   print "\n"
888   end
889 CODE
892 47.11
893 OUTPUT
895     pasm_output_like( <<'CODE', <<'OUTPUT', "nci_pi - align" );
896   loadlib P1, "libnci_test"
897   dlfunc P0, P1, "nci_pi", "pi"
898   # this test function returns a struct { char; int }
899   set_args "0", 2
900   invokecc P0
901   get_results "0", P5
902   new P2, ['ResizablePMCArray']
903 .include "datatypes.pasm"
904   push P2, .DATATYPE_CHAR
905   push P2, 0
906   push P2, 0
907   push P2, .DATATYPE_INT
908   push P2, 0
909   push P2, 0
910   assign P5, P2
911   set I0, P5[0]
912   print I0
913   print "\n"
914   set I0, P5[1]
915   print I0
916   print "\n"
917   # check the offset of the int
918   set I0, P2[5]
919   print I0
920   print "\n"
921   end
922 CODE
925 (4|8)
927 OUTPUT
929     pasm_output_is( <<'CODE', <<'OUTPUT', "nci_pi - char*" );
930   loadlib P1, "libnci_test"
931   dlfunc P0, P1, "nci_pi", "pi"
932   # this test function returns a struct { char*; int }
933   set_args "0", 3
934   invokecc P0
935   get_results "0", P5
936   new P2, ['ResizablePMCArray']
937 .include "datatypes.pasm"
938   push P2, .DATATYPE_CSTR
939   push P2, 0
940   push P2, 0
941   push P2, .DATATYPE_INT
942   push P2, 0
943   push P2, 0
944   assign P5, P2
945   set S0, P5[0]
946   print S0
947   print "\n"
948   set I0, P5[1]
949   print I0
950   print "\n"
951   end
952 CODE
953 hello
955 OUTPUT
957     pasm_output_is( <<'CODE', <<'OUTPUT', "nci_pi - nested struct *" );
958   loadlib P1, "libnci_test"
959   dlfunc P0, P1, "nci_pi", "pi"
960   # this test function returns a struct { char; x->{int, double} }
961   set_args "0", 4
962   invokecc P0
963   get_results "0", P5
964 .include "datatypes.pasm"
965   # the contained structure
966   new P3, ['ResizablePMCArray']
967   push P3, .DATATYPE_INT
968   push P3, 0
969   push P3, 0
970   push P3, .DATATYPE_INT
971   push P3, 0
972   push P3, 0
973   push P3, .DATATYPE_DOUBLE
974   push P3, 0
975   push P3, 0
976   new P4, ['UnManagedStruct'], P3
977   # outer structure
978   new P2, ['ResizablePMCArray']
979   push P2, .DATATYPE_CHAR
980   push P2, 0
981   push P2, 0
982   push P2, .DATATYPE_STRUCT_PTR
983   # attach the unmanged struct as property
984   set P1, P2[-1]
985   setprop P1, "_struct", P4
986   push P2, 0
987   push P2, 0
988   # attach struct initializer
989   assign P5, P2
990   set I0, P5[0]
991   print I0
992   print "\n"
993   # get item x->int
994   set I0, P5[1;0]
995   print I0
996   print "\n"
997   set I0, P5[1;1]
998   print I0
999   print "\n"
1000   # get item x->double
1001   set N0, P5[1;2]
1002   print N0
1003   print "\n"
1004   end
1005 CODE
1010 OUTPUT
1012     pasm_output_is( <<'CODE', <<'OUTPUT', "nci_pi - nested struct * w named access" );
1013   loadlib P1, "libnci_test"
1014   dlfunc P0, P1, "nci_pi", "pi"
1015   set_args "0", 8
1016   invokecc P0
1017   get_results "0", P5
1018 .include "datatypes.pasm"
1019   # the contained structure pointer
1020   new  P6, 'OrderedHash'
1021   set  P6[ 'i' ], .DATATYPE_INT
1022   push P6, 0
1023   push P6, 0
1024   set  P6[ 'j' ], .DATATYPE_INT
1025   push P6, 0
1026   push P6, 0
1027   new P7, ['UnManagedStruct'], P6
1028   # the contained structure
1029   new  P3, 'OrderedHash'
1030   set  P3[ 'i'  ], .DATATYPE_INT
1031   push P3, 0
1032   push P3, 0
1033   set  P3[ 'j'  ], .DATATYPE_INT
1034   push P3, 0
1035   push P3, 0
1036   set  P3[ '_z' ], .DATATYPE_STRUCT_PTR
1037   set  P1, P3[-1]
1038   setprop P1, "_struct", P7
1039   push P3, 0
1040   push P3, 0
1041   new P4, ['UnManagedStruct'], P3
1042   # outer structure
1043   new P2, ['OrderedHash']
1044   set  P2[ 'x'  ], .DATATYPE_INT
1045   push P2, 0
1046   push P2, 0
1047   set  P2[ '_y' ], .DATATYPE_STRUCT
1048   # attach the unmanged struct as property
1049   set P1, P2[-1]
1050   setprop P1, "_struct", P4
1051   push P2, 0
1052   push P2, 0
1053   set  P2[ 'z'  ], .DATATYPE_INT
1054   push P2, 0
1055   push P2, 0
1056   # attach struct initializer
1057   assign P5, P2
1058   set I0, P5[ 'x' ]
1059   print I0
1060   print "\n"
1061   set I0, P5[ '_y'; 'i' ]
1062   print I0
1063   print "\n"
1064   set I0, P5[ '_y'; 'j' ]
1065   print I0
1066   print "\n"
1067   set I0, P5[ '_y'; '_z'; 'i' ]
1068   print I0
1069   print "\n"
1070   set I0, P5[ '_y'; '_z'; 'j' ]
1071   print I0
1072   print "\n"
1073   end
1074 CODE
1077 12345
1080 OUTPUT
1082     pasm_output_is( <<'CODE', <<'OUTPUT', "nci_pi - func_ptr* with signature" );
1083   loadlib P1, "libnci_test"
1084   dlfunc P0, P1, "nci_pi", "pi"
1085   # this test function returns a struct { int (*f)(char *) }
1086   set_args "0", 5
1087   invokecc P0
1088   get_results "0", P5
1089   new P2, ['ResizablePMCArray']
1090 .include "datatypes.pasm"
1091   push P2, .DATATYPE_FUNC_PTR
1092   # attach function signature property to this type
1093   set P1, P2[-1]
1094   new P3, ['String']
1095   set P3, "it"
1096   setprop P1, "_signature", P3
1097   push P2, 0
1098   push P2, 0
1099   assign P5, P2
1100   # now we get a callable NCI PMC
1101   set P0, P5[0]
1102   set_args "0", "hello call_back"
1103   invokecc P0
1104   get_results "0", I5
1105   print I5
1106   print "\n"
1107   end
1108 CODE
1109 hello call_back
1110 4711
1111 OUTPUT
1113     pasm_output_is( <<'CODE', <<'OUTPUT', "nci_pi - nested struct aligned" );
1114   loadlib P1, "libnci_test"
1115   dlfunc P0, P1, "nci_pi", "pi"
1116   # this test function returns a struct { int; {int; int} int }
1117   set_args "0", 6
1118   invokecc P0
1119   get_results "0", P5
1120 .include "datatypes.pasm"
1121   # the nested structure
1122   new P3, ['ResizablePMCArray']
1123   push P3, .DATATYPE_INT
1124   push P3, 0
1125   push P3, 0
1126   push P3, .DATATYPE_INT
1127   push P3, 0
1128   push P3, 0
1129   new P4, ['UnManagedStruct'], P3
1130   # outer structure
1131   new P2, ['ResizablePMCArray']
1132   push P2, .DATATYPE_INT
1133   push P2, 0
1134   push P2, 0
1135   push P2, .DATATYPE_STRUCT
1136   # attach the unmanged struct as property
1137   set P1, P2[-1]
1138   setprop P1, "_struct", P4
1139   push P2, 0
1140   push P2, 0
1141   push P2, .DATATYPE_INT
1142   push P2, 0
1143   push P2, 0
1144   # attach struct initializer
1145   assign P5, P2
1146   set I0, P5[0]
1147   print I0
1148   print "\n"
1149   # get item _y.i
1150   set I0, P5[1;0]
1151   print I0
1152   print "\n"
1153   # _y.j
1154   set I0, P5[1;1]
1155   print I0
1156   print "\n"
1157   set I0, P5[2]
1158   print I0
1159   print "\n"
1160   end
1161 CODE
1164 12345
1166 OUTPUT
1168     pasm_output_is( <<'CODE', <<'OUTPUT', "nci_pi - nested struct unaligned" );
1169   loadlib P1, "libnci_test"
1170   dlfunc P0, P1, "nci_pi", "pi"
1171   # this test function returns a struct { char; {char; int} char }
1172   set_args "0", 7
1173   invokecc P0
1174   get_results "0", P5
1175 .include "datatypes.pasm"
1176   # the nested structure
1177   new P3, ['ResizablePMCArray']
1178   push P3, .DATATYPE_CHAR
1179   push P3, 0
1180   push P3, 0
1181   push P3, .DATATYPE_INT
1182   push P3, 0
1183   push P3, 0
1184   new P4, ['UnManagedStruct'], P3
1185   # outer structure
1186   new P2, ['ResizablePMCArray']
1187   push P2, .DATATYPE_CHAR
1188   push P2, 0
1189   push P2, 0
1190   push P2, .DATATYPE_STRUCT
1191   # attach the unmanged struct as property
1192   set P1, P2[-1]
1193   setprop P1, "_struct", P4
1194   push P2, 0
1195   push P2, 0
1196   push P2, .DATATYPE_CHAR
1197   push P2, 0
1198   push P2, 0
1199   # attach struct initializer
1200   assign P5, P2
1201   set I0, P5[0]
1202   print I0
1203   print "\n"
1204   # get item _y.i
1205   set I0, P5[1;0]
1206   print I0
1207   print "\n"
1208   # _y.j
1209   set I0, P5[1;1]
1210   print I0
1211   print "\n"
1212   set I0, P5[2]
1213   print I0
1214   print "\n"
1215   end
1216 CODE
1219 12345
1221 OUTPUT
1223     pasm_output_is( <<'CODE', <<'OUTPUT', "nci_pi - nested, unaligned, named" );
1224   loadlib P1, "libnci_test"
1225   dlfunc P0, P1, "nci_pi", "pi"
1226   # this test function returns a struct { char; {char; int} char }
1227   set_args "0", 7
1228   invokecc P0
1229   get_results "0", P5
1230 .include "datatypes.pasm"
1231   # the nested structure
1232   new P3, ['OrderedHash']
1233   set P3["i"], .DATATYPE_CHAR
1234   push P3, 0
1235   push P3, 0
1236   set P3["j"], .DATATYPE_INT
1237   push P3, 0
1238   push P3, 0
1239   new P4, ['UnManagedStruct'], P3
1240   # outer structure
1241   new P2, ['OrderedHash']
1242   set P2["x"], .DATATYPE_CHAR
1243   push P2, 0
1244   push P2, 0
1245   set P2["_y"], .DATATYPE_STRUCT
1246   # attach the unmanged struct as property
1247   set P1, P2[-1]
1248   setprop P1, "_struct", P4
1249   push P2, 0
1250   push P2, 0
1251   set P2["z"], .DATATYPE_CHAR
1252   push P2, 0
1253   push P2, 0
1254   # attach struct initializer
1255   assign P5, P2
1256   set I0, P5["x"]
1257   print I0
1258   print "\n"
1259   # get item _y.i
1260   set I0, P5["_y";"i"]
1261   print I0
1262   print "\n"
1263   # _y.j
1264   set I0, P5["_y"; "j"]
1265   print I0
1266   print "\n"
1267   set I0, P5["z"]
1268   print I0
1269   print "\n"
1270   end
1271 CODE
1274 12345
1276 OUTPUT
1278     pir_output_is( << 'CODE', << "OUTPUT", "nci_pi - int" );
1280 .include "datatypes.pasm"
1282 .sub test :main
1284   # load library
1285   .local pmc libnci_test
1286   libnci_test = loadlib "libnci_test"
1287   unless libnci_test goto NOT_LOADED
1288   print "libnci_test was successfully loaded\n"
1290   # calling a function in libnci_test
1291   .local pmc nci_pi
1292   dlfunc nci_pi, libnci_test, "nci_pi", "pi"
1293   .local pmc nci_pi_out
1294   ( nci_pi_out ) = nci_pi( 9 )
1296   # the contained structure pointer
1297   .local pmc nci_pi_out_decl
1298   nci_pi_out_decl = new ['ResizablePMCArray']
1299   push nci_pi_out_decl, .DATATYPE_INT
1300   push nci_pi_out_decl, 0
1301   push nci_pi_out_decl, 0
1303   # attach struct initializer
1304   assign nci_pi_out, nci_pi_out_decl
1305   set $I0, nci_pi_out[0]
1306   print $I0
1307 NOT_LOADED:
1308   print "\n"
1309 .end
1310 CODE
1311 libnci_test was successfully loaded
1312 55555
1313 OUTPUT
1315     pasm_output_is( <<'CODE', <<'OUTPUT', "nci_ip" );
1316   loadlib P1, "libnci_test"
1317   dlfunc P0, P1, "nci_ip", "ip"
1318   # this test function wants a struct
1319   # { double d; float f; int i; char*}
1320   # and returns the sum of these values
1321   new P2, ['ResizablePMCArray']
1322 .include "datatypes.pasm"
1323   push P2, .DATATYPE_DOUBLE
1324   push P2, 0
1325   push P2, 0
1326   push P2, .DATATYPE_FLOAT
1327   push P2, 0    # 1 elem array
1328   push P2, 0
1329   push P2, .DATATYPE_INT
1330   push P2, 0    # 1 elem array
1331   push P2, 0
1332   push P2, .DATATYPE_CSTR
1333   push P2, 0    # 1 elem array
1334   push P2, 0
1335   new P5, ['ManagedStruct'], P2
1336   set P5[0], 10.0
1337   set P5[1], 4.0
1338   set P5[2], 17
1339   set P5[3], "hello from Parrot\x0"
1340   set I5, 1
1341   set_args "0", P5
1342   invokecc P0
1343   get_results "0", I5
1344   print I5
1345   print "\n"
1346   end
1347 CODE
1348 hello from Parrot
1350 OUTPUT
1352     pir_output_is( << 'CODE', << "OUTPUT", "nci_pi - null" );
1354 .include "datatypes.pasm"
1356 .sub test :main
1358   # load library
1359   .local pmc libnci_test
1360   libnci_test = loadlib "libnci_test"
1361   unless libnci_test goto FAILED
1363   # calling a function in libnci_test
1364   .local pmc nci_pi
1365   dlfunc nci_pi, libnci_test, "nci_pi", "pi"
1366   .local pmc result
1367   result = nci_pi( 10 )
1368   unless_null result, FAILED
1369   print "got null"
1370 FAILED:
1371   print "\n"
1372 .end
1373 CODE
1374 got null
1375 OUTPUT
1377     pasm_output_is( <<'CODE', <<'OUTPUT', "nci_vP", todo => 'Disabled to avoid linkage problems, see src/nci_test.c' );
1378   loadlib P1, "libnci_test"
1379   dlfunc P0, P1, "nci_vP", "vP"
1380   new P5, ['String']
1381   set P5, "ok\n"
1382   set_args "0", P5
1383   invokecc P0
1384   null P5
1385   set_args "0", P5
1386   invokecc P0
1387   end
1388 CODE
1390 got null
1391 OUTPUT
1393   # Tests with callback functions
1394   my @todo = $ENV{TEST_PROG_ARGS} =~ /--runcore=jit/ ?
1395     ( todo => 'TT #1316, add scheduler tasks to JIT' ) : ();
1397   pasm_output_is( <<'CODE', <<'OUTPUT', "nci_cb_C1 - PASM", @todo );
1399   # we need a flag if the call_back is already done
1400   new P10, ['Integer']
1401   set_global "cb_done", P10
1402   # first attempt - create cb manually (this step will be hidden later)
1403   .const 'Sub' P6 = "_call_back"
1404   # prepare user data
1405   new P7, ['Integer']
1406   set P7, 42
1407   new_callback P5, P6, P7, "vtU" # Z in pdd16
1408   print "ok 1\n"
1409   # now call the external sub, that takes a call_back and user_data
1410   loadlib P1, "libnci_test"
1411   dlfunc P0, P1, "nci_cb_C1", "vpP"
1412   print "ok 2\n"
1413   # P5 is the cb
1414   # P7 is user_data
1415   set_args "0,0", P5, P7
1416   invokecc P0
1417   # call_back will be called at any time
1418   # so spin a bit
1419   set I20, 0
1420 loop:
1421   inc I20
1422   sleep 0.01
1423   get_global P11, "cb_done"
1424   if P11, fin
1425   gt I20, 10, err
1426   branch loop
1427 fin:
1428   print "done.\n"
1429   end
1430 err:
1431   print "cb didnt run\n"
1432   end
1434 .pcc_sub _call_back:
1435   get_params "0,0", P5, S5
1436   print "in callback\n"
1437   print "user data: "
1438   print P5
1439   print "\n"
1440   print "external data: "
1441   print S5
1442   print "\n"
1443   get_global P12, "cb_done"
1444   inc P12
1445   returncc
1447 CODE
1448 ok 1
1449 ok 2
1450 in callback
1451 user data: 42
1452 external data: succeeded
1453 done.
1454 OUTPUT
1456     pir_output_is( <<'CODE', <<'OUTPUT', "nci_cb_C1 - PIR", @todo );
1458 .sub test :main
1460     # this flag will be set by the callback function
1461     .local pmc cb_done
1462     cb_done = new ['Integer']
1463     cb_done = 0
1464     set_global "cb_done", cb_done
1466     # prepare user data
1467     .local pmc user_data
1468     user_data = new ['Integer']
1469     user_data = 42
1471     # A Sub that can be given to the library
1472     # this callback function will eventually by called by the library
1473     .const 'Sub' cb = "_call_back"
1474     .local pmc cb_wrapped
1475     cb_wrapped = new_callback cb, user_data, "vtU"  # Z in pdd16
1476     print "created a callback sub\n"
1478     # now call the external sub, that takes a callback and user data
1479     .local pmc libnci_test
1480     libnci_test = loadlib "libnci_test"
1481     .local pmc nci_cb_C1
1482     nci_cb_C1 = dlfunc libnci_test, "nci_cb_C1", "vpP"
1483     print "loaded a function that takes a callback\n"
1484     nci_cb_C1( cb_wrapped, user_data )
1486     # callback will be called at any time
1487     # so spin a bit
1488     .local int sleep_cnt
1489     sleep_cnt = 0
1490 LOOP:
1491     sleep_cnt += 1
1492     sleep 0.01
1493     .local pmc callback_has_run
1494     callback_has_run = get_global "cb_done"
1495     if callback_has_run goto FINISHED
1496     if sleep_cnt > 10 goto ERROR
1497     goto LOOP
1498 FINISHED:
1499     print "the callback has run\n"
1500     end
1501 ERROR:
1502     print "the callback didnt run\n"
1503     end
1504 .end
1506 .sub _call_back
1507 .param pmc u
1508 .param string s
1509   print "in callback\n"
1510   print "user data: "
1511   print u
1512   print "\n"
1513   print "external data: "
1514   print s
1515   print "\n"
1516   get_global $P12, "cb_done"
1517   inc $P12
1518   returncc
1519 .end
1521 CODE
1522 created a callback sub
1523 loaded a function that takes a callback
1524 in callback
1525 user data: 42
1526 external data: succeeded
1527 the callback has run
1528 OUTPUT
1530     pasm_output_is( <<'CODE', <<'OUTPUT', "nci_cb_C2 - PASM", @todo );
1531   # we need a flag if the call_back is already done
1532   new P10, ['Integer']
1533   set_global "cb_done", P10
1534   # first attempt - create cb manually (this step will be hidden later)
1535   .const 'Sub' P6 = "_call_back"
1536   # prepare user data
1537   new P7, ['Integer']
1538   set P7, 42
1539   new_callback P5, P6, P7, "viU"    # Z in pdd16
1540   print "ok 1\n"
1541   # now call the external sub, that takes a call_back and user_data
1542   loadlib P1, "libnci_test"
1543   dlfunc P0, P1, "nci_cb_C2", "vpP"
1544   print "ok 2\n"
1545   # P5 is the cb
1546   # P7 is user_data
1547   set_args "0,0", P5, P7
1548   invokecc P0
1549   # call_back will be called at any time
1550   # so spin a bit
1551   set I20, 0
1552 loop:
1553   inc I20
1554   sleep 0.01
1555   get_global P11, "cb_done"
1556   if P11, fin
1557   gt I20, 10, err
1558   branch loop
1559 fin:
1560   print "done.\n"
1561   end
1562 err:
1563   print "cb didnt run\n"
1564   end
1566 .pcc_sub _call_back:
1567   get_params "0,0", P5, I5
1568   print "in callback\n"
1569   print "user data: "
1570   print P5
1571   print "\n"
1572   print "external data: "
1573   print I5
1574   print "\n"
1575   get_global P12, "cb_done"
1576   inc P12
1577   returncc
1580 CODE
1581 ok 1
1582 ok 2
1583 in callback
1584 user data: 42
1585 external data: 77
1586 done.
1587 OUTPUT
1589     pir_output_is( <<'CODE', <<'OUTPUT', "nci_cb_C3 - PIR", @todo );
1592 .include "datatypes.pasm"
1594 .sub test :main
1596     # this flag will be set by the callback function
1597     .local pmc cb_done
1598     cb_done = new ['Integer']
1599     cb_done = 0
1600     set_global "cb_done", cb_done
1602     # prepare user data
1603     .local pmc user_data
1604     user_data = new ['Integer']
1605     user_data = 42
1607     # A Sub that can be given to the library
1608     # this callback function will eventually by called by the library
1609     .const 'Sub' cb = "_call_back"
1610     .local pmc cb_wrapped
1611     cb_wrapped = new_callback cb, user_data, "vpU"  # Z in pdd16
1612     print "created a callback sub\n"
1614     # now call the external sub, that takes a callback and user data
1615     .local pmc libnci_test
1616     libnci_test = loadlib "libnci_test"
1617     .local pmc nci_cb_C3
1618     nci_cb_C3 = dlfunc libnci_test, "nci_cb_C3", "vpP"
1619     print "loaded a function that takes a callback\n"
1620     nci_cb_C3( cb_wrapped, user_data )
1622     # callback will be called at any time
1623     # so spin a bit
1624     .local int sleep_cnt
1625     sleep_cnt = 0
1626 LOOP:
1627     sleep_cnt += 1
1628     sleep 0.01
1629     .local pmc callback_has_run
1630     callback_has_run = get_global "cb_done"
1631     if callback_has_run goto FINISHED
1632     if sleep_cnt > 10 goto ERROR
1633     goto LOOP
1634 FINISHED:
1635     print "the callback has run\n"
1636     end
1637 ERROR:
1638     print "the callback didnt run\n"
1639     end
1640 .end
1642 .sub _call_back
1643   get_params "0,0", $P5, $P6
1644   print "in callback\n"
1645   print "user data: "
1646   print $P5
1647   print "\n"
1649   # P6 is a UnManagedStruct PMC containing a pointer to an integer
1650   new $P2, ['ResizablePMCArray']
1651   push $P2, .DATATYPE_INT
1652   push $P2, 0
1653   push $P2, 0
1654   assign $P6, $P2
1656   # print referenced integer in libnci_test.so
1657   $I17 = $P6[0]
1658   print "external data: "
1659   print $I17
1660   print "\n"
1662   get_global $P12, "cb_done"
1663   inc $P12
1664   returncc
1665 .end
1667 CODE
1668 created a callback sub
1669 loaded a function that takes a callback
1670 in callback
1671 user data: 42
1672 external data: 99
1673 the callback has run
1674 OUTPUT
1676     pasm_output_is( <<'CODE', <<'OUTPUT', "nci_cb_D1 - PASM", @todo );
1678   # we need a flag if the call_back is already done
1679   new P10, ['Integer']
1680   set_global "cb_done", P10
1681   # first attempt - create cb manually (this step will be hidden later)
1682   .const 'Sub' P6 = "_call_back"
1683   # prepare user data
1684   new P7, ['Integer']
1685   set P7, 42
1686   new_callback P5, P6, P7, "vUt"    # Z in pdd16
1687   print "ok 1\n"
1688   # now call the external sub, that takes a call_back and user_data
1689   loadlib P1, "libnci_test"
1690   dlfunc P0, P1, "nci_cb_D1", "vpP"
1691   print "ok 2\n"
1692   # P5 is the cb
1693   # P7 is user_data
1694   set_args "0,0", P5, P7
1695   invokecc P0
1696   # call_back will be called at any time
1697   # so spin a bit
1698   set I20, 0
1699 loop:
1700   inc I20
1701   sleep 0.01
1702   get_global P11, "cb_done"
1703   if P11, fin
1704   gt I20, 10, err
1705   branch loop
1706 fin:
1707   print "done.\n"
1708   end
1709 err:
1710   print "cb didnt run\n"
1711   end
1713 .pcc_sub _call_back:
1714   get_params "0,0", P5, S5
1715   print "in callback\n"
1716   print "user data: "
1717   print P5
1718   print "\n"
1719   print "external data: "
1720   print S5
1721   print "\n"
1722   get_global P12, "cb_done"
1723   inc P12
1724   returncc
1726 CODE
1727 ok 1
1728 ok 2
1729 in callback
1730 user data: 42
1731 external data: succeeded
1732 done.
1733 OUTPUT
1735     pasm_output_is( <<'CODE', <<'OUTPUT', "nci_cb_D2 - PASM", @todo );
1736   # we need a flag if the call_back is already done
1737   new P10, ['Integer']
1738   set_global "cb_done", P10
1739   # first attempt - create cb manually (this step will be hidden later)
1740   .const 'Sub' P6 = "_call_back"
1741   # prepare user data
1742   new P7, ['Integer']
1743   set P7, 42
1744   new_callback P5, P6, P7, "vUi"    # Z in pdd16
1745   print "ok 1\n"
1746   # now call the external sub, that takes a call_back and user_data
1747   loadlib P1, "libnci_test"
1748   dlfunc P0, P1, "nci_cb_D2", "vpP"
1749   print "ok 2\n"
1750   # P5 is the cb
1751   # P7 is user_data
1752   set_args "0,0", P5, P7
1753   invokecc P0
1754   # call_back will be called at any time
1755   # so spin a bit
1756   set I20, 0
1757 loop:
1758   inc I20
1759   sleep 0.01
1760   get_global P11, "cb_done"
1761   if P11, fin
1762   gt I20, 10, err
1763   branch loop
1764 fin:
1765   print "done.\n"
1766   end
1767 err:
1768   print "cb didnt run\n"
1769   end
1771 .pcc_sub _call_back:
1772   get_params "0,0", P5, I5
1773   print "in callback\n"
1774   print "user data: "
1775   print P5
1776   print "\n"
1777   print "external data: "
1778   print I5
1779   print "\n"
1780   get_global P12, "cb_done"
1781   inc P12
1782   returncc
1785 CODE
1786 ok 1
1787 ok 2
1788 in callback
1789 user data: 42
1790 external data: 88
1791 done.
1792 OUTPUT
1794     pir_output_is( <<'CODE', <<'OUTPUT', "nci_cb_D2 - PIR", @todo );
1796 .sub test :main
1798     # this flag will be set by the callback function
1799     .local pmc cb_done
1800     cb_done = new ['Integer']
1801     cb_done = 0
1802     set_global "cb_done", cb_done
1804     # prepare user data
1805     .local pmc user_data
1806     user_data = new ['Integer']
1807     user_data = 42
1809     # A Sub that can be given to the library
1810     # this callback function will eventually by called by the library
1811     .const 'Sub' cb = "_call_back"
1812     .local pmc cb_wrapped
1813     cb_wrapped = new_callback cb, user_data, "vUi"  # Z in pdd16
1814     print "created a callback sub\n"
1816     # now call the external sub, that takes a callback and user data
1817     .local pmc libnci_test
1818     libnci_test = loadlib "libnci_test"
1819     .local pmc nci_cb_D2
1820     nci_cb_D2 = dlfunc libnci_test, "nci_cb_D2", "vpP"
1821     print "loaded a function that takes a callback\n"
1822     nci_cb_D2( cb_wrapped, user_data )
1824     # callback will be called at any time
1825     # so spin a bit
1826     .local int sleep_cnt
1827     sleep_cnt = 0
1828 LOOP:
1829     sleep_cnt += 1
1830     sleep 0.01
1831     .local pmc callback_has_run
1832     callback_has_run = get_global "cb_done"
1833     if callback_has_run goto FINISHED
1834     if sleep_cnt > 10 goto ERROR
1835     goto LOOP
1836 FINISHED:
1837     print "the callback has run\n"
1838     end
1839 ERROR:
1840     print "the callback didnt run\n"
1841     end
1842 .end
1844 .sub _call_back
1845 .param pmc u
1846 .param int i
1847   print "in callback\n"
1848   print "user data: "
1849   print u
1850   print "\n"
1851   print "external data: "
1852   print i
1853   print "\n"
1854   get_global $P12, "cb_done"
1855   inc $P12
1856   returncc
1857 .end
1859 CODE
1860 created a callback sub
1861 loaded a function that takes a callback
1862 in callback
1863 user data: 42
1864 external data: 88
1865 the callback has run
1866 OUTPUT
1868     pir_output_is( <<'CODE', <<'OUTPUT', "nci_cb_D3 - PIR", @todo );
1871 .include "datatypes.pasm"
1873 .sub test :main
1875     # this flag will be set by the callback function
1876     .local pmc cb_done
1877     cb_done = new ['Integer']
1878     cb_done = 0
1879     set_global "cb_done", cb_done
1881     # prepare user data
1882     .local pmc user_data
1883     user_data = new ['Integer']
1884     user_data = 42
1886     # A Sub that can be given to the library
1887     # this callback function will eventually by called by the library
1888     .const 'Sub' cb = "_call_back"
1889     .local pmc cb_wrapped
1890     cb_wrapped = new_callback cb, user_data, "vUp"  # Z in pdd16
1891     print "created a callback sub\n"
1893     # now call the external sub, that takes a callback and user data
1894     .local pmc libnci_test
1895     libnci_test = loadlib "libnci_test"
1896     .local pmc nci_cb_D3
1897     nci_cb_D3 = dlfunc libnci_test, "nci_cb_D3", "vpP"
1898     print "loaded a function that takes a callback\n"
1899     nci_cb_D3( cb_wrapped, user_data )
1901     # callback will be called at any time
1902     # so spin a bit
1903     .local int sleep_cnt
1904     sleep_cnt = 0
1905 LOOP:
1906     sleep_cnt += 1
1907     sleep 0.01
1908     .local pmc callback_has_run
1909     callback_has_run = get_global "cb_done"
1910     if callback_has_run goto FINISHED
1911     if sleep_cnt > 10 goto ERROR
1912     goto LOOP
1913 FINISHED:
1914     print "the callback has run\n"
1915     end
1916 ERROR:
1917     print "the callback didnt run\n"
1918     end
1919 .end
1921 .sub _call_back
1922 .param pmc u
1923 .param pmc s
1924   print "in callback\n"
1925   print "user data: "
1926   print u
1927   print "\n"
1929   # s is a UnManagedStruct PMC containing a pointer to an integer
1930   new $P2, ['ResizablePMCArray']
1931   push $P2, .DATATYPE_INT
1932   push $P2, 0
1933   push $P2, 0
1934   assign s, $P2
1936   # print referenced integer in libnci_test.so
1937   $I17 = s[0]
1938   print "external data: "
1939   print $I17
1940   print "\n"
1942   get_global $P12, "cb_done"
1943   inc $P12
1944   returncc
1945 .end
1947 CODE
1948 created a callback sub
1949 loaded a function that takes a callback
1950 in callback
1951 user data: 42
1952 external data: 111
1953 the callback has run
1954 OUTPUT
1956     pir_output_is( <<'CODE', <<'OUTPUT', "nci_cb_D4 - synchronous callbacks" );
1959 .include "datatypes.pasm"
1961 .sub test :main
1963     # turn off JIT or special core - no events yet
1964     bounds 1
1965     # prepare user data
1966     .local pmc user_data
1967     user_data = new ['Integer']
1968     user_data = 42
1970     # load libnci_test
1971     .local pmc libnci_test
1972     libnci_test = loadlib "libnci_test"
1974     # reset int_cb_D4 to 1
1975     .local pmc int_cb_D4
1976     int_cb_D4 = dlvar libnci_test, "int_cb_D4"
1977     .local pmc int_cb_D4_decl
1978     int_cb_D4_decl = new ['ResizablePMCArray']
1979     push int_cb_D4_decl, .DATATYPE_INT
1980     push int_cb_D4_decl, 0
1981     push int_cb_D4_decl, 0
1982     assign int_cb_D4, int_cb_D4_decl
1983     int_cb_D4[0] = 1
1985     # A Sub that can be given to the library
1986     # this callback function will eventually by called by the library
1987     .const 'Sub' cb = "_call_back"
1988     .local pmc cb_wrapped
1989     cb_wrapped = new_callback cb, user_data, "vUp"  # Z in pdd16
1990     print "created a callback sub\n"
1992     # now call the external sub, that takes a callback and user data
1993     .local pmc nci_cb_D4
1994     nci_cb_D4 = dlfunc libnci_test, "nci_cb_D4", "vpP"
1995     print "loaded a function that takes a callback\n"
1996     nci_cb_D4( cb_wrapped, user_data )
1998     # reset int_cb_D4 to 1
1999     int_cb_D4[0] = 1
2001     .local pmc synchronous
2002     synchronous = new ['Integer']
2003     synchronous = 1
2004     setprop user_data, "_synchronous", synchronous
2005     print "marked callback as synchronous\n"
2006     nci_cb_D4( cb_wrapped, user_data )
2008     end
2009 .end
2011 .sub _call_back
2012 .param pmc u
2013 .param pmc s
2014   # s is a UnManagedStruct PMC containing a pointer to an integer
2015   new $P2, ['ResizablePMCArray']
2016   push $P2, .DATATYPE_INT
2017   push $P2, 0
2018   push $P2, 0
2019   assign s, $P2
2021   print "external data: "
2022   $I17 = s[0]
2023   print $I17
2024   print "\n"
2025   $I17 = $I17 * 10
2026   s[0] = $I17
2028   returncc
2029 .end
2031 CODE
2032 created a callback sub
2033 loaded a function that takes a callback
2034 external data: 10
2035 external data: 100
2036 external data: 1000
2037 external data: 10000
2038 external data: 100000
2039 external data: 1000000
2040 external data: 10000000
2041 external data: 100000000
2042 external data: 1000000000
2043 marked callback as synchronous
2044 external data: 1
2045 external data: 11
2046 external data: 111
2047 external data: 1111
2048 external data: 11111
2049 external data: 111111
2050 external data: 1111111
2051 external data: 11111111
2052 external data: 111111111
2053 OUTPUT
2055     pasm_output_is( <<'CODE', <<'OUTPUT', 'nci_pip - array of structs' );
2057 .include "datatypes.pasm"
2058   new P3, ['OrderedHash']
2059   set  P3["x"], .DATATYPE_INT
2060   push P3, 0
2061   push P3, 0
2062   set  P3["y"], .DATATYPE_INT
2063   push P3, 0
2064   push P3, 0
2065   set  P3["w"], .DATATYPE_INT
2066   push P3, 0
2067   push P3, 0
2068   set  P3["h"], .DATATYPE_INT
2069   push P3, 0
2070   push P3, 0
2071   new P6, ['UnManagedStruct'], P3
2073   new P4, ['OrderedHash']
2074   set  P4["Rect"], .DATATYPE_STRUCT
2075   set P1, P4[-1]
2076   setprop P1, "_struct", P6
2077   push P4, 4
2078   push P4, 0
2080   new P5, ['ManagedStruct'], P4
2081   set P5[0;0;'x'], 100
2082   set P5[0;0;'y'], 110
2083   set P5['Rect';0;'w'], 120
2084   set P5[0;0;'h'], 130
2086   set P5[0;1;'x'], 200
2087   set P5[0;1;'y'], 210
2088   set P5[0;1;'w'], 220
2089   set P5[0;1;'h'], 230
2091   set P5[0;2;'x'], 300
2092   set P5[0;2;'y'], 310
2093   set P5[0;2;'w'], 320
2094   set P5[0;2;'h'], 330
2096   set P5[0;3;'x'], 400
2097   set P5[0;3;'y'], 410
2098   set P5[0;3;'w'], 420
2099   set P5[0;3;'h'], 430
2101   loadlib P1, "libnci_test"
2102   set_args "0,0", 4, P5
2103   dlfunc P0, P1, "nci_pip", "pip"
2104   invokecc P0
2105   end
2107 CODE
2108 Count: 4
2109 X: 100
2110 Y: 110
2111 W: 120
2112 H: 130
2113 X: 200
2114 Y: 210
2115 W: 220
2116 H: 230
2117 X: 300
2118 Y: 310
2119 W: 320
2120 H: 330
2121 X: 400
2122 Y: 410
2123 W: 420
2124 H: 430
2125 OUTPUT
2127     pasm_output_is( <<'CODE', <<'OUTPUT', 'nci_i33 - out parameters and return values' );
2129 .include "datatypes.pasm"
2130   new P2, ['Integer']
2131   set P2, 3
2132   new P3, ['Integer']
2133   set P3, 2
2135   loadlib P1, "libnci_test"
2136   set_args "0,0", P2, P3
2137   dlfunc P0, P1, "nci_i33", "i33"
2138   invokecc P0
2139   get_results "0", I5
2141   print "Double: "
2142   print P2
2143   print "\nTriple: "
2144   print P3
2145   print "\nSum: "
2146   print I5
2147   print "\n"
2149   end
2150 CODE
2151 Double: 6
2152 Triple: 6
2153 Sum: 12
2154 OUTPUT
2156 pasm_output_is( <<'CODE', <<'OUTPUT', 'nci_vpii - nested structs' );
2158 .include "datatypes.pasm"
2159   new  P8, 'OrderedHash'
2160   set  P8[ 'y' ],      .DATATYPE_INT
2161   push P8, 0
2162   push P8, 0
2163   new  P9, 'ManagedStruct', P8
2165   new  P6, 'OrderedHash'
2166   set  P6[ 'x' ],      .DATATYPE_INT
2167   push P6, 0
2168   push P6, 0
2169   set  P6[ 'nested' ], .DATATYPE_STRUCT_PTR
2171   set  P7, P6[ -1 ]
2172   setprop P7, '_struct', P9
2174   push P6, 0
2175   push P6, 0
2177   new  P5, 'ManagedStruct', P6
2178   set  P5[ 'nested'; 'y' ], 200
2179   set  P5[ 'x' ], 100
2181   set I0, P5[ 'x' ]
2182   set I1, P5[ 'nested'; 'y' ]
2183   print "Old X: "
2184   say I0
2185   print "Old Y: "
2186   say I1
2188   set_args "0,0,0", P5, 1, 2
2189   loadlib P1, "libnci_test"
2190   dlfunc P0, P1, "nci_vpii", "vpii"
2191   invokecc P0
2193   set I0, P5[ 'x' ]
2194   set P6, P5[ 'nested' ]
2195   set I1, P6[ 'y' ]
2196   print "X: "
2197   say I0
2198   print "Y: "
2199   say I1
2200   # extract struct
2201   set P6, P5[ 'nested' ]
2202   set I1, P6[ 'y' ]
2203   say I1
2204   end
2205 CODE
2206 Old X: 100
2207 Old Y: 200
2208 X: 1
2209 Y: 2
2211 OUTPUT
2213     pasm_output_is( <<'CODE', <<'OUTPUT', 'nci_piiii - nested array in a struct' );
2214 .include "datatypes.pasm"
2216   loadlib P1, "libnci_test"
2217   dlfunc P0, P1, "nci_piiii", "piiii"
2218   set_args "0,0,0,0", 100,200,400,800
2219   invokecc P0
2220   get_results "0", P5
2222   new  P6, 'OrderedHash'
2223   set  P6[ 'count' ], .DATATYPE_INT
2224   push P6, 0
2225   push P6, 0
2227   new  P7, 'OrderedHash'
2228   set  P7[ 'array' ], .DATATYPE_INT
2229   push P7, 0
2230   push P7, 0
2231   new P8, ['UnManagedStruct'], P7
2232   # yes, the array within the struct has _4_ elements
2233   # but with an UnManagedStruct, you can't always know the amount beforehand
2234   set  P6[ 'array' ], .DATATYPE_STRUCT_PTR
2235   set P9, P6[-1]
2236   setprop P9, "_struct", P8
2237   push P6, 0
2238   push P6, 0
2240   assign P5, P6
2241   set    I0, P5[ 'count' ]
2243   print "Count: "
2244   print I0
2245   print "\n"
2247   # now that we do know, update the UnManagedStruct appropriately
2248   set    P7[ 1 ], I0
2249   assign P5, P6
2251   set I0, P5[1; 'array'; 0 ]
2252   set I1, P5[ 1;'array'; 1 ]
2253   set I2, P5[ 1;'array'; 2 ]
2254   set I3, P5[ 1;'array'; 3 ]
2255   print "0: "
2256   print I0
2257   print "\n1: "
2258   print I1
2259   print "\n2: "
2260   print I2
2261   print "\n3: "
2262   print I3
2263   print "\n"
2265   end
2266 CODE
2267 Count: 4
2268 0: 100
2269 1: 200
2270 2: 400
2271 3: 800
2272 OUTPUT
2274     pir_output_is( << 'CODE', << "OUTPUT", "nci_pii - writing back to libnci_test.so" );
2276 .include "datatypes.pasm"
2278 .sub test :main
2280   # load library
2281   .local pmc libnci_test
2282   libnci_test = loadlib "libnci_test"
2283   unless libnci_test goto NOT_LOADED
2284   print "libnci_test was successfully loaded\n"
2286   # calling a function in libnci_test
2287   .local pmc multiply
2288   multiply = dlfunc libnci_test, "nci_pii", "pii"
2289   .local pmc product_pointer
2290   ( product_pointer ) = multiply( -5, 11111 )
2292   # the contained structure pointer
2293   .local pmc product_pointer_decl
2294   product_pointer_decl = new ['ResizablePMCArray']
2295   push product_pointer_decl, .DATATYPE_INT
2296   push product_pointer_decl, 0
2297   push product_pointer_decl, 0
2298   assign product_pointer, product_pointer_decl
2300   # check result of multiplication
2301   .local int product
2302   product = product_pointer[0]
2303   print product
2304   print "\n"
2306   # Write back into libnci_test and check it
2307   product_pointer[0] = 333
2308   product = 4444
2309   print product
2310   print "\n"
2311   .local pmc nci_i
2312   dlfunc nci_i, libnci_test, "nci_i", "i"
2313   ( product ) = nci_i()
2314   print product
2315   print "\n"
2317 NOT_LOADED:
2318   end
2319 .end
2320 CODE
2321 libnci_test was successfully loaded
2322 -55555
2323 4444
2325 OUTPUT
2327 SKIP:
2328     {
2330         skip( "nci_dlvar_int hangs on HP-UX", 1 ) if $^O eq 'hpux';
2332         pir_output_is( << 'CODE', << 'OUTPUT', "nci_vv and nci_dlvar_int" );
2334 .include "datatypes.pasm"
2336 .sub test :main
2338     # load libnci_test.so
2339     .local string library_name
2340     library_name = 'libnci_test'
2341     .local pmc libnci_test
2342     libnci_test = loadlib library_name
2343     unless libnci_test goto NOT_LOADED
2344     print library_name
2345     print " was successfully loaded\n"
2347     # address of nci_dlvar_int
2348     .local pmc nci_dlvar_int
2349     nci_dlvar_int = dlvar libnci_test, "nci_dlvar_int"
2351     # the contained structure pointer
2352     .local pmc nci_dlvar_int_decl
2353     nci_dlvar_int_decl = new ['ResizablePMCArray']
2354     push nci_dlvar_int_decl, .DATATYPE_INT
2355     push nci_dlvar_int_decl, 0
2356     push nci_dlvar_int_decl, 0
2357     assign nci_dlvar_int, nci_dlvar_int_decl
2359     $I2 = nci_dlvar_int[0]
2360     print $I2
2361     print "\n"
2363     .local pmc nci_vv
2364     nci_vv = dlfunc libnci_test, "nci_vv", ""
2365     nci_vv()
2366     $I1 = nci_dlvar_int[0]
2367     print $I1
2368     print "\n"
2369     nci_vv()
2370     $I1 = nci_dlvar_int[0]
2371     print $I1
2372     print "\n"
2373     nci_vv()
2374     $I1 = nci_dlvar_int[0]
2375     print $I1
2376     print "\n"
2377     nci_vv()
2378     $I1 = nci_dlvar_int[0]
2379     print $I1
2380     print "\n"
2381 NOT_LOADED:
2382 .end
2383 CODE
2384 libnci_test was successfully loaded
2385 -4444
2386 -13332
2387 -39996
2388 -119988
2389 -359964
2390 OUTPUT
2391     }
2393     pir_output_is( << 'CODE', << 'OUTPUT', "dlvar - unknown symbol" );
2395 .include "datatypes.pasm"
2397 .sub test :main
2399     # load libnci_test.so
2400     .local string library_name
2401     library_name = 'libnci_test'
2402     .local pmc libnci_test
2403     libnci_test = loadlib library_name
2404     unless libnci_test goto NOT_LOADED
2405     print library_name
2406     print " was successfully loaded\n"
2408     # address of nci_dlvar_int
2409     .local pmc non_existing
2410     non_existing = dlvar libnci_test, "non_existing"
2411     .local int is_defined
2412     is_defined = defined non_existing
2413     if is_defined goto IS_DEFINED
2414     print "'non_existing' is not defined\n"
2415 IS_DEFINED:
2416 NOT_LOADED:
2417 .end
2418 CODE
2419 libnci_test was successfully loaded
2420 'non_existing' is not defined
2421 OUTPUT
2423     pir_output_is( << 'CODE', << 'OUTPUT', "dlfunc - unknown symbol" );
2425 .include "datatypes.pasm"
2427 .sub test :main
2429     # load libnci_test.so
2430     .local string library_name
2431     library_name = 'libnci_test'
2432     .local pmc libnci_test
2433     libnci_test = loadlib library_name
2434     unless libnci_test goto NOT_LOADED
2435     print library_name
2436     print " was successfully loaded\n"
2438     # address of nci_dlvar_int
2439     .local pmc non_existing
2440     non_existing = dlfunc libnci_test, "non_existing", "iiii"
2441     .local int is_defined
2442     is_defined = defined non_existing
2443     if is_defined goto IS_DEFINED
2444     print "'non_existing' is not defined\n"
2445 IS_DEFINED:
2446 NOT_LOADED:
2447 .end
2448 CODE
2449 libnci_test was successfully loaded
2450 'non_existing' is not defined
2451 OUTPUT
2453     pasm_output_is( << 'CODE', << 'OUTPUT', "loading same library twice" );
2454       loadlib P1, "libnci_test"
2455       if P1, OK1
2456       print "not "
2457 OK1:  print "ok 1\n"
2458       loadlib P2, "libnci_test"
2459       if P2, OK2
2460       print "not "
2461 OK2:  print "ok 2\n"
2462       issame I0, P1, P2
2463       if I0, OK3
2464       print "not "
2465 OK3:  print "ok 3\n"
2466       end
2467 CODE
2468 ok 1
2469 ok 2
2470 ok 3
2471 OUTPUT
2473 }    # SKIP
2475 pir_output_is( << 'CODE', << 'OUTPUT', "opcode 'does'" );
2477 .sub test :main
2478     .local pmc pmc1
2479     pmc1 = new ['ParrotLibrary']
2480     .local int bool1
2481     does bool1, pmc1, "scalar"
2482     print bool1
2483     print "\n"
2484     does bool1, pmc1, "library"
2485     print bool1
2486     print "\n"
2487     does bool1, pmc1, "no_interface"
2488     print bool1
2489     print "\n"
2490     end
2491 .end
2492 CODE
2496 OUTPUT
2498 pir_output_is( << 'CODE', << 'OUTPUT', "conversion d <-> P" );
2499 .sub test :main
2500     .local string library_name
2501     library_name = 'libnci_test'
2502     .local pmc libnci_test
2503     libnci_test = loadlib  library_name
2504     .local pmc twice
2505     twice = dlfunc libnci_test, "nci_dd", "dd"
2506     .local pmc f, g
2507     f = new ['Integer']
2508     f = 21
2509     g = twice( f )
2510     print g
2511     print "\n"
2512 .end
2513 CODE
2515 OUTPUT
2517 pir_output_is( << 'CODE', << 'OUTPUT', "conversion S <-> P" );
2518 .sub test :main
2519     .local string library_name
2520     library_name = 'libnci_test'
2521     .local pmc libnci_test
2522     libnci_test = loadlib  library_name
2523     .local pmc reverse
2524     reverse = dlfunc libnci_test, "nci_tt", "tt"
2525     .local pmc s, t
2526     s = new ['String']
2527     s = "ko"
2528     t = reverse( s )
2529     print t
2530 .end
2531 CODE
2532 ok worked
2533 OUTPUT
2535 pir_output_is( << 'CODE', << 'OUTPUT', "conversion I <-> P" );
2536 .sub test :main
2537     .local string library_name
2538     library_name = 'libnci_test'
2539     .local pmc libnci_test
2540     libnci_test = loadlib  library_name
2541     .local pmc mult
2542     mult = dlfunc libnci_test, "nci_i4i", "i4i"
2543     .local pmc i, j
2544     i = new ['Integer']
2545     i = 2
2546     j = mult( 21, i )       # call signature is PI
2547     say j
2548 .end
2549 CODE
2551 OUTPUT
2553 pir_output_is(
2554     << 'CODE', << 'OUTPUT', 'nested structs should be independent' );
2555 .include 'datatypes.pasm'
2557 .sub 'test' :main
2558     .local string library_name
2559     library_name = 'libnci_test'
2561     .local pmc libnci_test
2562     libnci_test = loadlib library_name
2564     .local pmc types
2565     types = new ['OrderedHash']
2566     types['y'] = .DATATYPE_INT
2567     push types, 0
2568     push types, 0
2570     .local pmc nested
2571     nested = new ['ManagedStruct'], types
2573     .local pmc outer
2574     outer = make_outer_struct( nested )
2575     outer[ 'x' ] = 0
2576     outer[ 'nested'; 'y' ] = 0
2578     .local pmc nci_func
2579     nci_func = dlfunc libnci_test, 'nci_vpii', 'vpii'
2581     print_values( outer )
2582     nci_func( outer, 1, 100 )
2583     print_values( outer )
2585     .local pmc other
2586     other = make_outer_struct( nested )
2588     # autovivify the nested hash
2589     other[ 'nested'; 'y' ] = 1
2590     nci_func( other, 2, 200 )
2592     print_values( outer )
2593     print_values( other )
2594 .end
2596 .sub 'print_values'
2597     .param pmc outer
2599     .local int x, y
2600     x = outer['x']
2601     y = outer[ 'nested'; 'y' ]
2602     print "X: "
2603     say x
2604     print "Y: "
2605     say y
2606 .end
2608 .sub 'make_outer_struct'
2609     .param pmc nested
2611     .local pmc types
2612     types        = new ['OrderedHash']
2613     types[ 'x' ] = .DATATYPE_INT
2614     push types, 0
2615     push types, 0
2616     types[ 'nested' ] = .DATATYPE_STRUCT_PTR
2618     .local pmc struct_ptr
2619     struct_ptr = types[-1]
2620     setprop struct_ptr, '_struct', nested
2621     push types, 0
2622     push types, 0
2624     .local pmc outer
2625     outer = new ['ManagedStruct'], types
2627     .return( outer )
2628 .end
2629 CODE
2630 X: 0
2631 Y: 0
2632 X: 1
2633 Y: 100
2634 X: 1
2635 Y: 100
2636 X: 2
2637 Y: 200
2638 OUTPUT
2640 pir_output_is( << 'CODE', << 'OUTPUT', "arity" );
2641 .sub test :main
2642     .local string library_name
2643     library_name = 'libnci_test'
2644     .local pmc libnci_test
2645     libnci_test = loadlib  library_name
2647     .local pmc nci_c
2648     nci_c = dlfunc libnci_test, "nci_c", "c"
2649     $I0 = nci_c.'arity'()
2650     say $I0
2652     .local pmc multiply
2653     multiply = dlfunc libnci_test, "nci_pii", "pii"
2654     $I0 = multiply.'arity'()
2655     say $I0
2657     .local pmc nci_iiii
2658     nci_iiii = dlfunc libnci_test, "nci_iiii", "iiii"
2659     $I0 = nci_iiii.'arity'()
2660     say $I0
2661 .end
2662 CODE
2666 OUTPUT
2668 pir_output_is( << 'CODE', << 'OUTPUT', "nci_vVi - void** out parameter" );
2669 .sub test :main
2670     .local string library_name
2671     library_name = 'libnci_test'
2672     .local pmc libnci_test
2673     libnci_test = loadlib  library_name
2675     .local pmc nci_vVi
2676     nci_vVi = dlfunc libnci_test, "nci_vVi", "vVi"
2678     .local pmc nci_vp
2679     nci_vp = dlfunc libnci_test, "nci_vp", "vp"
2681     .local pmc opaque
2682     null opaque
2683     nci_vp(opaque)
2685     opaque = new ['Pointer']
2686     $I0 = 10
2687     nci_vVi(opaque, $I0)
2688     nci_vp(opaque)
2689 .end
2690 CODE
2691 got null
2692 got 10
2693 OUTPUT
2695 pir_output_is( << 'CODE', << 'OUTPUT', "nci_ttt - t_tt parameter" );
2696 .sub test :main
2697     .local string library_name
2698     library_name = 'libnci_test'
2699     .local pmc libnci_test
2700     libnci_test = loadlib  library_name
2702     .local pmc nci_ttt
2703     nci_ttt = dlfunc libnci_test, "nci_ttt", "ttt"
2705     $S0 = nci_ttt("Hello", "Waldo")
2706     say $S0
2707 .end
2708 CODE
2709 Waldo, Waldo, Hello
2710 Waldo, Waldo, Hello
2711 OUTPUT
2713 pir_output_is( << 'CODE', << 'OUTPUT', "nci_vfff - v_fff parameter" );
2714 .sub test :main
2715     .local string library_name
2716     library_name = 'libnci_test'
2717     .local pmc libnci_test
2718     libnci_test = loadlib  library_name
2720     .local pmc nci_vfff
2721     nci_vfff = dlfunc libnci_test, "nci_vfff", "vfff"
2723     nci_vfff(3456.54, 10.1999, 14245.567)
2724 .end
2725 CODE
2729 OUTPUT
2731 pir_output_is( << 'CODE', << 'OUTPUT', "nci_vV - char** out parameter" );
2732 .sub test :main
2733     .local string library_name
2734     library_name = 'libnci_test'
2735     .local pmc libnci_test
2736     libnci_test = loadlib  library_name
2738     .local pmc nci_vV
2739     nci_vV = dlfunc libnci_test, "nci_vV", "vV"
2741     .local pmc char_s_s
2742     char_s_s = new ['Pointer']
2743     nci_vV(char_s_s)
2744     $S0 = char_s_s
2745     print $S0
2746 .end
2747 CODE
2748 Hello bright new world
2749 OUTPUT
2751 pir_output_is( << 'CODE', << 'OUTPUT', "nci_vVV - multiple char** out parameters" );
2752 .sub test :main
2753     .local string library_name
2754     library_name = 'libnci_test'
2755     .local pmc libnci_test
2756     libnci_test = loadlib  library_name
2758     .local pmc nci_vVVV
2759     nci_vVVV = dlfunc libnci_test, "nci_vVVV", "vVVV"
2761     .local pmc char_s_s1, char_s_s2, char_s_s3
2762     char_s_s1 = new ['Pointer']
2763     char_s_s2 = new ['Pointer']
2764     char_s_s3 = new ['Pointer']
2765     nci_vVVV(char_s_s1, char_s_s2, char_s_s3)
2766     $S1 = char_s_s1
2767     print $S1
2768     $S1 = char_s_s2
2769     print $S1
2770     $S1 = char_s_s3
2771     print $S1
2772 .end
2773 CODE
2774 Hello bright new world!
2775 It is a beautiful day!
2776 Go suck a lemon.
2777 OUTPUT
2779 # Local Variables:
2780 #   mode: cperl
2781 #   cperl-indent-level: 4
2782 #   fill-column: 100
2783 # End:
2784 # vim: expandtab shiftwidth=4: