File Coverage

ext/XS-Typemap/Typemap.xs
Criterion Covered Total %
statement 123 140 87.9
branch n/a
condition n/a
subroutine n/a
total 123 140 87.9


line stmt bran cond sub time code
1           /*
2           XS code to test the typemap entries
3            
4           Copyright (C) 2001 Tim Jenness.
5           All Rights Reserved
6            
7           */
8            
9           #define PERL_NO_GET_CONTEXT
10            
11           #include "EXTERN.h" /* std perl include */
12           #include "perl.h" /* std perl include */
13           #include "XSUB.h" /* XSUB include */
14            
15           /* Prototypes for external functions */
16           FILE * xsfopen( const char * );
17           int xsfclose( FILE * );
18           int xsfprintf( FILE *, const char *);
19            
20           /* Type definitions required for the XS typemaps */
21           typedef SV * SVREF; /* T_SVREF */
22           typedef int SysRet; /* T_SYSRET */
23           typedef int Int; /* T_INT */
24           typedef int intRef; /* T_PTRREF */
25           typedef int intObj; /* T_PTROBJ */
26           typedef int intRefIv; /* T_REF_IV_PTR */
27           typedef int intArray; /* T_ARRAY */
28           typedef int intTINT; /* T_INT */
29           typedef int intTLONG; /* T_LONG */
30           typedef short shortOPQ; /* T_OPAQUE */
31           typedef int intOpq; /* T_OPAQUEPTR */
32           typedef unsigned intUnsigned; /* T_U_INT */
33           typedef PerlIO * inputfh; /* T_IN */
34           typedef PerlIO * outputfh; /* T_OUT */
35            
36           /* A structure to test T_OPAQUEPTR and T_PACKED */
37           struct t_opaqueptr {
38           int a;
39           int b;
40           double c;
41           };
42            
43           typedef struct t_opaqueptr astruct;
44           typedef struct t_opaqueptr anotherstruct;
45            
46           /* Some static memory for the tests */
47           static I32 xst_anint;
48           static intRef xst_anintref;
49           static intObj xst_anintobj;
50           static intRefIv xst_anintrefiv;
51           static intOpq xst_anintopq;
52            
53           /* A different type to refer to for testing the different
54           * AV*, HV*, etc typemaps */
55           typedef AV AV_FIXED;
56           typedef HV HV_FIXED;
57           typedef CV CV_FIXED;
58           typedef SVREF SVREF_FIXED;
59            
60           /* Helper functions */
61            
62           /* T_ARRAY - allocate some memory */
63 2         intArray * intArrayPtr( int nelem ) {
64           intArray * array;
65 2         Newx(array, nelem, intArray);
66 2         return array;
67           }
68            
69           /* test T_PACKED */
70           STATIC void
71 2         XS_pack_anotherstructPtr(SV *out, anotherstruct *in)
72           {
73           dTHX;
74 2         HV *hash = newHV();
75 2         if (NULL == hv_stores(hash, "a", newSViv(in->a)))
76 0         croak("Failed to store data in hash");
77 2         if (NULL == hv_stores(hash, "b", newSViv(in->b)))
78 0         croak("Failed to store data in hash");
79 2         if (NULL == hv_stores(hash, "c", newSVnv(in->c)))
80 0         croak("Failed to store data in hash");
81 2         sv_setsv(out, sv_2mortal(newRV_noinc((SV*)hash)));
82 2         }
83            
84           STATIC anotherstruct *
85 2         XS_unpack_anotherstructPtr(SV *in)
86 2         {
87           dTHX; /* rats, this is expensive */
88           /* this is similar to T_HVREF since we chose to use a hash */
89           HV *inhash;
90           SV **elem;
91           anotherstruct *out;
92           SV *const tmp = in;
93 2         SvGETMAGIC(tmp);
94 2         if (SvROK(tmp) && SvTYPE(SvRV(tmp)) == SVt_PVHV)
95 2         inhash = (HV*)SvRV(tmp);
96           else
97 0         Perl_croak(aTHX_ "Argument is not a HASH reference");
98            
99           /* FIXME dunno if supposed to use perl mallocs here */
100 2         Newxz(out, 1, anotherstruct);
101            
102 2         elem = hv_fetchs(inhash, "a", 0);
103 2         if (elem == NULL)
104 0         Perl_croak(aTHX_ "Shouldn't happen: hv_fetchs returns NULL");
105 2         out->a = SvIV(*elem);
106            
107 2         elem = hv_fetchs(inhash, "b", 0);
108 2         if (elem == NULL)
109 0         Perl_croak(aTHX_ "Shouldn't happen: hv_fetchs returns NULL");
110 2         out->b = SvIV(*elem);
111            
112 2         elem = hv_fetchs(inhash, "c", 0);
113 2         if (elem == NULL)
114 0         Perl_croak(aTHX_ "Shouldn't happen: hv_fetchs returns NULL");
115 2         out->c = SvNV(*elem);
116            
117 2         return out;
118           }
119            
120           /* test T_PACKEDARRAY */
121           STATIC void
122 2         XS_pack_anotherstructPtrPtr(SV *out, anotherstruct **in, UV cnt)
123           {
124           dTHX;
125           UV i;
126 2         AV *ary = newAV();
127 8         for (i = 0; i < cnt; ++i) {
128 6         HV *hash = newHV();
129 6         if (NULL == hv_stores(hash, "a", newSViv(in[i]->a)))
130 0         croak("Failed to store data in hash");
131 6         if (NULL == hv_stores(hash, "b", newSViv(in[i]->b)))
132 0         croak("Failed to store data in hash");
133 6         if (NULL == hv_stores(hash, "c", newSVnv(in[i]->c)))
134 0         croak("Failed to store data in hash");
135 6         av_push(ary, newRV_noinc((SV*)hash));
136           }
137 2         sv_setsv(out, sv_2mortal(newRV_noinc((SV*)ary)));
138 2         }
139            
140           STATIC anotherstruct **
141 2         XS_unpack_anotherstructPtrPtr(SV *in)
142 8         {
143           dTHX; /* rats, this is expensive */
144           /* this is similar to T_HVREF since we chose to use a hash */
145           HV *inhash;
146           AV *inary;
147           SV **elem;
148           anotherstruct **out;
149           UV nitems, i;
150           SV *tmp;
151            
152           /* safely deref the input array ref */
153           tmp = in;
154 2         SvGETMAGIC(tmp);
155 2         if (SvROK(tmp) && SvTYPE(SvRV(tmp)) == SVt_PVAV)
156 2         inary = (AV*)SvRV(tmp);
157           else
158 0         Perl_croak(aTHX_ "Argument is not an ARRAY reference");
159            
160 2         nitems = av_len(inary) + 1;
161            
162           /* FIXME dunno if supposed to use perl mallocs here */
163           /* N+1 elements so we know the last one is NULL */
164 2         Newxz(out, nitems+1, anotherstruct*);
165            
166           /* WARNING: in real code, we'd have to Safefree() on exception, but
167           * since we're testing perl, if we croak() here, stuff is
168           * rotten anyway! */
169 8         for (i = 0; i < nitems; ++i) {
170 6         Newxz(out[i], 1, anotherstruct);
171 6         elem = av_fetch(inary, i, 0);
172 6         if (elem == NULL)
173 0         Perl_croak(aTHX_ "Shouldn't happen: av_fetch returns NULL");
174 6         tmp = *elem;
175 6         SvGETMAGIC(tmp);
176 6         if (SvROK(tmp) && SvTYPE(SvRV(tmp)) == SVt_PVHV)
177 6         inhash = (HV*)SvRV(tmp);
178           else
179 0         Perl_croak(aTHX_ "Array element %"UVuf" is not a HASH reference", i);
180            
181 6         elem = hv_fetchs(inhash, "a", 0);
182 6         if (elem == NULL)
183 0         Perl_croak(aTHX_ "Shouldn't happen: hv_fetchs returns NULL");
184 6         out[i]->a = SvIV(*elem);
185            
186 6         elem = hv_fetchs(inhash, "b", 0);
187 6         if (elem == NULL)
188 0         Perl_croak(aTHX_ "Shouldn't happen: hv_fetchs returns NULL");
189 6         out[i]->b = SvIV(*elem);
190            
191 6         elem = hv_fetchs(inhash, "c", 0);
192 6         if (elem == NULL)
193 0         Perl_croak(aTHX_ "Shouldn't happen: hv_fetchs returns NULL");
194 6         out[i]->c = SvNV(*elem);
195           }
196            
197 2         return out;
198           }
199            
200           /* no special meaning as far as typemaps are concerned,
201           * just for convenience */
202           void
203 4         XS_release_anotherstructPtrPtr(anotherstruct **in)
204           {
205           unsigned int i = 0;
206 20         while (in[i] != NULL)
207 12         Safefree(in[i++]);
208 4         Safefree(in);
209 4         }
210            
211            
212           MODULE = XS::Typemap PACKAGE = XS::Typemap
213            
214           PROTOTYPES: DISABLE
215            
216           TYPEMAP: <
217            
218           # Typemap file for typemap testing
219           # includes bonus typemap entries
220           # Mainly so that all the standard typemaps can be exercised even when
221           # there is not a corresponding type explicitly identified in the standard
222           # typemap
223            
224           svtype T_ENUM
225           intRef * T_PTRREF
226           intRef T_IV
227           intObj * T_PTROBJ
228           intObj T_IV
229           intRefIv * T_REF_IV_PTR
230           intRefIv T_IV
231           intArray * T_ARRAY
232           intOpq T_IV
233           intOpq * T_OPAQUEPTR
234           intUnsigned T_U_INT
235           intTINT T_INT
236           intTLONG T_LONG
237           shortOPQ T_OPAQUE
238           shortOPQ * T_OPAQUEPTR
239           astruct * T_OPAQUEPTR
240           anotherstruct * T_PACKED
241           anotherstruct ** T_PACKEDARRAY
242           AV_FIXED * T_AVREF_REFCOUNT_FIXED
243           HV_FIXED * T_HVREF_REFCOUNT_FIXED
244           CV_FIXED * T_CVREF_REFCOUNT_FIXED
245           SVREF_FIXED T_SVREF_REFCOUNT_FIXED
246           inputfh T_IN
247           outputfh T_OUT
248            
249           END_OF_TYPEMAP
250            
251            
252           ## T_SV
253            
254           SV *
255           T_SV( sv )
256           SV * sv
257           CODE:
258           /* create a new sv for return that is a copy of the input
259           do not simply copy the pointer since the SV will be marked
260           mortal by the INPUT typemap when it is pushed back onto the stack */
261 2         RETVAL = sv_mortalcopy( sv );
262           /* increment the refcount since the default INPUT typemap mortalizes
263           by default and we don't want to decrement the ref count twice
264           by mistake */
265           SvREFCNT_inc(RETVAL);
266           OUTPUT:
267           RETVAL
268            
269            
270           ## T_SVREF
271            
272           SVREF
273           T_SVREF( svref )
274           SVREF svref
275           CODE:
276           RETVAL = svref;
277           OUTPUT:
278           RETVAL
279            
280            
281           ## T_SVREF_FIXED
282            
283           SVREF_FIXED
284           T_SVREF_REFCOUNT_FIXED( svref )
285           SVREF_FIXED svref
286           CODE:
287           SvREFCNT_inc(svref);
288           RETVAL = svref;
289           OUTPUT:
290           RETVAL
291            
292            
293           ## T_AVREF
294            
295           AV *
296           T_AVREF( av )
297           AV * av
298           CODE:
299           RETVAL = av;
300           OUTPUT:
301           RETVAL
302            
303            
304           ## T_AVREF_REFCOUNT_FIXED
305            
306           AV_FIXED*
307           T_AVREF_REFCOUNT_FIXED( av )
308           AV_FIXED * av
309           CODE:
310           SvREFCNT_inc(av);
311           RETVAL = av;
312           OUTPUT:
313           RETVAL
314            
315            
316           ## T_HVREF
317            
318           HV *
319           T_HVREF( hv )
320           HV * hv
321           CODE:
322           RETVAL = hv;
323           OUTPUT:
324           RETVAL
325            
326            
327           ## T_HVREF_REFCOUNT_FIXED
328            
329           HV_FIXED*
330           T_HVREF_REFCOUNT_FIXED( hv )
331           HV_FIXED * hv
332           CODE:
333           SvREFCNT_inc(hv);
334           RETVAL = hv;
335           OUTPUT:
336           RETVAL
337            
338            
339           ## T_CVREF
340            
341           CV *
342           T_CVREF( cv )
343           CV * cv
344           CODE:
345           RETVAL = cv;
346           OUTPUT:
347           RETVAL
348            
349            
350           ## T_CVREF_REFCOUNT_FIXED
351            
352           CV_FIXED *
353           T_CVREF_REFCOUNT_FIXED( cv )
354           CV_FIXED * cv
355           CODE:
356           SvREFCNT_inc(cv);
357           RETVAL = cv;
358           OUTPUT:
359           RETVAL
360            
361            
362           ## T_SYSRET
363            
364           # Test a successful return
365            
366           SysRet
367           T_SYSRET_pass()
368           CODE:
369           RETVAL = 0;
370           OUTPUT:
371           RETVAL
372            
373           # Test failure
374            
375           SysRet
376           T_SYSRET_fail()
377           CODE:
378           RETVAL = -1;
379           OUTPUT:
380           RETVAL
381            
382           ## T_UV
383            
384           unsigned int
385           T_UV( uv )
386           unsigned int uv
387           CODE:
388           RETVAL = uv;
389           OUTPUT:
390           RETVAL
391            
392            
393           ## T_IV
394            
395           long
396           T_IV( iv )
397           long iv
398           CODE:
399           RETVAL = iv;
400           OUTPUT:
401           RETVAL
402            
403            
404           ## T_INT
405            
406           intTINT
407           T_INT( i )
408           intTINT i
409           CODE:
410           RETVAL = i;
411           OUTPUT:
412           RETVAL
413            
414            
415           ## T_ENUM
416            
417           # The test should return the value for SVt_PVHV.
418           # 11 at the present time but we can't not rely on this
419           # for testing purposes.
420            
421           svtype
422           T_ENUM()
423           CODE:
424           RETVAL = SVt_PVHV;
425           OUTPUT:
426           RETVAL
427            
428            
429           ## T_BOOL
430            
431           bool
432           T_BOOL( in )
433           bool in
434           CODE:
435           RETVAL = in;
436           OUTPUT:
437           RETVAL
438            
439           bool
440           T_BOOL_2( in )
441           bool in
442           CODE:
443           OUTPUT:
444           in
445            
446           void
447           T_BOOL_OUT( out, in )
448           bool out
449           bool in
450           CODE:
451           out = in;
452           OUTPUT:
453           out
454            
455           ## T_U_INT
456            
457           intUnsigned
458           T_U_INT( uint )
459           intUnsigned uint
460           CODE:
461           RETVAL = uint;
462           OUTPUT:
463           RETVAL
464            
465            
466           ## T_SHORT
467            
468           short
469           T_SHORT( s )
470           short s
471           CODE:
472           RETVAL = s;
473           OUTPUT:
474           RETVAL
475            
476            
477           ## T_U_SHORT
478            
479           U16
480           T_U_SHORT( in )
481           U16 in
482           CODE:
483           RETVAL = in;
484           OUTPUT:
485           RETVAL
486            
487            
488           ## T_LONG
489            
490           intTLONG
491           T_LONG( in )
492           intTLONG in
493           CODE:
494           RETVAL = in;
495           OUTPUT:
496           RETVAL
497            
498           ## T_U_LONG
499            
500           U32
501           T_U_LONG( in )
502           U32 in
503           CODE:
504           RETVAL = in;
505           OUTPUT:
506           RETVAL
507            
508            
509           ## T_CHAR
510            
511           char
512           T_CHAR( in );
513           char in
514           CODE:
515 8         RETVAL = in;
516           OUTPUT:
517           RETVAL
518            
519            
520           ## T_U_CHAR
521            
522           unsigned char
523           T_U_CHAR( in );
524           unsigned char in
525           CODE:
526           RETVAL = in;
527           OUTPUT:
528           RETVAL
529            
530            
531           ## T_FLOAT
532            
533           float
534           T_FLOAT( in )
535           float in
536           CODE:
537           RETVAL = in;
538           OUTPUT:
539           RETVAL
540            
541            
542           ## T_NV
543            
544           NV
545           T_NV( in )
546           NV in
547           CODE:
548           RETVAL = in;
549           OUTPUT:
550           RETVAL
551            
552            
553           ## T_DOUBLE
554            
555           double
556           T_DOUBLE( in )
557           double in
558           CODE:
559           RETVAL = in;
560           OUTPUT:
561           RETVAL
562            
563            
564           ## T_PV
565            
566           char *
567           T_PV( in )
568           char * in
569           CODE:
570           RETVAL = in;
571           OUTPUT:
572           RETVAL
573            
574           char *
575           T_PV_null()
576           CODE:
577           RETVAL = NULL;
578           OUTPUT:
579           RETVAL
580            
581            
582           ## T_PTR
583            
584           # Pass in a value. Store the value in some static memory and
585           # then return the pointer
586            
587           void *
588           T_PTR_OUT( in )
589           int in;
590           CODE:
591 2         xst_anint = in;
592           RETVAL = &xst_anint;
593           OUTPUT:
594           RETVAL
595            
596           # pass in the pointer and return the value
597            
598           int
599           T_PTR_IN( ptr )
600           void * ptr
601           CODE:
602 2         RETVAL = *(int *)ptr;
603           OUTPUT:
604           RETVAL
605            
606            
607           ## T_PTRREF
608            
609           # Similar test to T_PTR
610           # Pass in a value. Store the value in some static memory and
611           # then return the pointer
612            
613           intRef *
614           T_PTRREF_OUT( in )
615           intRef in;
616           CODE:
617 2         xst_anintref = in;
618           RETVAL = &xst_anintref;
619           OUTPUT:
620           RETVAL
621            
622           # pass in the pointer and return the value
623            
624           intRef
625           T_PTRREF_IN( ptr )
626           intRef * ptr
627           CODE:
628 2         RETVAL = *ptr;
629           OUTPUT:
630           RETVAL
631            
632            
633           ## T_PTROBJ
634            
635           # Similar test to T_PTRREF
636           # Pass in a value. Store the value in some static memory and
637           # then return the pointer
638            
639           intObj *
640           T_PTROBJ_OUT( in )
641           intObj in;
642           CODE:
643 2         xst_anintobj = in;
644           RETVAL = &xst_anintobj;
645           OUTPUT:
646           RETVAL
647            
648           # pass in the pointer and return the value
649            
650           MODULE = XS::Typemap PACKAGE = intObjPtr
651            
652           intObj
653           T_PTROBJ_IN( ptr )
654           intObj * ptr
655           CODE:
656 4         RETVAL = *ptr;
657           OUTPUT:
658           RETVAL
659            
660           MODULE = XS::Typemap PACKAGE = XS::Typemap
661            
662            
663           ## T_REF_IV_REF
664           ## NOT YET
665            
666            
667           ## T_REF_IV_PTR
668            
669           # Similar test to T_PTROBJ
670           # Pass in a value. Store the value in some static memory and
671           # then return the pointer
672            
673           intRefIv *
674           T_REF_IV_PTR_OUT( in )
675           intRefIv in;
676           CODE:
677 2         xst_anintrefiv = in;
678           RETVAL = &xst_anintrefiv;
679           OUTPUT:
680           RETVAL
681            
682           # pass in the pointer and return the value
683            
684           MODULE = XS::Typemap PACKAGE = intRefIvPtr
685            
686           intRefIv
687           T_REF_IV_PTR_IN( ptr )
688           intRefIv * ptr
689           CODE:
690 2         RETVAL = *ptr;
691           OUTPUT:
692           RETVAL
693            
694            
695           MODULE = XS::Typemap PACKAGE = XS::Typemap
696            
697           ## T_PTRDESC
698           ## NOT YET
699            
700            
701           ## T_REFREF
702           ## NOT YET
703            
704            
705           ## T_REFOBJ
706           ## NOT YET
707            
708            
709           ## T_OPAQUEPTR
710            
711           intOpq *
712           T_OPAQUEPTR_IN( val )
713           intOpq val
714           CODE:
715 2         xst_anintopq = val;
716           RETVAL = &xst_anintopq;
717           OUTPUT:
718           RETVAL
719            
720           intOpq
721           T_OPAQUEPTR_OUT( ptr )
722           intOpq * ptr
723           CODE:
724 2         RETVAL = *ptr;
725           OUTPUT:
726           RETVAL
727            
728           short
729           T_OPAQUEPTR_OUT_short( ptr )
730           shortOPQ * ptr
731           CODE:
732 2         RETVAL = *ptr;
733           OUTPUT:
734           RETVAL
735            
736           # Test it with a structure
737           astruct *
738           T_OPAQUEPTR_IN_struct( a,b,c )
739           int a
740           int b
741           double c
742           PREINIT:
743           struct t_opaqueptr test;
744           CODE:
745 2         test.a = a;
746 2         test.b = b;
747 2         test.c = c;
748           RETVAL = &test;
749           OUTPUT:
750           RETVAL
751            
752           void
753           T_OPAQUEPTR_OUT_struct( test )
754           astruct * test
755           PPCODE:
756 2         XPUSHs(sv_2mortal(newSViv(test->a)));
757 2         XPUSHs(sv_2mortal(newSViv(test->b)));
758 2         XPUSHs(sv_2mortal(newSVnv(test->c)));
759            
760            
761           ## T_OPAQUE
762            
763           shortOPQ
764           T_OPAQUE_IN( val )
765           int val
766           CODE:
767 2         RETVAL = (shortOPQ)val;
768           OUTPUT:
769           RETVAL
770            
771           IV
772           T_OPAQUE_OUT( val )
773           shortOPQ val
774           CODE:
775 2         RETVAL = (IV)val;
776           OUTPUT:
777           RETVAL
778            
779           array(int,3)
780           T_OPAQUE_array( a,b,c)
781           int a
782           int b
783           int c
784           PREINIT:
785           int array[3];
786           CODE:
787 2         array[0] = a;
788 2         array[1] = b;
789 2         array[2] = c;
790           RETVAL = array;
791           OUTPUT:
792           RETVAL
793            
794            
795           ## T_PACKED
796            
797           void
798           T_PACKED_in(in)
799           anotherstruct *in;
800           PPCODE:
801 2         mXPUSHi(in->a);
802 2         mXPUSHi(in->b);
803 2         mXPUSHn(in->c);
804 2         Safefree(in);
805 2         XSRETURN(3);
806            
807           anotherstruct *
808           T_PACKED_out(a, b ,c)
809           int a;
810           int b;
811           double c;
812           CODE:
813 2         Newxz(RETVAL, 1, anotherstruct);
814 2         RETVAL->a = a;
815 2         RETVAL->b = b;
816 2         RETVAL->c = c;
817           OUTPUT: RETVAL
818           CLEANUP:
819 2         Safefree(RETVAL);
820            
821           ## T_PACKEDARRAY
822            
823           void
824           T_PACKEDARRAY_in(in)
825           anotherstruct **in;
826           PREINIT:
827           unsigned int i = 0;
828           PPCODE:
829 10         while (in[i] != NULL) {
830 6         mXPUSHi(in[i]->a);
831 6         mXPUSHi(in[i]->b);
832 6         mXPUSHn(in[i]->c);
833 6         ++i;
834           }
835 2         XS_release_anotherstructPtrPtr(in);
836 2         XSRETURN(3*i);
837            
838           anotherstruct **
839           T_PACKEDARRAY_out(...)
840           PREINIT:
841           unsigned int i, nstructs, count_anotherstructPtrPtr;
842           CODE:
843 2         if ((items % 3) != 0)
844 0         croak("Need nitems divisible by 3");
845 2         nstructs = (unsigned int)(items / 3);
846           count_anotherstructPtrPtr = nstructs;
847 2         Newxz(RETVAL, nstructs+1, anotherstruct *);
848 8         for (i = 0; i < nstructs; ++i) {
849 6         Newxz(RETVAL[i], 1, anotherstruct);
850 6         RETVAL[i]->a = SvIV(ST(3*i));
851 6         RETVAL[i]->b = SvIV(ST(3*i+1));
852 6         RETVAL[i]->c = SvNV(ST(3*i+2));
853           }
854           OUTPUT: RETVAL
855           CLEANUP:
856 2         XS_release_anotherstructPtrPtr(RETVAL);
857            
858            
859           ## T_DATAUNIT
860           ## NOT YET
861            
862            
863           ## T_CALLBACK
864           ## NOT YET
865            
866            
867           ## T_ARRAY
868            
869           # Test passes in an integer array and returns it along with
870           # the number of elements
871           # Pass in a dummy value to test offsetting
872            
873           # Problem is that xsubpp does XSRETURN(1) because we arent
874           # using PPCODE. This means that only the first element
875           # is returned. KLUGE this by using CLEANUP to return before the
876           # end.
877           # Note: I read this as: The "T_ARRAY" typemap is really rather broken,
878           # at least for OUTPUT. That is apart from the general design
879           # weaknesses. --Steffen
880            
881           intArray *
882           T_ARRAY( dummy, array, ... )
883           int dummy = 0;
884           intArray * array
885           PREINIT:
886           U32 size_RETVAL;
887           CODE:
888           dummy += 0; /* Fix -Wall */
889           size_RETVAL = ix_array;
890           RETVAL = array;
891           OUTPUT:
892           RETVAL
893           CLEANUP:
894 2         Safefree(array);
895 2         XSRETURN(size_RETVAL);
896            
897            
898           ## T_STDIO
899            
900           FILE *
901           T_STDIO_open( file )
902           const char * file
903           CODE:
904 2         RETVAL = xsfopen( file );
905           OUTPUT:
906           RETVAL
907            
908           SysRet
909           T_STDIO_close( f )
910           PerlIO * f
911           PREINIT:
912           FILE * stream;
913           CODE:
914           /* Get the FILE* */
915 2         stream = PerlIO_findFILE( f );
916           /* Release the FILE* from the PerlIO system so that we do
917           not close the file twice */
918 2         PerlIO_releaseFILE(f,stream);
919           /* Must release the file before closing it */
920 2         RETVAL = xsfclose( stream );
921           OUTPUT:
922           RETVAL
923            
924           int
925           T_STDIO_print( stream, string )
926           FILE * stream
927           const char * string
928           CODE:
929 2         RETVAL = xsfprintf( stream, string );
930           OUTPUT:
931           RETVAL
932            
933            
934           ## T_INOUT
935            
936           PerlIO *
937           T_INOUT(in)
938           PerlIO *in;
939           CODE:
940           RETVAL = in; /* silly test but better than nothing */
941           OUTPUT: RETVAL
942            
943            
944           ## T_IN
945            
946           inputfh
947           T_IN(in)
948           inputfh in;
949           CODE:
950           RETVAL = in; /* silly test but better than nothing */
951           OUTPUT: RETVAL
952            
953            
954           ## T_OUT
955            
956           outputfh
957           T_OUT(in)
958           outputfh in;
959           CODE:
960           RETVAL = in; /* silly test but better than nothing */
961           OUTPUT: RETVAL
962