772bae2c37eba525482b6f9ca90325dcd9d22ab6
[perl4caml.git] / perl_c.c
1 /* Interface to Perl from OCaml.
2  * Copyright (C) 2003 Merjis Ltd.
3  * $Id: perl_c.c,v 1.13 2003-12-11 17:41:52 rich Exp $
4  */
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <assert.h>
9 #include <unistd.h>
10 #include <alloca.h>
11
12 #include <caml/alloc.h>
13 #include <caml/callback.h>
14 #include <caml/custom.h>
15 #include <caml/fail.h>
16 #include <caml/memory.h>
17 #include <caml/mlvalues.h>
18
19 /* XXX This was required to avoid an error on my machine when loading the Perl
20  * headers. Not clear why this is missing.
21  */
22 #define off64_t __off64_t
23
24 /* XXX This is required by Perl >= 5.8.2. */
25 #define __USE_GNU
26 #include <crypt.h>
27
28 #include <EXTERN.h>
29 #include <perl.h>
30
31 /* Perl requires the interpreter to be called literally 'my_perl'! */
32 static PerlInterpreter *my_perl;
33
34 /* Wrap up an arbitrary void pointer in an opaque OCaml object. */
35 static value Val_voidptr (void *ptr);
36
37 /* Wrap up an SV, AV or HV in a custom OCaml object which will decrement
38  * the reference count on finalization.
39  */
40 static value Val_xv (SV *sv);
41
42 /* Get the concrete value from an optional field. */
43 static value unoption (value option, value deflt);
44
45 /* Unwrap an arbitrary void pointer from an opaque OCaml object. */
46 #define Voidptr_val(type,rv) ((type *) Field ((rv), 0))
47
48 /* Unwrap a custom block. */
49 #define Xv_val(rv) (*((void **)Data_custom_val(rv)))
50
51 /* Hide Perl types in opaque OCaml objects. */
52 #define Val_perl(pl) (Val_voidptr ((pl)))
53 #define Perl_val(plv) (Voidptr_val (PerlInterpreter, (plv)))
54 #define Val_sv(sv) (Val_xv ((sv)))
55 #define Sv_val(svv) ((SV *) Xv_val (svv))
56 #define Val_av(av) (Val_xv ((SV *)(av)))
57 #define Av_val(avv) ((AV *) Xv_val (avv))
58 #define Val_hv(hv) (Val_xv ((SV *)(hv)))
59 #define Hv_val(hvv) ((HV *) Xv_val (hvv))
60
61 static void
62 xs_init (pTHX)
63 {
64   char *file = __FILE__;
65   EXTERN_C void boot_DynaLoader (pTHX_ CV* cv);
66
67   newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
68 }
69
70 CAMLprim value
71 perl4caml_init (value unit)
72 {
73   CAMLparam1 (unit);
74   int argc = 4;
75   static char *argv[] = { "", "-w", "-e", "0" };
76
77   PERL_SYS_INIT3 (NULL, NULL, NULL);
78   my_perl = perl_alloc ();
79   perl_construct (my_perl);
80   PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
81   perl_parse (my_perl, xs_init, argc, argv, NULL);
82   /*perl_run (my_perl);*/
83
84   CAMLreturn (Val_unit);
85 }
86
87 CAMLprim value
88 perl4caml_int_of_sv (value svv)
89 {
90   CAMLparam1 (svv);
91   SV *sv = Sv_val (svv);
92   CAMLreturn (Val_int (SvIV (sv)));
93 }
94
95 CAMLprim value
96 perl4caml_sv_of_int (value iv)
97 {
98   CAMLparam1 (iv);
99   CAMLreturn (Val_sv (newSViv (Int_val (iv))));
100 }
101
102 CAMLprim value
103 perl4caml_float_of_sv (value svv)
104 {
105   CAMLparam1 (svv);
106   SV *sv = Sv_val (svv);
107   CAMLlocal1 (f);
108   f = copy_double (SvNV (sv));
109   CAMLreturn (f);
110 }
111
112 CAMLprim value
113 perl4caml_sv_of_float (value fv)
114 {
115   CAMLparam1 (fv);
116   CAMLreturn (Val_sv (newSViv (Double_val (fv))));
117 }
118
119 CAMLprim value
120 perl4caml_string_of_sv (value svv)
121 {
122   CAMLparam1 (svv);
123   SV *sv = Sv_val (svv);
124   char *str;
125   STRLEN len;
126   CAMLlocal1 (strv);
127   str = SvPV (sv, len);
128   /* XXX This won't work if the string contains NUL. */
129   strv = copy_string (str);
130   CAMLreturn (strv);
131 }
132
133 CAMLprim value
134 perl4caml_sv_of_string (value strv)
135 {
136   CAMLparam1 (strv);
137   CAMLreturn (Val_sv (newSVpv (String_val (strv), string_length (strv))));
138 }
139
140 CAMLprim value
141 perl4caml_sv_is_true (value svv)
142 {
143   CAMLparam1 (svv);
144   SV *sv = Sv_val (svv);
145   CAMLreturn (SvTRUE (sv) ? Val_true : Val_false);
146 }
147
148 CAMLprim value
149 perl4caml_sv_undef (value unit)
150 {
151   CAMLparam1 (unit);
152   CAMLreturn (Val_sv (newSV (0)));
153 }
154
155 CAMLprim value
156 perl4caml_sv_yes (value unit)
157 {
158   CAMLparam1 (unit);
159   CAMLreturn (Val_sv (&PL_sv_yes));
160 }
161
162 CAMLprim value
163 perl4caml_sv_no (value unit)
164 {
165   CAMLparam1 (unit);
166   CAMLreturn (Val_sv (&PL_sv_no));
167 }
168
169 CAMLprim value
170 perl4caml_sv_type (value svv)
171 {
172   CAMLparam1 (svv);
173   SV *sv = Sv_val (svv);
174
175   switch (SvTYPE (sv))
176     {
177     case SVt_IV: CAMLreturn (Val_int (1));
178     case SVt_NV: CAMLreturn (Val_int (2));
179     case SVt_PV: CAMLreturn (Val_int (3));
180     case SVt_RV: CAMLreturn (Val_int (4));
181     case SVt_PVAV: CAMLreturn (Val_int (5));
182     case SVt_PVHV: CAMLreturn (Val_int (6));
183     case SVt_PVCV: CAMLreturn (Val_int (7));
184     case SVt_PVGV: CAMLreturn (Val_int (8));
185     case SVt_PVMG: CAMLreturn (Val_int (9));
186     default: CAMLreturn (Val_int (0));
187     }
188 }
189
190 CAMLprim value
191 perl4caml_scalarref (value svv)
192 {
193   CAMLparam1 (svv);
194   CAMLlocal1 (rsvv);
195   SV *sv = Sv_val (svv);
196   rsvv = Val_sv (newRV_inc (sv));
197   CAMLreturn (rsvv);
198 }
199
200 CAMLprim value
201 perl4caml_arrayref (value avv)
202 {
203   CAMLparam1 (avv);
204   CAMLlocal1 (rsvv);
205   AV *av = Av_val (avv);
206   rsvv = Val_sv (newRV_inc ((SV *) av));
207   CAMLreturn (rsvv);
208 }
209
210 CAMLprim value
211 perl4caml_hashref (value hvv)
212 {
213   CAMLparam1 (hvv);
214   CAMLlocal1 (rsvv);
215   HV *hv = Hv_val (hvv);
216   rsvv = Val_sv (newRV_inc ((SV *) hv));
217   CAMLreturn (rsvv);
218 }
219
220 CAMLprim value
221 perl4caml_deref (value svv)
222 {
223   CAMLparam1 (svv);
224   CAMLlocal1 (rsvv);
225   SV *sv = Sv_val (svv);
226
227   if (SvTYPE (sv) != SVt_RV)
228     invalid_argument ("deref: SV is not a reference");
229   switch (SvTYPE (SvRV (sv))) {
230   case SVt_IV:
231   case SVt_NV:
232   case SVt_PV:
233   case SVt_RV:
234   case SVt_PVMG:
235     break;
236   default:
237     invalid_argument ("deref: SV is not a reference to a scalar");
238   }
239   rsvv = Val_sv (SvRV (sv));
240   CAMLreturn (rsvv);
241 }
242
243 CAMLprim value
244 perl4caml_deref_array (value svv)
245 {
246   CAMLparam1 (svv);
247   CAMLlocal1 (ravv);
248   SV *sv = Sv_val (svv);
249
250   if (SvTYPE (sv) != SVt_RV)
251     invalid_argument ("deref_array: SV is not a reference");
252   switch (SvTYPE (SvRV (sv))) {
253   case SVt_PVAV:
254     break;
255   default:
256     invalid_argument ("deref_array: SV is not a reference to an array");
257   }
258   ravv = Val_av ((AV *) SvRV (sv));
259   CAMLreturn (ravv);
260 }
261
262 CAMLprim value
263 perl4caml_deref_hash (value svv)
264 {
265   CAMLparam1 (svv);
266   CAMLlocal1 (rhvv);
267   SV *sv = Sv_val (svv);
268
269   if (SvTYPE (sv) != SVt_RV)
270     invalid_argument ("deref_array: SV is not a reference");
271   switch (SvTYPE (SvRV (sv))) {
272   case SVt_PVHV:
273     break;
274   default:
275     invalid_argument ("deref_array: SV is not a reference to a hash");
276   }
277   rhvv = Val_hv ((HV *) SvRV (sv));
278   CAMLreturn (rhvv);
279 }
280
281 CAMLprim value
282 perl4caml_av_empty (value unit)
283 {
284   CAMLparam1 (unit);
285   AV *av = newAV ();
286   CAMLreturn (Val_av (av));
287 }
288
289 /* We don't know in advance how long the list will be, which makes this
290  * a little harder.
291  */
292 CAMLprim value
293 perl4caml_av_of_sv_list (value svlistv)
294 {
295   CAMLparam1 (svlistv);
296   CAMLlocal1 (svv);
297   SV *sv, **svlist = 0;
298   int alloc = 0, size = 0;
299   AV *av;
300
301   for (; svlistv != Val_int (0); svlistv = Field (svlistv, 1))
302     {
303       svv = Field (svlistv, 0);
304       sv = Sv_val (svv);
305       if (size >= alloc) {
306         alloc = alloc == 0 ? 1 : alloc * 2;
307         svlist = realloc (svlist, alloc * sizeof (SV *));
308       }
309       svlist[size++] = sv;
310     }
311
312   av = av_make (size, svlist);
313
314   if (alloc > 0) free (svlist); /* Free memory allocated to SV list. */
315
316   CAMLreturn (Val_av (av));
317 }
318
319 /* XXX av_map would be faster if we also had sv_list_of_av. */
320
321 CAMLprim value
322 perl4caml_av_push (value avv, value svv)
323 {
324   CAMLparam2 (avv, svv);
325   AV *av = Av_val (avv);
326   SV *sv = Sv_val (svv);
327   av_push (av, sv);
328   CAMLreturn (Val_unit);
329 }
330
331 CAMLprim value
332 perl4caml_av_pop (value avv)
333 {
334   CAMLparam1 (avv);
335   AV *av = Av_val (avv);
336   SV *sv = av_pop (av);
337   CAMLreturn (Val_sv (sv));
338 }
339
340 CAMLprim value
341 perl4caml_av_unshift (value avv, value svv)
342 {
343   CAMLparam2 (avv, svv);
344   AV *av = Av_val (avv);
345   SV *sv = Sv_val (svv);
346   av_unshift (av, 1);
347   SvREFCNT_inc (sv);
348   if (av_store (av, 0, sv) == 0)
349     SvREFCNT_dec (sv);
350   CAMLreturn (Val_unit);
351 }
352
353 CAMLprim value
354 perl4caml_av_shift (value avv)
355 {
356   CAMLparam1 (avv);
357   AV *av = Av_val (avv);
358   SV *sv = av_shift (av);
359   CAMLreturn (Val_sv (sv));
360 }
361
362 CAMLprim value
363 perl4caml_av_length (value avv)
364 {
365   CAMLparam1 (avv);
366   AV *av = Av_val (avv);
367   CAMLreturn (Val_int (av_len (av) + 1));
368 }
369
370 CAMLprim value
371 perl4caml_av_set (value avv, value i, value svv)
372 {
373   CAMLparam3 (avv, i, svv);
374   AV *av = Av_val (avv);
375   SV *sv = Sv_val (svv);
376   SvREFCNT_inc (sv);
377   if (av_store (av, Int_val (i), sv) == 0)
378     SvREFCNT_dec (sv);
379   CAMLreturn (Val_unit);
380 }
381
382 CAMLprim value
383 perl4caml_av_get (value avv, value i)
384 {
385   CAMLparam2 (avv, i);
386   AV *av = Av_val (avv);
387   SV **svp = av_fetch (av, Int_val (i), 0);
388   if (svp == 0) invalid_argument ("av_get: index out of bounds");
389   CAMLreturn (Val_sv (*svp));
390 }
391
392 CAMLprim value
393 perl4caml_av_clear (value avv)
394 {
395   CAMLparam1 (avv);
396   AV *av = Av_val (avv);
397   av_clear (av);
398   CAMLreturn (Val_unit);
399 }
400
401 CAMLprim value
402 perl4caml_av_undef (value avv)
403 {
404   CAMLparam1 (avv);
405   AV *av = Av_val (avv);
406   av_undef (av);
407   CAMLreturn (Val_unit);
408 }
409
410 CAMLprim value
411 perl4caml_av_extend (value avv, value i)
412 {
413   CAMLparam2 (avv, i);
414   AV *av = Av_val (avv);
415   av_extend (av, Int_val (i));
416   CAMLreturn (Val_unit);
417 }
418
419 CAMLprim value
420 perl4caml_hv_empty (value unit)
421 {
422   CAMLparam1 (unit);
423   HV *hv = newHV ();
424   CAMLreturn (Val_hv (hv));
425 }
426
427 CAMLprim value
428 perl4caml_hv_set (value hvv, value key, value svv)
429 {
430   CAMLparam3 (hvv, key, svv);
431   HV *hv = Hv_val (hvv);
432   SV *sv = Sv_val (svv);
433   SvREFCNT_inc (sv);
434   if (hv_store (hv, String_val (key), string_length (key), sv, 0) == 0)
435     SvREFCNT_dec (sv);
436   CAMLreturn (Val_unit);
437 }
438
439 CAMLprim value
440 perl4caml_hv_get (value hvv, value key)
441 {
442   CAMLparam2 (hvv, key);
443   HV *hv = Hv_val (hvv);
444   SV **svp = hv_fetch (hv, String_val (key), string_length (key), 0);
445   if (svp == 0) raise_not_found ();
446   CAMLreturn (Val_sv (*svp));
447 }
448
449 CAMLprim value
450 perl4caml_hv_exists (value hvv, value key)
451 {
452   CAMLparam2 (hvv, key);
453   HV *hv = Hv_val (hvv);
454   bool r = hv_exists (hv, String_val (key), string_length (key));
455   CAMLreturn (r ? Val_true : Val_false);
456 }
457
458 CAMLprim value
459 perl4caml_hv_delete (value hvv, value key)
460 {
461   CAMLparam2 (hvv, key);
462   HV *hv = Hv_val (hvv);
463   hv_delete (hv, String_val (key), string_length (key), G_DISCARD);
464   CAMLreturn (Val_unit);
465 }
466
467 CAMLprim value
468 perl4caml_hv_clear (value hvv)
469 {
470   CAMLparam1 (hvv);
471   HV *hv = Hv_val (hvv);
472   hv_clear (hv);
473   CAMLreturn (Val_unit);
474 }
475
476 CAMLprim value
477 perl4caml_hv_undef (value hvv)
478 {
479   CAMLparam1 (hvv);
480   HV *hv = Hv_val (hvv);
481   hv_undef (hv);
482   CAMLreturn (Val_unit);
483 }
484
485 CAMLprim value
486 perl4caml_get_sv (value optcreate, value name)
487 {
488   CAMLparam2 (optcreate, name);
489   CAMLlocal1 (create);
490   SV *sv;
491
492   create = unoption (optcreate, Val_false);
493   sv = get_sv (String_val (name), create == Val_true ? TRUE : FALSE);
494   if (sv == NULL) raise_not_found ();
495
496   CAMLreturn (Val_sv (sv));
497 }
498
499 CAMLprim value
500 perl4caml_get_av (value optcreate, value name)
501 {
502   CAMLparam2 (optcreate, name);
503   CAMLlocal1 (create);
504   AV *av;
505
506   create = unoption (optcreate, Val_false);
507   av = get_av (String_val (name), create == Val_true ? TRUE : FALSE);
508   if (av == NULL) raise_not_found ();
509
510   CAMLreturn (Val_av (av));
511 }
512
513 CAMLprim value
514 perl4caml_get_hv (value optcreate, value name)
515 {
516   CAMLparam2 (optcreate, name);
517   CAMLlocal1 (create);
518   HV *hv;
519
520   create = unoption (optcreate, Val_false);
521   hv = get_hv (String_val (name), create == Val_true ? TRUE : FALSE);
522   if (hv == NULL) raise_not_found ();
523
524   CAMLreturn (Val_hv (hv));
525 }
526
527 static inline void
528 check_perl_failure ()
529 {
530   SV *errsv = get_sv ("@", TRUE);
531
532   if (SvTRUE (errsv))           /* Equivalent of $@ in Perl. */
533     {
534       CAMLlocal1 (errv);
535       STRLEN n_a;
536       const char *err = SvPV (errsv, n_a);
537
538       errv = copy_string (err);
539
540       raise_with_arg (*caml_named_value ("perl4caml_perl_failure"), errv);
541     }
542 }
543
544 CAMLprim value
545 perl4caml_call (value optsv, value optfnname, value arglist)
546 {
547   CAMLparam3 (optsv, optfnname, arglist);
548   dSP;
549   int count;
550   SV *sv;
551   CAMLlocal3 (errv, svv, fnname);
552
553   ENTER;
554   SAVETMPS;
555
556   /* Push the parameter list. */
557   PUSHMARK (SP);
558
559   /* Iteration over the linked list. */
560   for (; arglist != Val_int (0); arglist = Field (arglist, 1))
561     {
562       svv = Field (arglist, 0);
563       sv = Sv_val (svv);
564       XPUSHs (sv_2mortal (newSVsv (sv)));
565     }
566
567   PUTBACK;
568
569   if (optsv != Val_int (0))
570     {
571       svv = unoption (optsv, Val_false);
572       sv = Sv_val (svv);
573       count = call_sv (sv, G_EVAL|G_SCALAR);
574     }
575   else if (optfnname != Val_int (0))
576     {
577       fnname = unoption (optfnname, Val_false);
578       count = call_pv (String_val (fnname), G_EVAL|G_SCALAR);
579     }
580   else
581     {
582       fprintf (stderr,
583                "Perl.call: must supply either 'sv' or 'fn' parameters.");
584       abort ();
585     }
586
587   SPAGAIN;
588
589   assert (count == 1); /* Pretty sure it should never be anything else. */
590
591   /* Pop return value off the stack. Note that the return value on the
592    * stack is mortal, so we need to take a copy.
593    */
594   sv = newSVsv (POPs);
595   PUTBACK;
596   FREETMPS;
597   LEAVE;
598
599   check_perl_failure ();
600
601   svv = Val_sv (sv);
602   CAMLreturn (svv);
603 }
604
605 CAMLprim value
606 perl4caml_call_array (value optsv, value optfnname, value arglist)
607 {
608   CAMLparam3 (optsv, optfnname, arglist);
609   dSP;
610   int i, count;
611   SV *sv;
612   CAMLlocal5 (errv, svv, fnname, list, cons);
613
614   ENTER;
615   SAVETMPS;
616
617   /* Push the parameter list. */
618   PUSHMARK (SP);
619
620   /* Iteration over the linked list. */
621   for (; arglist != Val_int (0); arglist = Field (arglist, 1))
622     {
623       svv = Field (arglist, 0);
624       sv = Sv_val (svv);
625       XPUSHs (sv_2mortal (newSVsv (sv)));
626     }
627
628   PUTBACK;
629
630   if (optsv != Val_int (0))
631     {
632       svv = unoption (optsv, Val_false);
633       sv = Sv_val (svv);
634       count = call_sv (sv, G_EVAL|G_ARRAY);
635     }
636   else if (optfnname != Val_int (0))
637     {
638       fnname = unoption (optfnname, Val_false);
639       count = call_pv (String_val (fnname), G_EVAL|G_ARRAY);
640     }
641   else
642     {
643       fprintf (stderr,
644                "Perl.call_array: must supply either 'sv' or 'fn' parameters.");
645       abort ();
646     }
647
648   SPAGAIN;
649
650   /* Pop all the return values off the stack into a list. Values on the
651    * stack are mortal, so we must copy them.
652    */
653   list = Val_int (0);
654   for (i = 0; i < count; ++i) {
655     SV *sv;
656
657     cons = alloc (2, 0);
658     Field (cons, 1) = list;
659     list = cons;
660     sv = newSVsv (POPs);
661     Field (cons, 0) = Val_sv (sv);
662   }
663
664   /* Restore the stack. */
665   PUTBACK;
666   FREETMPS;
667   LEAVE;
668
669   check_perl_failure ();
670
671   CAMLreturn (list);
672 }
673
674 CAMLprim value
675 perl4caml_call_void (value optsv, value optfnname, value arglist)
676 {
677   CAMLparam3 (optsv, optfnname, arglist);
678   dSP;
679   int count;
680   SV *sv;
681   CAMLlocal3 (errv, svv, fnname);
682
683   ENTER;
684   SAVETMPS;
685
686   /* Push the parameter list. */
687   PUSHMARK (SP);
688
689   /* Iteration over the linked list. */
690   for (; arglist != Val_int (0); arglist = Field (arglist, 1))
691     {
692       svv = Field (arglist, 0);
693       sv = Sv_val (svv);
694       XPUSHs (sv_2mortal (newSVsv (sv)));
695     }
696
697   PUTBACK;
698
699   if (optsv != Val_int (0))
700     {
701       svv = unoption (optsv, Val_false);
702       sv = Sv_val (svv);
703       count = call_sv (sv, G_EVAL|G_VOID);
704     }
705   else if (optfnname != Val_int (0))
706     {
707       fnname = unoption (optfnname, Val_false);
708       count = call_pv (String_val (fnname), G_EVAL|G_VOID|G_DISCARD);
709     }
710   else
711     {
712       fprintf (stderr,
713                "Perl.call_void: must supply either 'sv' or 'fn' parameters.");
714       abort ();
715     }
716
717   SPAGAIN;
718
719   assert (count == 0);
720
721   /* Restore the stack. */
722   PUTBACK;
723   FREETMPS;
724   LEAVE;
725
726   check_perl_failure ();
727
728   CAMLreturn (Val_unit);
729 }
730
731 CAMLprim value
732 perl4caml_eval (value expr)
733 {
734   CAMLparam1 (expr);
735   dSP;
736   SV *sv;
737   CAMLlocal2 (errv, svv);
738
739   sv = eval_pv (String_val (expr), G_SCALAR);
740
741   check_perl_failure ();
742
743   svv = Val_sv (sv);
744   CAMLreturn (svv);
745 }
746
747 CAMLprim value
748 perl4caml_call_method (value ref, value name, value arglist)
749 {
750   CAMLparam3 (ref, name, arglist);
751   dSP;
752   int count;
753   SV *sv;
754   CAMLlocal2 (errv, svv);
755
756   ENTER;
757   SAVETMPS;
758
759   /* Push the parameter list. */
760   PUSHMARK (SP);
761
762   sv = Sv_val (ref);
763   XPUSHs (sv_2mortal (newSVsv (sv)));
764
765   /* Iteration over the linked list. */
766   for (; arglist != Val_int (0); arglist = Field (arglist, 1))
767     {
768       svv = Field (arglist, 0);
769       sv = Sv_val (svv);
770       XPUSHs (sv_2mortal (newSVsv (sv)));
771     }
772
773   PUTBACK;
774
775   count = call_method (String_val (name), G_EVAL|G_SCALAR);
776
777   SPAGAIN;
778
779   assert (count == 1); /* Pretty sure it should never be anything else. */
780
781   /* Pop return value off the stack. Note that the return value on the
782    * stack is mortal, so we need to take a copy.
783    */
784   sv = newSVsv (POPs);
785   PUTBACK;
786   FREETMPS;
787   LEAVE;
788
789   check_perl_failure ();
790
791   svv = Val_sv (sv);
792   CAMLreturn (svv);
793 }
794
795 CAMLprim value
796 perl4caml_call_method_array (value ref, value name, value arglist)
797 {
798   CAMLparam3 (ref, name, arglist);
799   dSP;
800   int count, i;
801   SV *sv;
802   CAMLlocal4 (errv, svv, list, cons);
803
804   ENTER;
805   SAVETMPS;
806
807   /* Push the parameter list. */
808   PUSHMARK (SP);
809
810   sv = Sv_val (ref);
811   XPUSHs (sv_2mortal (newSVsv (sv)));
812
813   /* Iteration over the linked list. */
814   for (; arglist != Val_int (0); arglist = Field (arglist, 1))
815     {
816       svv = Field (arglist, 0);
817       sv = Sv_val (svv);
818       XPUSHs (sv_2mortal (newSVsv (sv)));
819     }
820
821   PUTBACK;
822
823   count = call_method (String_val (name), G_EVAL|G_ARRAY);
824
825   SPAGAIN;
826
827   /* Pop all return values off the stack. Note that the return values on the
828    * stack are mortal, so we need to take a copy.
829    */
830   list = Val_int (0);
831   for (i = 0; i < count; ++i) {
832     SV *sv;
833
834     cons = alloc (2, 0);
835     Field (cons, 1) = list;
836     list = cons;
837     sv = newSVsv (POPs);
838     Field (cons, 0) = Val_sv (sv);
839   }
840
841   /* Restore the stack. */
842   PUTBACK;
843   FREETMPS;
844   LEAVE;
845
846   check_perl_failure ();
847
848   CAMLreturn (list);
849 }
850
851 CAMLprim value
852 perl4caml_call_method_void (value ref, value name, value arglist)
853 {
854   CAMLparam3 (ref, name, arglist);
855   dSP;
856   int count;
857   SV *sv;
858   CAMLlocal2 (errv, svv);
859
860   ENTER;
861   SAVETMPS;
862
863   /* Push the parameter list. */
864   PUSHMARK (SP);
865
866   sv = Sv_val (ref);
867   XPUSHs (sv_2mortal (newSVsv (sv)));
868
869   /* Iteration over the linked list. */
870   for (; arglist != Val_int (0); arglist = Field (arglist, 1))
871     {
872       svv = Field (arglist, 0);
873       sv = Sv_val (svv);
874       XPUSHs (sv_2mortal (newSVsv (sv)));
875     }
876
877   PUTBACK;
878
879   count = call_method (String_val (name), G_EVAL|G_VOID|G_DISCARD);
880
881   SPAGAIN;
882
883   assert (count == 0);
884
885   /* Restore the stack. */
886   PUTBACK;
887   FREETMPS;
888   LEAVE;
889
890   check_perl_failure ();
891
892   CAMLreturn (Val_unit);
893 }
894
895 CAMLprim value
896 perl4caml_call_class_method (value classname, value name, value arglist)
897 {
898   CAMLparam3 (classname, name, arglist);
899   dSP;
900   int count;
901   SV *sv;
902   CAMLlocal2 (errv, svv);
903
904   ENTER;
905   SAVETMPS;
906
907   /* Push the parameter list. */
908   PUSHMARK (SP);
909
910   XPUSHs (sv_2mortal (newSVpv (String_val (classname), 0)));
911
912   /* Iteration over the linked list. */
913   for (; arglist != Val_int (0); arglist = Field (arglist, 1))
914     {
915       svv = Field (arglist, 0);
916       sv = Sv_val (svv);
917       XPUSHs (sv_2mortal (newSVsv (sv)));
918     }
919
920   PUTBACK;
921
922   count = call_method (String_val (name), G_EVAL|G_SCALAR);
923
924   SPAGAIN;
925
926   assert (count == 1); /* Pretty sure it should never be anything else. */
927
928   /* Pop return value off the stack. Note that the return value on the
929    * stack is mortal, so we need to take a copy.
930    */
931   sv = newSVsv (POPs);
932   PUTBACK;
933   FREETMPS;
934   LEAVE;
935
936   check_perl_failure ();
937
938   svv = Val_sv (sv);
939   CAMLreturn (svv);
940 }
941
942 CAMLprim value
943 perl4caml_call_class_method_array (value classname, value name, value arglist)
944 {
945   CAMLparam3 (classname, name, arglist);
946   dSP;
947   int count, i;
948   SV *sv;
949   CAMLlocal4 (errv, svv, list, cons);
950
951   ENTER;
952   SAVETMPS;
953
954   /* Push the parameter list. */
955   PUSHMARK (SP);
956
957   XPUSHs (sv_2mortal (newSVpv (String_val (classname), 0)));
958
959   /* Iteration over the linked list. */
960   for (; arglist != Val_int (0); arglist = Field (arglist, 1))
961     {
962       svv = Field (arglist, 0);
963       sv = Sv_val (svv);
964       XPUSHs (sv_2mortal (newSVsv (sv)));
965     }
966
967   PUTBACK;
968
969   count = call_method (String_val (name), G_EVAL|G_ARRAY);
970
971   SPAGAIN;
972
973   /* Pop all return values off the stack. Note that the return values on the
974    * stack are mortal, so we need to take a copy.
975    */
976   list = Val_int (0);
977   for (i = 0; i < count; ++i) {
978     cons = alloc (2, 0);
979     Field (cons, 1) = list;
980     list = cons;
981     Field (cons, 0) = Val_sv (newSVsv (POPs));
982   }
983
984   /* Restore the stack. */
985   PUTBACK;
986   FREETMPS;
987   LEAVE;
988
989   check_perl_failure ();
990
991   CAMLreturn (list);
992 }
993
994 CAMLprim value
995 perl4caml_call_class_method_void (value classname, value name, value arglist)
996 {
997   CAMLparam3 (classname, name, arglist);
998   dSP;
999   int count;
1000   SV *sv;
1001   CAMLlocal2 (errv, svv);
1002
1003   ENTER;
1004   SAVETMPS;
1005
1006   /* Push the parameter list. */
1007   PUSHMARK (SP);
1008
1009   XPUSHs (sv_2mortal (newSVpv (String_val (classname), 0)));
1010
1011   /* Iteration over the linked list. */
1012   for (; arglist != Val_int (0); arglist = Field (arglist, 1))
1013     {
1014       svv = Field (arglist, 0);
1015       sv = Sv_val (svv);
1016       XPUSHs (sv_2mortal (newSVsv (sv)));
1017     }
1018
1019   PUTBACK;
1020
1021   count = call_method (String_val (name), G_EVAL|G_VOID|G_DISCARD);
1022
1023   SPAGAIN;
1024
1025   assert (count == 0);
1026
1027   /* Restore the stack. */
1028   PUTBACK;
1029   FREETMPS;
1030   LEAVE;
1031
1032   check_perl_failure ();
1033
1034   CAMLreturn (Val_unit);
1035 }
1036
1037 static value
1038 Val_voidptr (void *ptr)
1039 {
1040   CAMLparam0 ();
1041   CAMLlocal1 (rv);
1042   rv = alloc (1, Abstract_tag);
1043   Field(rv, 0) = (value) ptr;
1044   CAMLreturn (rv);
1045 }
1046
1047 static void
1048 xv_finalize (value v)
1049 {
1050   SvREFCNT_dec ((SV *) Xv_val (v));
1051 }
1052
1053 static struct custom_operations xv_custom_operations = {
1054   "xv_custom_operations",
1055   xv_finalize,
1056   custom_compare_default,
1057   custom_hash_default,
1058   custom_serialize_default,
1059   custom_deserialize_default
1060 };
1061
1062 static value
1063 Val_xv (SV *sv)
1064 {
1065   CAMLparam0 ();
1066   CAMLlocal1 (rv);
1067   rv = alloc_custom (&xv_custom_operations, sizeof (void *), 0, 1);
1068   Xv_val (rv) = sv;
1069   CAMLreturn (rv);
1070 }
1071
1072 static value
1073 unoption (value option, value deflt)
1074 {
1075   if (option == Val_int (0))    /* "None" */
1076     return deflt;
1077   else                          /* "Some 'a" */
1078     return Field (option, 0);
1079 }