This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Fix failing Test::Simple test
[perl5.git] / ext / XS / APItest / APItest.xs
CommitLineData
6a93a7e5 1#define PERL_IN_XS_APITEST
3e61d65a
JH
2#include "EXTERN.h"
3#include "perl.h"
4#include "XSUB.h"
5
85ce96a1
DM
6
7/* for my_cxt tests */
8
9#define MY_CXT_KEY "XS::APItest::_guts" XS_VERSION
10
11typedef struct {
12 int i;
13 SV *sv;
14} my_cxt_t;
15
16START_MY_CXT
17
18/* indirect functions to test the [pa]MY_CXT macros */
f16dd614 19
85ce96a1
DM
20int
21my_cxt_getint_p(pMY_CXT)
22{
23 return MY_CXT.i;
24}
f16dd614 25
85ce96a1
DM
26void
27my_cxt_setint_p(pMY_CXT_ int i)
28{
29 MY_CXT.i = i;
30}
f16dd614
DM
31
32SV*
5d477a6d 33my_cxt_getsv_interp(void)
f16dd614
DM
34{
35#ifdef PERL_IMPLICIT_CONTEXT
36 dTHX;
37 dMY_CXT_INTERP(my_perl);
38#else
39 dMY_CXT;
40#endif
41 return MY_CXT.sv;
42}
43
85ce96a1
DM
44void
45my_cxt_setsv_p(SV* sv _pMY_CXT)
46{
47 MY_CXT.sv = sv;
48}
49
50
9b5c3821 51/* from exception.c */
7a646707 52int apitest_exception(int);
0314122a 53
ff66e713
SH
54/* from core_or_not.inc */
55bool sv_setsv_cow_hashkey_core(void);
56bool sv_setsv_cow_hashkey_notcore(void);
57
2dc92170
NC
58/* A routine to test hv_delayfree_ent
59 (which itself is tested by testing on hv_free_ent */
60
61typedef void (freeent_function)(pTHX_ HV *, register HE *);
62
63void
64test_freeent(freeent_function *f) {
65 dTHX;
66 dSP;
67 HV *test_hash = newHV();
68 HE *victim;
69 SV *test_scalar;
70 U32 results[4];
71 int i;
72
8afd2d2e
NC
73#ifdef PURIFY
74 victim = (HE*)safemalloc(sizeof(HE));
75#else
2dc92170
NC
76 /* Storing then deleting something should ensure that a hash entry is
77 available. */
78 hv_store(test_hash, "", 0, &PL_sv_yes, 0);
79 hv_delete(test_hash, "", 0, 0);
80
81 /* We need to "inline" new_he here as it's static, and the functions we
82 test expect to be able to call del_HE on the HE */
6a93a7e5 83 if (!PL_body_roots[HE_SVSLOT])
2dc92170 84 croak("PL_he_root is 0");
8a722a80 85 victim = (HE*) PL_body_roots[HE_SVSLOT];
6a93a7e5 86 PL_body_roots[HE_SVSLOT] = HeNEXT(victim);
8afd2d2e 87#endif
2dc92170
NC
88
89 victim->hent_hek = Perl_share_hek(aTHX_ "", 0, 0);
90
91 test_scalar = newSV(0);
92 SvREFCNT_inc(test_scalar);
de616631 93 HeVAL(victim) = test_scalar;
2dc92170
NC
94
95 /* Need this little game else we free the temps on the return stack. */
96 results[0] = SvREFCNT(test_scalar);
97 SAVETMPS;
98 results[1] = SvREFCNT(test_scalar);
99 f(aTHX_ test_hash, victim);
100 results[2] = SvREFCNT(test_scalar);
101 FREETMPS;
102 results[3] = SvREFCNT(test_scalar);
103
104 i = 0;
105 do {
106 mPUSHu(results[i]);
107 } while (++i < sizeof(results)/sizeof(results[0]));
108
109 /* Goodbye to our extra reference. */
110 SvREFCNT_dec(test_scalar);
111}
112
b54b4831
NC
113
114static I32
115rot13_key(pTHX_ IV action, SV *field) {
116 MAGIC *mg = mg_find(field, PERL_MAGIC_uvar);
117 SV *keysv;
118 if (mg && (keysv = mg->mg_obj)) {
119 STRLEN len;
120 const char *p = SvPV(keysv, len);
121
122 if (len) {
123 SV *newkey = newSV(len);
124 char *new_p = SvPVX(newkey);
125
126 /* There's a deliberate fencepost error here to loop len + 1 times
127 to copy the trailing \0 */
128 do {
129 char new_c = *p++;
130 /* Try doing this cleanly and clearly in EBCDIC another way: */
131 switch (new_c) {
132 case 'A': new_c = 'N'; break;
133 case 'B': new_c = 'O'; break;
134 case 'C': new_c = 'P'; break;
135 case 'D': new_c = 'Q'; break;
136 case 'E': new_c = 'R'; break;
137 case 'F': new_c = 'S'; break;
138 case 'G': new_c = 'T'; break;
139 case 'H': new_c = 'U'; break;
140 case 'I': new_c = 'V'; break;
141 case 'J': new_c = 'W'; break;
142 case 'K': new_c = 'X'; break;
143 case 'L': new_c = 'Y'; break;
144 case 'M': new_c = 'Z'; break;
145 case 'N': new_c = 'A'; break;
146 case 'O': new_c = 'B'; break;
147 case 'P': new_c = 'C'; break;
148 case 'Q': new_c = 'D'; break;
149 case 'R': new_c = 'E'; break;
150 case 'S': new_c = 'F'; break;
151 case 'T': new_c = 'G'; break;
152 case 'U': new_c = 'H'; break;
153 case 'V': new_c = 'I'; break;
154 case 'W': new_c = 'J'; break;
155 case 'X': new_c = 'K'; break;
156 case 'Y': new_c = 'L'; break;
157 case 'Z': new_c = 'M'; break;
158 case 'a': new_c = 'n'; break;
159 case 'b': new_c = 'o'; break;
160 case 'c': new_c = 'p'; break;
161 case 'd': new_c = 'q'; break;
162 case 'e': new_c = 'r'; break;
163 case 'f': new_c = 's'; break;
164 case 'g': new_c = 't'; break;
165 case 'h': new_c = 'u'; break;
166 case 'i': new_c = 'v'; break;
167 case 'j': new_c = 'w'; break;
168 case 'k': new_c = 'x'; break;
169 case 'l': new_c = 'y'; break;
170 case 'm': new_c = 'z'; break;
171 case 'n': new_c = 'a'; break;
172 case 'o': new_c = 'b'; break;
173 case 'p': new_c = 'c'; break;
174 case 'q': new_c = 'd'; break;
175 case 'r': new_c = 'e'; break;
176 case 's': new_c = 'f'; break;
177 case 't': new_c = 'g'; break;
178 case 'u': new_c = 'h'; break;
179 case 'v': new_c = 'i'; break;
180 case 'w': new_c = 'j'; break;
181 case 'x': new_c = 'k'; break;
182 case 'y': new_c = 'l'; break;
183 case 'z': new_c = 'm'; break;
184 }
185 *new_p++ = new_c;
186 } while (len--);
187 SvCUR_set(newkey, SvCUR(keysv));
188 SvPOK_on(newkey);
189 if (SvUTF8(keysv))
190 SvUTF8_on(newkey);
191
192 mg->mg_obj = newkey;
193 }
194 }
195 return 0;
196}
197
55289a74
NC
198#include "const-c.inc"
199
0314122a
NC
200MODULE = XS::APItest:Hash PACKAGE = XS::APItest::Hash
201
55289a74
NC
202INCLUDE: const-xs.inc
203
b54b4831
NC
204void
205rot13_hash(hash)
206 HV *hash
207 CODE:
208 {
209 struct ufuncs uf;
210 uf.uf_val = rot13_key;
211 uf.uf_set = 0;
212 uf.uf_index = 0;
213
214 sv_magic((SV*)hash, NULL, PERL_MAGIC_uvar, (char*)&uf, sizeof(uf));
215 }
216
028f8eaa
MHM
217#define UTF8KLEN(sv, len) (SvUTF8(sv) ? -(I32)len : (I32)len)
218
0314122a
NC
219bool
220exists(hash, key_sv)
221 PREINIT:
222 STRLEN len;
223 const char *key;
224 INPUT:
225 HV *hash
226 SV *key_sv
227 CODE:
228 key = SvPV(key_sv, len);
028f8eaa 229 RETVAL = hv_exists(hash, key, UTF8KLEN(key_sv, len));
0314122a
NC
230 OUTPUT:
231 RETVAL
232
b60cf05a 233SV *
55289a74 234delete(hash, key_sv, flags = 0)
b60cf05a
NC
235 PREINIT:
236 STRLEN len;
237 const char *key;
238 INPUT:
239 HV *hash
240 SV *key_sv
55289a74 241 I32 flags;
b60cf05a
NC
242 CODE:
243 key = SvPV(key_sv, len);
244 /* It's already mortal, so need to increase reference count. */
55289a74
NC
245 RETVAL
246 = SvREFCNT_inc(hv_delete(hash, key, UTF8KLEN(key_sv, len), flags));
247 OUTPUT:
248 RETVAL
249
250SV *
251delete_ent(hash, key_sv, flags = 0)
252 INPUT:
253 HV *hash
254 SV *key_sv
255 I32 flags;
256 CODE:
257 /* It's already mortal, so need to increase reference count. */
258 RETVAL = SvREFCNT_inc(hv_delete_ent(hash, key_sv, flags, 0));
b60cf05a
NC
259 OUTPUT:
260 RETVAL
261
262SV *
858117f8
NC
263store_ent(hash, key, value)
264 PREINIT:
265 SV *copy;
266 HE *result;
267 INPUT:
268 HV *hash
269 SV *key
270 SV *value
271 CODE:
272 copy = newSV(0);
273 result = hv_store_ent(hash, key, copy, 0);
274 SvSetMagicSV(copy, value);
275 if (!result) {
276 SvREFCNT_dec(copy);
277 XSRETURN_EMPTY;
278 }
279 /* It's about to become mortal, so need to increase reference count.
280 */
281 RETVAL = SvREFCNT_inc(HeVAL(result));
282 OUTPUT:
283 RETVAL
284
285
286SV *
b60cf05a
NC
287store(hash, key_sv, value)
288 PREINIT:
289 STRLEN len;
290 const char *key;
291 SV *copy;
292 SV **result;
293 INPUT:
294 HV *hash
295 SV *key_sv
296 SV *value
297 CODE:
298 key = SvPV(key_sv, len);
299 copy = newSV(0);
028f8eaa 300 result = hv_store(hash, key, UTF8KLEN(key_sv, len), copy, 0);
858117f8 301 SvSetMagicSV(copy, value);
b60cf05a
NC
302 if (!result) {
303 SvREFCNT_dec(copy);
304 XSRETURN_EMPTY;
305 }
306 /* It's about to become mortal, so need to increase reference count.
307 */
308 RETVAL = SvREFCNT_inc(*result);
309 OUTPUT:
310 RETVAL
311
312
313SV *
314fetch(hash, key_sv)
315 PREINIT:
316 STRLEN len;
317 const char *key;
318 SV **result;
319 INPUT:
320 HV *hash
321 SV *key_sv
322 CODE:
323 key = SvPV(key_sv, len);
028f8eaa 324 result = hv_fetch(hash, key, UTF8KLEN(key_sv, len), 0);
b60cf05a
NC
325 if (!result) {
326 XSRETURN_EMPTY;
327 }
328 /* Force mg_get */
329 RETVAL = newSVsv(*result);
330 OUTPUT:
331 RETVAL
2dc92170 332
439efdfe 333void
2dc92170
NC
334test_hv_free_ent()
335 PPCODE:
336 test_freeent(&Perl_hv_free_ent);
337 XSRETURN(4);
338
439efdfe 339void
2dc92170
NC
340test_hv_delayfree_ent()
341 PPCODE:
342 test_freeent(&Perl_hv_delayfree_ent);
343 XSRETURN(4);
35ab5632
NC
344
345SV *
346test_share_unshare_pvn(input)
347 PREINIT:
35ab5632
NC
348 STRLEN len;
349 U32 hash;
350 char *pvx;
351 char *p;
352 INPUT:
353 SV *input
354 CODE:
355 pvx = SvPV(input, len);
356 PERL_HASH(hash, pvx, len);
357 p = sharepvn(pvx, len, hash);
358 RETVAL = newSVpvn(p, len);
359 unsharepvn(p, len, hash);
360 OUTPUT:
361 RETVAL
d8c5b3c5
NC
362
363bool
364refcounted_he_exists(key, level=0)
365 SV *key
366 IV level
367 CODE:
368 if (level) {
369 croak("level must be zero, not %"IVdf, level);
370 }
371 RETVAL = (Perl_refcounted_he_fetch(aTHX_ PL_curcop->cop_hints_hash,
372 key, NULL, 0, 0, 0)
373 != &PL_sv_placeholder);
374 OUTPUT:
375 RETVAL
376
377
378SV *
379refcounted_he_fetch(key, level=0)
380 SV *key
381 IV level
382 CODE:
383 if (level) {
384 croak("level must be zero, not %"IVdf, level);
385 }
386 RETVAL = Perl_refcounted_he_fetch(aTHX_ PL_curcop->cop_hints_hash, key,
387 NULL, 0, 0, 0);
388 SvREFCNT_inc(RETVAL);
389 OUTPUT:
390 RETVAL
391
35ab5632 392
0314122a
NC
393=pod
394
395sub TIEHASH { bless {}, $_[0] }
396sub STORE { $_[0]->{$_[1]} = $_[2] }
397sub FETCH { $_[0]->{$_[1]} }
398sub FIRSTKEY { my $a = scalar keys %{$_[0]}; each %{$_[0]} }
399sub NEXTKEY { each %{$_[0]} }
400sub EXISTS { exists $_[0]->{$_[1]} }
401sub DELETE { delete $_[0]->{$_[1]} }
402sub CLEAR { %{$_[0]} = () }
403
404=cut
405
3e61d65a
JH
406MODULE = XS::APItest PACKAGE = XS::APItest
407
408PROTOTYPES: DISABLE
409
85ce96a1
DM
410BOOT:
411{
412 MY_CXT_INIT;
413 MY_CXT.i = 99;
414 MY_CXT.sv = newSVpv("initial",0);
415}
416
417void
418CLONE(...)
419 CODE:
420 MY_CXT_CLONE;
421 MY_CXT.sv = newSVpv("initial_clone",0);
422
3e61d65a
JH
423void
424print_double(val)
425 double val
426 CODE:
427 printf("%5.3f\n",val);
428
429int
430have_long_double()
431 CODE:
432#ifdef HAS_LONG_DOUBLE
433 RETVAL = 1;
434#else
435 RETVAL = 0;
436#endif
cabb36f0
CN
437 OUTPUT:
438 RETVAL
3e61d65a
JH
439
440void
441print_long_double()
442 CODE:
443#ifdef HAS_LONG_DOUBLE
fc0bf671 444# if defined(PERL_PRIfldbl) && (LONG_DOUBLESIZE > DOUBLESIZE)
3e61d65a
JH
445 long double val = 7.0;
446 printf("%5.3" PERL_PRIfldbl "\n",val);
447# else
448 double val = 7.0;
449 printf("%5.3f\n",val);
450# endif
451#endif
452
453void
3e61d65a
JH
454print_int(val)
455 int val
456 CODE:
457 printf("%d\n",val);
458
459void
460print_long(val)
461 long val
462 CODE:
463 printf("%ld\n",val);
464
465void
466print_float(val)
467 float val
468 CODE:
469 printf("%5.3f\n",val);
9d911683
NIS
470
471void
472print_flush()
473 CODE:
474 fflush(stdout);
d4b90eee
SH
475
476void
477mpushp()
478 PPCODE:
479 EXTEND(SP, 3);
480 mPUSHp("one", 3);
481 mPUSHp("two", 3);
482 mPUSHp("three", 5);
483 XSRETURN(3);
484
485void
486mpushn()
487 PPCODE:
488 EXTEND(SP, 3);
489 mPUSHn(0.5);
490 mPUSHn(-0.25);
491 mPUSHn(0.125);
492 XSRETURN(3);
493
494void
495mpushi()
496 PPCODE:
497 EXTEND(SP, 3);
d75b63cf
MHM
498 mPUSHi(-1);
499 mPUSHi(2);
500 mPUSHi(-3);
d4b90eee
SH
501 XSRETURN(3);
502
503void
504mpushu()
505 PPCODE:
506 EXTEND(SP, 3);
d75b63cf
MHM
507 mPUSHu(1);
508 mPUSHu(2);
509 mPUSHu(3);
d4b90eee
SH
510 XSRETURN(3);
511
512void
513mxpushp()
514 PPCODE:
515 mXPUSHp("one", 3);
516 mXPUSHp("two", 3);
517 mXPUSHp("three", 5);
518 XSRETURN(3);
519
520void
521mxpushn()
522 PPCODE:
523 mXPUSHn(0.5);
524 mXPUSHn(-0.25);
525 mXPUSHn(0.125);
526 XSRETURN(3);
527
528void
529mxpushi()
530 PPCODE:
d75b63cf
MHM
531 mXPUSHi(-1);
532 mXPUSHi(2);
533 mXPUSHi(-3);
d4b90eee
SH
534 XSRETURN(3);
535
536void
537mxpushu()
538 PPCODE:
d75b63cf
MHM
539 mXPUSHu(1);
540 mXPUSHu(2);
541 mXPUSHu(3);
d4b90eee 542 XSRETURN(3);
d1f347d7
DM
543
544
545void
546call_sv(sv, flags, ...)
547 SV* sv
548 I32 flags
549 PREINIT:
550 I32 i;
551 PPCODE:
552 for (i=0; i<items-2; i++)
553 ST(i) = ST(i+2); /* pop first two args */
554 PUSHMARK(SP);
555 SP += items - 2;
556 PUTBACK;
557 i = call_sv(sv, flags);
558 SPAGAIN;
559 EXTEND(SP, 1);
560 PUSHs(sv_2mortal(newSViv(i)));
561
562void
563call_pv(subname, flags, ...)
564 char* subname
565 I32 flags
566 PREINIT:
567 I32 i;
568 PPCODE:
569 for (i=0; i<items-2; i++)
570 ST(i) = ST(i+2); /* pop first two args */
571 PUSHMARK(SP);
572 SP += items - 2;
573 PUTBACK;
574 i = call_pv(subname, flags);
575 SPAGAIN;
576 EXTEND(SP, 1);
577 PUSHs(sv_2mortal(newSViv(i)));
578
579void
580call_method(methname, flags, ...)
581 char* methname
582 I32 flags
583 PREINIT:
584 I32 i;
585 PPCODE:
586 for (i=0; i<items-2; i++)
587 ST(i) = ST(i+2); /* pop first two args */
588 PUSHMARK(SP);
589 SP += items - 2;
590 PUTBACK;
591 i = call_method(methname, flags);
592 SPAGAIN;
593 EXTEND(SP, 1);
594 PUSHs(sv_2mortal(newSViv(i)));
595
596void
597eval_sv(sv, flags)
598 SV* sv
599 I32 flags
600 PREINIT:
601 I32 i;
602 PPCODE:
603 PUTBACK;
604 i = eval_sv(sv, flags);
605 SPAGAIN;
606 EXTEND(SP, 1);
607 PUSHs(sv_2mortal(newSViv(i)));
608
b8e65a9b 609void
d1f347d7
DM
610eval_pv(p, croak_on_error)
611 const char* p
612 I32 croak_on_error
d1f347d7
DM
613 PPCODE:
614 PUTBACK;
615 EXTEND(SP, 1);
616 PUSHs(eval_pv(p, croak_on_error));
617
618void
619require_pv(pv)
620 const char* pv
d1f347d7
DM
621 PPCODE:
622 PUTBACK;
623 require_pv(pv);
624
0ca3a874 625int
7a646707 626apitest_exception(throw_e)
0ca3a874
MHM
627 int throw_e
628 OUTPUT:
629 RETVAL
d1f347d7 630
ef469b03 631void
7e7a3dfc
GA
632mycroak(sv)
633 SV* sv
ef469b03 634 CODE:
7e7a3dfc
GA
635 if (SvOK(sv)) {
636 Perl_croak(aTHX_ "%s", SvPV_nolen(sv));
637 }
638 else {
639 Perl_croak(aTHX_ NULL);
640 }
5d2b1485
NC
641
642SV*
643strtab()
644 CODE:
645 RETVAL = newRV_inc((SV*)PL_strtab);
646 OUTPUT:
647 RETVAL
85ce96a1
DM
648
649int
650my_cxt_getint()
651 CODE:
652 dMY_CXT;
653 RETVAL = my_cxt_getint_p(aMY_CXT);
654 OUTPUT:
655 RETVAL
656
657void
658my_cxt_setint(i)
659 int i;
660 CODE:
661 dMY_CXT;
662 my_cxt_setint_p(aMY_CXT_ i);
663
664void
665my_cxt_getsv()
666 PPCODE:
85ce96a1 667 EXTEND(SP, 1);
f16dd614 668 ST(0) = my_cxt_getsv_interp();
85ce96a1
DM
669 XSRETURN(1);
670
671void
672my_cxt_setsv(sv)
673 SV *sv;
674 CODE:
675 dMY_CXT;
676 SvREFCNT_dec(MY_CXT.sv);
677 my_cxt_setsv_p(sv _aMY_CXT);
678 SvREFCNT_inc(sv);
34482cd6
NC
679
680bool
681sv_setsv_cow_hashkey_core()
682
683bool
684sv_setsv_cow_hashkey_notcore()
84ac5fd7
NC
685
686void
687BEGIN()
688 CODE:
689 sv_inc(get_sv("XS::APItest::BEGIN_called", GV_ADD|GV_ADDMULTI));
690
691void
692CHECK()
693 CODE:
694 sv_inc(get_sv("XS::APItest::CHECK_called", GV_ADD|GV_ADDMULTI));
695
696void
697UNITCHECK()
698 CODE:
0932863f 699 sv_inc(get_sv("XS::APItest::UNITCHECK_called", GV_ADD|GV_ADDMULTI));
84ac5fd7
NC
700
701void
702INIT()
703 CODE:
704 sv_inc(get_sv("XS::APItest::INIT_called", GV_ADD|GV_ADDMULTI));
705
706void
707END()
708 CODE:
709 sv_inc(get_sv("XS::APItest::END_called", GV_ADD|GV_ADDMULTI));