Clean up test files left behind (on Win32, at least) by Archive-Extract
[p5sagit/p5-mst-13.2.git] / ext / XS / APItest / APItest.xs
CommitLineData
6a93a7e5 1#define PERL_IN_XS_APITEST
3e61d65a 2#include "EXTERN.h"
3#include "perl.h"
4#include "XSUB.h"
5
85ce96a1 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 20int
21my_cxt_getint_p(pMY_CXT)
22{
23 return MY_CXT.i;
24}
f16dd614 25
85ce96a1 26void
27my_cxt_setint_p(pMY_CXT_ int i)
28{
29 MY_CXT.i = i;
30}
f16dd614 31
32SV*
5d477a6d 33my_cxt_getsv_interp(void)
f16dd614 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 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 54/* from core_or_not.inc */
55bool sv_setsv_cow_hashkey_core(void);
56bool sv_setsv_cow_hashkey_notcore(void);
57
2dc92170 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 73#ifdef PURIFY
74 victim = (HE*)safemalloc(sizeof(HE));
75#else
2dc92170 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 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 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 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
0314122a 198MODULE = XS::APItest:Hash PACKAGE = XS::APItest::Hash
199
b54b4831 200void
201rot13_hash(hash)
202 HV *hash
203 CODE:
204 {
205 struct ufuncs uf;
206 uf.uf_val = rot13_key;
207 uf.uf_set = 0;
208 uf.uf_index = 0;
209
210 sv_magic((SV*)hash, NULL, PERL_MAGIC_uvar, (char*)&uf, sizeof(uf));
211 }
212
028f8eaa 213#define UTF8KLEN(sv, len) (SvUTF8(sv) ? -(I32)len : (I32)len)
214
0314122a 215bool
216exists(hash, key_sv)
217 PREINIT:
218 STRLEN len;
219 const char *key;
220 INPUT:
221 HV *hash
222 SV *key_sv
223 CODE:
224 key = SvPV(key_sv, len);
028f8eaa 225 RETVAL = hv_exists(hash, key, UTF8KLEN(key_sv, len));
0314122a 226 OUTPUT:
227 RETVAL
228
b60cf05a 229SV *
230delete(hash, key_sv)
231 PREINIT:
232 STRLEN len;
233 const char *key;
234 INPUT:
235 HV *hash
236 SV *key_sv
237 CODE:
238 key = SvPV(key_sv, len);
239 /* It's already mortal, so need to increase reference count. */
028f8eaa 240 RETVAL = SvREFCNT_inc(hv_delete(hash, key, UTF8KLEN(key_sv, len), 0));
b60cf05a 241 OUTPUT:
242 RETVAL
243
244SV *
858117f8 245store_ent(hash, key, value)
246 PREINIT:
247 SV *copy;
248 HE *result;
249 INPUT:
250 HV *hash
251 SV *key
252 SV *value
253 CODE:
254 copy = newSV(0);
255 result = hv_store_ent(hash, key, copy, 0);
256 SvSetMagicSV(copy, value);
257 if (!result) {
258 SvREFCNT_dec(copy);
259 XSRETURN_EMPTY;
260 }
261 /* It's about to become mortal, so need to increase reference count.
262 */
263 RETVAL = SvREFCNT_inc(HeVAL(result));
264 OUTPUT:
265 RETVAL
266
267
268SV *
b60cf05a 269store(hash, key_sv, value)
270 PREINIT:
271 STRLEN len;
272 const char *key;
273 SV *copy;
274 SV **result;
275 INPUT:
276 HV *hash
277 SV *key_sv
278 SV *value
279 CODE:
280 key = SvPV(key_sv, len);
281 copy = newSV(0);
028f8eaa 282 result = hv_store(hash, key, UTF8KLEN(key_sv, len), copy, 0);
858117f8 283 SvSetMagicSV(copy, value);
b60cf05a 284 if (!result) {
285 SvREFCNT_dec(copy);
286 XSRETURN_EMPTY;
287 }
288 /* It's about to become mortal, so need to increase reference count.
289 */
290 RETVAL = SvREFCNT_inc(*result);
291 OUTPUT:
292 RETVAL
293
294
295SV *
296fetch(hash, key_sv)
297 PREINIT:
298 STRLEN len;
299 const char *key;
300 SV **result;
301 INPUT:
302 HV *hash
303 SV *key_sv
304 CODE:
305 key = SvPV(key_sv, len);
028f8eaa 306 result = hv_fetch(hash, key, UTF8KLEN(key_sv, len), 0);
b60cf05a 307 if (!result) {
308 XSRETURN_EMPTY;
309 }
310 /* Force mg_get */
311 RETVAL = newSVsv(*result);
312 OUTPUT:
313 RETVAL
2dc92170 314
439efdfe 315void
2dc92170 316test_hv_free_ent()
317 PPCODE:
318 test_freeent(&Perl_hv_free_ent);
319 XSRETURN(4);
320
439efdfe 321void
2dc92170 322test_hv_delayfree_ent()
323 PPCODE:
324 test_freeent(&Perl_hv_delayfree_ent);
325 XSRETURN(4);
35ab5632 326
327SV *
328test_share_unshare_pvn(input)
329 PREINIT:
35ab5632 330 STRLEN len;
331 U32 hash;
332 char *pvx;
333 char *p;
334 INPUT:
335 SV *input
336 CODE:
337 pvx = SvPV(input, len);
338 PERL_HASH(hash, pvx, len);
339 p = sharepvn(pvx, len, hash);
340 RETVAL = newSVpvn(p, len);
341 unsharepvn(p, len, hash);
342 OUTPUT:
343 RETVAL
d8c5b3c5 344
345bool
346refcounted_he_exists(key, level=0)
347 SV *key
348 IV level
349 CODE:
350 if (level) {
351 croak("level must be zero, not %"IVdf, level);
352 }
353 RETVAL = (Perl_refcounted_he_fetch(aTHX_ PL_curcop->cop_hints_hash,
354 key, NULL, 0, 0, 0)
355 != &PL_sv_placeholder);
356 OUTPUT:
357 RETVAL
358
359
360SV *
361refcounted_he_fetch(key, level=0)
362 SV *key
363 IV level
364 CODE:
365 if (level) {
366 croak("level must be zero, not %"IVdf, level);
367 }
368 RETVAL = Perl_refcounted_he_fetch(aTHX_ PL_curcop->cop_hints_hash, key,
369 NULL, 0, 0, 0);
370 SvREFCNT_inc(RETVAL);
371 OUTPUT:
372 RETVAL
373
35ab5632 374
0314122a 375=pod
376
377sub TIEHASH { bless {}, $_[0] }
378sub STORE { $_[0]->{$_[1]} = $_[2] }
379sub FETCH { $_[0]->{$_[1]} }
380sub FIRSTKEY { my $a = scalar keys %{$_[0]}; each %{$_[0]} }
381sub NEXTKEY { each %{$_[0]} }
382sub EXISTS { exists $_[0]->{$_[1]} }
383sub DELETE { delete $_[0]->{$_[1]} }
384sub CLEAR { %{$_[0]} = () }
385
386=cut
387
3e61d65a 388MODULE = XS::APItest PACKAGE = XS::APItest
389
390PROTOTYPES: DISABLE
391
85ce96a1 392BOOT:
393{
394 MY_CXT_INIT;
395 MY_CXT.i = 99;
396 MY_CXT.sv = newSVpv("initial",0);
397}
398
399void
400CLONE(...)
401 CODE:
402 MY_CXT_CLONE;
403 MY_CXT.sv = newSVpv("initial_clone",0);
404
3e61d65a 405void
406print_double(val)
407 double val
408 CODE:
409 printf("%5.3f\n",val);
410
411int
412have_long_double()
413 CODE:
414#ifdef HAS_LONG_DOUBLE
415 RETVAL = 1;
416#else
417 RETVAL = 0;
418#endif
cabb36f0 419 OUTPUT:
420 RETVAL
3e61d65a 421
422void
423print_long_double()
424 CODE:
425#ifdef HAS_LONG_DOUBLE
fc0bf671 426# if defined(PERL_PRIfldbl) && (LONG_DOUBLESIZE > DOUBLESIZE)
3e61d65a 427 long double val = 7.0;
428 printf("%5.3" PERL_PRIfldbl "\n",val);
429# else
430 double val = 7.0;
431 printf("%5.3f\n",val);
432# endif
433#endif
434
435void
3e61d65a 436print_int(val)
437 int val
438 CODE:
439 printf("%d\n",val);
440
441void
442print_long(val)
443 long val
444 CODE:
445 printf("%ld\n",val);
446
447void
448print_float(val)
449 float val
450 CODE:
451 printf("%5.3f\n",val);
9d911683 452
453void
454print_flush()
455 CODE:
456 fflush(stdout);
d4b90eee 457
458void
459mpushp()
460 PPCODE:
461 EXTEND(SP, 3);
462 mPUSHp("one", 3);
463 mPUSHp("two", 3);
464 mPUSHp("three", 5);
465 XSRETURN(3);
466
467void
468mpushn()
469 PPCODE:
470 EXTEND(SP, 3);
471 mPUSHn(0.5);
472 mPUSHn(-0.25);
473 mPUSHn(0.125);
474 XSRETURN(3);
475
476void
477mpushi()
478 PPCODE:
479 EXTEND(SP, 3);
d75b63cf 480 mPUSHi(-1);
481 mPUSHi(2);
482 mPUSHi(-3);
d4b90eee 483 XSRETURN(3);
484
485void
486mpushu()
487 PPCODE:
488 EXTEND(SP, 3);
d75b63cf 489 mPUSHu(1);
490 mPUSHu(2);
491 mPUSHu(3);
d4b90eee 492 XSRETURN(3);
493
494void
495mxpushp()
496 PPCODE:
497 mXPUSHp("one", 3);
498 mXPUSHp("two", 3);
499 mXPUSHp("three", 5);
500 XSRETURN(3);
501
502void
503mxpushn()
504 PPCODE:
505 mXPUSHn(0.5);
506 mXPUSHn(-0.25);
507 mXPUSHn(0.125);
508 XSRETURN(3);
509
510void
511mxpushi()
512 PPCODE:
d75b63cf 513 mXPUSHi(-1);
514 mXPUSHi(2);
515 mXPUSHi(-3);
d4b90eee 516 XSRETURN(3);
517
518void
519mxpushu()
520 PPCODE:
d75b63cf 521 mXPUSHu(1);
522 mXPUSHu(2);
523 mXPUSHu(3);
d4b90eee 524 XSRETURN(3);
d1f347d7 525
526
527void
528call_sv(sv, flags, ...)
529 SV* sv
530 I32 flags
531 PREINIT:
532 I32 i;
533 PPCODE:
534 for (i=0; i<items-2; i++)
535 ST(i) = ST(i+2); /* pop first two args */
536 PUSHMARK(SP);
537 SP += items - 2;
538 PUTBACK;
539 i = call_sv(sv, flags);
540 SPAGAIN;
541 EXTEND(SP, 1);
542 PUSHs(sv_2mortal(newSViv(i)));
543
544void
545call_pv(subname, flags, ...)
546 char* subname
547 I32 flags
548 PREINIT:
549 I32 i;
550 PPCODE:
551 for (i=0; i<items-2; i++)
552 ST(i) = ST(i+2); /* pop first two args */
553 PUSHMARK(SP);
554 SP += items - 2;
555 PUTBACK;
556 i = call_pv(subname, flags);
557 SPAGAIN;
558 EXTEND(SP, 1);
559 PUSHs(sv_2mortal(newSViv(i)));
560
561void
562call_method(methname, flags, ...)
563 char* methname
564 I32 flags
565 PREINIT:
566 I32 i;
567 PPCODE:
568 for (i=0; i<items-2; i++)
569 ST(i) = ST(i+2); /* pop first two args */
570 PUSHMARK(SP);
571 SP += items - 2;
572 PUTBACK;
573 i = call_method(methname, flags);
574 SPAGAIN;
575 EXTEND(SP, 1);
576 PUSHs(sv_2mortal(newSViv(i)));
577
578void
579eval_sv(sv, flags)
580 SV* sv
581 I32 flags
582 PREINIT:
583 I32 i;
584 PPCODE:
585 PUTBACK;
586 i = eval_sv(sv, flags);
587 SPAGAIN;
588 EXTEND(SP, 1);
589 PUSHs(sv_2mortal(newSViv(i)));
590
b8e65a9b 591void
d1f347d7 592eval_pv(p, croak_on_error)
593 const char* p
594 I32 croak_on_error
d1f347d7 595 PPCODE:
596 PUTBACK;
597 EXTEND(SP, 1);
598 PUSHs(eval_pv(p, croak_on_error));
599
600void
601require_pv(pv)
602 const char* pv
d1f347d7 603 PPCODE:
604 PUTBACK;
605 require_pv(pv);
606
0ca3a874 607int
7a646707 608apitest_exception(throw_e)
0ca3a874 609 int throw_e
610 OUTPUT:
611 RETVAL
d1f347d7 612
ef469b03 613void
7e7a3dfc 614mycroak(sv)
615 SV* sv
ef469b03 616 CODE:
7e7a3dfc 617 if (SvOK(sv)) {
618 Perl_croak(aTHX_ "%s", SvPV_nolen(sv));
619 }
620 else {
621 Perl_croak(aTHX_ NULL);
622 }
5d2b1485 623
624SV*
625strtab()
626 CODE:
627 RETVAL = newRV_inc((SV*)PL_strtab);
628 OUTPUT:
629 RETVAL
85ce96a1 630
631int
632my_cxt_getint()
633 CODE:
634 dMY_CXT;
635 RETVAL = my_cxt_getint_p(aMY_CXT);
636 OUTPUT:
637 RETVAL
638
639void
640my_cxt_setint(i)
641 int i;
642 CODE:
643 dMY_CXT;
644 my_cxt_setint_p(aMY_CXT_ i);
645
646void
647my_cxt_getsv()
648 PPCODE:
85ce96a1 649 EXTEND(SP, 1);
f16dd614 650 ST(0) = my_cxt_getsv_interp();
85ce96a1 651 XSRETURN(1);
652
653void
654my_cxt_setsv(sv)
655 SV *sv;
656 CODE:
657 dMY_CXT;
658 SvREFCNT_dec(MY_CXT.sv);
659 my_cxt_setsv_p(sv _aMY_CXT);
660 SvREFCNT_inc(sv);
34482cd6 661
662bool
663sv_setsv_cow_hashkey_core()
664
665bool
666sv_setsv_cow_hashkey_notcore()
84ac5fd7 667
668void
669BEGIN()
670 CODE:
671 sv_inc(get_sv("XS::APItest::BEGIN_called", GV_ADD|GV_ADDMULTI));
672
673void
674CHECK()
675 CODE:
676 sv_inc(get_sv("XS::APItest::CHECK_called", GV_ADD|GV_ADDMULTI));
677
678void
679UNITCHECK()
680 CODE:
0932863f 681 sv_inc(get_sv("XS::APItest::UNITCHECK_called", GV_ADD|GV_ADDMULTI));
84ac5fd7 682
683void
684INIT()
685 CODE:
686 sv_inc(get_sv("XS::APItest::INIT_called", GV_ADD|GV_ADDMULTI));
687
688void
689END()
690 CODE:
691 sv_inc(get_sv("XS::APItest::END_called", GV_ADD|GV_ADDMULTI));