This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
APItest: Add U8* typemap, and use it
[perl5.git] / ext / XS-APItest / APItest.xs
1 #define PERL_IN_XS_APITEST
2
3 /* We want to be able to test things that aren't API yet. */
4 #define PERL_EXT
5
6 /* Do *not* define PERL_NO_GET_CONTEXT.  This is the one place where we get
7    to test implicit Perl_get_context().  */
8
9 #include "EXTERN.h"
10 #include "perl.h"
11 #include "XSUB.h"
12
13 typedef FILE NativeFile;
14
15 #include "fakesdio.h"   /* Causes us to use PerlIO below */
16
17 typedef SV *SVREF;
18 typedef PTR_TBL_t *XS__APItest__PtrTable;
19 typedef PerlIO * InputStream;
20 typedef PerlIO * OutputStream;
21
22 #define croak_fail() croak("fail at " __FILE__ " line %d", __LINE__)
23 #define croak_fail_nep(h, w) croak("fail %p!=%p at " __FILE__ " line %d", (h), (w), __LINE__)
24 #define croak_fail_nei(h, w) croak("fail %d!=%d at " __FILE__ " line %d", (int)(h), (int)(w), __LINE__)
25
26 #ifdef EBCDIC
27
28 void
29 cat_utf8a2n(SV* sv, const char * const ascii_utf8, STRLEN len)
30 {
31     /* Converts variant UTF-8 text pointed to by 'ascii_utf8' of length 'len',
32      * to UTF-EBCDIC, appending that text to the text already in 'sv'.
33      * Currently doesn't work on invariants, as that is unneeded here, and we
34      * could get double translations if we did.
35      *
36      * It has the algorithm for strict UTF-8 hard-coded in to find the code
37      * point it represents, then calls uvchr_to_utf8() to convert to
38      * UTF-EBCDIC).
39      *
40      * Note that this uses code points, not characters.  Thus if the input is
41      * the UTF-8 for the code point 0xFF, the output will be the UTF-EBCDIC for
42      * 0xFF, even though that code point represents different characters on
43      * ASCII vs EBCDIC platforms. */
44
45     dTHX;
46     char * p = (char *) ascii_utf8;
47     const char * const e = p + len;
48
49     while (p < e) {
50         UV code_point;
51         U8 native_utf8[UTF8_MAXBYTES + 1];
52         U8 * char_end;
53         U8 start = (U8) *p;
54
55         /* Start bytes are the same in both UTF-8 and I8, therefore we can
56          * treat this ASCII UTF-8 byte as an I8 byte.  But PL_utf8skip[] is
57          * indexed by NATIVE_UTF8 bytes, so transform to that */
58         STRLEN char_bytes_len = PL_utf8skip[I8_TO_NATIVE_UTF8(start)];
59
60         if (start < 0xc2) {
61             croak("fail: Expecting start byte, instead got 0x%X at %s line %d",
62                                                   (U8) *p, __FILE__, __LINE__);
63         }
64         code_point = (start & (((char_bytes_len) >= 7)
65                                 ? 0x00
66                                 : (0x1F >> ((char_bytes_len)-2))));
67         p++;
68         while (p < e && ((( (U8) *p) & 0xC0) == 0x80)) {
69
70             code_point = (code_point << 6) | (( (U8) *p) & 0x3F);
71             p++;
72         }
73
74         char_end = uvchr_to_utf8(native_utf8, code_point);
75         sv_catpvn(sv, (char *) native_utf8, char_end - native_utf8);
76     }
77 }
78
79 #endif
80
81 /* for my_cxt tests */
82
83 #define MY_CXT_KEY "XS::APItest::_guts" XS_VERSION
84
85 typedef struct {
86     int i;
87     SV *sv;
88     GV *cscgv;
89     AV *cscav;
90     AV *bhkav;
91     bool bhk_record;
92     peep_t orig_peep;
93     peep_t orig_rpeep;
94     int peep_recording;
95     AV *peep_recorder;
96     AV *rpeep_recorder;
97     AV *xop_record;
98 } my_cxt_t;
99
100 START_MY_CXT
101
102 int
103 S_myset_set(pTHX_ SV* sv, MAGIC* mg)
104 {
105     SV *isv = (SV*)mg->mg_ptr;
106
107     PERL_UNUSED_ARG(sv);
108     SvIVX(isv)++;
109     return 0;
110 }
111
112 MGVTBL vtbl_foo, vtbl_bar;
113 MGVTBL vtbl_myset = { 0, S_myset_set, 0, 0, 0, 0, 0, 0 };
114
115
116 /* indirect functions to test the [pa]MY_CXT macros */
117
118 int
119 my_cxt_getint_p(pMY_CXT)
120 {
121     return MY_CXT.i;
122 }
123
124 void
125 my_cxt_setint_p(pMY_CXT_ int i)
126 {
127     MY_CXT.i = i;
128 }
129
130 SV*
131 my_cxt_getsv_interp_context(void)
132 {
133     dTHX;
134     dMY_CXT_INTERP(my_perl);
135     return MY_CXT.sv;
136 }
137
138 SV*
139 my_cxt_getsv_interp(void)
140 {
141     dMY_CXT;
142     return MY_CXT.sv;
143 }
144
145 void
146 my_cxt_setsv_p(SV* sv _pMY_CXT)
147 {
148     MY_CXT.sv = sv;
149 }
150
151
152 /* from exception.c */
153 int apitest_exception(int);
154
155 /* from core_or_not.inc */
156 bool sv_setsv_cow_hashkey_core(void);
157 bool sv_setsv_cow_hashkey_notcore(void);
158
159 /* A routine to test hv_delayfree_ent
160    (which itself is tested by testing on hv_free_ent  */
161
162 typedef void (freeent_function)(pTHX_ HV *, HE *);
163
164 void
165 test_freeent(freeent_function *f) {
166     dSP;
167     HV *test_hash = newHV();
168     HE *victim;
169     SV *test_scalar;
170     U32 results[4];
171     int i;
172
173 #ifdef PURIFY
174     victim = (HE*)safemalloc(sizeof(HE));
175 #else
176     /* Storing then deleting something should ensure that a hash entry is
177        available.  */
178     (void) hv_stores(test_hash, "", &PL_sv_yes);
179     (void) hv_deletes(test_hash, "", 0);
180
181     /* We need to "inline" new_he here as it's static, and the functions we
182        test expect to be able to call del_HE on the HE  */
183     if (!PL_body_roots[HE_SVSLOT])
184         croak("PL_he_root is 0");
185     victim = (HE*) PL_body_roots[HE_SVSLOT];
186     PL_body_roots[HE_SVSLOT] = HeNEXT(victim);
187 #endif
188
189     victim->hent_hek = Perl_share_hek(aTHX_ "", 0, 0);
190
191     test_scalar = newSV(0);
192     SvREFCNT_inc(test_scalar);
193     HeVAL(victim) = test_scalar;
194
195     /* Need this little game else we free the temps on the return stack.  */
196     results[0] = SvREFCNT(test_scalar);
197     SAVETMPS;
198     results[1] = SvREFCNT(test_scalar);
199     f(aTHX_ test_hash, victim);
200     results[2] = SvREFCNT(test_scalar);
201     FREETMPS;
202     results[3] = SvREFCNT(test_scalar);
203
204     i = 0;
205     do {
206         mXPUSHu(results[i]);
207     } while (++i < (int)(sizeof(results)/sizeof(results[0])));
208
209     /* Goodbye to our extra reference.  */
210     SvREFCNT_dec(test_scalar);
211 }
212
213 /* Not that it matters much, but it's handy for the flipped character to just
214  * be the opposite case (at least for ASCII-range and most Latin1 as well). */
215 #define FLIP_BIT ('A' ^ 'a')
216
217 static I32
218 bitflip_key(pTHX_ IV action, SV *field) {
219     MAGIC *mg = mg_find(field, PERL_MAGIC_uvar);
220     SV *keysv;
221     PERL_UNUSED_ARG(action);
222     if (mg && (keysv = mg->mg_obj)) {
223         STRLEN len;
224         const char *p = SvPV(keysv, len);
225
226         if (len) {
227             /* Allow for the flipped val to be longer than the original.  This
228              * is just for testing, so can afford to have some slop */
229             const STRLEN newlen = len * 2;
230
231             SV *newkey = newSV(newlen);
232             const char * const new_p_orig = SvPVX(newkey);
233             char *new_p = (char *) new_p_orig;
234
235             if (SvUTF8(keysv)) {
236                 const char *const end = p + len;
237                 while (p < end) {
238                     STRLEN curlen;
239                     UV chr = utf8_to_uvchr_buf((U8 *)p, (U8 *) end, &curlen);
240
241                     /* Make sure don't exceed bounds */
242                     assert(new_p - new_p_orig + curlen < newlen);
243
244                     new_p = (char *)uvchr_to_utf8((U8 *)new_p, chr ^ FLIP_BIT);
245                     p += curlen;
246                 }
247                 SvUTF8_on(newkey);
248             } else {
249                 while (len--)
250                     *new_p++ = *p++ ^ FLIP_BIT;
251             }
252             *new_p = '\0';
253             SvCUR_set(newkey, new_p - new_p_orig);
254             SvPOK_on(newkey);
255
256             mg->mg_obj = newkey;
257         }
258     }
259     return 0;
260 }
261
262 static I32
263 rot13_key(pTHX_ IV action, SV *field) {
264     MAGIC *mg = mg_find(field, PERL_MAGIC_uvar);
265     SV *keysv;
266     PERL_UNUSED_ARG(action);
267     if (mg && (keysv = mg->mg_obj)) {
268         STRLEN len;
269         const char *p = SvPV(keysv, len);
270
271         if (len) {
272             SV *newkey = newSV(len);
273             char *new_p = SvPVX(newkey);
274
275             /* There's a deliberate fencepost error here to loop len + 1 times
276                to copy the trailing \0  */
277             do {
278                 char new_c = *p++;
279                 /* Try doing this cleanly and clearly in EBCDIC another way: */
280                 switch (new_c) {
281                 case 'A': new_c = 'N'; break;
282                 case 'B': new_c = 'O'; break;
283                 case 'C': new_c = 'P'; break;
284                 case 'D': new_c = 'Q'; break;
285                 case 'E': new_c = 'R'; break;
286                 case 'F': new_c = 'S'; break;
287                 case 'G': new_c = 'T'; break;
288                 case 'H': new_c = 'U'; break;
289                 case 'I': new_c = 'V'; break;
290                 case 'J': new_c = 'W'; break;
291                 case 'K': new_c = 'X'; break;
292                 case 'L': new_c = 'Y'; break;
293                 case 'M': new_c = 'Z'; break;
294                 case 'N': new_c = 'A'; break;
295                 case 'O': new_c = 'B'; break;
296                 case 'P': new_c = 'C'; break;
297                 case 'Q': new_c = 'D'; break;
298                 case 'R': new_c = 'E'; break;
299                 case 'S': new_c = 'F'; break;
300                 case 'T': new_c = 'G'; break;
301                 case 'U': new_c = 'H'; break;
302                 case 'V': new_c = 'I'; break;
303                 case 'W': new_c = 'J'; break;
304                 case 'X': new_c = 'K'; break;
305                 case 'Y': new_c = 'L'; break;
306                 case 'Z': new_c = 'M'; break;
307                 case 'a': new_c = 'n'; break;
308                 case 'b': new_c = 'o'; break;
309                 case 'c': new_c = 'p'; break;
310                 case 'd': new_c = 'q'; break;
311                 case 'e': new_c = 'r'; break;
312                 case 'f': new_c = 's'; break;
313                 case 'g': new_c = 't'; break;
314                 case 'h': new_c = 'u'; break;
315                 case 'i': new_c = 'v'; break;
316                 case 'j': new_c = 'w'; break;
317                 case 'k': new_c = 'x'; break;
318                 case 'l': new_c = 'y'; break;
319                 case 'm': new_c = 'z'; break;
320                 case 'n': new_c = 'a'; break;
321                 case 'o': new_c = 'b'; break;
322                 case 'p': new_c = 'c'; break;
323                 case 'q': new_c = 'd'; break;
324                 case 'r': new_c = 'e'; break;
325                 case 's': new_c = 'f'; break;
326                 case 't': new_c = 'g'; break;
327                 case 'u': new_c = 'h'; break;
328                 case 'v': new_c = 'i'; break;
329                 case 'w': new_c = 'j'; break;
330                 case 'x': new_c = 'k'; break;
331                 case 'y': new_c = 'l'; break;
332                 case 'z': new_c = 'm'; break;
333                 }
334                 *new_p++ = new_c;
335             } while (len--);
336             SvCUR_set(newkey, SvCUR(keysv));
337             SvPOK_on(newkey);
338             if (SvUTF8(keysv))
339                 SvUTF8_on(newkey);
340
341             mg->mg_obj = newkey;
342         }
343     }
344     return 0;
345 }
346
347 STATIC I32
348 rmagical_a_dummy(pTHX_ IV idx, SV *sv) {
349     PERL_UNUSED_ARG(idx);
350     PERL_UNUSED_ARG(sv);
351     return 0;
352 }
353
354 /* We could do "= { 0 };" but some versions of gcc do warn
355  * (with -Wextra) about missing initializer, this is probably gcc
356  * being a bit too paranoid.  But since this is file-static, we can
357  * just have it without initializer, since it should get
358  * zero-initialized. */
359 STATIC MGVTBL rmagical_b;
360
361 STATIC void
362 blockhook_csc_start(pTHX_ int full)
363 {
364     dMY_CXT;
365     AV *const cur = GvAV(MY_CXT.cscgv);
366
367     PERL_UNUSED_ARG(full);
368     SAVEGENERICSV(GvAV(MY_CXT.cscgv));
369
370     if (cur) {
371         I32 i;
372         AV *const new_av = newAV();
373
374         for (i = 0; i <= av_tindex(cur); i++) {
375             av_store(new_av, i, newSVsv(*av_fetch(cur, i, 0)));
376         }
377
378         GvAV(MY_CXT.cscgv) = new_av;
379     }
380 }
381
382 STATIC void
383 blockhook_csc_pre_end(pTHX_ OP **o)
384 {
385     dMY_CXT;
386
387     PERL_UNUSED_ARG(o);
388     /* if we hit the end of a scope we missed the start of, we need to
389      * unconditionally clear @CSC */
390     if (GvAV(MY_CXT.cscgv) == MY_CXT.cscav && MY_CXT.cscav) {
391         av_clear(MY_CXT.cscav);
392     }
393
394 }
395
396 STATIC void
397 blockhook_test_start(pTHX_ int full)
398 {
399     dMY_CXT;
400     AV *av;
401     
402     if (MY_CXT.bhk_record) {
403         av = newAV();
404         av_push(av, newSVpvs("start"));
405         av_push(av, newSViv(full));
406         av_push(MY_CXT.bhkav, newRV_noinc(MUTABLE_SV(av)));
407     }
408 }
409
410 STATIC void
411 blockhook_test_pre_end(pTHX_ OP **o)
412 {
413     dMY_CXT;
414
415     PERL_UNUSED_ARG(o);
416     if (MY_CXT.bhk_record)
417         av_push(MY_CXT.bhkav, newSVpvs("pre_end"));
418 }
419
420 STATIC void
421 blockhook_test_post_end(pTHX_ OP **o)
422 {
423     dMY_CXT;
424
425     PERL_UNUSED_ARG(o);
426     if (MY_CXT.bhk_record)
427         av_push(MY_CXT.bhkav, newSVpvs("post_end"));
428 }
429
430 STATIC void
431 blockhook_test_eval(pTHX_ OP *const o)
432 {
433     dMY_CXT;
434     AV *av;
435
436     if (MY_CXT.bhk_record) {
437         av = newAV();
438         av_push(av, newSVpvs("eval"));
439         av_push(av, newSVpv(OP_NAME(o), 0));
440         av_push(MY_CXT.bhkav, newRV_noinc(MUTABLE_SV(av)));
441     }
442 }
443
444 STATIC BHK bhk_csc, bhk_test;
445
446 STATIC void
447 my_peep (pTHX_ OP *o)
448 {
449     dMY_CXT;
450
451     if (!o)
452         return;
453
454     MY_CXT.orig_peep(aTHX_ o);
455
456     if (!MY_CXT.peep_recording)
457         return;
458
459     for (; o; o = o->op_next) {
460         if (o->op_type == OP_CONST && cSVOPx_sv(o) && SvPOK(cSVOPx_sv(o))) {
461             av_push(MY_CXT.peep_recorder, newSVsv(cSVOPx_sv(o)));
462         }
463     }
464 }
465
466 STATIC void
467 my_rpeep (pTHX_ OP *o)
468 {
469     dMY_CXT;
470
471     if (!o)
472         return;
473
474     MY_CXT.orig_rpeep(aTHX_ o);
475
476     if (!MY_CXT.peep_recording)
477         return;
478
479     for (; o; o = o->op_next) {
480         if (o->op_type == OP_CONST && cSVOPx_sv(o) && SvPOK(cSVOPx_sv(o))) {
481             av_push(MY_CXT.rpeep_recorder, newSVsv(cSVOPx_sv(o)));
482         }
483     }
484 }
485
486 STATIC OP *
487 THX_ck_entersub_args_lists(pTHX_ OP *entersubop, GV *namegv, SV *ckobj)
488 {
489     PERL_UNUSED_ARG(namegv);
490     PERL_UNUSED_ARG(ckobj);
491     return ck_entersub_args_list(entersubop);
492 }
493
494 STATIC OP *
495 THX_ck_entersub_args_scalars(pTHX_ OP *entersubop, GV *namegv, SV *ckobj)
496 {
497     OP *aop = cUNOPx(entersubop)->op_first;
498     PERL_UNUSED_ARG(namegv);
499     PERL_UNUSED_ARG(ckobj);
500     if (!OpHAS_SIBLING(aop))
501         aop = cUNOPx(aop)->op_first;
502     for (aop = OpSIBLING(aop); OpHAS_SIBLING(aop); aop = OpSIBLING(aop)) {
503         op_contextualize(aop, G_SCALAR);
504     }
505     return entersubop;
506 }
507
508 STATIC OP *
509 THX_ck_entersub_multi_sum(pTHX_ OP *entersubop, GV *namegv, SV *ckobj)
510 {
511     OP *sumop = NULL;
512     OP *parent = entersubop;
513     OP *pushop = cUNOPx(entersubop)->op_first;
514     PERL_UNUSED_ARG(namegv);
515     PERL_UNUSED_ARG(ckobj);
516     if (!OpHAS_SIBLING(pushop)) {
517         parent = pushop;
518         pushop = cUNOPx(pushop)->op_first;
519     }
520     while (1) {
521         OP *aop = OpSIBLING(pushop);
522         if (!OpHAS_SIBLING(aop))
523             break;
524         /* cut out first arg */
525         op_sibling_splice(parent, pushop, 1, NULL);
526         op_contextualize(aop, G_SCALAR);
527         if (sumop) {
528             sumop = newBINOP(OP_ADD, 0, sumop, aop);
529         } else {
530             sumop = aop;
531         }
532     }
533     if (!sumop)
534         sumop = newSVOP(OP_CONST, 0, newSViv(0));
535     op_free(entersubop);
536     return sumop;
537 }
538
539 STATIC void test_op_list_describe_part(SV *res, OP *o);
540 STATIC void
541 test_op_list_describe_part(SV *res, OP *o)
542 {
543     sv_catpv(res, PL_op_name[o->op_type]);
544     switch (o->op_type) {
545         case OP_CONST: {
546             sv_catpvf(res, "(%d)", (int)SvIV(cSVOPx(o)->op_sv));
547         } break;
548     }
549     if (o->op_flags & OPf_KIDS) {
550         OP *k;
551         sv_catpvs(res, "[");
552         for (k = cUNOPx(o)->op_first; k; k = OpSIBLING(k))
553             test_op_list_describe_part(res, k);
554         sv_catpvs(res, "]");
555     } else {
556         sv_catpvs(res, ".");
557     }
558 }
559
560 STATIC char *
561 test_op_list_describe(OP *o)
562 {
563     SV *res = sv_2mortal(newSVpvs(""));
564     if (o)
565         test_op_list_describe_part(res, o);
566     return SvPVX(res);
567 }
568
569 /* the real new*OP functions have a tendency to call fold_constants, and
570  * other such unhelpful things, so we need our own versions for testing */
571
572 #define mkUNOP(t, f) THX_mkUNOP(aTHX_ (t), (f))
573 static OP *
574 THX_mkUNOP(pTHX_ U32 type, OP *first)
575 {
576     UNOP *unop;
577     NewOp(1103, unop, 1, UNOP);
578     unop->op_type   = (OPCODE)type;
579     op_sibling_splice((OP*)unop, NULL, 0, first);
580     return (OP *)unop;
581 }
582
583 #define mkBINOP(t, f, l) THX_mkBINOP(aTHX_ (t), (f), (l))
584 static OP *
585 THX_mkBINOP(pTHX_ U32 type, OP *first, OP *last)
586 {
587     BINOP *binop;
588     NewOp(1103, binop, 1, BINOP);
589     binop->op_type      = (OPCODE)type;
590     op_sibling_splice((OP*)binop, NULL, 0, last);
591     op_sibling_splice((OP*)binop, NULL, 0, first);
592     return (OP *)binop;
593 }
594
595 #define mkLISTOP(t, f, s, l) THX_mkLISTOP(aTHX_ (t), (f), (s), (l))
596 static OP *
597 THX_mkLISTOP(pTHX_ U32 type, OP *first, OP *sib, OP *last)
598 {
599     LISTOP *listop;
600     NewOp(1103, listop, 1, LISTOP);
601     listop->op_type     = (OPCODE)type;
602     op_sibling_splice((OP*)listop, NULL, 0, last);
603     op_sibling_splice((OP*)listop, NULL, 0, sib);
604     op_sibling_splice((OP*)listop, NULL, 0, first);
605     return (OP *)listop;
606 }
607
608 static char *
609 test_op_linklist_describe(OP *start)
610 {
611     SV *rv = sv_2mortal(newSVpvs(""));
612     OP *o;
613     o = start = LINKLIST(start);
614     do {
615         sv_catpvs(rv, ".");
616         sv_catpv(rv, OP_NAME(o));
617         if (o->op_type == OP_CONST)
618             sv_catsv(rv, cSVOPo->op_sv);
619         o = o->op_next;
620     } while (o && o != start);
621     return SvPVX(rv);
622 }
623
624 /** establish_cleanup operator, ripped off from Scope::Cleanup **/
625
626 STATIC void
627 THX_run_cleanup(pTHX_ void *cleanup_code_ref)
628 {
629     dSP;
630     PUSHSTACK;
631     ENTER;
632     SAVETMPS;
633     PUSHMARK(SP);
634     call_sv((SV*)cleanup_code_ref, G_VOID|G_DISCARD);
635     FREETMPS;
636     LEAVE;
637     POPSTACK;
638 }
639
640 STATIC OP *
641 THX_pp_establish_cleanup(pTHX)
642 {
643     dSP;
644     SV *cleanup_code_ref;
645     cleanup_code_ref = newSVsv(POPs);
646     SAVEFREESV(cleanup_code_ref);
647     SAVEDESTRUCTOR_X(THX_run_cleanup, cleanup_code_ref);
648     if(GIMME_V != G_VOID) PUSHs(&PL_sv_undef);
649     RETURN;
650 }
651
652 STATIC OP *
653 THX_ck_entersub_establish_cleanup(pTHX_ OP *entersubop, GV *namegv, SV *ckobj)
654 {
655     OP *parent, *pushop, *argop, *estop;
656     ck_entersub_args_proto(entersubop, namegv, ckobj);
657     parent = entersubop;
658     pushop = cUNOPx(entersubop)->op_first;
659     if(!OpHAS_SIBLING(pushop)) {
660         parent = pushop;
661         pushop = cUNOPx(pushop)->op_first;
662     }
663     /* extract out first arg, then delete the rest of the tree */
664     argop = OpSIBLING(pushop);
665     op_sibling_splice(parent, pushop, 1, NULL);
666     op_free(entersubop);
667
668     estop = mkUNOP(OP_RAND, argop);
669     estop->op_ppaddr = THX_pp_establish_cleanup;
670     PL_hints |= HINT_BLOCK_SCOPE;
671     return estop;
672 }
673
674 STATIC OP *
675 THX_ck_entersub_postinc(pTHX_ OP *entersubop, GV *namegv, SV *ckobj)
676 {
677     OP *parent, *pushop, *argop;
678     ck_entersub_args_proto(entersubop, namegv, ckobj);
679     parent = entersubop;
680     pushop = cUNOPx(entersubop)->op_first;
681     if(!OpHAS_SIBLING(pushop)) {
682         parent = pushop;
683         pushop = cUNOPx(pushop)->op_first;
684     }
685     argop = OpSIBLING(pushop);
686     op_sibling_splice(parent, pushop, 1, NULL);
687     op_free(entersubop);
688     return newUNOP(OP_POSTINC, 0,
689         op_lvalue(op_contextualize(argop, G_SCALAR), OP_POSTINC));
690 }
691
692 STATIC OP *
693 THX_ck_entersub_pad_scalar(pTHX_ OP *entersubop, GV *namegv, SV *ckobj)
694 {
695     OP *pushop, *argop;
696     PADOFFSET padoff = NOT_IN_PAD;
697     SV *a0, *a1;
698     ck_entersub_args_proto(entersubop, namegv, ckobj);
699     pushop = cUNOPx(entersubop)->op_first;
700     if(!OpHAS_SIBLING(pushop))
701         pushop = cUNOPx(pushop)->op_first;
702     argop = OpSIBLING(pushop);
703     if(argop->op_type != OP_CONST || OpSIBLING(argop)->op_type != OP_CONST)
704         croak("bad argument expression type for pad_scalar()");
705     a0 = cSVOPx_sv(argop);
706     a1 = cSVOPx_sv(OpSIBLING(argop));
707     switch(SvIV(a0)) {
708         case 1: {
709             SV *namesv = sv_2mortal(newSVpvs("$"));
710             sv_catsv(namesv, a1);
711             padoff = pad_findmy_sv(namesv, 0);
712         } break;
713         case 2: {
714             char *namepv;
715             STRLEN namelen;
716             SV *namesv = sv_2mortal(newSVpvs("$"));
717             sv_catsv(namesv, a1);
718             namepv = SvPV(namesv, namelen);
719             padoff = pad_findmy_pvn(namepv, namelen, SvUTF8(namesv));
720         } break;
721         case 3: {
722             char *namepv;
723             SV *namesv = sv_2mortal(newSVpvs("$"));
724             sv_catsv(namesv, a1);
725             namepv = SvPV_nolen(namesv);
726             padoff = pad_findmy_pv(namepv, SvUTF8(namesv));
727         } break;
728         case 4: {
729             padoff = pad_findmy_pvs("$foo", 0);
730         } break;
731         default: croak("bad type value for pad_scalar()");
732     }
733     op_free(entersubop);
734     if(padoff == NOT_IN_PAD) {
735         return newSVOP(OP_CONST, 0, newSVpvs("NOT_IN_PAD"));
736     } else if(PAD_COMPNAME_FLAGS_isOUR(padoff)) {
737         return newSVOP(OP_CONST, 0, newSVpvs("NOT_MY"));
738     } else {
739         OP *padop = newOP(OP_PADSV, 0);
740         padop->op_targ = padoff;
741         return padop;
742     }
743 }
744
745 /** RPN keyword parser **/
746
747 #define sv_is_glob(sv) (SvTYPE(sv) == SVt_PVGV)
748 #define sv_is_regexp(sv) (SvTYPE(sv) == SVt_REGEXP)
749 #define sv_is_string(sv) \
750     (!sv_is_glob(sv) && !sv_is_regexp(sv) && \
751      (SvFLAGS(sv) & (SVf_IOK|SVf_NOK|SVf_POK|SVp_IOK|SVp_NOK|SVp_POK)))
752
753 static SV *hintkey_rpn_sv, *hintkey_calcrpn_sv, *hintkey_stufftest_sv;
754 static SV *hintkey_swaptwostmts_sv, *hintkey_looprest_sv;
755 static SV *hintkey_scopelessblock_sv;
756 static SV *hintkey_stmtasexpr_sv, *hintkey_stmtsasexpr_sv;
757 static SV *hintkey_loopblock_sv, *hintkey_blockasexpr_sv;
758 static SV *hintkey_swaplabel_sv, *hintkey_labelconst_sv;
759 static SV *hintkey_arrayfullexpr_sv, *hintkey_arraylistexpr_sv;
760 static SV *hintkey_arraytermexpr_sv, *hintkey_arrayarithexpr_sv;
761 static SV *hintkey_arrayexprflags_sv;
762 static SV *hintkey_DEFSV_sv;
763 static SV *hintkey_with_vars_sv;
764 static SV *hintkey_join_with_space_sv;
765 static int (*next_keyword_plugin)(pTHX_ char *, STRLEN, OP **);
766
767 /* low-level parser helpers */
768
769 #define PL_bufptr (PL_parser->bufptr)
770 #define PL_bufend (PL_parser->bufend)
771
772 /* RPN parser */
773
774 #define parse_var() THX_parse_var(aTHX)
775 static OP *THX_parse_var(pTHX)
776 {
777     char *s = PL_bufptr;
778     char *start = s;
779     PADOFFSET varpos;
780     OP *padop;
781     if(*s != '$') croak("RPN syntax error");
782     while(1) {
783         char c = *++s;
784         if(!isALNUM(c)) break;
785     }
786     if(s-start < 2) croak("RPN syntax error");
787     lex_read_to(s);
788     varpos = pad_findmy_pvn(start, s-start, 0);
789     if(varpos == NOT_IN_PAD || PAD_COMPNAME_FLAGS_isOUR(varpos))
790         croak("RPN only supports \"my\" variables");
791     padop = newOP(OP_PADSV, 0);
792     padop->op_targ = varpos;
793     return padop;
794 }
795
796 #define push_rpn_item(o) \
797     op_sibling_splice(parent, NULL, 0, o);
798 #define pop_rpn_item() ( \
799     (tmpop = op_sibling_splice(parent, NULL, 1, NULL)) \
800         ? tmpop : (croak("RPN stack underflow"), (OP*)NULL))
801
802 #define parse_rpn_expr() THX_parse_rpn_expr(aTHX)
803 static OP *THX_parse_rpn_expr(pTHX)
804 {
805     OP *tmpop;
806     /* fake parent for splice to mess with */
807     OP *parent = mkBINOP(OP_NULL, NULL, NULL);
808
809     while(1) {
810         I32 c;
811         lex_read_space(0);
812         c = lex_peek_unichar(0);
813         switch(c) {
814             case /*(*/')': case /*{*/'}': {
815                 OP *result = pop_rpn_item();
816                 if(cLISTOPx(parent)->op_first)
817                     croak("RPN expression must return a single value");
818                 op_free(parent);
819                 return result;
820             } break;
821             case '0': case '1': case '2': case '3': case '4':
822             case '5': case '6': case '7': case '8': case '9': {
823                 UV val = 0;
824                 do {
825                     lex_read_unichar(0);
826                     val = 10*val + (c - '0');
827                     c = lex_peek_unichar(0);
828                 } while(c >= '0' && c <= '9');
829                 push_rpn_item(newSVOP(OP_CONST, 0, newSVuv(val)));
830             } break;
831             case '$': {
832                 push_rpn_item(parse_var());
833             } break;
834             case '+': {
835                 OP *b = pop_rpn_item();
836                 OP *a = pop_rpn_item();
837                 lex_read_unichar(0);
838                 push_rpn_item(newBINOP(OP_I_ADD, 0, a, b));
839             } break;
840             case '-': {
841                 OP *b = pop_rpn_item();
842                 OP *a = pop_rpn_item();
843                 lex_read_unichar(0);
844                 push_rpn_item(newBINOP(OP_I_SUBTRACT, 0, a, b));
845             } break;
846             case '*': {
847                 OP *b = pop_rpn_item();
848                 OP *a = pop_rpn_item();
849                 lex_read_unichar(0);
850                 push_rpn_item(newBINOP(OP_I_MULTIPLY, 0, a, b));
851             } break;
852             case '/': {
853                 OP *b = pop_rpn_item();
854                 OP *a = pop_rpn_item();
855                 lex_read_unichar(0);
856                 push_rpn_item(newBINOP(OP_I_DIVIDE, 0, a, b));
857             } break;
858             case '%': {
859                 OP *b = pop_rpn_item();
860                 OP *a = pop_rpn_item();
861                 lex_read_unichar(0);
862                 push_rpn_item(newBINOP(OP_I_MODULO, 0, a, b));
863             } break;
864             default: {
865                 croak("RPN syntax error");
866             } break;
867         }
868     }
869 }
870
871 #define parse_keyword_rpn() THX_parse_keyword_rpn(aTHX)
872 static OP *THX_parse_keyword_rpn(pTHX)
873 {
874     OP *op;
875     lex_read_space(0);
876     if(lex_peek_unichar(0) != '('/*)*/)
877         croak("RPN expression must be parenthesised");
878     lex_read_unichar(0);
879     op = parse_rpn_expr();
880     if(lex_peek_unichar(0) != /*(*/')')
881         croak("RPN expression must be parenthesised");
882     lex_read_unichar(0);
883     return op;
884 }
885
886 #define parse_keyword_calcrpn() THX_parse_keyword_calcrpn(aTHX)
887 static OP *THX_parse_keyword_calcrpn(pTHX)
888 {
889     OP *varop, *exprop;
890     lex_read_space(0);
891     varop = parse_var();
892     lex_read_space(0);
893     if(lex_peek_unichar(0) != '{'/*}*/)
894         croak("RPN expression must be braced");
895     lex_read_unichar(0);
896     exprop = parse_rpn_expr();
897     if(lex_peek_unichar(0) != /*{*/'}')
898         croak("RPN expression must be braced");
899     lex_read_unichar(0);
900     return newASSIGNOP(OPf_STACKED, varop, 0, exprop);
901 }
902
903 #define parse_keyword_stufftest() THX_parse_keyword_stufftest(aTHX)
904 static OP *THX_parse_keyword_stufftest(pTHX)
905 {
906     I32 c;
907     bool do_stuff;
908     lex_read_space(0);
909     do_stuff = lex_peek_unichar(0) == '+';
910     if(do_stuff) {
911         lex_read_unichar(0);
912         lex_read_space(0);
913     }
914     c = lex_peek_unichar(0);
915     if(c == ';') {
916         lex_read_unichar(0);
917     } else if(c != /*{*/'}') {
918         croak("syntax error");
919     }
920     if(do_stuff) lex_stuff_pvs(" ", 0);
921     return newOP(OP_NULL, 0);
922 }
923
924 #define parse_keyword_swaptwostmts() THX_parse_keyword_swaptwostmts(aTHX)
925 static OP *THX_parse_keyword_swaptwostmts(pTHX)
926 {
927     OP *a, *b;
928     a = parse_fullstmt(0);
929     b = parse_fullstmt(0);
930     if(a && b)
931         PL_hints |= HINT_BLOCK_SCOPE;
932     return op_append_list(OP_LINESEQ, b, a);
933 }
934
935 #define parse_keyword_looprest() THX_parse_keyword_looprest(aTHX)
936 static OP *THX_parse_keyword_looprest(pTHX)
937 {
938     return newWHILEOP(0, 1, NULL, newSVOP(OP_CONST, 0, &PL_sv_yes),
939                         parse_stmtseq(0), NULL, 1);
940 }
941
942 #define parse_keyword_scopelessblock() THX_parse_keyword_scopelessblock(aTHX)
943 static OP *THX_parse_keyword_scopelessblock(pTHX)
944 {
945     I32 c;
946     OP *body;
947     lex_read_space(0);
948     if(lex_peek_unichar(0) != '{'/*}*/) croak("syntax error");
949     lex_read_unichar(0);
950     body = parse_stmtseq(0);
951     c = lex_peek_unichar(0);
952     if(c != /*{*/'}' && c != /*[*/']' && c != /*(*/')') croak("syntax error");
953     lex_read_unichar(0);
954     return body;
955 }
956
957 #define parse_keyword_stmtasexpr() THX_parse_keyword_stmtasexpr(aTHX)
958 static OP *THX_parse_keyword_stmtasexpr(pTHX)
959 {
960     OP *o = parse_barestmt(0);
961     if (!o) o = newOP(OP_STUB, 0);
962     if (PL_hints & HINT_BLOCK_SCOPE) o->op_flags |= OPf_PARENS;
963     return op_scope(o);
964 }
965
966 #define parse_keyword_stmtsasexpr() THX_parse_keyword_stmtsasexpr(aTHX)
967 static OP *THX_parse_keyword_stmtsasexpr(pTHX)
968 {
969     OP *o;
970     lex_read_space(0);
971     if(lex_peek_unichar(0) != '{'/*}*/) croak("syntax error");
972     lex_read_unichar(0);
973     o = parse_stmtseq(0);
974     lex_read_space(0);
975     if(lex_peek_unichar(0) != /*{*/'}') croak("syntax error");
976     lex_read_unichar(0);
977     if (!o) o = newOP(OP_STUB, 0);
978     if (PL_hints & HINT_BLOCK_SCOPE) o->op_flags |= OPf_PARENS;
979     return op_scope(o);
980 }
981
982 #define parse_keyword_loopblock() THX_parse_keyword_loopblock(aTHX)
983 static OP *THX_parse_keyword_loopblock(pTHX)
984 {
985     return newWHILEOP(0, 1, NULL, newSVOP(OP_CONST, 0, &PL_sv_yes),
986                         parse_block(0), NULL, 1);
987 }
988
989 #define parse_keyword_blockasexpr() THX_parse_keyword_blockasexpr(aTHX)
990 static OP *THX_parse_keyword_blockasexpr(pTHX)
991 {
992     OP *o = parse_block(0);
993     if (!o) o = newOP(OP_STUB, 0);
994     if (PL_hints & HINT_BLOCK_SCOPE) o->op_flags |= OPf_PARENS;
995     return op_scope(o);
996 }
997
998 #define parse_keyword_swaplabel() THX_parse_keyword_swaplabel(aTHX)
999 static OP *THX_parse_keyword_swaplabel(pTHX)
1000 {
1001     OP *sop = parse_barestmt(0);
1002     SV *label = parse_label(PARSE_OPTIONAL);
1003     if (label) sv_2mortal(label);
1004     return newSTATEOP(label ? SvUTF8(label) : 0,
1005                       label ? savepv(SvPVX(label)) : NULL,
1006                       sop);
1007 }
1008
1009 #define parse_keyword_labelconst() THX_parse_keyword_labelconst(aTHX)
1010 static OP *THX_parse_keyword_labelconst(pTHX)
1011 {
1012     return newSVOP(OP_CONST, 0, parse_label(0));
1013 }
1014
1015 #define parse_keyword_arrayfullexpr() THX_parse_keyword_arrayfullexpr(aTHX)
1016 static OP *THX_parse_keyword_arrayfullexpr(pTHX)
1017 {
1018     return newANONLIST(parse_fullexpr(0));
1019 }
1020
1021 #define parse_keyword_arraylistexpr() THX_parse_keyword_arraylistexpr(aTHX)
1022 static OP *THX_parse_keyword_arraylistexpr(pTHX)
1023 {
1024     return newANONLIST(parse_listexpr(0));
1025 }
1026
1027 #define parse_keyword_arraytermexpr() THX_parse_keyword_arraytermexpr(aTHX)
1028 static OP *THX_parse_keyword_arraytermexpr(pTHX)
1029 {
1030     return newANONLIST(parse_termexpr(0));
1031 }
1032
1033 #define parse_keyword_arrayarithexpr() THX_parse_keyword_arrayarithexpr(aTHX)
1034 static OP *THX_parse_keyword_arrayarithexpr(pTHX)
1035 {
1036     return newANONLIST(parse_arithexpr(0));
1037 }
1038
1039 #define parse_keyword_arrayexprflags() THX_parse_keyword_arrayexprflags(aTHX)
1040 static OP *THX_parse_keyword_arrayexprflags(pTHX)
1041 {
1042     U32 flags = 0;
1043     I32 c;
1044     OP *o;
1045     lex_read_space(0);
1046     c = lex_peek_unichar(0);
1047     if (c != '!' && c != '?') croak("syntax error");
1048     lex_read_unichar(0);
1049     if (c == '?') flags |= PARSE_OPTIONAL;
1050     o = parse_listexpr(flags);
1051     return o ? newANONLIST(o) : newANONHASH(newOP(OP_STUB, 0));
1052 }
1053
1054 #define parse_keyword_DEFSV() THX_parse_keyword_DEFSV(aTHX)
1055 static OP *THX_parse_keyword_DEFSV(pTHX)
1056 {
1057     return newDEFSVOP();
1058 }
1059
1060 #define sv_cat_c(a,b) THX_sv_cat_c(aTHX_ a, b)
1061 static void THX_sv_cat_c(pTHX_ SV *sv, U32 c) {
1062     char ds[UTF8_MAXBYTES + 1], *d;
1063     d = (char *)uvchr_to_utf8((U8 *)ds, c);
1064     if (d - ds > 1) {
1065         sv_utf8_upgrade(sv);
1066     }
1067     sv_catpvn(sv, ds, d - ds);
1068 }
1069
1070 #define parse_keyword_with_vars() THX_parse_keyword_with_vars(aTHX)
1071 static OP *THX_parse_keyword_with_vars(pTHX)
1072 {
1073     I32 c;
1074     IV count;
1075     int save_ix;
1076     OP *vardeclseq, *body;
1077
1078     save_ix = block_start(TRUE);
1079     vardeclseq = NULL;
1080
1081     count = 0;
1082
1083     lex_read_space(0);
1084     c = lex_peek_unichar(0);
1085     while (c != '{') {
1086         SV *varname;
1087         PADOFFSET padoff;
1088
1089         if (c == -1) {
1090             croak("unexpected EOF; expecting '{'");
1091         }
1092
1093         if (!isIDFIRST_uni(c)) {
1094             croak("unexpected '%c'; expecting an identifier", (int)c);
1095         }
1096
1097         varname = newSVpvs("$");
1098         if (lex_bufutf8()) {
1099             SvUTF8_on(varname);
1100         }
1101
1102         sv_cat_c(varname, c);
1103         lex_read_unichar(0);
1104
1105         while (c = lex_peek_unichar(0), c != -1 && isIDCONT_uni(c)) {
1106             sv_cat_c(varname, c);
1107             lex_read_unichar(0);
1108         }
1109
1110         padoff = pad_add_name_sv(varname, padadd_NO_DUP_CHECK, NULL, NULL);
1111
1112         {
1113             OP *my_var = newOP(OP_PADSV, OPf_MOD | (OPpLVAL_INTRO << 8));
1114             my_var->op_targ = padoff;
1115
1116             vardeclseq = op_append_list(
1117                 OP_LINESEQ,
1118                 vardeclseq,
1119                 newSTATEOP(
1120                     0, NULL,
1121                     newASSIGNOP(
1122                         OPf_STACKED,
1123                         my_var, 0,
1124                         newSVOP(
1125                             OP_CONST, 0,
1126                             newSViv(++count)
1127                         )
1128                     )
1129                 )
1130             );
1131         }
1132
1133         lex_read_space(0);
1134         c = lex_peek_unichar(0);
1135     }
1136
1137     intro_my();
1138
1139     body = parse_block(0);
1140
1141     return block_end(save_ix, op_append_list(OP_LINESEQ, vardeclseq, body));
1142 }
1143
1144 #define parse_join_with_space() THX_parse_join_with_space(aTHX)
1145 static OP *THX_parse_join_with_space(pTHX)
1146 {
1147     OP *delim, *args;
1148
1149     args = parse_listexpr(0);
1150     delim = newSVOP(OP_CONST, 0, newSVpvs(" "));
1151     return op_convert_list(OP_JOIN, 0, op_prepend_elem(OP_LIST, delim, args));
1152 }
1153
1154 /* plugin glue */
1155
1156 #define keyword_active(hintkey_sv) THX_keyword_active(aTHX_ hintkey_sv)
1157 static int THX_keyword_active(pTHX_ SV *hintkey_sv)
1158 {
1159     HE *he;
1160     if(!GvHV(PL_hintgv)) return 0;
1161     he = hv_fetch_ent(GvHV(PL_hintgv), hintkey_sv, 0,
1162                 SvSHARED_HASH(hintkey_sv));
1163     return he && SvTRUE(HeVAL(he));
1164 }
1165
1166 static int my_keyword_plugin(pTHX_
1167     char *keyword_ptr, STRLEN keyword_len, OP **op_ptr)
1168 {
1169     if (memEQs(keyword_ptr, keyword_len, "rpn") &&
1170                     keyword_active(hintkey_rpn_sv)) {
1171         *op_ptr = parse_keyword_rpn();
1172         return KEYWORD_PLUGIN_EXPR;
1173     } else if (memEQs(keyword_ptr, keyword_len, "calcrpn") &&
1174                     keyword_active(hintkey_calcrpn_sv)) {
1175         *op_ptr = parse_keyword_calcrpn();
1176         return KEYWORD_PLUGIN_STMT;
1177     } else if (memEQs(keyword_ptr, keyword_len, "stufftest") &&
1178                     keyword_active(hintkey_stufftest_sv)) {
1179         *op_ptr = parse_keyword_stufftest();
1180         return KEYWORD_PLUGIN_STMT;
1181     } else if (memEQs(keyword_ptr, keyword_len, "swaptwostmts") &&
1182                     keyword_active(hintkey_swaptwostmts_sv)) {
1183         *op_ptr = parse_keyword_swaptwostmts();
1184         return KEYWORD_PLUGIN_STMT;
1185     } else if (memEQs(keyword_ptr, keyword_len, "looprest") &&
1186                     keyword_active(hintkey_looprest_sv)) {
1187         *op_ptr = parse_keyword_looprest();
1188         return KEYWORD_PLUGIN_STMT;
1189     } else if (memEQs(keyword_ptr, keyword_len, "scopelessblock") &&
1190                     keyword_active(hintkey_scopelessblock_sv)) {
1191         *op_ptr = parse_keyword_scopelessblock();
1192         return KEYWORD_PLUGIN_STMT;
1193     } else if (memEQs(keyword_ptr, keyword_len, "stmtasexpr") &&
1194                     keyword_active(hintkey_stmtasexpr_sv)) {
1195         *op_ptr = parse_keyword_stmtasexpr();
1196         return KEYWORD_PLUGIN_EXPR;
1197     } else if (memEQs(keyword_ptr, keyword_len, "stmtsasexpr") &&
1198                     keyword_active(hintkey_stmtsasexpr_sv)) {
1199         *op_ptr = parse_keyword_stmtsasexpr();
1200         return KEYWORD_PLUGIN_EXPR;
1201     } else if (memEQs(keyword_ptr, keyword_len, "loopblock") &&
1202                     keyword_active(hintkey_loopblock_sv)) {
1203         *op_ptr = parse_keyword_loopblock();
1204         return KEYWORD_PLUGIN_STMT;
1205     } else if (memEQs(keyword_ptr, keyword_len, "blockasexpr") &&
1206                     keyword_active(hintkey_blockasexpr_sv)) {
1207         *op_ptr = parse_keyword_blockasexpr();
1208         return KEYWORD_PLUGIN_EXPR;
1209     } else if (memEQs(keyword_ptr, keyword_len, "swaplabel") &&
1210                     keyword_active(hintkey_swaplabel_sv)) {
1211         *op_ptr = parse_keyword_swaplabel();
1212         return KEYWORD_PLUGIN_STMT;
1213     } else if (memEQs(keyword_ptr, keyword_len, "labelconst") &&
1214                     keyword_active(hintkey_labelconst_sv)) {
1215         *op_ptr = parse_keyword_labelconst();
1216         return KEYWORD_PLUGIN_EXPR;
1217     } else if (memEQs(keyword_ptr, keyword_len, "arrayfullexpr") &&
1218                     keyword_active(hintkey_arrayfullexpr_sv)) {
1219         *op_ptr = parse_keyword_arrayfullexpr();
1220         return KEYWORD_PLUGIN_EXPR;
1221     } else if (memEQs(keyword_ptr, keyword_len, "arraylistexpr") &&
1222                     keyword_active(hintkey_arraylistexpr_sv)) {
1223         *op_ptr = parse_keyword_arraylistexpr();
1224         return KEYWORD_PLUGIN_EXPR;
1225     } else if (memEQs(keyword_ptr, keyword_len, "arraytermexpr") &&
1226                     keyword_active(hintkey_arraytermexpr_sv)) {
1227         *op_ptr = parse_keyword_arraytermexpr();
1228         return KEYWORD_PLUGIN_EXPR;
1229     } else if (memEQs(keyword_ptr, keyword_len, "arrayarithexpr") &&
1230                     keyword_active(hintkey_arrayarithexpr_sv)) {
1231         *op_ptr = parse_keyword_arrayarithexpr();
1232         return KEYWORD_PLUGIN_EXPR;
1233     } else if (memEQs(keyword_ptr, keyword_len, "arrayexprflags") &&
1234                     keyword_active(hintkey_arrayexprflags_sv)) {
1235         *op_ptr = parse_keyword_arrayexprflags();
1236         return KEYWORD_PLUGIN_EXPR;
1237     } else if (memEQs(keyword_ptr, keyword_len, "DEFSV") &&
1238                     keyword_active(hintkey_DEFSV_sv)) {
1239         *op_ptr = parse_keyword_DEFSV();
1240         return KEYWORD_PLUGIN_EXPR;
1241     } else if (memEQs(keyword_ptr, keyword_len, "with_vars") &&
1242                     keyword_active(hintkey_with_vars_sv)) {
1243         *op_ptr = parse_keyword_with_vars();
1244         return KEYWORD_PLUGIN_STMT;
1245     } else if (memEQs(keyword_ptr, keyword_len, "join_with_space") &&
1246                     keyword_active(hintkey_join_with_space_sv)) {
1247         *op_ptr = parse_join_with_space();
1248         return KEYWORD_PLUGIN_EXPR;
1249     } else {
1250         assert(next_keyword_plugin != my_keyword_plugin);
1251         return next_keyword_plugin(aTHX_ keyword_ptr, keyword_len, op_ptr);
1252     }
1253 }
1254
1255 static XOP my_xop;
1256
1257 static OP *
1258 pp_xop(pTHX)
1259 {
1260     return PL_op->op_next;
1261 }
1262
1263 static void
1264 peep_xop(pTHX_ OP *o, OP *oldop)
1265 {
1266     dMY_CXT;
1267     av_push(MY_CXT.xop_record, newSVpvf("peep:%" UVxf, PTR2UV(o)));
1268     av_push(MY_CXT.xop_record, newSVpvf("oldop:%" UVxf, PTR2UV(oldop)));
1269 }
1270
1271 static I32
1272 filter_call(pTHX_ int idx, SV *buf_sv, int maxlen)
1273 {
1274     char *p;
1275     char *end;
1276     int n = FILTER_READ(idx + 1, buf_sv, maxlen);
1277
1278     if (n<=0) return n;
1279
1280     p = SvPV_force_nolen(buf_sv);
1281     end = p + SvCUR(buf_sv);
1282     while (p < end) {
1283         if (*p == 'o') *p = 'e';
1284         p++;
1285     }
1286     return SvCUR(buf_sv);
1287 }
1288
1289 static AV *
1290 myget_linear_isa(pTHX_ HV *stash, U32 level) {
1291     GV **gvp = (GV **)hv_fetchs(stash, "ISA", 0);
1292     PERL_UNUSED_ARG(level);
1293     return gvp && *gvp && GvAV(*gvp)
1294          ? GvAV(*gvp)
1295          : (AV *)sv_2mortal((SV *)newAV());
1296 }
1297
1298
1299 XS_EXTERNAL(XS_XS__APItest__XSUB_XS_VERSION_undef);
1300 XS_EXTERNAL(XS_XS__APItest__XSUB_XS_VERSION_empty);
1301 XS_EXTERNAL(XS_XS__APItest__XSUB_XS_APIVERSION_invalid);
1302
1303 static struct mro_alg mymro;
1304
1305 static Perl_check_t addissub_nxck_add;
1306
1307 static OP *
1308 addissub_myck_add(pTHX_ OP *op)
1309 {
1310     SV **flag_svp = hv_fetchs(GvHV(PL_hintgv), "XS::APItest/addissub", 0);
1311     OP *aop, *bop;
1312     U8 flags;
1313     if (!(flag_svp && SvTRUE(*flag_svp) && (op->op_flags & OPf_KIDS) &&
1314             (aop = cBINOPx(op)->op_first) && (bop = OpSIBLING(aop)) &&
1315             !OpHAS_SIBLING(bop)))
1316         return addissub_nxck_add(aTHX_ op);
1317     flags = op->op_flags;
1318     op_sibling_splice(op, NULL, 1, NULL); /* excise aop */
1319     op_sibling_splice(op, NULL, 1, NULL); /* excise bop */
1320     op_free(op); /* free the empty husk */
1321     flags &= ~OPf_KIDS;
1322     return newBINOP(OP_SUBTRACT, flags, aop, bop);
1323 }
1324
1325 static Perl_check_t old_ck_rv2cv;
1326
1327 static OP *
1328 my_ck_rv2cv(pTHX_ OP *o)
1329 {
1330     SV *ref;
1331     SV **flag_svp = hv_fetchs(GvHV(PL_hintgv), "XS::APItest/addunder", 0);
1332     OP *aop;
1333
1334     if (flag_svp && SvTRUE(*flag_svp) && (o->op_flags & OPf_KIDS)
1335      && (aop = cUNOPx(o)->op_first) && aop->op_type == OP_CONST
1336      && aop->op_private & (OPpCONST_ENTERED|OPpCONST_BARE)
1337      && (ref = cSVOPx(aop)->op_sv) && SvPOK(ref) && SvCUR(ref)
1338      && *(SvEND(ref)-1) == 'o')
1339     {
1340         SvGROW(ref, SvCUR(ref)+2);
1341         *SvEND(ref) = '_';
1342         SvCUR(ref)++;
1343         *SvEND(ref) = '\0';
1344     }
1345     return old_ck_rv2cv(aTHX_ o);
1346 }
1347
1348 #include "const-c.inc"
1349
1350 MODULE = XS::APItest            PACKAGE = XS::APItest
1351
1352 INCLUDE: const-xs.inc
1353
1354 INCLUDE: numeric.xs
1355
1356 void
1357 assertx(int x)
1358     CODE:
1359         /* this only needs to compile and checks that assert() can be
1360            used this way syntactically */
1361         (void)(assert(x), 1);
1362         (void)(x);
1363
1364 MODULE = XS::APItest::utf8      PACKAGE = XS::APItest::utf8
1365
1366 int
1367 bytes_cmp_utf8(bytes, utf8)
1368         SV *bytes
1369         SV *utf8
1370     PREINIT:
1371         const U8 *b;
1372         STRLEN blen;
1373         const U8 *u;
1374         STRLEN ulen;
1375     CODE:
1376         b = (const U8 *)SvPVbyte(bytes, blen);
1377         u = (const U8 *)SvPVbyte(utf8, ulen);
1378         RETVAL = bytes_cmp_utf8(b, blen, u, ulen);
1379     OUTPUT:
1380         RETVAL
1381
1382 AV *
1383 test_utf8_to_bytes(bytes, len)
1384         U8 * bytes
1385         STRLEN len
1386     PREINIT:
1387         char * ret;
1388     CODE:
1389         RETVAL = newAV();
1390         sv_2mortal((SV*)RETVAL);
1391
1392         ret = (char *) utf8_to_bytes(bytes, &len);
1393         av_push(RETVAL, newSVpv(ret, 0));
1394
1395         /* utf8_to_bytes uses (STRLEN)-1 to signal errors, and we want to
1396          * return that as -1 to perl, so cast to SSize_t in case
1397          * sizeof(IV) > sizeof(STRLEN) */
1398         av_push(RETVAL, newSViv((SSize_t)len));
1399         av_push(RETVAL, newSVpv((const char *) bytes, 0));
1400
1401     OUTPUT:
1402         RETVAL
1403
1404 AV *
1405 test_utf8n_to_uvchr_msgs(s, len, flags)
1406         char *s
1407         STRLEN len
1408         U32 flags
1409     PREINIT:
1410         STRLEN retlen;
1411         UV ret;
1412         U32 errors;
1413         AV *msgs = NULL;
1414
1415     CODE:
1416         RETVAL = newAV();
1417         sv_2mortal((SV*)RETVAL);
1418
1419         ret = utf8n_to_uvchr_msgs((U8*)  s,
1420                                          len,
1421                                          &retlen,
1422                                          flags,
1423                                          &errors,
1424                                          &msgs);
1425
1426         /* Returns the return value in [0]; <retlen> in [1], <errors> in [2] */
1427         av_push(RETVAL, newSVuv(ret));
1428         if (retlen == (STRLEN) -1) {
1429             av_push(RETVAL, newSViv(-1));
1430         }
1431         else {
1432             av_push(RETVAL, newSVuv(retlen));
1433         }
1434         av_push(RETVAL, newSVuv(errors));
1435
1436         /* And any messages in [3] */
1437         if (msgs) {
1438             av_push(RETVAL, newRV_noinc((SV*)msgs));
1439         }
1440
1441     OUTPUT:
1442         RETVAL
1443
1444 AV *
1445 test_utf8n_to_uvchr_error(s, len, flags)
1446
1447         char *s
1448         STRLEN len
1449         U32 flags
1450     PREINIT:
1451         STRLEN retlen;
1452         UV ret;
1453         U32 errors;
1454
1455     CODE:
1456         /* Now that utf8n_to_uvchr() is a trivial wrapper for
1457          * utf8n_to_uvchr_error(), call the latter with the inputs.  It always
1458          * asks for the actual length to be returned and errors to be returned
1459          *
1460          * Length to assume <s> is; not checked, so could have buffer overflow
1461          */
1462         RETVAL = newAV();
1463         sv_2mortal((SV*)RETVAL);
1464
1465         ret = utf8n_to_uvchr_error((U8*) s,
1466                                          len,
1467                                          &retlen,
1468                                          flags,
1469                                          &errors);
1470
1471         /* Returns the return value in [0]; <retlen> in [1], <errors> in [2] */
1472         av_push(RETVAL, newSVuv(ret));
1473         if (retlen == (STRLEN) -1) {
1474             av_push(RETVAL, newSViv(-1));
1475         }
1476         else {
1477             av_push(RETVAL, newSVuv(retlen));
1478         }
1479         av_push(RETVAL, newSVuv(errors));
1480
1481     OUTPUT:
1482         RETVAL
1483
1484 AV *
1485 test_valid_utf8_to_uvchr(s)
1486
1487         SV *s
1488     PREINIT:
1489         STRLEN retlen;
1490         UV ret;
1491
1492     CODE:
1493         /* Call utf8n_to_uvchr() with the inputs.  It always asks for the
1494          * actual length to be returned
1495          *
1496          * Length to assume <s> is; not checked, so could have buffer overflow
1497          */
1498         RETVAL = newAV();
1499         sv_2mortal((SV*)RETVAL);
1500
1501         ret = valid_utf8_to_uvchr((U8*) SvPV_nolen(s), &retlen);
1502
1503         /* Returns the return value in [0]; <retlen> in [1] */
1504         av_push(RETVAL, newSVuv(ret));
1505         av_push(RETVAL, newSVuv(retlen));
1506
1507     OUTPUT:
1508         RETVAL
1509
1510 SV *
1511 test_uvchr_to_utf8_flags(uv, flags)
1512
1513         SV *uv
1514         SV *flags
1515     PREINIT:
1516         U8 dest[UTF8_MAXBYTES + 1];
1517         U8 *ret;
1518
1519     CODE:
1520         /* Call uvchr_to_utf8_flags() with the inputs.  */
1521         ret = uvchr_to_utf8_flags(dest, SvUV(uv), SvUV(flags));
1522         if (! ret) {
1523             XSRETURN_UNDEF;
1524         }
1525         RETVAL = newSVpvn((char *) dest, ret - dest);
1526
1527     OUTPUT:
1528         RETVAL
1529
1530 AV *
1531 test_uvchr_to_utf8_flags_msgs(uv, flags)
1532
1533         SV *uv
1534         SV *flags
1535     PREINIT:
1536         U8 dest[UTF8_MAXBYTES + 1];
1537         U8 *ret;
1538
1539     CODE:
1540         HV *msgs = NULL;
1541         RETVAL = newAV();
1542         sv_2mortal((SV*)RETVAL);
1543
1544         ret = uvchr_to_utf8_flags_msgs(dest, SvUV(uv), SvUV(flags), &msgs);
1545
1546         if (ret) {
1547             av_push(RETVAL, newSVpvn((char *) dest, ret - dest));
1548         }
1549         else {
1550             av_push(RETVAL,  &PL_sv_undef);
1551         }
1552
1553         if (msgs) {
1554             av_push(RETVAL, newRV_noinc((SV*)msgs));
1555         }
1556
1557     OUTPUT:
1558         RETVAL
1559
1560 MODULE = XS::APItest:Overload   PACKAGE = XS::APItest::Overload
1561
1562 void
1563 amagic_deref_call(sv, what)
1564         SV *sv
1565         int what
1566     PPCODE:
1567         /* The reference is owned by something else.  */
1568         PUSHs(amagic_deref_call(sv, what));
1569
1570 # I'd certainly like to discourage the use of this macro, given that we now
1571 # have amagic_deref_call
1572
1573 void
1574 tryAMAGICunDEREF_var(sv, what)
1575         SV *sv
1576         int what
1577     PPCODE:
1578         {
1579             SV **sp = &sv;
1580             switch(what) {
1581             case to_av_amg:
1582                 tryAMAGICunDEREF(to_av);
1583                 break;
1584             case to_cv_amg:
1585                 tryAMAGICunDEREF(to_cv);
1586                 break;
1587             case to_gv_amg:
1588                 tryAMAGICunDEREF(to_gv);
1589                 break;
1590             case to_hv_amg:
1591                 tryAMAGICunDEREF(to_hv);
1592                 break;
1593             case to_sv_amg:
1594                 tryAMAGICunDEREF(to_sv);
1595                 break;
1596             default:
1597                 croak("Invalid value %d passed to tryAMAGICunDEREF_var", what);
1598             }
1599         }
1600         /* The reference is owned by something else.  */
1601         PUSHs(sv);
1602
1603 MODULE = XS::APItest            PACKAGE = XS::APItest::XSUB
1604
1605 BOOT:
1606     newXS("XS::APItest::XSUB::XS_VERSION_undef", XS_XS__APItest__XSUB_XS_VERSION_undef, __FILE__);
1607     newXS("XS::APItest::XSUB::XS_VERSION_empty", XS_XS__APItest__XSUB_XS_VERSION_empty, __FILE__);
1608     newXS("XS::APItest::XSUB::XS_APIVERSION_invalid", XS_XS__APItest__XSUB_XS_APIVERSION_invalid, __FILE__);
1609
1610 void
1611 XS_VERSION_defined(...)
1612     PPCODE:
1613         XS_VERSION_BOOTCHECK;
1614         XSRETURN_EMPTY;
1615
1616 void
1617 XS_APIVERSION_valid(...)
1618     PPCODE:
1619         XS_APIVERSION_BOOTCHECK;
1620         XSRETURN_EMPTY;
1621
1622 void
1623 xsreturn( int len )
1624     PPCODE:
1625         int i = 0;
1626         EXTEND( SP, len );
1627         for ( ; i < len; i++ ) {
1628             ST(i) = sv_2mortal( newSViv(i) );
1629         }
1630         XSRETURN( len );
1631
1632 void
1633 xsreturn_iv()
1634     PPCODE:
1635         XSRETURN_IV(I32_MIN + 1);
1636
1637 void
1638 xsreturn_uv()
1639     PPCODE:
1640         XSRETURN_UV( (U32)((1U<<31) + 1) );
1641
1642 void
1643 xsreturn_nv()
1644     PPCODE:
1645         XSRETURN_NV(0.25);
1646
1647 void
1648 xsreturn_pv()
1649     PPCODE:
1650         XSRETURN_PV("returned");
1651
1652 void
1653 xsreturn_pvn()
1654     PPCODE:
1655         XSRETURN_PVN("returned too much",8);
1656
1657 void
1658 xsreturn_no()
1659     PPCODE:
1660         XSRETURN_NO;
1661
1662 void
1663 xsreturn_yes()
1664     PPCODE:
1665         XSRETURN_YES;
1666
1667 void
1668 xsreturn_undef()
1669     PPCODE:
1670         XSRETURN_UNDEF;
1671
1672 void
1673 xsreturn_empty()
1674     PPCODE:
1675         XSRETURN_EMPTY;
1676
1677 MODULE = XS::APItest:Hash               PACKAGE = XS::APItest::Hash
1678
1679 void
1680 rot13_hash(hash)
1681         HV *hash
1682         CODE:
1683         {
1684             struct ufuncs uf;
1685             uf.uf_val = rot13_key;
1686             uf.uf_set = 0;
1687             uf.uf_index = 0;
1688
1689             sv_magic((SV*)hash, NULL, PERL_MAGIC_uvar, (char*)&uf, sizeof(uf));
1690         }
1691
1692 void
1693 bitflip_hash(hash)
1694         HV *hash
1695         CODE:
1696         {
1697             struct ufuncs uf;
1698             uf.uf_val = bitflip_key;
1699             uf.uf_set = 0;
1700             uf.uf_index = 0;
1701
1702             sv_magic((SV*)hash, NULL, PERL_MAGIC_uvar, (char*)&uf, sizeof(uf));
1703         }
1704
1705 #define UTF8KLEN(sv, len)   (SvUTF8(sv) ? -(I32)len : (I32)len)
1706
1707 bool
1708 exists(hash, key_sv)
1709         PREINIT:
1710         STRLEN len;
1711         const char *key;
1712         INPUT:
1713         HV *hash
1714         SV *key_sv
1715         CODE:
1716         key = SvPV(key_sv, len);
1717         RETVAL = hv_exists(hash, key, UTF8KLEN(key_sv, len));
1718         OUTPUT:
1719         RETVAL
1720
1721 bool
1722 exists_ent(hash, key_sv)
1723         PREINIT:
1724         INPUT:
1725         HV *hash
1726         SV *key_sv
1727         CODE:
1728         RETVAL = hv_exists_ent(hash, key_sv, 0);
1729         OUTPUT:
1730         RETVAL
1731
1732 SV *
1733 delete(hash, key_sv, flags = 0)
1734         PREINIT:
1735         STRLEN len;
1736         const char *key;
1737         INPUT:
1738         HV *hash
1739         SV *key_sv
1740         I32 flags;
1741         CODE:
1742         key = SvPV(key_sv, len);
1743         /* It's already mortal, so need to increase reference count.  */
1744         RETVAL
1745             = SvREFCNT_inc(hv_delete(hash, key, UTF8KLEN(key_sv, len), flags));
1746         OUTPUT:
1747         RETVAL
1748
1749 SV *
1750 delete_ent(hash, key_sv, flags = 0)
1751         INPUT:
1752         HV *hash
1753         SV *key_sv
1754         I32 flags;
1755         CODE:
1756         /* It's already mortal, so need to increase reference count.  */
1757         RETVAL = SvREFCNT_inc(hv_delete_ent(hash, key_sv, flags, 0));
1758         OUTPUT:
1759         RETVAL
1760
1761 SV *
1762 store_ent(hash, key, value)
1763         PREINIT:
1764         SV *copy;
1765         HE *result;
1766         INPUT:
1767         HV *hash
1768         SV *key
1769         SV *value
1770         CODE:
1771         copy = newSV(0);
1772         result = hv_store_ent(hash, key, copy, 0);
1773         SvSetMagicSV(copy, value);
1774         if (!result) {
1775             SvREFCNT_dec(copy);
1776             XSRETURN_EMPTY;
1777         }
1778         /* It's about to become mortal, so need to increase reference count.
1779          */
1780         RETVAL = SvREFCNT_inc(HeVAL(result));
1781         OUTPUT:
1782         RETVAL
1783
1784 SV *
1785 store(hash, key_sv, value)
1786         PREINIT:
1787         STRLEN len;
1788         const char *key;
1789         SV *copy;
1790         SV **result;
1791         INPUT:
1792         HV *hash
1793         SV *key_sv
1794         SV *value
1795         CODE:
1796         key = SvPV(key_sv, len);
1797         copy = newSV(0);
1798         result = hv_store(hash, key, UTF8KLEN(key_sv, len), copy, 0);
1799         SvSetMagicSV(copy, value);
1800         if (!result) {
1801             SvREFCNT_dec(copy);
1802             XSRETURN_EMPTY;
1803         }
1804         /* It's about to become mortal, so need to increase reference count.
1805          */
1806         RETVAL = SvREFCNT_inc(*result);
1807         OUTPUT:
1808         RETVAL
1809
1810 SV *
1811 fetch_ent(hash, key_sv)
1812         PREINIT:
1813         HE *result;
1814         INPUT:
1815         HV *hash
1816         SV *key_sv
1817         CODE:
1818         result = hv_fetch_ent(hash, key_sv, 0, 0);
1819         if (!result) {
1820             XSRETURN_EMPTY;
1821         }
1822         /* Force mg_get  */
1823         RETVAL = newSVsv(HeVAL(result));
1824         OUTPUT:
1825         RETVAL
1826
1827 SV *
1828 fetch(hash, key_sv)
1829         PREINIT:
1830         STRLEN len;
1831         const char *key;
1832         SV **result;
1833         INPUT:
1834         HV *hash
1835         SV *key_sv
1836         CODE:
1837         key = SvPV(key_sv, len);
1838         result = hv_fetch(hash, key, UTF8KLEN(key_sv, len), 0);
1839         if (!result) {
1840             XSRETURN_EMPTY;
1841         }
1842         /* Force mg_get  */
1843         RETVAL = newSVsv(*result);
1844         OUTPUT:
1845         RETVAL
1846
1847 #if defined (hv_common)
1848
1849 SV *
1850 common(params)
1851         INPUT:
1852         HV *params
1853         PREINIT:
1854         HE *result;
1855         HV *hv = NULL;
1856         SV *keysv = NULL;
1857         const char *key = NULL;
1858         STRLEN klen = 0;
1859         int flags = 0;
1860         int action = 0;
1861         SV *val = NULL;
1862         U32 hash = 0;
1863         SV **svp;
1864         CODE:
1865         if ((svp = hv_fetchs(params, "hv", 0))) {
1866             SV *const rv = *svp;
1867             if (!SvROK(rv))
1868                 croak("common passed a non-reference for parameter hv");
1869             hv = (HV *)SvRV(rv);
1870         }
1871         if ((svp = hv_fetchs(params, "keysv", 0)))
1872             keysv = *svp;
1873         if ((svp = hv_fetchs(params, "keypv", 0))) {
1874             key = SvPV_const(*svp, klen);
1875             if (SvUTF8(*svp))
1876                 flags = HVhek_UTF8;
1877         }
1878         if ((svp = hv_fetchs(params, "action", 0)))
1879             action = SvIV(*svp);
1880         if ((svp = hv_fetchs(params, "val", 0)))
1881             val = newSVsv(*svp);
1882         if ((svp = hv_fetchs(params, "hash", 0)))
1883             hash = SvUV(*svp);
1884
1885         if (hv_fetchs(params, "hash_pv", 0)) {
1886             assert(key);
1887             PERL_HASH(hash, key, klen);
1888         }
1889         if (hv_fetchs(params, "hash_sv", 0)) {
1890             assert(keysv);
1891             {
1892               STRLEN len;
1893               const char *const p = SvPV(keysv, len);
1894               PERL_HASH(hash, p, len);
1895             }
1896         }
1897
1898         result = (HE *)hv_common(hv, keysv, key, klen, flags, action, val, hash);
1899         if (!result) {
1900             XSRETURN_EMPTY;
1901         }
1902         /* Force mg_get  */
1903         RETVAL = newSVsv(HeVAL(result));
1904         OUTPUT:
1905         RETVAL
1906
1907 #endif
1908
1909 void
1910 test_hv_free_ent()
1911         PPCODE:
1912         test_freeent(&Perl_hv_free_ent);
1913         XSRETURN(4);
1914
1915 void
1916 test_hv_delayfree_ent()
1917         PPCODE:
1918         test_freeent(&Perl_hv_delayfree_ent);
1919         XSRETURN(4);
1920
1921 SV *
1922 test_share_unshare_pvn(input)
1923         PREINIT:
1924         STRLEN len;
1925         U32 hash;
1926         char *pvx;
1927         char *p;
1928         INPUT:
1929         SV *input
1930         CODE:
1931         pvx = SvPV(input, len);
1932         PERL_HASH(hash, pvx, len);
1933         p = sharepvn(pvx, len, hash);
1934         RETVAL = newSVpvn(p, len);
1935         unsharepvn(p, len, hash);
1936         OUTPUT:
1937         RETVAL
1938
1939 #if PERL_VERSION >= 9
1940
1941 bool
1942 refcounted_he_exists(key, level=0)
1943         SV *key
1944         IV level
1945         CODE:
1946         if (level) {
1947             croak("level must be zero, not %" IVdf, level);
1948         }
1949         RETVAL = (cop_hints_fetch_sv(PL_curcop, key, 0, 0) != &PL_sv_placeholder);
1950         OUTPUT:
1951         RETVAL
1952
1953 SV *
1954 refcounted_he_fetch(key, level=0)
1955         SV *key
1956         IV level
1957         CODE:
1958         if (level) {
1959             croak("level must be zero, not %" IVdf, level);
1960         }
1961         RETVAL = cop_hints_fetch_sv(PL_curcop, key, 0, 0);
1962         SvREFCNT_inc(RETVAL);
1963         OUTPUT:
1964         RETVAL
1965
1966 #endif
1967
1968 void
1969 test_force_keys(HV *hv)
1970     PREINIT:
1971         HE *he;
1972         SSize_t count = 0;
1973     PPCODE:
1974         hv_iterinit(hv);
1975         he = hv_iternext(hv);
1976         while (he) {
1977             SV *sv = HeSVKEY_force(he);
1978             ++count;
1979             EXTEND(SP, count);
1980             PUSHs(sv_mortalcopy(sv));
1981             he = hv_iternext(hv);
1982         }
1983
1984 =pod
1985
1986 sub TIEHASH  { bless {}, $_[0] }
1987 sub STORE    { $_[0]->{$_[1]} = $_[2] }
1988 sub FETCH    { $_[0]->{$_[1]} }
1989 sub FIRSTKEY { my $a = scalar keys %{$_[0]}; each %{$_[0]} }
1990 sub NEXTKEY  { each %{$_[0]} }
1991 sub EXISTS   { exists $_[0]->{$_[1]} }
1992 sub DELETE   { delete $_[0]->{$_[1]} }
1993 sub CLEAR    { %{$_[0]} = () }
1994
1995 =cut
1996
1997 MODULE = XS::APItest:TempLv             PACKAGE = XS::APItest::TempLv
1998
1999 void
2000 make_temp_mg_lv(sv)
2001 SV* sv
2002     PREINIT:
2003         SV * const lv = newSV_type(SVt_PVLV);
2004         STRLEN len;
2005     PPCODE:
2006         SvPV(sv, len);
2007
2008         sv_magic(lv, NULL, PERL_MAGIC_substr, NULL, 0);
2009         LvTYPE(lv) = 'x';
2010         LvTARG(lv) = SvREFCNT_inc_simple(sv);
2011         LvTARGOFF(lv) = len == 0 ? 0 : 1;
2012         LvTARGLEN(lv) = len < 2 ? 0 : len-2;
2013
2014         EXTEND(SP, 1);
2015         ST(0) = sv_2mortal(lv);
2016         XSRETURN(1);
2017
2018
2019 MODULE = XS::APItest::PtrTable  PACKAGE = XS::APItest::PtrTable PREFIX = ptr_table_
2020
2021 void
2022 ptr_table_new(classname)
2023 const char * classname
2024     PPCODE:
2025     PUSHs(sv_setref_pv(sv_newmortal(), classname, (void*)ptr_table_new()));
2026
2027 void
2028 DESTROY(table)
2029 XS::APItest::PtrTable table
2030     CODE:
2031     ptr_table_free(table);
2032
2033 void
2034 ptr_table_store(table, from, to)
2035 XS::APItest::PtrTable table
2036 SVREF from
2037 SVREF to
2038    CODE:
2039    ptr_table_store(table, from, to);
2040
2041 UV
2042 ptr_table_fetch(table, from)
2043 XS::APItest::PtrTable table
2044 SVREF from
2045    CODE:
2046    RETVAL = PTR2UV(ptr_table_fetch(table, from));
2047    OUTPUT:
2048    RETVAL
2049
2050 void
2051 ptr_table_split(table)
2052 XS::APItest::PtrTable table
2053
2054 void
2055 ptr_table_clear(table)
2056 XS::APItest::PtrTable table
2057
2058 MODULE = XS::APItest::AutoLoader        PACKAGE = XS::APItest::AutoLoader
2059
2060 SV *
2061 AUTOLOAD()
2062     CODE:
2063         RETVAL = newSVpvn_flags(SvPVX(cv), SvCUR(cv), SvUTF8(cv));
2064     OUTPUT:
2065         RETVAL
2066
2067 SV *
2068 AUTOLOADp(...)
2069     PROTOTYPE: *$
2070     CODE:
2071         PERL_UNUSED_ARG(items);
2072         RETVAL = newSVpvn_flags(SvPVX(cv), SvCUR(cv), SvUTF8(cv));
2073     OUTPUT:
2074         RETVAL
2075
2076
2077 MODULE = XS::APItest            PACKAGE = XS::APItest
2078
2079 PROTOTYPES: DISABLE
2080
2081 BOOT:
2082     mymro.resolve = myget_linear_isa;
2083     mymro.name    = "justisa";
2084     mymro.length  = 7;
2085     mymro.kflags  = 0;
2086     mymro.hash    = 0;
2087     Perl_mro_register(aTHX_ &mymro);
2088
2089 HV *
2090 xop_custom_ops ()
2091     CODE:
2092         RETVAL = PL_custom_ops;
2093     OUTPUT:
2094         RETVAL
2095
2096 HV *
2097 xop_custom_op_names ()
2098     CODE:
2099         PL_custom_op_names = newHV();
2100         RETVAL = PL_custom_op_names;
2101     OUTPUT:
2102         RETVAL
2103
2104 HV *
2105 xop_custom_op_descs ()
2106     CODE:
2107         PL_custom_op_descs = newHV();
2108         RETVAL = PL_custom_op_descs;
2109     OUTPUT:
2110         RETVAL
2111
2112 void
2113 xop_register ()
2114     CODE:
2115         XopENTRY_set(&my_xop, xop_name, "my_xop");
2116         XopENTRY_set(&my_xop, xop_desc, "XOP for testing");
2117         XopENTRY_set(&my_xop, xop_class, OA_UNOP);
2118         XopENTRY_set(&my_xop, xop_peep, peep_xop);
2119         Perl_custom_op_register(aTHX_ pp_xop, &my_xop);
2120
2121 void
2122 xop_clear ()
2123     CODE:
2124         XopDISABLE(&my_xop, xop_name);
2125         XopDISABLE(&my_xop, xop_desc);
2126         XopDISABLE(&my_xop, xop_class);
2127         XopDISABLE(&my_xop, xop_peep);
2128
2129 IV
2130 xop_my_xop ()
2131     CODE:
2132         RETVAL = PTR2IV(&my_xop);
2133     OUTPUT:
2134         RETVAL
2135
2136 IV
2137 xop_ppaddr ()
2138     CODE:
2139         RETVAL = PTR2IV(pp_xop);
2140     OUTPUT:
2141         RETVAL
2142
2143 IV
2144 xop_OA_UNOP ()
2145     CODE:
2146         RETVAL = OA_UNOP;
2147     OUTPUT:
2148         RETVAL
2149
2150 AV *
2151 xop_build_optree ()
2152     CODE:
2153         dMY_CXT;
2154         UNOP *unop;
2155         OP *kid;
2156
2157         MY_CXT.xop_record = newAV();
2158
2159         kid = newSVOP(OP_CONST, 0, newSViv(42));
2160         
2161         unop = (UNOP*)mkUNOP(OP_CUSTOM, kid);
2162         unop->op_ppaddr     = pp_xop;
2163         unop->op_private    = 0;
2164         unop->op_next       = NULL;
2165         kid->op_next        = (OP*)unop;
2166
2167         av_push(MY_CXT.xop_record, newSVpvf("unop:%" UVxf, PTR2UV(unop)));
2168         av_push(MY_CXT.xop_record, newSVpvf("kid:%" UVxf, PTR2UV(kid)));
2169
2170         av_push(MY_CXT.xop_record, newSVpvf("NAME:%s", OP_NAME((OP*)unop)));
2171         av_push(MY_CXT.xop_record, newSVpvf("DESC:%s", OP_DESC((OP*)unop)));
2172         av_push(MY_CXT.xop_record, newSVpvf("CLASS:%d", (int)OP_CLASS((OP*)unop)));
2173
2174         PL_rpeepp(aTHX_ kid);
2175
2176         FreeOp(kid);
2177         FreeOp(unop);
2178
2179         RETVAL = MY_CXT.xop_record;
2180         MY_CXT.xop_record = NULL;
2181     OUTPUT:
2182         RETVAL
2183
2184 IV
2185 xop_from_custom_op ()
2186     CODE:
2187 /* author note: this test doesn't imply Perl_custom_op_xop is or isn't public
2188    API or that Perl_custom_op_xop is known to be used outside the core */
2189         UNOP *unop;
2190         XOP *xop;
2191
2192         unop = (UNOP*)mkUNOP(OP_CUSTOM, NULL);
2193         unop->op_ppaddr     = pp_xop;
2194         unop->op_private    = 0;
2195         unop->op_next       = NULL;
2196
2197         xop = Perl_custom_op_xop(aTHX_ (OP *)unop);
2198         FreeOp(unop);
2199         RETVAL = PTR2IV(xop);
2200     OUTPUT:
2201         RETVAL
2202
2203 BOOT:
2204 {
2205     MY_CXT_INIT;
2206
2207     MY_CXT.i  = 99;
2208     MY_CXT.sv = newSVpv("initial",0);
2209
2210     MY_CXT.bhkav = get_av("XS::APItest::bhkav", GV_ADDMULTI);
2211     MY_CXT.bhk_record = 0;
2212
2213     BhkENTRY_set(&bhk_test, bhk_start, blockhook_test_start);
2214     BhkENTRY_set(&bhk_test, bhk_pre_end, blockhook_test_pre_end);
2215     BhkENTRY_set(&bhk_test, bhk_post_end, blockhook_test_post_end);
2216     BhkENTRY_set(&bhk_test, bhk_eval, blockhook_test_eval);
2217     Perl_blockhook_register(aTHX_ &bhk_test);
2218
2219     MY_CXT.cscgv = gv_fetchpvs("XS::APItest::COMPILE_SCOPE_CONTAINER",
2220         GV_ADDMULTI, SVt_PVAV);
2221     MY_CXT.cscav = GvAV(MY_CXT.cscgv);
2222
2223     BhkENTRY_set(&bhk_csc, bhk_start, blockhook_csc_start);
2224     BhkENTRY_set(&bhk_csc, bhk_pre_end, blockhook_csc_pre_end);
2225     Perl_blockhook_register(aTHX_ &bhk_csc);
2226
2227     MY_CXT.peep_recorder = newAV();
2228     MY_CXT.rpeep_recorder = newAV();
2229
2230     MY_CXT.orig_peep = PL_peepp;
2231     MY_CXT.orig_rpeep = PL_rpeepp;
2232     PL_peepp = my_peep;
2233     PL_rpeepp = my_rpeep;
2234 }
2235
2236 void
2237 CLONE(...)
2238     CODE:
2239     MY_CXT_CLONE;
2240     PERL_UNUSED_VAR(items);
2241     MY_CXT.sv = newSVpv("initial_clone",0);
2242     MY_CXT.cscgv = gv_fetchpvs("XS::APItest::COMPILE_SCOPE_CONTAINER",
2243         GV_ADDMULTI, SVt_PVAV);
2244     MY_CXT.cscav = NULL;
2245     MY_CXT.bhkav = get_av("XS::APItest::bhkav", GV_ADDMULTI);
2246     MY_CXT.bhk_record = 0;
2247     MY_CXT.peep_recorder = newAV();
2248     MY_CXT.rpeep_recorder = newAV();
2249
2250 void
2251 print_double(val)
2252         double val
2253         CODE:
2254         printf("%5.3f\n",val);
2255
2256 int
2257 have_long_double()
2258         CODE:
2259 #ifdef HAS_LONG_DOUBLE
2260         RETVAL = 1;
2261 #else
2262         RETVAL = 0;
2263 #endif
2264         OUTPUT:
2265         RETVAL
2266
2267 void
2268 print_long_double()
2269         CODE:
2270 #ifdef HAS_LONG_DOUBLE
2271 #   if defined(PERL_PRIfldbl) && (LONG_DOUBLESIZE > DOUBLESIZE)
2272         long double val = 7.0;
2273         printf("%5.3" PERL_PRIfldbl "\n",val);
2274 #   else
2275         double val = 7.0;
2276         printf("%5.3f\n",val);
2277 #   endif
2278 #endif
2279
2280 void
2281 print_int(val)
2282         int val
2283         CODE:
2284         printf("%d\n",val);
2285
2286 void
2287 print_long(val)
2288         long val
2289         CODE:
2290         printf("%ld\n",val);
2291
2292 void
2293 print_float(val)
2294         float val
2295         CODE:
2296         printf("%5.3f\n",val);
2297         
2298 void
2299 print_flush()
2300         CODE:
2301         fflush(stdout);
2302
2303 void
2304 mpushp()
2305         PPCODE:
2306         EXTEND(SP, 3);
2307         mPUSHp("one", 3);
2308         mPUSHp("two", 3);
2309         mPUSHp("three", 5);
2310         XSRETURN(3);
2311
2312 void
2313 mpushn()
2314         PPCODE:
2315         EXTEND(SP, 3);
2316         mPUSHn(0.5);
2317         mPUSHn(-0.25);
2318         mPUSHn(0.125);
2319         XSRETURN(3);
2320
2321 void
2322 mpushi()
2323         PPCODE:
2324         EXTEND(SP, 3);
2325         mPUSHi(-1);
2326         mPUSHi(2);
2327         mPUSHi(-3);
2328         XSRETURN(3);
2329
2330 void
2331 mpushu()
2332         PPCODE:
2333         EXTEND(SP, 3);
2334         mPUSHu(1);
2335         mPUSHu(2);
2336         mPUSHu(3);
2337         XSRETURN(3);
2338
2339 void
2340 mxpushp()
2341         PPCODE:
2342         mXPUSHp("one", 3);
2343         mXPUSHp("two", 3);
2344         mXPUSHp("three", 5);
2345         XSRETURN(3);
2346
2347 void
2348 mxpushn()
2349         PPCODE:
2350         mXPUSHn(0.5);
2351         mXPUSHn(-0.25);
2352         mXPUSHn(0.125);
2353         XSRETURN(3);
2354
2355 void
2356 mxpushi()
2357         PPCODE:
2358         mXPUSHi(-1);
2359         mXPUSHi(2);
2360         mXPUSHi(-3);
2361         XSRETURN(3);
2362
2363 void
2364 mxpushu()
2365         PPCODE:
2366         mXPUSHu(1);
2367         mXPUSHu(2);
2368         mXPUSHu(3);
2369         XSRETURN(3);
2370
2371
2372  # test_EXTEND(): excerise the EXTEND() macro.
2373  # After calling EXTEND(), it also does *(p+n) = NULL and
2374  # *PL_stack_max = NULL to allow valgrind etc to spot if the stack hasn't
2375  # actually been extended properly.
2376  #
2377  # max_offset specifies the SP to use.  It is treated as a signed offset
2378  #              from PL_stack_max.
2379  # nsv        is the SV holding the value of n indicating how many slots
2380  #              to extend the stack by.
2381  # use_ss     is a boolean indicating that n should be cast to a SSize_t
2382
2383 void
2384 test_EXTEND(max_offset, nsv, use_ss)
2385     IV   max_offset;
2386     SV  *nsv;
2387     bool use_ss;
2388 PREINIT:
2389     SV **sp = PL_stack_max + max_offset;
2390 PPCODE:
2391     if (use_ss) {
2392         SSize_t n = (SSize_t)SvIV(nsv);
2393         EXTEND(sp, n);
2394         *(sp + n) = NULL;
2395     }
2396     else {
2397         IV n = SvIV(nsv);
2398         EXTEND(sp, n);
2399         *(sp + n) = NULL;
2400     }
2401     *PL_stack_max = NULL;
2402
2403
2404 void
2405 call_sv_C()
2406 PREINIT:
2407     CV * i_sub;
2408     GV * i_gv;
2409     I32 retcnt;
2410     SV * errsv;
2411     char * errstr;
2412     STRLEN errlen;
2413     SV * miscsv = sv_newmortal();
2414     HV * hv = (HV*)sv_2mortal((SV*)newHV());
2415 CODE:
2416     i_sub = get_cv("i", 0);
2417     PUSHMARK(SP);
2418     /* PUTBACK not needed since this sub was called with 0 args, and is calling
2419       0 args, so global SP doesn't need to be moved before a call_* */
2420     retcnt = call_sv((SV*)i_sub, 0); /* try a CV* */
2421     SPAGAIN;
2422     SP -= retcnt; /* dont care about return count, wipe everything off */
2423     sv_setpvs(miscsv, "i");
2424     PUSHMARK(SP);
2425     retcnt = call_sv(miscsv, 0); /* try a PV */
2426     SPAGAIN;
2427     SP -= retcnt;
2428     /* no add and SVt_NULL are intentional, sub i should be defined already */
2429     i_gv = gv_fetchpvn_flags("i", sizeof("i")-1, 0, SVt_NULL);
2430     PUSHMARK(SP);
2431     retcnt = call_sv((SV*)i_gv, 0); /* try a GV* */
2432     SPAGAIN;
2433     SP -= retcnt;
2434     /* the tests below are not declaring this being public API behavior,
2435        only current internal behavior, these tests can be changed in the
2436        future if necessery */
2437     PUSHMARK(SP);
2438     retcnt = call_sv(&PL_sv_yes, G_EVAL);
2439     SPAGAIN;
2440     SP -= retcnt;
2441     errsv = ERRSV;
2442     errstr = SvPV(errsv, errlen);
2443     if(memBEGINs(errstr, errlen, "Undefined subroutine &main::1 called at")) {
2444         PUSHMARK(SP);
2445         retcnt = call_sv((SV*)i_sub, 0); /* call again to increase counter */
2446         SPAGAIN;
2447         SP -= retcnt;
2448     }
2449     PUSHMARK(SP);
2450     retcnt = call_sv(&PL_sv_no, G_EVAL);
2451     SPAGAIN;
2452     SP -= retcnt;
2453     errsv = ERRSV;
2454     errstr = SvPV(errsv, errlen);
2455     if(memBEGINs(errstr, errlen, "Undefined subroutine &main:: called at")) {
2456         PUSHMARK(SP);
2457         retcnt = call_sv((SV*)i_sub, 0); /* call again to increase counter */
2458         SPAGAIN;
2459         SP -= retcnt;
2460     }
2461     PUSHMARK(SP);
2462     retcnt = call_sv(&PL_sv_undef,  G_EVAL);
2463     SPAGAIN;
2464     SP -= retcnt;
2465     errsv = ERRSV;
2466     errstr = SvPV(errsv, errlen);
2467     if(memBEGINs(errstr, errlen, "Can't use an undefined value as a subroutine reference at")) {
2468         PUSHMARK(SP);
2469         retcnt = call_sv((SV*)i_sub, 0); /* call again to increase counter */
2470         SPAGAIN;
2471         SP -= retcnt;
2472     }
2473     PUSHMARK(SP);
2474     retcnt = call_sv((SV*)hv,  G_EVAL);
2475     SPAGAIN;
2476     SP -= retcnt;
2477     errsv = ERRSV;
2478     errstr = SvPV(errsv, errlen);
2479     if(memBEGINs(errstr, errlen, "Not a CODE reference at")) {
2480         PUSHMARK(SP);
2481         retcnt = call_sv((SV*)i_sub, 0); /* call again to increase counter */
2482         SPAGAIN;
2483         SP -= retcnt;
2484     }
2485
2486 void
2487 call_sv(sv, flags, ...)
2488     SV* sv
2489     I32 flags
2490     PREINIT:
2491         I32 i;
2492     PPCODE:
2493         for (i=0; i<items-2; i++)
2494             ST(i) = ST(i+2); /* pop first two args */
2495         PUSHMARK(SP);
2496         SP += items - 2;
2497         PUTBACK;
2498         i = call_sv(sv, flags);
2499         SPAGAIN;
2500         EXTEND(SP, 1);
2501         PUSHs(sv_2mortal(newSViv(i)));
2502
2503 void
2504 call_pv(subname, flags, ...)
2505     char* subname
2506     I32 flags
2507     PREINIT:
2508         I32 i;
2509     PPCODE:
2510         for (i=0; i<items-2; i++)
2511             ST(i) = ST(i+2); /* pop first two args */
2512         PUSHMARK(SP);
2513         SP += items - 2;
2514         PUTBACK;
2515         i = call_pv(subname, flags);
2516         SPAGAIN;
2517         EXTEND(SP, 1);
2518         PUSHs(sv_2mortal(newSViv(i)));
2519
2520 void
2521 call_argv(subname, flags, ...)
2522     char* subname
2523     I32 flags
2524     PREINIT:
2525         I32 i;
2526         char *tmpary[4];
2527     PPCODE:
2528         for (i=0; i<items-2; i++)
2529             tmpary[i] = SvPV_nolen(ST(i+2)); /* ignore first two args */
2530         tmpary[i] = NULL;
2531         PUTBACK;
2532         i = call_argv(subname, flags, tmpary);
2533         SPAGAIN;
2534         EXTEND(SP, 1);
2535         PUSHs(sv_2mortal(newSViv(i)));
2536
2537 void
2538 call_method(methname, flags, ...)
2539     char* methname
2540     I32 flags
2541     PREINIT:
2542         I32 i;
2543     PPCODE:
2544         for (i=0; i<items-2; i++)
2545             ST(i) = ST(i+2); /* pop first two args */
2546         PUSHMARK(SP);
2547         SP += items - 2;
2548         PUTBACK;
2549         i = call_method(methname, flags);
2550         SPAGAIN;
2551         EXTEND(SP, 1);
2552         PUSHs(sv_2mortal(newSViv(i)));
2553
2554 void
2555 newCONSTSUB(stash, name, flags, sv)
2556     HV* stash
2557     SV* name
2558     I32 flags
2559     SV* sv
2560     ALIAS:
2561         newCONSTSUB_flags = 1
2562     PREINIT:
2563         CV* mycv = NULL;
2564         STRLEN len;
2565         const char *pv = SvPV(name, len);
2566     PPCODE:
2567         switch (ix) {
2568            case 0:
2569                mycv = newCONSTSUB(stash, pv, SvOK(sv) ? SvREFCNT_inc(sv) : NULL);
2570                break;
2571            case 1:
2572                mycv = newCONSTSUB_flags(
2573                  stash, pv, len, flags | SvUTF8(name), SvOK(sv) ? SvREFCNT_inc(sv) : NULL
2574                );
2575                break;
2576         }
2577         EXTEND(SP, 2);
2578         assert(mycv);
2579         PUSHs( CvCONST(mycv) ? &PL_sv_yes : &PL_sv_no );
2580         PUSHs((SV*)CvGV(mycv));
2581
2582 void
2583 gv_init_type(namesv, multi, flags, type)
2584     SV* namesv
2585     int multi
2586     I32 flags
2587     int type
2588     PREINIT:
2589         STRLEN len;
2590         const char * const name = SvPV_const(namesv, len);
2591         GV *gv = *(GV**)hv_fetch(PL_defstash, name, len, TRUE);
2592     PPCODE:
2593         if (SvTYPE(gv) == SVt_PVGV)
2594             Perl_croak(aTHX_ "GV is already a PVGV");
2595         if (multi) flags |= GV_ADDMULTI;
2596         switch (type) {
2597            case 0:
2598                gv_init(gv, PL_defstash, name, len, multi);
2599                break;
2600            case 1:
2601                gv_init_sv(gv, PL_defstash, namesv, flags);
2602                break;
2603            case 2:
2604                gv_init_pv(gv, PL_defstash, name, flags | SvUTF8(namesv));
2605                break;
2606            case 3:
2607                gv_init_pvn(gv, PL_defstash, name, len, flags | SvUTF8(namesv));
2608                break;
2609         }
2610         XPUSHs( gv ? (SV*)gv : &PL_sv_undef);
2611
2612 void
2613 gv_fetchmeth_type(stash, methname, type, level, flags)
2614     HV* stash
2615     SV* methname
2616     int type
2617     I32 level
2618     I32 flags
2619     PREINIT:
2620         STRLEN len;
2621         const char * const name = SvPV_const(methname, len);
2622         GV* gv = NULL;
2623     PPCODE:
2624         switch (type) {
2625            case 0:
2626                gv = gv_fetchmeth(stash, name, len, level);
2627                break;
2628            case 1:
2629                gv = gv_fetchmeth_sv(stash, methname, level, flags);
2630                break;
2631            case 2:
2632                gv = gv_fetchmeth_pv(stash, name, level, flags | SvUTF8(methname));
2633                break;
2634            case 3:
2635                gv = gv_fetchmeth_pvn(stash, name, len, level, flags | SvUTF8(methname));
2636                break;
2637         }
2638         XPUSHs( gv ? MUTABLE_SV(gv) : &PL_sv_undef );
2639
2640 void
2641 gv_fetchmeth_autoload_type(stash, methname, type, level, flags)
2642     HV* stash
2643     SV* methname
2644     int type
2645     I32 level
2646     I32 flags
2647     PREINIT:
2648         STRLEN len;
2649         const char * const name = SvPV_const(methname, len);
2650         GV* gv = NULL;
2651     PPCODE:
2652         switch (type) {
2653            case 0:
2654                gv = gv_fetchmeth_autoload(stash, name, len, level);
2655                break;
2656            case 1:
2657                gv = gv_fetchmeth_sv_autoload(stash, methname, level, flags);
2658                break;
2659            case 2:
2660                gv = gv_fetchmeth_pv_autoload(stash, name, level, flags | SvUTF8(methname));
2661                break;
2662            case 3:
2663                gv = gv_fetchmeth_pvn_autoload(stash, name, len, level, flags | SvUTF8(methname));
2664                break;
2665         }
2666         XPUSHs( gv ? MUTABLE_SV(gv) : &PL_sv_undef );
2667
2668 void
2669 gv_fetchmethod_flags_type(stash, methname, type, flags)
2670     HV* stash
2671     SV* methname
2672     int type
2673     I32 flags
2674     PREINIT:
2675         GV* gv = NULL;
2676     PPCODE:
2677         switch (type) {
2678            case 0:
2679                gv = gv_fetchmethod_flags(stash, SvPVX_const(methname), flags);
2680                break;
2681            case 1:
2682                gv = gv_fetchmethod_sv_flags(stash, methname, flags);
2683                break;
2684            case 2:
2685                gv = gv_fetchmethod_pv_flags(stash, SvPV_nolen(methname), flags | SvUTF8(methname));
2686                break;
2687            case 3: {
2688                STRLEN len;
2689                const char * const name = SvPV_const(methname, len);
2690                gv = gv_fetchmethod_pvn_flags(stash, name, len, flags | SvUTF8(methname));
2691                break;
2692             }
2693            case 4:
2694                gv = gv_fetchmethod_pvn_flags(stash, SvPV_nolen(methname),
2695                                              flags, SvUTF8(methname));
2696         }
2697         XPUSHs( gv ? (SV*)gv : &PL_sv_undef);
2698
2699 void
2700 gv_autoload_type(stash, methname, type, method)
2701     HV* stash
2702     SV* methname
2703     int type
2704     I32 method
2705     PREINIT:
2706         STRLEN len;
2707         const char * const name = SvPV_const(methname, len);
2708         GV* gv = NULL;
2709         I32 flags = method ? GV_AUTOLOAD_ISMETHOD : 0;
2710     PPCODE:
2711         switch (type) {
2712            case 0:
2713                gv = gv_autoload4(stash, name, len, method);
2714                break;
2715            case 1:
2716                gv = gv_autoload_sv(stash, methname, flags);
2717                break;
2718            case 2:
2719                gv = gv_autoload_pv(stash, name, flags | SvUTF8(methname));
2720                break;
2721            case 3:
2722                gv = gv_autoload_pvn(stash, name, len, flags | SvUTF8(methname));
2723                break;
2724         }
2725         XPUSHs( gv ? (SV*)gv : &PL_sv_undef);
2726
2727 SV *
2728 gv_const_sv(SV *name)
2729     PREINIT:
2730         GV *gv;
2731     CODE:
2732         if (SvPOK(name)) {
2733             HV *stash = gv_stashpv("main",0);
2734             HE *he = hv_fetch_ent(stash, name, 0, 0);
2735             gv = (GV *)HeVAL(he);
2736         }
2737         else {
2738             gv = (GV *)name;
2739         }
2740         RETVAL = gv_const_sv(gv);
2741         if (!RETVAL)
2742             XSRETURN_EMPTY;
2743         RETVAL = newSVsv(RETVAL);
2744     OUTPUT:
2745         RETVAL
2746
2747 void
2748 whichsig_type(namesv, type)
2749     SV* namesv
2750     int type
2751     PREINIT:
2752         STRLEN len;
2753         const char * const name = SvPV_const(namesv, len);
2754         I32 i = 0;
2755     PPCODE:
2756         switch (type) {
2757            case 0:
2758               i = whichsig(name);
2759                break;
2760            case 1:
2761                i = whichsig_sv(namesv);
2762                break;
2763            case 2:
2764                i = whichsig_pv(name);
2765                break;
2766            case 3:
2767                i = whichsig_pvn(name, len);
2768                break;
2769         }
2770         XPUSHs(sv_2mortal(newSViv(i)));
2771
2772 void
2773 eval_sv(sv, flags)
2774     SV* sv
2775     I32 flags
2776     PREINIT:
2777         I32 i;
2778     PPCODE:
2779         PUTBACK;
2780         i = eval_sv(sv, flags);
2781         SPAGAIN;
2782         EXTEND(SP, 1);
2783         PUSHs(sv_2mortal(newSViv(i)));
2784
2785 void
2786 eval_pv(p, croak_on_error)
2787     const char* p
2788     I32 croak_on_error
2789     PPCODE:
2790         PUTBACK;
2791         EXTEND(SP, 1);
2792         PUSHs(eval_pv(p, croak_on_error));
2793
2794 void
2795 require_pv(pv)
2796     const char* pv
2797     PPCODE:
2798         PUTBACK;
2799         require_pv(pv);
2800
2801 int
2802 apitest_exception(throw_e)
2803     int throw_e
2804     OUTPUT:
2805         RETVAL
2806
2807 void
2808 mycroak(sv)
2809     SV* sv
2810     CODE:
2811     if (SvOK(sv)) {
2812         Perl_croak(aTHX_ "%s", SvPV_nolen(sv));
2813     }
2814     else {
2815         Perl_croak(aTHX_ NULL);
2816     }
2817
2818 SV*
2819 strtab()
2820    CODE:
2821    RETVAL = newRV_inc((SV*)PL_strtab);
2822    OUTPUT:
2823    RETVAL
2824
2825 int
2826 my_cxt_getint()
2827     CODE:
2828         dMY_CXT;
2829         RETVAL = my_cxt_getint_p(aMY_CXT);
2830     OUTPUT:
2831         RETVAL
2832
2833 void
2834 my_cxt_setint(i)
2835     int i;
2836     CODE:
2837         dMY_CXT;
2838         my_cxt_setint_p(aMY_CXT_ i);
2839
2840 void
2841 my_cxt_getsv(how)
2842     bool how;
2843     PPCODE:
2844         EXTEND(SP, 1);
2845         ST(0) = how ? my_cxt_getsv_interp_context() : my_cxt_getsv_interp();
2846         XSRETURN(1);
2847
2848 void
2849 my_cxt_setsv(sv)
2850     SV *sv;
2851     CODE:
2852         dMY_CXT;
2853         SvREFCNT_dec(MY_CXT.sv);
2854         my_cxt_setsv_p(sv _aMY_CXT);
2855         SvREFCNT_inc(sv);
2856
2857 bool
2858 sv_setsv_cow_hashkey_core()
2859
2860 bool
2861 sv_setsv_cow_hashkey_notcore()
2862
2863 void
2864 sv_set_deref(SV *sv, SV *sv2, int which)
2865     CODE:
2866     {
2867         STRLEN len;
2868         const char *pv = SvPV(sv2,len);
2869         if (!SvROK(sv)) croak("Not a ref");
2870         sv = SvRV(sv);
2871         switch (which) {
2872             case 0: sv_setsv(sv,sv2); break;
2873             case 1: sv_setpv(sv,pv); break;
2874             case 2: sv_setpvn(sv,pv,len); break;
2875         }
2876     }
2877
2878 void
2879 rmagical_cast(sv, type)
2880     SV *sv;
2881     SV *type;
2882     PREINIT:
2883         struct ufuncs uf;
2884     PPCODE:
2885         if (!SvOK(sv) || !SvROK(sv) || !SvOK(type)) { XSRETURN_UNDEF; }
2886         sv = SvRV(sv);
2887         if (SvTYPE(sv) != SVt_PVHV) { XSRETURN_UNDEF; }
2888         uf.uf_val = rmagical_a_dummy;
2889         uf.uf_set = NULL;
2890         uf.uf_index = 0;
2891         if (SvTRUE(type)) { /* b */
2892             sv_magicext(sv, NULL, PERL_MAGIC_ext, &rmagical_b, NULL, 0);
2893         } else { /* a */
2894             sv_magic(sv, NULL, PERL_MAGIC_uvar, (char *) &uf, sizeof(uf));
2895         }
2896         XSRETURN_YES;
2897
2898 void
2899 rmagical_flags(sv)
2900     SV *sv;
2901     PPCODE:
2902         if (!SvOK(sv) || !SvROK(sv)) { XSRETURN_UNDEF; }
2903         sv = SvRV(sv);
2904         EXTEND(SP, 3); 
2905         mXPUSHu(SvFLAGS(sv) & SVs_GMG);
2906         mXPUSHu(SvFLAGS(sv) & SVs_SMG);
2907         mXPUSHu(SvFLAGS(sv) & SVs_RMG);
2908         XSRETURN(3);
2909
2910 void
2911 my_caller(level)
2912         I32 level
2913     PREINIT:
2914         const PERL_CONTEXT *cx, *dbcx;
2915         const char *pv;
2916         const GV *gv;
2917         HV *hv;
2918     PPCODE:
2919         cx = caller_cx(level, &dbcx);
2920         EXTEND(SP, 8);
2921
2922         pv = CopSTASHPV(cx->blk_oldcop);
2923         ST(0) = pv ? sv_2mortal(newSVpv(pv, 0)) : &PL_sv_undef;
2924         gv = CvGV(cx->blk_sub.cv);
2925         ST(1) = isGV(gv) ? sv_2mortal(newSVpv(GvNAME(gv), 0)) : &PL_sv_undef;
2926
2927         pv = CopSTASHPV(dbcx->blk_oldcop);
2928         ST(2) = pv ? sv_2mortal(newSVpv(pv, 0)) : &PL_sv_undef;
2929         gv = CvGV(dbcx->blk_sub.cv);
2930         ST(3) = isGV(gv) ? sv_2mortal(newSVpv(GvNAME(gv), 0)) : &PL_sv_undef;
2931
2932         ST(4) = cop_hints_fetch_pvs(cx->blk_oldcop, "foo", 0);
2933         ST(5) = cop_hints_fetch_pvn(cx->blk_oldcop, "foo", 3, 0, 0);
2934         ST(6) = cop_hints_fetch_sv(cx->blk_oldcop, 
2935                 sv_2mortal(newSVpvs("foo")), 0, 0);
2936
2937         hv = cop_hints_2hv(cx->blk_oldcop, 0);
2938         ST(7) = hv ? sv_2mortal(newRV_noinc((SV *)hv)) : &PL_sv_undef;
2939
2940         XSRETURN(8);
2941
2942 void
2943 DPeek (sv)
2944     SV   *sv
2945
2946   PPCODE:
2947     ST (0) = newSVpv (Perl_sv_peek (aTHX_ sv), 0);
2948     XSRETURN (1);
2949
2950 void
2951 BEGIN()
2952     CODE:
2953         sv_inc(get_sv("XS::APItest::BEGIN_called", GV_ADD|GV_ADDMULTI));
2954
2955 void
2956 CHECK()
2957     CODE:
2958         sv_inc(get_sv("XS::APItest::CHECK_called", GV_ADD|GV_ADDMULTI));
2959
2960 void
2961 UNITCHECK()
2962     CODE:
2963         sv_inc(get_sv("XS::APItest::UNITCHECK_called", GV_ADD|GV_ADDMULTI));
2964
2965 void
2966 INIT()
2967     CODE:
2968         sv_inc(get_sv("XS::APItest::INIT_called", GV_ADD|GV_ADDMULTI));
2969
2970 void
2971 END()
2972     CODE:
2973         sv_inc(get_sv("XS::APItest::END_called", GV_ADD|GV_ADDMULTI));
2974
2975 void
2976 utf16_to_utf8 (sv, ...)
2977     SV* sv
2978         ALIAS:
2979             utf16_to_utf8_reversed = 1
2980     PREINIT:
2981         STRLEN len;
2982         U8 *source;
2983         SV *dest;
2984         I32 got; /* Gah, badly thought out APIs */
2985     CODE:
2986         if (ix) (void)SvPV_force_nolen(sv);
2987         source = (U8 *)SvPVbyte(sv, len);
2988         /* Optionally only convert part of the buffer.  */      
2989         if (items > 1) {
2990             len = SvUV(ST(1));
2991         }
2992         /* Mortalise this right now, as we'll be testing croak()s  */
2993         dest = sv_2mortal(newSV(len * 2 + 1));
2994         if (ix) {
2995             utf16_to_utf8_reversed(source, (U8 *)SvPVX(dest), len, &got);
2996         } else {
2997             utf16_to_utf8(source, (U8 *)SvPVX(dest), len, &got);
2998         }
2999         SvCUR_set(dest, got);
3000         SvPVX(dest)[got] = '\0';
3001         SvPOK_on(dest);
3002         ST(0) = dest;
3003         XSRETURN(1);
3004
3005 void
3006 my_exit(int exitcode)
3007         PPCODE:
3008         my_exit(exitcode);
3009
3010 U8
3011 first_byte(sv)
3012         SV *sv
3013    CODE:
3014     char *s;
3015     STRLEN len;
3016         s = SvPVbyte(sv, len);
3017         RETVAL = s[0];
3018    OUTPUT:
3019     RETVAL
3020
3021 I32
3022 sv_count()
3023         CODE:
3024             RETVAL = PL_sv_count;
3025         OUTPUT:
3026             RETVAL
3027
3028 void
3029 bhk_record(bool on)
3030     CODE:
3031         dMY_CXT;
3032         MY_CXT.bhk_record = on;
3033         if (on)
3034             av_clear(MY_CXT.bhkav);
3035
3036 void
3037 test_magic_chain()
3038     PREINIT:
3039         SV *sv;
3040         MAGIC *callmg, *uvarmg;
3041     CODE:
3042         sv = sv_2mortal(newSV(0));
3043         if (SvTYPE(sv) >= SVt_PVMG) croak_fail();
3044         if (SvMAGICAL(sv)) croak_fail();
3045         sv_magic(sv, &PL_sv_yes, PERL_MAGIC_checkcall, (char*)&callmg, 0);
3046         if (SvTYPE(sv) < SVt_PVMG) croak_fail();
3047         if (!SvMAGICAL(sv)) croak_fail();
3048         if (mg_find(sv, PERL_MAGIC_uvar)) croak_fail();
3049         callmg = mg_find(sv, PERL_MAGIC_checkcall);
3050         if (!callmg) croak_fail();
3051         if (callmg->mg_obj != &PL_sv_yes || callmg->mg_ptr != (char*)&callmg)
3052             croak_fail();
3053         sv_magic(sv, &PL_sv_no, PERL_MAGIC_uvar, (char*)&uvarmg, 0);
3054         if (SvTYPE(sv) < SVt_PVMG) croak_fail();
3055         if (!SvMAGICAL(sv)) croak_fail();
3056         if (mg_find(sv, PERL_MAGIC_checkcall) != callmg) croak_fail();
3057         uvarmg = mg_find(sv, PERL_MAGIC_uvar);
3058         if (!uvarmg) croak_fail();
3059         if (callmg->mg_obj != &PL_sv_yes || callmg->mg_ptr != (char*)&callmg)
3060             croak_fail();
3061         if (uvarmg->mg_obj != &PL_sv_no || uvarmg->mg_ptr != (char*)&uvarmg)
3062             croak_fail();
3063         mg_free_type(sv, PERL_MAGIC_vec);
3064         if (SvTYPE(sv) < SVt_PVMG) croak_fail();
3065         if (!SvMAGICAL(sv)) croak_fail();
3066         if (mg_find(sv, PERL_MAGIC_checkcall) != callmg) croak_fail();
3067         if (mg_find(sv, PERL_MAGIC_uvar) != uvarmg) croak_fail();
3068         if (callmg->mg_obj != &PL_sv_yes || callmg->mg_ptr != (char*)&callmg)
3069             croak_fail();
3070         if (uvarmg->mg_obj != &PL_sv_no || uvarmg->mg_ptr != (char*)&uvarmg)
3071             croak_fail();
3072         mg_free_type(sv, PERL_MAGIC_uvar);
3073         if (SvTYPE(sv) < SVt_PVMG) croak_fail();
3074         if (!SvMAGICAL(sv)) croak_fail();
3075         if (mg_find(sv, PERL_MAGIC_checkcall) != callmg) croak_fail();
3076         if (mg_find(sv, PERL_MAGIC_uvar)) croak_fail();
3077         if (callmg->mg_obj != &PL_sv_yes || callmg->mg_ptr != (char*)&callmg)
3078             croak_fail();
3079         sv_magic(sv, &PL_sv_no, PERL_MAGIC_uvar, (char*)&uvarmg, 0);
3080         if (SvTYPE(sv) < SVt_PVMG) croak_fail();
3081         if (!SvMAGICAL(sv)) croak_fail();
3082         if (mg_find(sv, PERL_MAGIC_checkcall) != callmg) croak_fail();
3083         uvarmg = mg_find(sv, PERL_MAGIC_uvar);
3084         if (!uvarmg) croak_fail();
3085         if (callmg->mg_obj != &PL_sv_yes || callmg->mg_ptr != (char*)&callmg)
3086             croak_fail();
3087         if (uvarmg->mg_obj != &PL_sv_no || uvarmg->mg_ptr != (char*)&uvarmg)
3088             croak_fail();
3089         mg_free_type(sv, PERL_MAGIC_checkcall);
3090         if (SvTYPE(sv) < SVt_PVMG) croak_fail();
3091         if (!SvMAGICAL(sv)) croak_fail();
3092         if (mg_find(sv, PERL_MAGIC_uvar) != uvarmg) croak_fail();
3093         if (mg_find(sv, PERL_MAGIC_checkcall)) croak_fail();
3094         if (uvarmg->mg_obj != &PL_sv_no || uvarmg->mg_ptr != (char*)&uvarmg)
3095             croak_fail();
3096         mg_free_type(sv, PERL_MAGIC_uvar);
3097         if (SvMAGICAL(sv)) croak_fail();
3098         if (mg_find(sv, PERL_MAGIC_checkcall)) croak_fail();
3099         if (mg_find(sv, PERL_MAGIC_uvar)) croak_fail();
3100
3101 void
3102 test_op_contextualize()
3103     PREINIT:
3104         OP *o;
3105     CODE:
3106         o = newSVOP(OP_CONST, 0, newSViv(0));
3107         o->op_flags &= ~OPf_WANT;
3108         o = op_contextualize(o, G_SCALAR);
3109         if (o->op_type != OP_CONST ||
3110                 (o->op_flags & OPf_WANT) != OPf_WANT_SCALAR)
3111             croak_fail();
3112         op_free(o);
3113         o = newSVOP(OP_CONST, 0, newSViv(0));
3114         o->op_flags &= ~OPf_WANT;
3115         o = op_contextualize(o, G_ARRAY);
3116         if (o->op_type != OP_CONST ||
3117                 (o->op_flags & OPf_WANT) != OPf_WANT_LIST)
3118             croak_fail();
3119         op_free(o);
3120         o = newSVOP(OP_CONST, 0, newSViv(0));
3121         o->op_flags &= ~OPf_WANT;
3122         o = op_contextualize(o, G_VOID);
3123         if (o->op_type != OP_NULL) croak_fail();
3124         op_free(o);
3125
3126 void
3127 test_rv2cv_op_cv()
3128     PROTOTYPE:
3129     PREINIT:
3130         GV *troc_gv;
3131         CV *troc_cv;
3132         OP *o;
3133     CODE:
3134         troc_gv = gv_fetchpv("XS::APItest::test_rv2cv_op_cv", 0, SVt_PVGV);
3135         troc_cv = get_cv("XS::APItest::test_rv2cv_op_cv", 0);
3136         o = newCVREF(0, newGVOP(OP_GV, 0, troc_gv));
3137         if (rv2cv_op_cv(o, 0) != troc_cv) croak_fail();
3138         if (rv2cv_op_cv(o, RV2CVOPCV_RETURN_NAME_GV) != (CV*)troc_gv)
3139             croak_fail();
3140         o->op_private |= OPpENTERSUB_AMPER;
3141         if (rv2cv_op_cv(o, 0)) croak_fail();
3142         if (rv2cv_op_cv(o, RV2CVOPCV_RETURN_NAME_GV)) croak_fail();
3143         o->op_private &= ~OPpENTERSUB_AMPER;
3144         if (cUNOPx(o)->op_first->op_private & OPpEARLY_CV) croak_fail();
3145         if (rv2cv_op_cv(o, RV2CVOPCV_MARK_EARLY) != troc_cv) croak_fail();
3146         if (cUNOPx(o)->op_first->op_private & OPpEARLY_CV) croak_fail();
3147         op_free(o);
3148         o = newSVOP(OP_CONST, 0, newSVpv("XS::APItest::test_rv2cv_op_cv", 0));
3149         o->op_private = OPpCONST_BARE;
3150         o = newCVREF(0, o);
3151         if (rv2cv_op_cv(o, 0) != troc_cv) croak_fail();
3152         if (rv2cv_op_cv(o, RV2CVOPCV_RETURN_NAME_GV) != (CV*)troc_gv)
3153             croak_fail();
3154         o->op_private |= OPpENTERSUB_AMPER;
3155         if (rv2cv_op_cv(o, 0)) croak_fail();
3156         if (rv2cv_op_cv(o, RV2CVOPCV_RETURN_NAME_GV)) croak_fail();
3157         op_free(o);
3158         o = newCVREF(0, newSVOP(OP_CONST, 0, newRV_inc((SV*)troc_cv)));
3159         if (rv2cv_op_cv(o, 0) != troc_cv) croak_fail();
3160         if (rv2cv_op_cv(o, RV2CVOPCV_RETURN_NAME_GV) != (CV*)troc_gv)
3161             croak_fail();
3162         o->op_private |= OPpENTERSUB_AMPER;
3163         if (rv2cv_op_cv(o, 0)) croak_fail();
3164         if (rv2cv_op_cv(o, RV2CVOPCV_RETURN_NAME_GV)) croak_fail();
3165         o->op_private &= ~OPpENTERSUB_AMPER;
3166         if (cUNOPx(o)->op_first->op_private & OPpEARLY_CV) croak_fail();
3167         if (rv2cv_op_cv(o, RV2CVOPCV_MARK_EARLY) != troc_cv) croak_fail();
3168         if (cUNOPx(o)->op_first->op_private & OPpEARLY_CV) croak_fail();
3169         op_free(o);
3170         o = newCVREF(0, newUNOP(OP_RAND, 0, newSVOP(OP_CONST, 0, newSViv(0))));
3171         if (rv2cv_op_cv(o, 0)) croak_fail();
3172         if (rv2cv_op_cv(o, RV2CVOPCV_RETURN_NAME_GV)) croak_fail();
3173         o->op_private |= OPpENTERSUB_AMPER;
3174         if (rv2cv_op_cv(o, 0)) croak_fail();
3175         if (rv2cv_op_cv(o, RV2CVOPCV_RETURN_NAME_GV)) croak_fail();
3176         o->op_private &= ~OPpENTERSUB_AMPER;
3177         if (cUNOPx(o)->op_first->op_private & OPpEARLY_CV) croak_fail();
3178         if (rv2cv_op_cv(o, RV2CVOPCV_MARK_EARLY)) croak_fail();
3179         if (cUNOPx(o)->op_first->op_private & OPpEARLY_CV) croak_fail();
3180         op_free(o);
3181         o = newUNOP(OP_RAND, 0, newSVOP(OP_CONST, 0, newSViv(0)));
3182         if (rv2cv_op_cv(o, 0)) croak_fail();
3183         if (rv2cv_op_cv(o, RV2CVOPCV_RETURN_NAME_GV)) croak_fail();
3184         op_free(o);
3185
3186 void
3187 test_cv_getset_call_checker()
3188     PREINIT:
3189         CV *troc_cv, *tsh_cv;
3190         Perl_call_checker ckfun;
3191         SV *ckobj;
3192         U32 ckflags;
3193     CODE:
3194 #define check_cc(cv, xckfun, xckobj, xckflags) \
3195     do { \
3196         cv_get_call_checker((cv), &ckfun, &ckobj); \
3197         if (ckfun != (xckfun)) croak_fail_nep(FPTR2DPTR(void *, ckfun), xckfun); \
3198         if (ckobj != (xckobj)) croak_fail_nep(FPTR2DPTR(void *, ckobj), xckobj); \
3199         cv_get_call_checker_flags((cv), CALL_CHECKER_REQUIRE_GV, &ckfun, &ckobj, &ckflags); \
3200         if (ckfun != (xckfun)) croak_fail_nep(FPTR2DPTR(void *, ckfun), xckfun); \
3201         if (ckobj != (xckobj)) croak_fail_nep(FPTR2DPTR(void *, ckobj), xckobj); \
3202         if (ckflags != CALL_CHECKER_REQUIRE_GV) croak_fail_nei(ckflags, CALL_CHECKER_REQUIRE_GV); \
3203         cv_get_call_checker_flags((cv), 0, &ckfun, &ckobj, &ckflags); \
3204         if (ckfun != (xckfun)) croak_fail_nep(FPTR2DPTR(void *, ckfun), xckfun); \
3205         if (ckobj != (xckobj)) croak_fail_nep(FPTR2DPTR(void *, ckobj), xckobj); \
3206         if (ckflags != (xckflags)) croak_fail_nei(ckflags, (xckflags)); \
3207     } while(0)
3208         troc_cv = get_cv("XS::APItest::test_rv2cv_op_cv", 0);
3209         tsh_cv = get_cv("XS::APItest::test_savehints", 0);
3210         check_cc(troc_cv, Perl_ck_entersub_args_proto_or_list, (SV*)troc_cv, 0);
3211         check_cc(tsh_cv, Perl_ck_entersub_args_proto_or_list, (SV*)tsh_cv, 0);
3212         cv_set_call_checker(tsh_cv, Perl_ck_entersub_args_proto_or_list,
3213                                     &PL_sv_yes);
3214         check_cc(troc_cv, Perl_ck_entersub_args_proto_or_list, (SV*)troc_cv, 0);
3215         check_cc(tsh_cv, Perl_ck_entersub_args_proto_or_list, &PL_sv_yes, CALL_CHECKER_REQUIRE_GV);
3216         cv_set_call_checker(troc_cv, THX_ck_entersub_args_scalars, &PL_sv_no);
3217         check_cc(troc_cv, THX_ck_entersub_args_scalars, &PL_sv_no, CALL_CHECKER_REQUIRE_GV);
3218         check_cc(tsh_cv, Perl_ck_entersub_args_proto_or_list, &PL_sv_yes, CALL_CHECKER_REQUIRE_GV);
3219         cv_set_call_checker(tsh_cv, Perl_ck_entersub_args_proto_or_list,
3220                                     (SV*)tsh_cv);
3221         check_cc(troc_cv, THX_ck_entersub_args_scalars, &PL_sv_no, CALL_CHECKER_REQUIRE_GV);
3222         check_cc(tsh_cv, Perl_ck_entersub_args_proto_or_list, (SV*)tsh_cv, 0);
3223         cv_set_call_checker(troc_cv, Perl_ck_entersub_args_proto_or_list,
3224                                     (SV*)troc_cv);
3225         check_cc(troc_cv, Perl_ck_entersub_args_proto_or_list, (SV*)troc_cv, 0);
3226         check_cc(tsh_cv, Perl_ck_entersub_args_proto_or_list, (SV*)tsh_cv, 0);
3227         if (SvMAGICAL((SV*)troc_cv) || SvMAGIC((SV*)troc_cv)) croak_fail();
3228         if (SvMAGICAL((SV*)tsh_cv) || SvMAGIC((SV*)tsh_cv)) croak_fail();
3229         cv_set_call_checker_flags(tsh_cv, Perl_ck_entersub_args_proto_or_list,
3230                                     &PL_sv_yes, 0);
3231         check_cc(tsh_cv, Perl_ck_entersub_args_proto_or_list, &PL_sv_yes, 0);
3232         cv_set_call_checker_flags(tsh_cv, Perl_ck_entersub_args_proto_or_list,
3233                                     &PL_sv_yes, CALL_CHECKER_REQUIRE_GV);
3234         check_cc(tsh_cv, Perl_ck_entersub_args_proto_or_list, &PL_sv_yes, CALL_CHECKER_REQUIRE_GV);
3235         cv_set_call_checker_flags(tsh_cv, Perl_ck_entersub_args_proto_or_list,
3236                                     (SV*)tsh_cv, 0);
3237         check_cc(tsh_cv, Perl_ck_entersub_args_proto_or_list, (SV*)tsh_cv, 0);
3238         if (SvMAGICAL((SV*)tsh_cv) || SvMAGIC((SV*)tsh_cv)) croak_fail();
3239         cv_set_call_checker_flags(tsh_cv, Perl_ck_entersub_args_proto_or_list,
3240                                     &PL_sv_yes, CALL_CHECKER_REQUIRE_GV);
3241         check_cc(tsh_cv, Perl_ck_entersub_args_proto_or_list, &PL_sv_yes, CALL_CHECKER_REQUIRE_GV);
3242         cv_set_call_checker_flags(tsh_cv, Perl_ck_entersub_args_proto_or_list,
3243                                     (SV*)tsh_cv, CALL_CHECKER_REQUIRE_GV);
3244         check_cc(tsh_cv, Perl_ck_entersub_args_proto_or_list, (SV*)tsh_cv, 0);
3245         if (SvMAGICAL((SV*)tsh_cv) || SvMAGIC((SV*)tsh_cv)) croak_fail();
3246 #undef check_cc
3247
3248 void
3249 cv_set_call_checker_lists(CV *cv)
3250     CODE:
3251         cv_set_call_checker(cv, THX_ck_entersub_args_lists, &PL_sv_undef);
3252
3253 void
3254 cv_set_call_checker_scalars(CV *cv)
3255     CODE:
3256         cv_set_call_checker(cv, THX_ck_entersub_args_scalars, &PL_sv_undef);
3257
3258 void
3259 cv_set_call_checker_proto(CV *cv, SV *proto)
3260     CODE:
3261         if (SvROK(proto))
3262             proto = SvRV(proto);
3263         cv_set_call_checker(cv, Perl_ck_entersub_args_proto, proto);
3264
3265 void
3266 cv_set_call_checker_proto_or_list(CV *cv, SV *proto)
3267     CODE:
3268         if (SvROK(proto))
3269             proto = SvRV(proto);
3270         cv_set_call_checker(cv, Perl_ck_entersub_args_proto_or_list, proto);
3271
3272 void
3273 cv_set_call_checker_multi_sum(CV *cv)
3274     CODE:
3275         cv_set_call_checker(cv, THX_ck_entersub_multi_sum, &PL_sv_undef);
3276
3277 void
3278 test_cophh()
3279     PREINIT:
3280         COPHH *a, *b;
3281 #ifdef EBCDIC
3282         SV* key_sv;
3283         char * key_name;
3284         STRLEN key_len;
3285 #endif
3286     CODE:
3287 #define check_ph(EXPR) \
3288             do { if((EXPR) != &PL_sv_placeholder) croak("fail"); } while(0)
3289 #define check_iv(EXPR, EXPECT) \
3290             do { if(SvIV(EXPR) != (EXPECT)) croak("fail"); } while(0)
3291 #define msvpvs(STR) sv_2mortal(newSVpvs(STR))
3292 #define msviv(VALUE) sv_2mortal(newSViv(VALUE))
3293         a = cophh_new_empty();
3294         check_ph(cophh_fetch_pvn(a, "foo_1", 5, 0, 0));
3295         check_ph(cophh_fetch_pvs(a, "foo_1", 0));
3296         check_ph(cophh_fetch_pv(a, "foo_1", 0, 0));
3297         check_ph(cophh_fetch_sv(a, msvpvs("foo_1"), 0, 0));
3298         a = cophh_store_pvn(a, "foo_1abc", 5, 0, msviv(111), 0);
3299         a = cophh_store_pvs(a, "foo_2", msviv(222), 0);
3300         a = cophh_store_pv(a, "foo_3", 0, msviv(333), 0);
3301         a = cophh_store_sv(a, msvpvs("foo_4"), 0, msviv(444), 0);
3302         check_iv(cophh_fetch_pvn(a, "foo_1xyz", 5, 0, 0), 111);
3303         check_iv(cophh_fetch_pvs(a, "foo_1", 0), 111);
3304         check_iv(cophh_fetch_pv(a, "foo_1", 0, 0), 111);
3305         check_iv(cophh_fetch_sv(a, msvpvs("foo_1"), 0, 0), 111);
3306         check_iv(cophh_fetch_pvs(a, "foo_2", 0), 222);
3307         check_iv(cophh_fetch_pvs(a, "foo_3", 0), 333);
3308         check_iv(cophh_fetch_pvs(a, "foo_4", 0), 444);
3309         check_ph(cophh_fetch_pvs(a, "foo_5", 0));
3310         b = cophh_copy(a);
3311         b = cophh_store_pvs(b, "foo_1", msviv(1111), 0);
3312         check_iv(cophh_fetch_pvs(a, "foo_1", 0), 111);
3313         check_iv(cophh_fetch_pvs(a, "foo_2", 0), 222);
3314         check_iv(cophh_fetch_pvs(a, "foo_3", 0), 333);
3315         check_iv(cophh_fetch_pvs(a, "foo_4", 0), 444);
3316         check_ph(cophh_fetch_pvs(a, "foo_5", 0));
3317         check_iv(cophh_fetch_pvs(b, "foo_1", 0), 1111);
3318         check_iv(cophh_fetch_pvs(b, "foo_2", 0), 222);
3319         check_iv(cophh_fetch_pvs(b, "foo_3", 0), 333);
3320         check_iv(cophh_fetch_pvs(b, "foo_4", 0), 444);
3321         check_ph(cophh_fetch_pvs(b, "foo_5", 0));
3322         a = cophh_delete_pvn(a, "foo_1abc", 5, 0, 0);
3323         a = cophh_delete_pvs(a, "foo_2", 0);
3324         b = cophh_delete_pv(b, "foo_3", 0, 0);
3325         b = cophh_delete_sv(b, msvpvs("foo_4"), 0, 0);
3326         check_ph(cophh_fetch_pvs(a, "foo_1", 0));
3327         check_ph(cophh_fetch_pvs(a, "foo_2", 0));
3328         check_iv(cophh_fetch_pvs(a, "foo_3", 0), 333);
3329         check_iv(cophh_fetch_pvs(a, "foo_4", 0), 444);
3330         check_ph(cophh_fetch_pvs(a, "foo_5", 0));
3331         check_iv(cophh_fetch_pvs(b, "foo_1", 0), 1111);
3332         check_iv(cophh_fetch_pvs(b, "foo_2", 0), 222);
3333         check_ph(cophh_fetch_pvs(b, "foo_3", 0));
3334         check_ph(cophh_fetch_pvs(b, "foo_4", 0));
3335         check_ph(cophh_fetch_pvs(b, "foo_5", 0));
3336         b = cophh_delete_pvs(b, "foo_3", 0);
3337         b = cophh_delete_pvs(b, "foo_5", 0);
3338         check_iv(cophh_fetch_pvs(b, "foo_1", 0), 1111);
3339         check_iv(cophh_fetch_pvs(b, "foo_2", 0), 222);
3340         check_ph(cophh_fetch_pvs(b, "foo_3", 0));
3341         check_ph(cophh_fetch_pvs(b, "foo_4", 0));
3342         check_ph(cophh_fetch_pvs(b, "foo_5", 0));
3343         cophh_free(b);
3344         check_ph(cophh_fetch_pvs(a, "foo_1", 0));
3345         check_ph(cophh_fetch_pvs(a, "foo_2", 0));
3346         check_iv(cophh_fetch_pvs(a, "foo_3", 0), 333);
3347         check_iv(cophh_fetch_pvs(a, "foo_4", 0), 444);
3348         check_ph(cophh_fetch_pvs(a, "foo_5", 0));
3349         a = cophh_store_pvs(a, "foo_1", msviv(11111), COPHH_KEY_UTF8);
3350         a = cophh_store_pvs(a, "foo_\xaa", msviv(123), 0);
3351 #ifndef EBCDIC
3352         a = cophh_store_pvs(a, "foo_\xc2\xbb", msviv(456), COPHH_KEY_UTF8);
3353 #else
3354         /* On EBCDIC, we need to translate the UTF-8 in the ASCII test to the
3355          * equivalent UTF-EBCDIC for the code page.  This is done at runtime
3356          * (with the helper function in this file).  Therefore we can't use
3357          * cophhh_store_pvs(), as we don't have literal string */
3358         key_sv = sv_2mortal(newSVpvs("foo_"));
3359         cat_utf8a2n(key_sv, STR_WITH_LEN("\xc2\xbb"));
3360         key_name = SvPV(key_sv, key_len);
3361         a = cophh_store_pvn(a, key_name, key_len, 0, msviv(456), COPHH_KEY_UTF8);
3362 #endif
3363 #ifndef EBCDIC
3364         a = cophh_store_pvs(a, "foo_\xc3\x8c", msviv(789), COPHH_KEY_UTF8);
3365 #else
3366         sv_setpvs(key_sv, "foo_");
3367         cat_utf8a2n(key_sv, STR_WITH_LEN("\xc3\x8c"));
3368         key_name = SvPV(key_sv, key_len);
3369         a = cophh_store_pvn(a, key_name, key_len, 0, msviv(789), COPHH_KEY_UTF8);
3370 #endif
3371 #ifndef EBCDIC
3372         a = cophh_store_pvs(a, "foo_\xd9\xa6", msviv(666), COPHH_KEY_UTF8);
3373 #else
3374         sv_setpvs(key_sv, "foo_");
3375         cat_utf8a2n(key_sv, STR_WITH_LEN("\xd9\xa6"));
3376         key_name = SvPV(key_sv, key_len);
3377         a = cophh_store_pvn(a, key_name, key_len, 0, msviv(666), COPHH_KEY_UTF8);
3378 #endif
3379         check_iv(cophh_fetch_pvs(a, "foo_1", 0), 11111);
3380         check_iv(cophh_fetch_pvs(a, "foo_1", COPHH_KEY_UTF8), 11111);
3381         check_iv(cophh_fetch_pvs(a, "foo_\xaa", 0), 123);
3382 #ifndef EBCDIC
3383         check_iv(cophh_fetch_pvs(a, "foo_\xc2\xaa", COPHH_KEY_UTF8), 123);
3384         check_ph(cophh_fetch_pvs(a, "foo_\xc2\xaa", 0));
3385 #else
3386         sv_setpvs(key_sv, "foo_");
3387         cat_utf8a2n(key_sv, STR_WITH_LEN("\xc2\xaa"));
3388         key_name = SvPV(key_sv, key_len);
3389         check_iv(cophh_fetch_pvn(a, key_name, key_len, 0, COPHH_KEY_UTF8), 123);
3390         check_ph(cophh_fetch_pvn(a, key_name, key_len, 0, 0));
3391 #endif
3392         check_iv(cophh_fetch_pvs(a, "foo_\xbb", 0), 456);
3393 #ifndef EBCDIC
3394         check_iv(cophh_fetch_pvs(a, "foo_\xc2\xbb", COPHH_KEY_UTF8), 456);
3395         check_ph(cophh_fetch_pvs(a, "foo_\xc2\xbb", 0));
3396 #else
3397         sv_setpvs(key_sv, "foo_");
3398         cat_utf8a2n(key_sv, STR_WITH_LEN("\xc2\xbb"));
3399         key_name = SvPV(key_sv, key_len);
3400         check_iv(cophh_fetch_pvn(a, key_name, key_len, 0, COPHH_KEY_UTF8), 456);
3401         check_ph(cophh_fetch_pvn(a, key_name, key_len, 0, 0));
3402 #endif
3403         check_iv(cophh_fetch_pvs(a, "foo_\xcc", 0), 789);
3404 #ifndef EBCDIC
3405         check_iv(cophh_fetch_pvs(a, "foo_\xc3\x8c", COPHH_KEY_UTF8), 789);
3406         check_ph(cophh_fetch_pvs(a, "foo_\xc2\x8c", 0));
3407 #else
3408         sv_setpvs(key_sv, "foo_");
3409         cat_utf8a2n(key_sv, STR_WITH_LEN("\xc3\x8c"));
3410         key_name = SvPV(key_sv, key_len);
3411         check_iv(cophh_fetch_pvn(a, key_name, key_len, 0, COPHH_KEY_UTF8), 789);
3412         check_ph(cophh_fetch_pvn(a, key_name, key_len, 0, 0));
3413 #endif
3414 #ifndef EBCDIC
3415         check_iv(cophh_fetch_pvs(a, "foo_\xd9\xa6", COPHH_KEY_UTF8), 666);
3416         check_ph(cophh_fetch_pvs(a, "foo_\xd9\xa6", 0));
3417 #else
3418         sv_setpvs(key_sv, "foo_");
3419         cat_utf8a2n(key_sv, STR_WITH_LEN("\xd9\xa6"));
3420         key_name = SvPV(key_sv, key_len);
3421         check_iv(cophh_fetch_pvn(a, key_name, key_len, 0, COPHH_KEY_UTF8), 666);
3422         check_ph(cophh_fetch_pvn(a, key_name, key_len, 0, 0));
3423 #endif
3424         ENTER;
3425         SAVEFREECOPHH(a);
3426         LEAVE;
3427 #undef check_ph
3428 #undef check_iv
3429 #undef msvpvs
3430 #undef msviv
3431
3432 void
3433 test_coplabel()
3434     PREINIT:
3435         COP *cop;
3436         const char *label;
3437         STRLEN len;
3438         U32 utf8;
3439     CODE:
3440         cop = &PL_compiling;
3441         Perl_cop_store_label(aTHX_ cop, "foo", 3, 0);
3442         label = Perl_cop_fetch_label(aTHX_ cop, &len, &utf8);
3443         if (strNE(label,"foo")) croak("fail # cop_fetch_label label");
3444         if (len != 3) croak("fail # cop_fetch_label len");
3445         if (utf8) croak("fail # cop_fetch_label utf8");
3446         /* SMALL GERMAN UMLAUT A */
3447         Perl_cop_store_label(aTHX_ cop, "fo\xc3\xa4", 4, SVf_UTF8);
3448         label = Perl_cop_fetch_label(aTHX_ cop, &len, &utf8);
3449         if (strNE(label,"fo\xc3\xa4")) croak("fail # cop_fetch_label label");
3450         if (len != 4) croak("fail # cop_fetch_label len");
3451         if (!utf8) croak("fail # cop_fetch_label utf8");
3452
3453
3454 HV *
3455 example_cophh_2hv()
3456     PREINIT:
3457         COPHH *a;
3458 #ifdef EBCDIC
3459         SV* key_sv;
3460         char * key_name;
3461         STRLEN key_len;
3462 #endif
3463     CODE:
3464 #define msviv(VALUE) sv_2mortal(newSViv(VALUE))
3465         a = cophh_new_empty();
3466         a = cophh_store_pvs(a, "foo_0", msviv(999), 0);
3467         a = cophh_store_pvs(a, "foo_1", msviv(111), 0);
3468         a = cophh_store_pvs(a, "foo_\xaa", msviv(123), 0);
3469 #ifndef EBCDIC
3470         a = cophh_store_pvs(a, "foo_\xc2\xbb", msviv(456), COPHH_KEY_UTF8);
3471 #else
3472         key_sv = sv_2mortal(newSVpvs("foo_"));
3473         cat_utf8a2n(key_sv, STR_WITH_LEN("\xc2\xbb"));
3474         key_name = SvPV(key_sv, key_len);
3475         a = cophh_store_pvn(a, key_name, key_len, 0, msviv(456), COPHH_KEY_UTF8);
3476 #endif
3477 #ifndef EBCDIC
3478         a = cophh_store_pvs(a, "foo_\xc3\x8c", msviv(789), COPHH_KEY_UTF8);
3479 #else
3480         sv_setpvs(key_sv, "foo_");
3481         cat_utf8a2n(key_sv, STR_WITH_LEN("\xc3\x8c"));
3482         key_name = SvPV(key_sv, key_len);
3483         a = cophh_store_pvn(a, key_name, key_len, 0, msviv(789), COPHH_KEY_UTF8);
3484 #endif
3485 #ifndef EBCDIC
3486         a = cophh_store_pvs(a, "foo_\xd9\xa6", msviv(666), COPHH_KEY_UTF8);
3487 #else
3488         sv_setpvs(key_sv, "foo_");
3489         cat_utf8a2n(key_sv, STR_WITH_LEN("\xd9\xa6"));
3490         key_name = SvPV(key_sv, key_len);
3491         a = cophh_store_pvn(a, key_name, key_len, 0, msviv(666), COPHH_KEY_UTF8);
3492 #endif
3493         a = cophh_delete_pvs(a, "foo_0", 0);
3494         a = cophh_delete_pvs(a, "foo_2", 0);
3495         RETVAL = cophh_2hv(a, 0);
3496         cophh_free(a);
3497 #undef msviv
3498     OUTPUT:
3499         RETVAL
3500
3501 void
3502 test_savehints()
3503     PREINIT:
3504         SV **svp, *sv;
3505     CODE:
3506 #define store_hint(KEY, VALUE) \
3507                 sv_setiv_mg(*hv_fetchs(GvHV(PL_hintgv), KEY, 1), (VALUE))
3508 #define hint_ok(KEY, EXPECT) \
3509                 ((svp = hv_fetchs(GvHV(PL_hintgv), KEY, 0)) && \
3510                     (sv = *svp) && SvIV(sv) == (EXPECT) && \
3511                     (sv = cop_hints_fetch_pvs(&PL_compiling, KEY, 0)) && \
3512                     SvIV(sv) == (EXPECT))
3513 #define check_hint(KEY, EXPECT) \
3514                 do { if (!hint_ok(KEY, EXPECT)) croak_fail(); } while(0)
3515         PL_hints |= HINT_LOCALIZE_HH;
3516         ENTER;
3517         SAVEHINTS();
3518         PL_hints &= HINT_INTEGER;
3519         store_hint("t0", 123);
3520         store_hint("t1", 456);
3521         if (PL_hints & HINT_INTEGER) croak_fail();
3522         check_hint("t0", 123); check_hint("t1", 456);
3523         ENTER;
3524         SAVEHINTS();
3525         if (PL_hints & HINT_INTEGER) croak_fail();
3526         check_hint("t0", 123); check_hint("t1", 456);
3527         PL_hints |= HINT_INTEGER;
3528         store_hint("t0", 321);
3529         if (!(PL_hints & HINT_INTEGER)) croak_fail();
3530         check_hint("t0", 321); check_hint("t1", 456);
3531         LEAVE;
3532         if (PL_hints & HINT_INTEGER) croak_fail();
3533         check_hint("t0", 123); check_hint("t1", 456);
3534         ENTER;
3535         SAVEHINTS();
3536         if (PL_hints & HINT_INTEGER) croak_fail();
3537         check_hint("t0", 123); check_hint("t1", 456);
3538         store_hint("t1", 654);
3539         if (PL_hints & HINT_INTEGER) croak_fail();
3540         check_hint("t0", 123); check_hint("t1", 654);
3541         LEAVE;
3542         if (PL_hints & HINT_INTEGER) croak_fail();
3543         check_hint("t0", 123); check_hint("t1", 456);
3544         LEAVE;
3545 #undef store_hint
3546 #undef hint_ok
3547 #undef check_hint
3548
3549 void
3550 test_copyhints()
3551     PREINIT:
3552         HV *a, *b;
3553     CODE:
3554         PL_hints |= HINT_LOCALIZE_HH;
3555         ENTER;
3556         SAVEHINTS();
3557         sv_setiv_mg(*hv_fetchs(GvHV(PL_hintgv), "t0", 1), 123);
3558         if (SvIV(cop_hints_fetch_pvs(&PL_compiling, "t0", 0)) != 123)
3559             croak_fail();
3560         a = newHVhv(GvHV(PL_hintgv));
3561         sv_2mortal((SV*)a);
3562         sv_setiv_mg(*hv_fetchs(a, "t0", 1), 456);
3563         if (SvIV(cop_hints_fetch_pvs(&PL_compiling, "t0", 0)) != 123)
3564             croak_fail();
3565         b = hv_copy_hints_hv(a);
3566         sv_2mortal((SV*)b);
3567         sv_setiv_mg(*hv_fetchs(b, "t0", 1), 789);
3568         if (SvIV(cop_hints_fetch_pvs(&PL_compiling, "t0", 0)) != 789)
3569             croak_fail();
3570         LEAVE;
3571
3572 void
3573 test_op_list()
3574     PREINIT:
3575         OP *a;
3576     CODE:
3577 #define iv_op(iv) newSVOP(OP_CONST, 0, newSViv(iv))
3578 #define check_op(o, expect) \
3579     do { \
3580         if (strNE(test_op_list_describe(o), (expect))) \
3581             croak("fail %s %s", test_op_list_describe(o), (expect)); \
3582     } while(0)
3583         a = op_append_elem(OP_LIST, NULL, NULL);
3584         check_op(a, "");
3585         a = op_append_elem(OP_LIST, iv_op(1), a);
3586         check_op(a, "const(1).");
3587         a = op_append_elem(OP_LIST, NULL, a);
3588         check_op(a, "const(1).");
3589         a = op_append_elem(OP_LIST, a, iv_op(2));
3590         check_op(a, "list[pushmark.const(1).const(2).]");
3591         a = op_append_elem(OP_LIST, a, iv_op(3));
3592         check_op(a, "list[pushmark.const(1).const(2).const(3).]");
3593         a = op_append_elem(OP_LIST, a, NULL);
3594         check_op(a, "list[pushmark.const(1).const(2).const(3).]");
3595         a = op_append_elem(OP_LIST, NULL, a);
3596         check_op(a, "list[pushmark.const(1).const(2).const(3).]");
3597         a = op_append_elem(OP_LIST, iv_op(4), a);
3598         check_op(a, "list[pushmark.const(4)."
3599                 "list[pushmark.const(1).const(2).const(3).]]");
3600         a = op_append_elem(OP_LIST, a, iv_op(5));
3601         check_op(a, "list[pushmark.const(4)."
3602                 "list[pushmark.const(1).const(2).const(3).]const(5).]");
3603         a = op_append_elem(OP_LIST, a, 
3604                 op_append_elem(OP_LIST, iv_op(7), iv_op(6)));
3605         check_op(a, "list[pushmark.const(4)."
3606                 "list[pushmark.const(1).const(2).const(3).]const(5)."
3607                 "list[pushmark.const(7).const(6).]]");
3608         op_free(a);
3609         a = op_append_elem(OP_LINESEQ, iv_op(1), iv_op(2));
3610         check_op(a, "lineseq[const(1).const(2).]");
3611         a = op_append_elem(OP_LINESEQ, a, iv_op(3));
3612         check_op(a, "lineseq[const(1).const(2).const(3).]");
3613         op_free(a);
3614         a = op_append_elem(OP_LINESEQ,
3615                 op_append_elem(OP_LIST, iv_op(1), iv_op(2)),
3616                 iv_op(3));
3617         check_op(a, "lineseq[list[pushmark.const(1).const(2).]const(3).]");
3618         op_free(a);
3619         a = op_prepend_elem(OP_LIST, NULL, NULL);
3620         check_op(a, "");
3621         a = op_prepend_elem(OP_LIST, a, iv_op(1));
3622         check_op(a, "const(1).");
3623         a = op_prepend_elem(OP_LIST, a, NULL);
3624         check_op(a, "const(1).");
3625         a = op_prepend_elem(OP_LIST, iv_op(2), a);
3626         check_op(a, "list[pushmark.const(2).const(1).]");
3627         a = op_prepend_elem(OP_LIST, iv_op(3), a);
3628         check_op(a, "list[pushmark.const(3).const(2).const(1).]");
3629         a = op_prepend_elem(OP_LIST, NULL, a);
3630         check_op(a, "list[pushmark.const(3).const(2).const(1).]");
3631         a = op_prepend_elem(OP_LIST, a, NULL);
3632         check_op(a, "list[pushmark.const(3).const(2).const(1).]");
3633         a = op_prepend_elem(OP_LIST, a, iv_op(4));
3634         check_op(a, "list[pushmark."
3635                 "list[pushmark.const(3).const(2).const(1).]const(4).]");
3636         a = op_prepend_elem(OP_LIST, iv_op(5), a);
3637         check_op(a, "list[pushmark.const(5)."
3638                 "list[pushmark.const(3).const(2).const(1).]const(4).]");
3639         a = op_prepend_elem(OP_LIST,
3640                 op_prepend_elem(OP_LIST, iv_op(6), iv_op(7)), a);
3641         check_op(a, "list[pushmark.list[pushmark.const(6).const(7).]const(5)."
3642                 "list[pushmark.const(3).const(2).const(1).]const(4).]");
3643         op_free(a);
3644         a = op_prepend_elem(OP_LINESEQ, iv_op(2), iv_op(1));
3645         check_op(a, "lineseq[const(2).const(1).]");
3646         a = op_prepend_elem(OP_LINESEQ, iv_op(3), a);
3647         check_op(a, "lineseq[const(3).const(2).const(1).]");
3648         op_free(a);
3649         a = op_prepend_elem(OP_LINESEQ, iv_op(3),
3650                 op_prepend_elem(OP_LIST, iv_op(2), iv_op(1)));
3651         check_op(a, "lineseq[const(3).list[pushmark.const(2).const(1).]]");
3652         op_free(a);
3653         a = op_append_list(OP_LINESEQ, NULL, NULL);
3654         check_op(a, "");
3655         a = op_append_list(OP_LINESEQ, iv_op(1), a);
3656         check_op(a, "const(1).");
3657         a = op_append_list(OP_LINESEQ, NULL, a);
3658         check_op(a, "const(1).");
3659         a = op_append_list(OP_LINESEQ, a, iv_op(2));
3660         check_op(a, "lineseq[const(1).const(2).]");
3661         a = op_append_list(OP_LINESEQ, a, iv_op(3));
3662         check_op(a, "lineseq[const(1).const(2).const(3).]");
3663         a = op_append_list(OP_LINESEQ, iv_op(4), a);
3664         check_op(a, "lineseq[const(4).const(1).const(2).const(3).]");
3665         a = op_append_list(OP_LINESEQ, a, NULL);
3666         check_op(a, "lineseq[const(4).const(1).const(2).const(3).]");
3667         a = op_append_list(OP_LINESEQ, NULL, a);
3668         check_op(a, "lineseq[const(4).const(1).const(2).const(3).]");
3669         a = op_append_list(OP_LINESEQ, a,
3670                 op_append_list(OP_LINESEQ, iv_op(5), iv_op(6)));
3671         check_op(a, "lineseq[const(4).const(1).const(2).const(3)."
3672                 "const(5).const(6).]");
3673         op_free(a);
3674         a = op_append_list(OP_LINESEQ,
3675                 op_append_list(OP_LINESEQ, iv_op(1), iv_op(2)),
3676                 op_append_list(OP_LIST, iv_op(3), iv_op(4)));
3677         check_op(a, "lineseq[const(1).const(2)."
3678                 "list[pushmark.const(3).const(4).]]");
3679         op_free(a);
3680         a = op_append_list(OP_LINESEQ,
3681                 op_append_list(OP_LIST, iv_op(1), iv_op(2)),
3682                 op_append_list(OP_LINESEQ, iv_op(3), iv_op(4)));
3683         check_op(a, "lineseq[list[pushmark.const(1).const(2).]"
3684                 "const(3).const(4).]");
3685         op_free(a);
3686 #undef check_op
3687
3688 void
3689 test_op_linklist ()
3690     PREINIT:
3691         OP *o;
3692     CODE:
3693 #define check_ll(o, expect) \
3694     STMT_START { \
3695         if (strNE(test_op_linklist_describe(o), (expect))) \
3696             croak("fail %s %s", test_op_linklist_describe(o), (expect)); \
3697     } STMT_END
3698         o = iv_op(1);
3699         check_ll(o, ".const1");
3700         op_free(o);
3701
3702         o = mkUNOP(OP_NOT, iv_op(1));
3703         check_ll(o, ".const1.not");
3704         op_free(o);
3705
3706         o = mkUNOP(OP_NOT, mkUNOP(OP_NEGATE, iv_op(1)));
3707         check_ll(o, ".const1.negate.not");
3708         op_free(o);
3709
3710         o = mkBINOP(OP_ADD, iv_op(1), iv_op(2));
3711         check_ll(o, ".const1.const2.add");
3712         op_free(o);
3713
3714         o = mkBINOP(OP_ADD, mkUNOP(OP_NOT, iv_op(1)), iv_op(2));
3715         check_ll(o, ".const1.not.const2.add");
3716         op_free(o);
3717
3718         o = mkUNOP(OP_NOT, mkBINOP(OP_ADD, iv_op(1), iv_op(2)));
3719         check_ll(o, ".const1.const2.add.not");
3720         op_free(o);
3721
3722         o = mkLISTOP(OP_LINESEQ, iv_op(1), iv_op(2), iv_op(3));
3723         check_ll(o, ".const1.const2.const3.lineseq");
3724         op_free(o);
3725
3726         o = mkLISTOP(OP_LINESEQ,
3727                 mkBINOP(OP_ADD, iv_op(1), iv_op(2)),
3728                 mkUNOP(OP_NOT, iv_op(3)),
3729                 mkLISTOP(OP_SUBSTR, iv_op(4), iv_op(5), iv_op(6)));
3730         check_ll(o, ".const1.const2.add.const3.not"
3731                     ".const4.const5.const6.substr.lineseq");
3732         op_free(o);
3733
3734         o = mkBINOP(OP_ADD, iv_op(1), iv_op(2));
3735         LINKLIST(o);
3736         o = mkBINOP(OP_SUBTRACT, o, iv_op(3));
3737         check_ll(o, ".const1.const2.add.const3.subtract");
3738         op_free(o);
3739 #undef check_ll
3740 #undef iv_op
3741
3742 void
3743 peep_enable ()
3744     PREINIT:
3745         dMY_CXT;
3746     CODE:
3747         av_clear(MY_CXT.peep_recorder);
3748         av_clear(MY_CXT.rpeep_recorder);
3749         MY_CXT.peep_recording = 1;
3750
3751 void
3752 peep_disable ()
3753     PREINIT:
3754         dMY_CXT;
3755     CODE:
3756         MY_CXT.peep_recording = 0;
3757
3758 SV *
3759 peep_record ()
3760     PREINIT:
3761         dMY_CXT;
3762     CODE:
3763         RETVAL = newRV_inc((SV *)MY_CXT.peep_recorder);
3764     OUTPUT:
3765         RETVAL
3766
3767 SV *
3768 rpeep_record ()
3769     PREINIT:
3770         dMY_CXT;
3771     CODE:
3772         RETVAL = newRV_inc((SV *)MY_CXT.rpeep_recorder);
3773     OUTPUT:
3774         RETVAL
3775
3776 =pod
3777
3778 multicall_each: call a sub for each item in the list. Used to test MULTICALL
3779
3780 =cut
3781
3782 void
3783 multicall_each(block,...)
3784     SV * block
3785 PROTOTYPE: &@
3786 CODE:
3787 {
3788     dMULTICALL;
3789     int index;
3790     GV *gv;
3791     HV *stash;
3792     I32 gimme = G_SCALAR;
3793     SV **args = &PL_stack_base[ax];
3794     CV *cv;
3795
3796     if(items <= 1) {
3797         XSRETURN_UNDEF;
3798     }
3799     cv = sv_2cv(block, &stash, &gv, 0);
3800     if (cv == Nullcv) {
3801        croak("multicall_each: not a subroutine reference");
3802     }
3803     PUSH_MULTICALL(cv);
3804     SAVESPTR(GvSV(PL_defgv));
3805
3806     for(index = 1 ; index < items ; index++) {
3807         GvSV(PL_defgv) = args[index];
3808         MULTICALL;
3809     }
3810     POP_MULTICALL;
3811     XSRETURN_UNDEF;
3812 }
3813
3814 =pod
3815
3816 multicall_return(): call the passed sub once in the specificed context
3817 and return whatever it returns
3818
3819 =cut
3820
3821 void
3822 multicall_return(block, context)
3823     SV *block
3824     I32 context
3825 PROTOTYPE: &$
3826 CODE:
3827 {
3828     dSP;
3829     dMULTICALL;
3830     GV *gv;
3831     HV *stash;
3832     I32 gimme = context;
3833     CV *cv;
3834     AV *av;
3835     SV **p;
3836     SSize_t i, size;
3837
3838     cv = sv_2cv(block, &stash, &gv, 0);
3839     if (cv == Nullcv) {
3840        croak("multicall_return not a subroutine reference");
3841     }
3842     PUSH_MULTICALL(cv);
3843
3844     MULTICALL;
3845
3846     /* copy returned values into an array so they're not freed during
3847      * POP_MULTICALL */
3848
3849     av = newAV();
3850     SPAGAIN;
3851
3852     switch (context) {
3853     case G_VOID:
3854         break;
3855
3856     case G_SCALAR:
3857         av_push(av, SvREFCNT_inc(TOPs));
3858         break;
3859
3860     case G_ARRAY:
3861         for (p = PL_stack_base + 1; p <= SP; p++)
3862             av_push(av, SvREFCNT_inc(*p));
3863         break;
3864     }
3865
3866     POP_MULTICALL;
3867
3868     size = AvFILLp(av) + 1;
3869     EXTEND(SP, size);
3870     for (i = 0; i < size; i++)
3871         ST(i) = *av_fetch(av, i, FALSE);
3872     sv_2mortal((SV*)av);
3873     XSRETURN(size);
3874 }
3875
3876
3877 #ifdef USE_ITHREADS
3878
3879 void
3880 clone_with_stack()
3881 CODE:
3882 {
3883     PerlInterpreter *interp = aTHX; /* The original interpreter */
3884     PerlInterpreter *interp_dup;    /* The duplicate interpreter */
3885     int oldscope = 1; /* We are responsible for all scopes */
3886
3887     interp_dup = perl_clone(interp, CLONEf_COPY_STACKS | CLONEf_CLONE_HOST );
3888
3889     /* destroy old perl */
3890     PERL_SET_CONTEXT(interp);
3891
3892     POPSTACK_TO(PL_mainstack);
3893     if (cxstack_ix >= 0) {
3894         dounwind(-1);
3895         cx_popblock(cxstack);
3896     }
3897     LEAVE_SCOPE(0);
3898     PL_scopestack_ix = oldscope;
3899     FREETMPS;
3900
3901     perl_destruct(interp);
3902     perl_free(interp);
3903
3904     /* switch to new perl */
3905     PERL_SET_CONTEXT(interp_dup);
3906
3907     /* continue after 'clone_with_stack' */
3908     if (interp_dup->Iop)
3909         interp_dup->Iop = interp_dup->Iop->op_next;
3910
3911     /* run with new perl */
3912     Perl_runops_standard(interp_dup);
3913
3914     /* We may have additional unclosed scopes if fork() was called
3915      * from within a BEGIN block.  See perlfork.pod for more details.
3916      * We cannot clean up these other scopes because they belong to a
3917      * different interpreter, but we also cannot leave PL_scopestack_ix
3918      * dangling because that can trigger an assertion in perl_destruct().
3919      */
3920     if (PL_scopestack_ix > oldscope) {
3921         PL_scopestack[oldscope-1] = PL_scopestack[PL_scopestack_ix-1];
3922         PL_scopestack_ix = oldscope;
3923     }
3924
3925     perl_destruct(interp_dup);
3926     perl_free(interp_dup);
3927
3928     /* call the real 'exit' not PerlProc_exit */
3929 #undef exit
3930     exit(0);
3931 }
3932
3933 #endif /* USE_ITHREDS */
3934
3935 SV*
3936 take_svref(SVREF sv)
3937 CODE:
3938     RETVAL = newRV_inc(sv);
3939 OUTPUT:
3940     RETVAL
3941
3942 SV*
3943 take_avref(AV* av)
3944 CODE:
3945     RETVAL = newRV_inc((SV*)av);
3946 OUTPUT:
3947     RETVAL
3948
3949 SV*
3950 take_hvref(HV* hv)
3951 CODE:
3952     RETVAL = newRV_inc((SV*)hv);
3953 OUTPUT:
3954     RETVAL
3955
3956
3957 SV*
3958 take_cvref(CV* cv)
3959 CODE:
3960     RETVAL = newRV_inc((SV*)cv);
3961 OUTPUT:
3962     RETVAL
3963
3964
3965 BOOT:
3966         {
3967         HV* stash;
3968         SV** meth = NULL;
3969         CV* cv;
3970         stash = gv_stashpv("XS::APItest::TempLv", 0);
3971         if (stash)
3972             meth = hv_fetchs(stash, "make_temp_mg_lv", 0);
3973         if (!meth)
3974             croak("lost method 'make_temp_mg_lv'");
3975         cv = GvCV(*meth);
3976         CvLVALUE_on(cv);
3977         }
3978
3979 BOOT:
3980 {
3981     hintkey_rpn_sv = newSVpvs_share("XS::APItest/rpn");
3982     hintkey_calcrpn_sv = newSVpvs_share("XS::APItest/calcrpn");
3983     hintkey_stufftest_sv = newSVpvs_share("XS::APItest/stufftest");
3984     hintkey_swaptwostmts_sv = newSVpvs_share("XS::APItest/swaptwostmts");
3985     hintkey_looprest_sv = newSVpvs_share("XS::APItest/looprest");
3986     hintkey_scopelessblock_sv = newSVpvs_share("XS::APItest/scopelessblock");
3987     hintkey_stmtasexpr_sv = newSVpvs_share("XS::APItest/stmtasexpr");
3988     hintkey_stmtsasexpr_sv = newSVpvs_share("XS::APItest/stmtsasexpr");
3989     hintkey_loopblock_sv = newSVpvs_share("XS::APItest/loopblock");
3990     hintkey_blockasexpr_sv = newSVpvs_share("XS::APItest/blockasexpr");
3991     hintkey_swaplabel_sv = newSVpvs_share("XS::APItest/swaplabel");
3992     hintkey_labelconst_sv = newSVpvs_share("XS::APItest/labelconst");
3993     hintkey_arrayfullexpr_sv = newSVpvs_share("XS::APItest/arrayfullexpr");
3994     hintkey_arraylistexpr_sv = newSVpvs_share("XS::APItest/arraylistexpr");
3995     hintkey_arraytermexpr_sv = newSVpvs_share("XS::APItest/arraytermexpr");
3996     hintkey_arrayarithexpr_sv = newSVpvs_share("XS::APItest/arrayarithexpr");
3997     hintkey_arrayexprflags_sv = newSVpvs_share("XS::APItest/arrayexprflags");
3998     hintkey_DEFSV_sv = newSVpvs_share("XS::APItest/DEFSV");
3999     hintkey_with_vars_sv = newSVpvs_share("XS::APItest/with_vars");
4000     hintkey_join_with_space_sv = newSVpvs_share("XS::APItest/join_with_space");
4001     wrap_keyword_plugin(my_keyword_plugin, &next_keyword_plugin);
4002 }
4003
4004 void
4005 establish_cleanup(...)
4006 PROTOTYPE: $
4007 CODE:
4008     PERL_UNUSED_VAR(items);
4009     croak("establish_cleanup called as a function");
4010
4011 BOOT:
4012 {
4013     CV *estcv = get_cv("XS::APItest::establish_cleanup", 0);
4014     cv_set_call_checker(estcv, THX_ck_entersub_establish_cleanup, (SV*)estcv);
4015 }
4016
4017 void
4018 postinc(...)
4019 PROTOTYPE: $
4020 CODE:
4021     PERL_UNUSED_VAR(items);
4022     croak("postinc called as a function");
4023
4024 void
4025 filter()
4026 CODE:
4027     filter_add(filter_call, NULL);
4028
4029 BOOT:
4030 {
4031     CV *asscv = get_cv("XS::APItest::postinc", 0);
4032     cv_set_call_checker(asscv, THX_ck_entersub_postinc, (SV*)asscv);
4033 }
4034
4035 SV *
4036 lv_temp_object()
4037 CODE:
4038     RETVAL =
4039           sv_bless(
4040             newRV_noinc(newSV(0)),
4041             gv_stashpvs("XS::APItest::TempObj",GV_ADD)
4042           );             /* Package defined in test script */
4043 OUTPUT:
4044     RETVAL
4045
4046 void
4047 fill_hash_with_nulls(HV *hv)
4048 PREINIT:
4049     UV i = 0;
4050 CODE:
4051     for(; i < 1000; ++i) {
4052         HE *entry = hv_fetch_ent(hv, sv_2mortal(newSVuv(i)), 1, 0);
4053         SvREFCNT_dec(HeVAL(entry));
4054         HeVAL(entry) = NULL;
4055     }
4056
4057 HV *
4058 newHVhv(HV *hv)
4059 CODE:
4060     RETVAL = newHVhv(hv);
4061 OUTPUT:
4062     RETVAL
4063
4064 U32
4065 SvIsCOW(SV *sv)
4066 CODE:
4067     RETVAL = SvIsCOW(sv);
4068 OUTPUT:
4069     RETVAL
4070
4071 void
4072 pad_scalar(...)
4073 PROTOTYPE: $$
4074 CODE:
4075     PERL_UNUSED_VAR(items);
4076     croak("pad_scalar called as a function");
4077
4078 BOOT:
4079 {
4080     CV *pscv = get_cv("XS::APItest::pad_scalar", 0);
4081     cv_set_call_checker(pscv, THX_ck_entersub_pad_scalar, (SV*)pscv);
4082 }
4083
4084 SV*
4085 fetch_pad_names( cv )
4086 CV* cv
4087  PREINIT:
4088   I32 i;
4089   PADNAMELIST *pad_namelist;
4090   AV *retav = newAV();
4091  CODE:
4092   pad_namelist = PadlistNAMES(CvPADLIST(cv));
4093
4094   for ( i = PadnamelistMAX(pad_namelist); i >= 0; i-- ) {
4095     PADNAME* name = PadnamelistARRAY(pad_namelist)[i];
4096
4097     if (PadnameLEN(name)) {
4098         av_push(retav, newSVpadname(name));
4099     }
4100   }
4101   RETVAL = newRV_noinc((SV*)retav);
4102  OUTPUT:
4103   RETVAL
4104
4105 STRLEN
4106 underscore_length()
4107 PROTOTYPE:
4108 PREINIT:
4109     SV *u;
4110     U8 *pv;
4111     STRLEN bytelen;
4112 CODE:
4113     u = find_rundefsv();
4114     pv = (U8*)SvPV(u, bytelen);
4115     RETVAL = SvUTF8(u) ? utf8_length(pv, pv+bytelen) : bytelen;
4116 OUTPUT:
4117     RETVAL
4118
4119 void
4120 stringify(SV *sv)
4121 CODE:
4122     (void)SvPV_nolen(sv);
4123
4124 SV *
4125 HvENAME(HV *hv)
4126 CODE:
4127     RETVAL = hv && HvENAME(hv)
4128               ? newSVpvn_flags(
4129                   HvENAME(hv),HvENAMELEN(hv),
4130                   (HvENAMEUTF8(hv) ? SVf_UTF8 : 0)
4131                 )
4132               : NULL;
4133 OUTPUT:
4134     RETVAL
4135
4136 int
4137 xs_cmp(int a, int b)
4138 CODE:
4139     /* Odd sorting (odd numbers first), to make sure we are actually
4140        being called */
4141     RETVAL = a % 2 != b % 2
4142                ? a % 2 ? -1 : 1
4143                : a < b ? -1 : a == b ? 0 : 1;
4144 OUTPUT:
4145     RETVAL
4146
4147 SV *
4148 xs_cmp_undef(SV *a, SV *b)
4149 CODE:
4150     PERL_UNUSED_ARG(a);
4151     PERL_UNUSED_ARG(b);
4152     RETVAL = &PL_sv_undef;
4153 OUTPUT:
4154     RETVAL
4155
4156 char *
4157 SvPVbyte(SV *sv)
4158 CODE:
4159     RETVAL = SvPVbyte_nolen(sv);
4160 OUTPUT:
4161     RETVAL
4162
4163 char *
4164 SvPVutf8(SV *sv)
4165 CODE:
4166     RETVAL = SvPVutf8_nolen(sv);
4167 OUTPUT:
4168     RETVAL
4169
4170 void
4171 setup_addissub()
4172 CODE:
4173     wrap_op_checker(OP_ADD, addissub_myck_add, &addissub_nxck_add);
4174
4175 void
4176 setup_rv2cv_addunderbar()
4177 CODE:
4178     wrap_op_checker(OP_RV2CV, my_ck_rv2cv, &old_ck_rv2cv);
4179
4180 #ifdef USE_ITHREADS
4181
4182 bool
4183 test_alloccopstash()
4184 CODE:
4185     RETVAL = PL_stashpad[alloccopstash(PL_defstash)] == PL_defstash;
4186 OUTPUT:
4187     RETVAL
4188
4189 #endif
4190
4191 bool
4192 test_newFOROP_without_slab()
4193 CODE:
4194     {
4195         const I32 floor = start_subparse(0,0);
4196         OP *o;
4197         /* The slab allocator does not like CvROOT being set. */
4198         CvROOT(PL_compcv) = (OP *)1;
4199         o = newFOROP(0, 0, newOP(OP_PUSHMARK, 0), 0, 0);
4200 #ifdef PERL_OP_PARENT
4201         if (cLOOPx(cUNOPo->op_first)->op_last->op_sibparent
4202                 != cUNOPo->op_first)
4203         {
4204             Perl_warn(aTHX_ "Op parent pointer is stale");
4205             RETVAL = FALSE;
4206         }
4207         else
4208 #endif
4209             /* If we do not crash before returning, the test passes. */
4210             RETVAL = TRUE;
4211         op_free(o);
4212         CvROOT(PL_compcv) = NULL;
4213         SvREFCNT_dec(PL_compcv);
4214         LEAVE_SCOPE(floor);
4215     }
4216 OUTPUT:
4217     RETVAL
4218
4219  # provide access to CALLREGEXEC, except replace pointers within the
4220  # string with offsets from the start of the string
4221
4222 I32
4223 callregexec(SV *prog, STRLEN stringarg, STRLEN strend, I32 minend, SV *sv, U32 nosave)
4224 CODE:
4225     {
4226         STRLEN len;
4227         char *strbeg;
4228         if (SvROK(prog))
4229             prog = SvRV(prog);
4230         strbeg = SvPV_force(sv, len);
4231         RETVAL = CALLREGEXEC((REGEXP *)prog,
4232                             strbeg + stringarg,
4233                             strbeg + strend,
4234                             strbeg,
4235                             minend,
4236                             sv,
4237                             NULL, /* data */
4238                             nosave);
4239     }
4240 OUTPUT:
4241     RETVAL
4242
4243 void
4244 lexical_import(SV *name, CV *cv)
4245     CODE:
4246     {
4247         PADLIST *pl;
4248         PADOFFSET off;
4249         if (!PL_compcv)
4250             Perl_croak(aTHX_
4251                       "lexical_import can only be called at compile time");
4252         pl = CvPADLIST(PL_compcv);
4253         ENTER;
4254         SAVESPTR(PL_comppad_name); PL_comppad_name = PadlistNAMES(pl);
4255         SAVESPTR(PL_comppad);      PL_comppad      = PadlistARRAY(pl)[1];
4256         SAVESPTR(PL_curpad);       PL_curpad       = PadARRAY(PL_comppad);
4257         off = pad_add_name_sv(sv_2mortal(newSVpvf("&%" SVf,name)),
4258                               padadd_STATE, 0, 0);
4259         SvREFCNT_dec(PL_curpad[off]);
4260         PL_curpad[off] = SvREFCNT_inc(cv);
4261         intro_my();
4262         LEAVE;
4263     }
4264
4265 SV *
4266 sv_mortalcopy(SV *sv)
4267     CODE:
4268         RETVAL = SvREFCNT_inc(sv_mortalcopy(sv));
4269     OUTPUT:
4270         RETVAL
4271
4272 SV *
4273 newRV(SV *sv)
4274
4275 void
4276 alias_av(AV *av, IV ix, SV *sv)
4277     CODE:
4278         av_store(av, ix, SvREFCNT_inc(sv));
4279
4280 SV *
4281 cv_name(SVREF ref, ...)
4282     CODE:
4283         RETVAL = SvREFCNT_inc(cv_name((CV *)ref,
4284                                       items>1 && ST(1) != &PL_sv_undef
4285                                         ? ST(1)
4286                                         : NULL,
4287                                       items>2 ? SvUV(ST(2)) : 0));
4288     OUTPUT:
4289         RETVAL
4290
4291 void
4292 sv_catpvn(SV *sv, SV *sv2)
4293     CODE:
4294     {
4295         STRLEN len;
4296         const char *s = SvPV(sv2,len);
4297         sv_catpvn_flags(sv,s,len, SvUTF8(sv2) ? SV_CATUTF8 : SV_CATBYTES);
4298     }
4299
4300 bool
4301 test_newOP_CUSTOM()
4302     CODE:
4303     {
4304         OP *o = newLISTOP(OP_CUSTOM, 0, NULL, NULL);
4305         op_free(o);
4306         o = newOP(OP_CUSTOM, 0);
4307         op_free(o);
4308         o = newUNOP(OP_CUSTOM, 0, NULL);
4309         op_free(o);
4310         o = newUNOP_AUX(OP_CUSTOM, 0, NULL, NULL);
4311         op_free(o);
4312         o = newMETHOP(OP_CUSTOM, 0, newOP(OP_NULL,0));
4313         op_free(o);
4314         o = newMETHOP_named(OP_CUSTOM, 0, newSV(0));
4315         op_free(o);
4316         o = newBINOP(OP_CUSTOM, 0, NULL, NULL);
4317         op_free(o);
4318         o = newPMOP(OP_CUSTOM, 0);
4319         op_free(o);
4320         o = newSVOP(OP_CUSTOM, 0, newSV(0));
4321         op_free(o);
4322 #ifdef USE_ITHREADS
4323         ENTER;
4324         lex_start(NULL, NULL, 0);
4325         {
4326             I32 ix = start_subparse(FALSE,0);
4327             o = newPADOP(OP_CUSTOM, 0, newSV(0));
4328             op_free(o);
4329             LEAVE_SCOPE(ix);
4330         }
4331         LEAVE;
4332 #endif
4333         o = newPVOP(OP_CUSTOM, 0, NULL);
4334         op_free(o);
4335         o = newLOGOP(OP_CUSTOM, 0, newOP(OP_NULL,0), newOP(OP_NULL,0));
4336         op_free(o);
4337         o = newLOOPEX(OP_CUSTOM, newOP(OP_NULL,0));
4338         op_free(o);
4339         RETVAL = TRUE;
4340     }
4341     OUTPUT:
4342         RETVAL
4343
4344 void
4345 test_sv_catpvf(SV *fmtsv)
4346     PREINIT:
4347         SV *sv;
4348         char *fmt;
4349     CODE:
4350         fmt = SvPV_nolen(fmtsv);
4351         sv = sv_2mortal(newSVpvn("", 0));
4352         sv_catpvf(sv, fmt, 5, 6, 7, 8);
4353
4354 void
4355 load_module(flags, name, ...)
4356     U32 flags
4357     SV *name
4358 CODE:
4359     if (items == 2) {
4360         Perl_load_module(aTHX_ flags, SvREFCNT_inc(name), NULL);
4361     } else if (items == 3) {
4362         Perl_load_module(aTHX_ flags, SvREFCNT_inc(name), SvREFCNT_inc(ST(2)));
4363     } else
4364         Perl_croak(aTHX_ "load_module can't yet support %" IVdf " items",
4365                           (IV)items);
4366
4367 SV *
4368 string_without_null(SV *sv)
4369     CODE:
4370     {
4371         STRLEN len;
4372         const char *s = SvPV(sv, len);
4373         RETVAL = newSVpvn_flags(s, len, SvUTF8(sv));
4374         *SvEND(RETVAL) = 0xff;
4375     }
4376     OUTPUT:
4377         RETVAL
4378
4379 CV *
4380 get_cv(SV *sv)
4381     CODE:
4382     {
4383         STRLEN len;
4384         const char *s = SvPV(sv, len);
4385         RETVAL = get_cvn_flags(s, len, 0);
4386     }
4387     OUTPUT:
4388         RETVAL
4389
4390 CV *
4391 get_cv_flags(SV *sv, UV flags)
4392     CODE:
4393     {
4394         STRLEN len;
4395         const char *s = SvPV(sv, len);
4396         RETVAL = get_cvn_flags(s, len, flags);
4397     }
4398     OUTPUT:
4399         RETVAL
4400
4401 PerlIO *
4402 PerlIO_stderr()
4403
4404 OutputStream
4405 PerlIO_stdout()
4406
4407 InputStream
4408 PerlIO_stdin()
4409
4410 #undef FILE
4411 #define FILE NativeFile
4412
4413 FILE *
4414 PerlIO_exportFILE(PerlIO *f, const char *mode)
4415
4416 MODULE = XS::APItest PACKAGE = XS::APItest::AUTOLOADtest
4417
4418 int
4419 AUTOLOAD(...)
4420   INIT:
4421     SV* comms;
4422     SV* class_and_method;
4423   CODE:
4424     PERL_UNUSED_ARG(items);
4425     class_and_method = GvSV(CvGV(cv));
4426     comms = get_sv("main::the_method", 1);
4427     if (class_and_method == NULL) {
4428       RETVAL = 1;
4429     } else if (!SvOK(class_and_method)) {
4430       RETVAL = 2;
4431     } else if (!SvPOK(class_and_method)) {
4432       RETVAL = 3;
4433     } else {
4434       sv_setsv(comms, class_and_method);
4435       RETVAL = 0;
4436     }
4437   OUTPUT: RETVAL
4438
4439
4440 MODULE = XS::APItest            PACKAGE = XS::APItest::Magic
4441
4442 PROTOTYPES: DISABLE
4443
4444 void
4445 sv_magic_foo(SV *sv, SV *thingy)
4446 ALIAS:
4447     sv_magic_bar = 1
4448 CODE:
4449     sv_magicext(SvRV(sv), NULL, PERL_MAGIC_ext, ix ? &vtbl_bar : &vtbl_foo, (const char *)thingy, 0);
4450
4451 SV *
4452 mg_find_foo(SV *sv)
4453 ALIAS:
4454     mg_find_bar = 1
4455 CODE:
4456     MAGIC *mg = mg_findext(SvRV(sv), PERL_MAGIC_ext, ix ? &vtbl_bar : &vtbl_foo);
4457     RETVAL = mg ? SvREFCNT_inc((SV *)mg->mg_ptr) : &PL_sv_undef;
4458 OUTPUT:
4459     RETVAL
4460
4461 void
4462 sv_unmagic_foo(SV *sv)
4463 ALIAS:
4464     sv_unmagic_bar = 1
4465 CODE:
4466     sv_unmagicext(SvRV(sv), PERL_MAGIC_ext, ix ? &vtbl_bar : &vtbl_foo);
4467
4468 void
4469 sv_magic(SV *sv, SV *thingy)
4470 CODE:
4471     sv_magic(SvRV(sv), NULL, PERL_MAGIC_ext, (const char *)thingy, 0);
4472
4473 UV
4474 test_get_vtbl()
4475     PREINIT:
4476         MGVTBL *have;
4477         MGVTBL *want;
4478     CODE:
4479 #define test_get_this_vtable(name) \
4480         want = (MGVTBL*)CAT2(&PL_vtbl_, name); \
4481         have = get_vtbl(CAT2(want_vtbl_, name)); \
4482         if (have != want) \
4483             croak("fail %p!=%p for get_vtbl(want_vtbl_" STRINGIFY(name) ") at " __FILE__ " line %d", have, want, __LINE__)
4484
4485         test_get_this_vtable(sv);
4486         test_get_this_vtable(env);
4487         test_get_this_vtable(envelem);
4488         test_get_this_vtable(sigelem);
4489         test_get_this_vtable(pack);
4490         test_get_this_vtable(packelem);
4491         test_get_this_vtable(dbline);
4492         test_get_this_vtable(isa);
4493         test_get_this_vtable(isaelem);
4494         test_get_this_vtable(arylen);
4495         test_get_this_vtable(mglob);
4496         test_get_this_vtable(nkeys);
4497         test_get_this_vtable(taint);
4498         test_get_this_vtable(substr);
4499         test_get_this_vtable(vec);
4500         test_get_this_vtable(pos);
4501         test_get_this_vtable(bm);
4502         test_get_this_vtable(fm);
4503         test_get_this_vtable(uvar);
4504         test_get_this_vtable(defelem);
4505         test_get_this_vtable(regexp);
4506         test_get_this_vtable(regdata);
4507         test_get_this_vtable(regdatum);
4508 #ifdef USE_LOCALE_COLLATE
4509         test_get_this_vtable(collxfrm);
4510 #endif
4511         test_get_this_vtable(backref);
4512         test_get_this_vtable(utf8);
4513
4514         RETVAL = PTR2UV(get_vtbl(-1));
4515     OUTPUT:
4516         RETVAL
4517
4518
4519     # attach ext magic to the SV pointed to by rsv that only has set magic,
4520     # where that magic's job is to increment thingy
4521
4522 void
4523 sv_magic_myset(SV *rsv, SV *thingy)
4524 CODE:
4525     sv_magicext(SvRV(rsv), NULL, PERL_MAGIC_ext, &vtbl_myset,
4526         (const char *)thingy, 0);
4527
4528
4529
4530 bool
4531 test_isBLANK_uni(UV ord)
4532     CODE:
4533         RETVAL = isBLANK_uni(ord);
4534     OUTPUT:
4535         RETVAL
4536
4537 bool
4538 test_isBLANK_uvchr(UV ord)
4539     CODE:
4540         RETVAL = isBLANK_uvchr(ord);
4541     OUTPUT:
4542         RETVAL
4543
4544 bool
4545 test_isBLANK_LC_uvchr(UV ord)
4546     CODE:
4547         RETVAL = isBLANK_LC_uvchr(ord);
4548     OUTPUT:
4549         RETVAL
4550
4551 bool
4552 test_isBLANK(UV ord)
4553     CODE:
4554         RETVAL = isBLANK(ord);
4555     OUTPUT:
4556         RETVAL
4557
4558 bool
4559 test_isBLANK_A(UV ord)
4560     CODE:
4561         RETVAL = isBLANK_A(ord);
4562     OUTPUT:
4563         RETVAL
4564
4565 bool
4566 test_isBLANK_L1(UV ord)
4567     CODE:
4568         RETVAL = isBLANK_L1(ord);
4569     OUTPUT:
4570         RETVAL
4571
4572 bool
4573 test_isBLANK_LC(UV ord)
4574     CODE:
4575         RETVAL = isBLANK_LC(ord);
4576     OUTPUT:
4577         RETVAL
4578
4579 bool
4580 test_isBLANK_utf8(U8 * p, int type)
4581     PREINIT:
4582         const U8 * e;
4583     CODE:
4584
4585         /* In this function and those that follow, the boolean 'type'
4586          * indicates if to pass a malformed UTF-8 string to the tested macro
4587          * (malformed by making it too short) */
4588         if (type >= 0) {
4589             e = p + UTF8SKIP(p) - type;
4590             RETVAL = isBLANK_utf8_safe(p, e);
4591         }
4592         else {
4593             RETVAL = isBLANK_utf8(p);
4594         }
4595     OUTPUT:
4596         RETVAL
4597
4598 bool
4599 test_isBLANK_LC_utf8(U8 * p, int type)
4600     PREINIT:
4601         const U8 * e;
4602     CODE:
4603         if (type >= 0) {
4604             e = p + UTF8SKIP(p) - type;
4605             RETVAL = isBLANK_LC_utf8_safe(p, e);
4606         }
4607         else {
4608             RETVAL = isBLANK_LC_utf8(p);
4609         }
4610     OUTPUT:
4611         RETVAL
4612
4613 bool
4614 test_isVERTWS_uni(UV ord)
4615     CODE:
4616         RETVAL = isVERTWS_uni(ord);
4617     OUTPUT:
4618         RETVAL
4619
4620 bool
4621 test_isVERTWS_uvchr(UV ord)
4622     CODE:
4623         RETVAL = isVERTWS_uvchr(ord);
4624     OUTPUT:
4625         RETVAL
4626
4627 bool
4628 test_isVERTWS_utf8(U8 * p, int type)
4629     PREINIT:
4630         const U8 * e;
4631     CODE:
4632         if (type >= 0) {
4633             e = p + UTF8SKIP(p) - type;
4634             RETVAL = isVERTWS_utf8_safe(p, e);
4635         }
4636         else {
4637             RETVAL = isVERTWS_utf8(p);
4638         }
4639     OUTPUT:
4640         RETVAL
4641
4642 bool
4643 test_isUPPER_uni(UV ord)
4644     CODE:
4645         RETVAL = isUPPER_uni(ord);
4646     OUTPUT:
4647         RETVAL
4648
4649 bool
4650 test_isUPPER_uvchr(UV ord)
4651     CODE:
4652         RETVAL = isUPPER_uvchr(ord);
4653     OUTPUT:
4654         RETVAL
4655
4656 bool
4657 test_isUPPER_LC_uvchr(UV ord)
4658     CODE:
4659         RETVAL = isUPPER_LC_uvchr(ord);
4660     OUTPUT:
4661         RETVAL
4662
4663 bool
4664 test_isUPPER(UV ord)
4665     CODE:
4666         RETVAL = isUPPER(ord);
4667     OUTPUT:
4668         RETVAL
4669
4670 bool
4671 test_isUPPER_A(UV ord)
4672     CODE:
4673         RETVAL = isUPPER_A(ord);
4674     OUTPUT:
4675         RETVAL
4676
4677 bool
4678 test_isUPPER_L1(UV ord)
4679     CODE:
4680         RETVAL = isUPPER_L1(ord);
4681     OUTPUT:
4682         RETVAL
4683
4684 bool
4685 test_isUPPER_LC(UV ord)
4686     CODE:
4687         RETVAL = isUPPER_LC(ord);
4688     OUTPUT:
4689         RETVAL
4690
4691 bool
4692 test_isUPPER_utf8(U8 * p, int type)
4693     PREINIT:
4694         const U8 * e;
4695     CODE:
4696         if (type >= 0) {
4697             e = p + UTF8SKIP(p) - type;