Silly Nick - change 32804 missed updating the list of global functions.
[perl.git] / universal.c
1 /*    universal.c
2  *
3  *    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
4  *    2005, 2006, 2007 by Larry Wall and others
5  *
6  *    You may distribute under the terms of either the GNU General Public
7  *    License or the Artistic License, as specified in the README file.
8  *
9  */
10
11 /*
12  * "The roots of those mountains must be roots indeed; there must be
13  * great secrets buried there which have not been discovered since the
14  * beginning." --Gandalf, relating Gollum's story
15  */
16
17 /* This file contains the code that implements the functions in Perl's
18  * UNIVERSAL package, such as UNIVERSAL->can().
19  *
20  * It is also used to store XS functions that need to be present in
21  * miniperl for a lack of a better place to put them. It might be
22  * clever to move them to seperate XS files which would then be pulled
23  * in by some to-be-written build process.
24  */
25
26 #include "EXTERN.h"
27 #define PERL_IN_UNIVERSAL_C
28 #include "perl.h"
29
30 #ifdef USE_PERLIO
31 #include "perliol.h" /* For the PERLIO_F_XXX */
32 #endif
33
34 /*
35  * Contributed by Graham Barr  <Graham.Barr@tiuk.ti.com>
36  * The main guts of traverse_isa was actually copied from gv_fetchmeth
37  */
38
39 STATIC bool
40 S_isa_lookup(pTHX_ HV *stash, const char * const name, const HV* const name_stash)
41 {
42     dVAR;
43     AV* stash_linear_isa;
44     SV** svp;
45     const char *hvname;
46     I32 items;
47
48     /* A stash/class can go by many names (ie. User == main::User), so 
49        we compare the stash itself just in case */
50     if (name_stash && ((const HV *)stash == name_stash))
51         return TRUE;
52
53     hvname = HvNAME_get(stash);
54
55     if (strEQ(hvname, name))
56         return TRUE;
57
58     if (strEQ(name, "UNIVERSAL"))
59         return TRUE;
60
61     stash_linear_isa = mro_get_linear_isa(stash);
62     svp = AvARRAY(stash_linear_isa) + 1;
63     items = AvFILLp(stash_linear_isa);
64     while (items--) {
65         SV* const basename_sv = *svp++;
66         HV* const basestash = gv_stashsv(basename_sv, 0);
67         if (!basestash) {
68             if (ckWARN(WARN_SYNTAX))
69                 Perl_warner(aTHX_ packWARN(WARN_SYNTAX),
70                             "Can't locate package %"SVf" for the parents of %s",
71                             SVfARG(basename_sv), hvname);
72             continue;
73         }
74         if(name_stash == basestash || strEQ(name, SvPVX(basename_sv)))
75             return TRUE;
76     }
77
78     return FALSE;
79 }
80
81 /*
82 =head1 SV Manipulation Functions
83
84 =for apidoc sv_derived_from
85
86 Returns a boolean indicating whether the SV is derived from the specified class
87 I<at the C level>.  To check derivation at the Perl level, call C<isa()> as a
88 normal Perl method.
89
90 =cut
91 */
92
93 bool
94 Perl_sv_derived_from(pTHX_ SV *sv, const char *name)
95 {
96     dVAR;
97     HV *stash;
98
99     SvGETMAGIC(sv);
100
101     if (SvROK(sv)) {
102         const char *type;
103         sv = SvRV(sv);
104         type = sv_reftype(sv,0);
105         if (type && strEQ(type,name))
106             return TRUE;
107         stash = SvOBJECT(sv) ? SvSTASH(sv) : NULL;
108     }
109     else {
110         stash = gv_stashsv(sv, 0);
111     }
112
113     if (stash) {
114         HV * const name_stash = gv_stashpv(name, 0);
115         return isa_lookup(stash, name, name_stash);
116     }
117     else
118         return FALSE;
119
120 }
121
122 /*
123 =for apidoc sv_does
124
125 Returns a boolean indicating whether the SV performs a specific, named role.
126 The SV can be a Perl object or the name of a Perl class.
127
128 =cut
129 */
130
131 #include "XSUB.h"
132
133 bool
134 Perl_sv_does(pTHX_ SV *sv, const char *name)
135 {
136     const char *classname;
137     bool does_it;
138     SV *methodname;
139
140     dSP;
141     ENTER;
142     SAVETMPS;
143
144     SvGETMAGIC(sv);
145
146     if (!SvOK(sv) || !(SvROK(sv) || (SvPOK(sv) && SvCUR(sv))
147                 || (SvGMAGICAL(sv) && SvPOKp(sv) && SvCUR(sv))))
148         return FALSE;
149
150     if (sv_isobject(sv)) {
151         classname = sv_reftype(SvRV(sv),TRUE);
152     } else {
153         classname = SvPV_nolen(sv);
154     }
155
156     if (strEQ(name,classname))
157         return TRUE;
158
159     PUSHMARK(SP);
160     XPUSHs(sv);
161     XPUSHs(sv_2mortal(newSVpv(name, 0)));
162     PUTBACK;
163
164     methodname = sv_2mortal(newSVpvs("isa"));
165     /* ugly hack: use the SvSCREAM flag so S_method_common
166      * can figure out we're calling DOES() and not isa(),
167      * and report eventual errors correctly. --rgs */
168     SvSCREAM_on(methodname);
169     call_sv(methodname, G_SCALAR | G_METHOD);
170     SPAGAIN;
171
172     does_it = SvTRUE( TOPs );
173     FREETMPS;
174     LEAVE;
175
176     return does_it;
177 }
178
179 PERL_XS_EXPORT_C void XS_UNIVERSAL_isa(pTHX_ CV *cv);
180 PERL_XS_EXPORT_C void XS_UNIVERSAL_can(pTHX_ CV *cv);
181 PERL_XS_EXPORT_C void XS_UNIVERSAL_DOES(pTHX_ CV *cv);
182 PERL_XS_EXPORT_C void XS_UNIVERSAL_VERSION(pTHX_ CV *cv);
183 XS(XS_version_new);
184 XS(XS_version_stringify);
185 XS(XS_version_numify);
186 XS(XS_version_normal);
187 XS(XS_version_vcmp);
188 XS(XS_version_boolean);
189 #ifdef HASATTRIBUTE_NORETURN
190 XS(XS_version_noop) __attribute__noreturn__;
191 #else
192 XS(XS_version_noop);
193 #endif
194 XS(XS_version_is_alpha);
195 XS(XS_version_qv);
196 XS(XS_utf8_is_utf8);
197 XS(XS_utf8_valid);
198 XS(XS_utf8_encode);
199 XS(XS_utf8_decode);
200 XS(XS_utf8_upgrade);
201 XS(XS_utf8_downgrade);
202 XS(XS_utf8_unicode_to_native);
203 XS(XS_utf8_native_to_unicode);
204 XS(XS_Internals_SvREADONLY);
205 XS(XS_Internals_SvREFCNT);
206 XS(XS_Internals_hv_clear_placehold);
207 XS(XS_PerlIO_get_layers);
208 XS(XS_Internals_hash_seed);
209 XS(XS_Internals_rehash_seed);
210 XS(XS_Internals_HvREHASH);
211 XS(XS_Internals_inc_sub_generation);
212 XS(XS_re_is_regexp); 
213 XS(XS_re_regname);
214 XS(XS_re_regnames);
215 XS(XS_re_regnames_count);
216 XS(XS_Tie_Hash_NamedCapture_FETCH);
217 XS(XS_Tie_Hash_NamedCapture_STORE);
218 XS(XS_Tie_Hash_NamedCapture_DELETE);
219 XS(XS_Tie_Hash_NamedCapture_CLEAR);
220 XS(XS_Tie_Hash_NamedCapture_EXISTS);
221 XS(XS_Tie_Hash_NamedCapture_FIRSTK);
222 XS(XS_Tie_Hash_NamedCapture_NEXTK);
223 XS(XS_Tie_Hash_NamedCapture_SCALAR);
224 XS(XS_Tie_Hash_NamedCapture_flags);
225
226 void
227 Perl_boot_core_UNIVERSAL(pTHX)
228 {
229     dVAR;
230     static const char file[] = __FILE__;
231
232     newXS("UNIVERSAL::isa",             XS_UNIVERSAL_isa,         file);
233     newXS("UNIVERSAL::can",             XS_UNIVERSAL_can,         file);
234     newXS("UNIVERSAL::DOES",            XS_UNIVERSAL_DOES,        file);
235     newXS("UNIVERSAL::VERSION",         XS_UNIVERSAL_VERSION,     file);
236     {
237         /* register the overloading (type 'A') magic */
238         PL_amagic_generation++;
239         /* Make it findable via fetchmethod */
240         newXS("version::()", XS_version_noop, file);
241         newXS("version::new", XS_version_new, file);
242         newXS("version::(\"\"", XS_version_stringify, file);
243         newXS("version::stringify", XS_version_stringify, file);
244         newXS("version::(0+", XS_version_numify, file);
245         newXS("version::numify", XS_version_numify, file);
246         newXS("version::normal", XS_version_normal, file);
247         newXS("version::(cmp", XS_version_vcmp, file);
248         newXS("version::(<=>", XS_version_vcmp, file);
249         newXS("version::vcmp", XS_version_vcmp, file);
250         newXS("version::(bool", XS_version_boolean, file);
251         newXS("version::boolean", XS_version_boolean, file);
252         newXS("version::(nomethod", XS_version_noop, file);
253         newXS("version::noop", XS_version_noop, file);
254         newXS("version::is_alpha", XS_version_is_alpha, file);
255         newXS("version::qv", XS_version_qv, file);
256     }
257     newXS("utf8::is_utf8", XS_utf8_is_utf8, file);
258     newXS("utf8::valid", XS_utf8_valid, file);
259     newXS("utf8::encode", XS_utf8_encode, file);
260     newXS("utf8::decode", XS_utf8_decode, file);
261     newXS("utf8::upgrade", XS_utf8_upgrade, file);
262     newXS("utf8::downgrade", XS_utf8_downgrade, file);
263     newXS("utf8::native_to_unicode", XS_utf8_native_to_unicode, file);
264     newXS("utf8::unicode_to_native", XS_utf8_unicode_to_native, file);
265     newXSproto("Internals::SvREADONLY",XS_Internals_SvREADONLY, file, "\\[$%@];$");
266     newXSproto("Internals::SvREFCNT",XS_Internals_SvREFCNT, file, "\\[$%@];$");
267     newXSproto("Internals::hv_clear_placeholders",
268                XS_Internals_hv_clear_placehold, file, "\\%");
269     newXSproto("PerlIO::get_layers",
270                XS_PerlIO_get_layers, file, "*;@");
271     newXSproto("Internals::hash_seed",XS_Internals_hash_seed, file, "");
272     newXSproto("Internals::rehash_seed",XS_Internals_rehash_seed, file, "");
273     newXSproto("Internals::HvREHASH", XS_Internals_HvREHASH, file, "\\%");
274     newXSproto("re::is_regexp", XS_re_is_regexp, file, "$");
275     newXSproto("re::regname", XS_re_regname, file, ";$$");
276     newXSproto("re::regnames", XS_re_regnames, file, ";$");
277     newXSproto("re::regnames_count", XS_re_regnames_count, file, "");
278     newXS("Tie::Hash::NamedCapture::FETCH", XS_Tie_Hash_NamedCapture_FETCH, file);
279     newXS("Tie::Hash::NamedCapture::STORE", XS_Tie_Hash_NamedCapture_STORE, file);
280     newXS("Tie::Hash::NamedCapture::DELETE", XS_Tie_Hash_NamedCapture_DELETE, file);
281     newXS("Tie::Hash::NamedCapture::CLEAR", XS_Tie_Hash_NamedCapture_CLEAR, file);
282     newXS("Tie::Hash::NamedCapture::EXISTS", XS_Tie_Hash_NamedCapture_EXISTS, file);
283     newXS("Tie::Hash::NamedCapture::FIRSTKEY", XS_Tie_Hash_NamedCapture_FIRSTK, file);
284     newXS("Tie::Hash::NamedCapture::NEXTKEY", XS_Tie_Hash_NamedCapture_NEXTK, file);
285     newXS("Tie::Hash::NamedCapture::SCALAR", XS_Tie_Hash_NamedCapture_SCALAR, file);
286     newXS("Tie::Hash::NamedCapture::flags", XS_Tie_Hash_NamedCapture_flags, file);
287 }
288
289
290 XS(XS_UNIVERSAL_isa)
291 {
292     dVAR;
293     dXSARGS;
294     PERL_UNUSED_ARG(cv);
295
296     if (items != 2)
297         Perl_croak(aTHX_ "Usage: UNIVERSAL::isa(reference, kind)");
298     else {
299         SV * const sv = ST(0);
300         const char *name;
301
302         SvGETMAGIC(sv);
303
304         if (!SvOK(sv) || !(SvROK(sv) || (SvPOK(sv) && SvCUR(sv))
305                     || (SvGMAGICAL(sv) && SvPOKp(sv) && SvCUR(sv))))
306             XSRETURN_UNDEF;
307
308         name = SvPV_nolen_const(ST(1));
309
310         ST(0) = boolSV(sv_derived_from(sv, name));
311         XSRETURN(1);
312     }
313 }
314
315 XS(XS_UNIVERSAL_can)
316 {
317     dVAR;
318     dXSARGS;
319     SV   *sv;
320     const char *name;
321     SV   *rv;
322     HV   *pkg = NULL;
323     PERL_UNUSED_ARG(cv);
324
325     if (items != 2)
326         Perl_croak(aTHX_ "Usage: UNIVERSAL::can(object-ref, method)");
327
328     sv = ST(0);
329
330     SvGETMAGIC(sv);
331
332     if (!SvOK(sv) || !(SvROK(sv) || (SvPOK(sv) && SvCUR(sv))
333                 || (SvGMAGICAL(sv) && SvPOKp(sv) && SvCUR(sv))))
334         XSRETURN_UNDEF;
335
336     name = SvPV_nolen_const(ST(1));
337     rv = &PL_sv_undef;
338
339     if (SvROK(sv)) {
340         sv = (SV*)SvRV(sv);
341         if (SvOBJECT(sv))
342             pkg = SvSTASH(sv);
343     }
344     else {
345         pkg = gv_stashsv(sv, 0);
346     }
347
348     if (pkg) {
349         GV * const gv = gv_fetchmethod_autoload(pkg, name, FALSE);
350         if (gv && isGV(gv))
351             rv = sv_2mortal(newRV((SV*)GvCV(gv)));
352     }
353
354     ST(0) = rv;
355     XSRETURN(1);
356 }
357
358 XS(XS_UNIVERSAL_DOES)
359 {
360     dVAR;
361     dXSARGS;
362     PERL_UNUSED_ARG(cv);
363
364     if (items != 2)
365         Perl_croak(aTHX_ "Usage: invocant->DOES(kind)");
366     else {
367         SV * const sv = ST(0);
368         const char *name;
369
370         name = SvPV_nolen_const(ST(1));
371         if (sv_does( sv, name ))
372             XSRETURN_YES;
373
374         XSRETURN_NO;
375     }
376 }
377
378 XS(XS_UNIVERSAL_VERSION)
379 {
380     dVAR;
381     dXSARGS;
382     HV *pkg;
383     GV **gvp;
384     GV *gv;
385     SV *sv;
386     const char *undef;
387     PERL_UNUSED_ARG(cv);
388
389     if (SvROK(ST(0))) {
390         sv = (SV*)SvRV(ST(0));
391         if (!SvOBJECT(sv))
392             Perl_croak(aTHX_ "Cannot find version of an unblessed reference");
393         pkg = SvSTASH(sv);
394     }
395     else {
396         pkg = gv_stashsv(ST(0), 0);
397     }
398
399     gvp = pkg ? (GV**)hv_fetchs(pkg, "VERSION", FALSE) : NULL;
400
401     if (gvp && isGV(gv = *gvp) && (sv = GvSV(gv)) && SvOK(sv)) {
402         SV * const nsv = sv_newmortal();
403         sv_setsv(nsv, sv);
404         sv = nsv;
405         if ( !sv_derived_from(sv, "version"))
406             upg_version(sv, FALSE);
407         undef = NULL;
408     }
409     else {
410         sv = (SV*)&PL_sv_undef;
411         undef = "(undef)";
412     }
413
414     if (items > 1) {
415         SV *req = ST(1);
416
417         if (undef) {
418             if (pkg) {
419                 const char * const name = HvNAME_get(pkg);
420                 Perl_croak(aTHX_
421                            "%s does not define $%s::VERSION--version check failed",
422                            name, name);
423             } else {
424                 Perl_croak(aTHX_
425                              "%s defines neither package nor VERSION--version check failed",
426                              SvPVx_nolen_const(ST(0)) );
427              }
428         }
429
430         if ( !sv_derived_from(req, "version")) {
431             /* req may very well be R/O, so create a new object */
432             req = sv_2mortal( new_version(req) );
433         }
434
435         if ( vcmp( req, sv ) > 0 ) {
436             if ( hv_exists((HV*)SvRV(req), "qv", 2 ) ) {
437                 Perl_croak(aTHX_ "%s version %"SVf" required--"
438                        "this is only version %"SVf"", HvNAME_get(pkg),
439                        SVfARG(vnormal(req)),
440                        SVfARG(vnormal(sv)));
441             } else {
442                 Perl_croak(aTHX_ "%s version %"SVf" required--"
443                        "this is only version %"SVf"", HvNAME_get(pkg),
444                        SVfARG(vstringify(req)),
445                        SVfARG(vstringify(sv)));
446             }
447         }
448
449     }
450
451     if ( SvOK(sv) && sv_derived_from(sv, "version") ) {
452         ST(0) = vstringify(sv);
453     } else {
454         ST(0) = sv;
455     }
456
457     XSRETURN(1);
458 }
459
460 XS(XS_version_new)
461 {
462     dVAR;
463     dXSARGS;
464     PERL_UNUSED_ARG(cv);
465     if (items > 3)
466         Perl_croak(aTHX_ "Usage: version::new(class, version)");
467     SP -= items;
468     {
469         SV *vs = ST(1);
470         SV *rv;
471         const char * const classname =
472             sv_isobject(ST(0)) /* get the class if called as an object method */
473                 ? HvNAME(SvSTASH(SvRV(ST(0))))
474                 : (char *)SvPV_nolen(ST(0));
475
476         if ( items == 1 || vs == &PL_sv_undef ) { /* no param or explicit undef */
477             /* create empty object */
478             vs = sv_newmortal();
479             sv_setpvn(vs,"",0);
480         }
481         else if ( items == 3 ) {
482             vs = sv_newmortal();
483             Perl_sv_setpvf(aTHX_ vs,"v%s",SvPV_nolen_const(ST(2)));
484         }
485
486         rv = new_version(vs);
487         if ( strcmp(classname,"version") != 0 ) /* inherited new() */
488             sv_bless(rv, gv_stashpv(classname, GV_ADD));
489
490         PUSHs(sv_2mortal(rv));
491         PUTBACK;
492         return;
493     }
494 }
495
496 XS(XS_version_stringify)
497 {
498      dVAR;
499      dXSARGS;
500      PERL_UNUSED_ARG(cv);
501      if (items < 1)
502           Perl_croak(aTHX_ "Usage: version::stringify(lobj, ...)");
503      SP -= items;
504      {
505           SV *  lobj;
506
507           if (sv_derived_from(ST(0), "version")) {
508                lobj = SvRV(ST(0));
509           }
510           else
511                Perl_croak(aTHX_ "lobj is not of type version");
512
513           PUSHs(sv_2mortal(vstringify(lobj)));
514
515           PUTBACK;
516           return;
517      }
518 }
519
520 XS(XS_version_numify)
521 {
522      dVAR;
523      dXSARGS;
524      PERL_UNUSED_ARG(cv);
525      if (items < 1)
526           Perl_croak(aTHX_ "Usage: version::numify(lobj, ...)");
527      SP -= items;
528      {
529           SV *  lobj;
530
531           if (sv_derived_from(ST(0), "version")) {
532                lobj = SvRV(ST(0));
533           }
534           else
535                Perl_croak(aTHX_ "lobj is not of type version");
536
537           PUSHs(sv_2mortal(vnumify(lobj)));
538
539           PUTBACK;
540           return;
541      }
542 }
543
544 XS(XS_version_normal)
545 {
546      dVAR;
547      dXSARGS;
548      PERL_UNUSED_ARG(cv);
549      if (items < 1)
550           Perl_croak(aTHX_ "Usage: version::normal(lobj, ...)");
551      SP -= items;
552      {
553           SV *  lobj;
554
555           if (sv_derived_from(ST(0), "version")) {
556                lobj = SvRV(ST(0));
557           }
558           else
559                Perl_croak(aTHX_ "lobj is not of type version");
560
561           PUSHs(sv_2mortal(vnormal(lobj)));
562
563           PUTBACK;
564           return;
565      }
566 }
567
568 XS(XS_version_vcmp)
569 {
570      dVAR;
571      dXSARGS;
572      PERL_UNUSED_ARG(cv);
573      if (items < 1)
574           Perl_croak(aTHX_ "Usage: version::vcmp(lobj, ...)");
575      SP -= items;
576      {
577           SV *  lobj;
578
579           if (sv_derived_from(ST(0), "version")) {
580                lobj = SvRV(ST(0));
581           }
582           else
583                Perl_croak(aTHX_ "lobj is not of type version");
584
585           {
586                SV       *rs;
587                SV       *rvs;
588                SV * robj = ST(1);
589                const IV  swap = (IV)SvIV(ST(2));
590
591                if ( ! sv_derived_from(robj, "version") )
592                {
593                     robj = new_version(robj);
594                }
595                rvs = SvRV(robj);
596
597                if ( swap )
598                {
599                     rs = newSViv(vcmp(rvs,lobj));
600                }
601                else
602                {
603                     rs = newSViv(vcmp(lobj,rvs));
604                }
605
606                PUSHs(sv_2mortal(rs));
607           }
608
609           PUTBACK;
610           return;
611      }
612 }
613
614 XS(XS_version_boolean)
615 {
616     dVAR;
617     dXSARGS;
618     PERL_UNUSED_ARG(cv);
619     if (items < 1)
620         Perl_croak(aTHX_ "Usage: version::boolean(lobj, ...)");
621     SP -= items;
622     if (sv_derived_from(ST(0), "version")) {
623         SV * const lobj = SvRV(ST(0));
624         SV * const rs = newSViv( vcmp(lobj,new_version(newSVpvs("0"))) );
625         PUSHs(sv_2mortal(rs));
626         PUTBACK;
627         return;
628     }
629     else
630         Perl_croak(aTHX_ "lobj is not of type version");
631 }
632
633 XS(XS_version_noop)
634 {
635     dVAR;
636     dXSARGS;
637     PERL_UNUSED_ARG(cv);
638     if (items < 1)
639         Perl_croak(aTHX_ "Usage: version::noop(lobj, ...)");
640     if (sv_derived_from(ST(0), "version"))
641         Perl_croak(aTHX_ "operation not supported with version object");
642     else
643         Perl_croak(aTHX_ "lobj is not of type version");
644 #ifndef HASATTRIBUTE_NORETURN
645     XSRETURN_EMPTY;
646 #endif
647 }
648
649 XS(XS_version_is_alpha)
650 {
651     dVAR;
652     dXSARGS;
653     PERL_UNUSED_ARG(cv);
654     if (items != 1)
655         Perl_croak(aTHX_ "Usage: version::is_alpha(lobj)");
656     SP -= items;
657     if (sv_derived_from(ST(0), "version")) {
658         SV * const lobj = ST(0);
659         if ( hv_exists((HV*)SvRV(lobj), "alpha", 5 ) )
660             XSRETURN_YES;
661         else
662             XSRETURN_NO;
663         PUTBACK;
664         return;
665     }
666     else
667         Perl_croak(aTHX_ "lobj is not of type version");
668 }
669
670 XS(XS_version_qv)
671 {
672     dVAR;
673     dXSARGS;
674     PERL_UNUSED_ARG(cv);
675     if (items != 1)
676         Perl_croak(aTHX_ "Usage: version::qv(ver)");
677     SP -= items;
678     {
679         SV *    ver = ST(0);
680         if ( !SvVOK(ver) ) { /* only need to do with if not already v-string */
681             SV * const rv = sv_newmortal();
682             sv_setsv(rv,ver); /* make a duplicate */
683             upg_version(rv, TRUE);
684             PUSHs(rv);
685         }
686         else
687         {
688             PUSHs(sv_2mortal(new_version(ver)));
689         }
690
691         PUTBACK;
692         return;
693     }
694 }
695
696 XS(XS_utf8_is_utf8)
697 {
698      dVAR;
699      dXSARGS;
700      PERL_UNUSED_ARG(cv);
701      if (items != 1)
702           Perl_croak(aTHX_ "Usage: utf8::is_utf8(sv)");
703      else {
704         const SV * const sv = ST(0);
705             if (SvUTF8(sv))
706                 XSRETURN_YES;
707             else
708                 XSRETURN_NO;
709      }
710      XSRETURN_EMPTY;
711 }
712
713 XS(XS_utf8_valid)
714 {
715      dVAR;
716      dXSARGS;
717      PERL_UNUSED_ARG(cv);
718      if (items != 1)
719           Perl_croak(aTHX_ "Usage: utf8::valid(sv)");
720     else {
721         SV * const sv = ST(0);
722         STRLEN len;
723         const char * const s = SvPV_const(sv,len);
724         if (!SvUTF8(sv) || is_utf8_string((const U8*)s,len))
725             XSRETURN_YES;
726         else
727             XSRETURN_NO;
728     }
729      XSRETURN_EMPTY;
730 }
731
732 XS(XS_utf8_encode)
733 {
734     dVAR;
735     dXSARGS;
736     PERL_UNUSED_ARG(cv);
737     if (items != 1)
738         Perl_croak(aTHX_ "Usage: utf8::encode(sv)");
739     sv_utf8_encode(ST(0));
740     XSRETURN_EMPTY;
741 }
742
743 XS(XS_utf8_decode)
744 {
745     dVAR;
746     dXSARGS;
747     PERL_UNUSED_ARG(cv);
748     if (items != 1)
749         Perl_croak(aTHX_ "Usage: utf8::decode(sv)");
750     else {
751         SV * const sv = ST(0);
752         const bool RETVAL = sv_utf8_decode(sv);
753         ST(0) = boolSV(RETVAL);
754         sv_2mortal(ST(0));
755     }
756     XSRETURN(1);
757 }
758
759 XS(XS_utf8_upgrade)
760 {
761     dVAR;
762     dXSARGS;
763     PERL_UNUSED_ARG(cv);
764     if (items != 1)
765         Perl_croak(aTHX_ "Usage: utf8::upgrade(sv)");
766     else {
767         SV * const sv = ST(0);
768         STRLEN  RETVAL;
769         dXSTARG;
770
771         RETVAL = sv_utf8_upgrade(sv);
772         XSprePUSH; PUSHi((IV)RETVAL);
773     }
774     XSRETURN(1);
775 }
776
777 XS(XS_utf8_downgrade)
778 {
779     dVAR;
780     dXSARGS;
781     PERL_UNUSED_ARG(cv);
782     if (items < 1 || items > 2)
783         Perl_croak(aTHX_ "Usage: utf8::downgrade(sv, failok=0)");
784     else {
785         SV * const sv = ST(0);
786         const bool failok = (items < 2) ? 0 : (int)SvIV(ST(1));
787         const bool RETVAL = sv_utf8_downgrade(sv, failok);
788
789         ST(0) = boolSV(RETVAL);
790         sv_2mortal(ST(0));
791     }
792     XSRETURN(1);
793 }
794
795 XS(XS_utf8_native_to_unicode)
796 {
797  dVAR;
798  dXSARGS;
799  const UV uv = SvUV(ST(0));
800  PERL_UNUSED_ARG(cv);
801
802  if (items > 1)
803      Perl_croak(aTHX_ "Usage: utf8::native_to_unicode(sv)");
804
805  ST(0) = sv_2mortal(newSViv(NATIVE_TO_UNI(uv)));
806  XSRETURN(1);
807 }
808
809 XS(XS_utf8_unicode_to_native)
810 {
811  dVAR;
812  dXSARGS;
813  const UV uv = SvUV(ST(0));
814  PERL_UNUSED_ARG(cv);
815
816  if (items > 1)
817      Perl_croak(aTHX_ "Usage: utf8::unicode_to_native(sv)");
818
819  ST(0) = sv_2mortal(newSViv(UNI_TO_NATIVE(uv)));
820  XSRETURN(1);
821 }
822
823 XS(XS_Internals_SvREADONLY)     /* This is dangerous stuff. */
824 {
825     dVAR;
826     dXSARGS;
827     SV * const sv = SvRV(ST(0));
828     PERL_UNUSED_ARG(cv);
829
830     if (items == 1) {
831          if (SvREADONLY(sv))
832              XSRETURN_YES;
833          else
834              XSRETURN_NO;
835     }
836     else if (items == 2) {
837         if (SvTRUE(ST(1))) {
838             SvREADONLY_on(sv);
839             XSRETURN_YES;
840         }
841         else {
842             /* I hope you really know what you are doing. */
843             SvREADONLY_off(sv);
844             XSRETURN_NO;
845         }
846     }
847     XSRETURN_UNDEF; /* Can't happen. */
848 }
849
850 XS(XS_Internals_SvREFCNT)       /* This is dangerous stuff. */
851 {
852     dVAR;
853     dXSARGS;
854     SV * const sv = SvRV(ST(0));
855     PERL_UNUSED_ARG(cv);
856
857     if (items == 1)
858          XSRETURN_IV(SvREFCNT(sv) - 1); /* Minus the ref created for us. */
859     else if (items == 2) {
860          /* I hope you really know what you are doing. */
861          SvREFCNT(sv) = SvIV(ST(1));
862          XSRETURN_IV(SvREFCNT(sv));
863     }
864     XSRETURN_UNDEF; /* Can't happen. */
865 }
866
867 XS(XS_Internals_hv_clear_placehold)
868 {
869     dVAR;
870     dXSARGS;
871     PERL_UNUSED_ARG(cv);
872
873     if (items != 1)
874         Perl_croak(aTHX_ "Usage: UNIVERSAL::hv_clear_placeholders(hv)");
875     else {
876         HV * const hv = (HV *) SvRV(ST(0));
877         hv_clear_placeholders(hv);
878         XSRETURN(0);
879     }
880 }
881
882 XS(XS_PerlIO_get_layers)
883 {
884     dVAR;
885     dXSARGS;
886     PERL_UNUSED_ARG(cv);
887     if (items < 1 || items % 2 == 0)
888         Perl_croak(aTHX_ "Usage: PerlIO_get_layers(filehandle[,args])");
889 #ifdef USE_PERLIO
890     {
891         SV *    sv;
892         GV *    gv;
893         IO *    io;
894         bool    input = TRUE;
895         bool    details = FALSE;
896
897         if (items > 1) {
898              SV * const *svp;
899              for (svp = MARK + 2; svp <= SP; svp += 2) {
900                   SV * const * const varp = svp;
901                   SV * const * const valp = svp + 1;
902                   STRLEN klen;
903                   const char * const key = SvPV_const(*varp, klen);
904
905                   switch (*key) {
906                   case 'i':
907                        if (klen == 5 && memEQ(key, "input", 5)) {
908                             input = SvTRUE(*valp);
909                             break;
910                        }
911                        goto fail;
912                   case 'o': 
913                        if (klen == 6 && memEQ(key, "output", 6)) {
914                             input = !SvTRUE(*valp);
915                             break;
916                        }
917                        goto fail;
918                   case 'd':
919                        if (klen == 7 && memEQ(key, "details", 7)) {
920                             details = SvTRUE(*valp);
921                             break;
922                        }
923                        goto fail;
924                   default:
925                   fail:
926                        Perl_croak(aTHX_
927                                   "get_layers: unknown argument '%s'",
928                                   key);
929                   }
930              }
931
932              SP -= (items - 1);
933         }
934
935         sv = POPs;
936         gv = (GV*)sv;
937
938         if (!isGV(sv)) {
939              if (SvROK(sv) && isGV(SvRV(sv)))
940                   gv = (GV*)SvRV(sv);
941              else if (SvPOKp(sv))
942                   gv = gv_fetchsv(sv, 0, SVt_PVIO);
943         }
944
945         if (gv && (io = GvIO(gv))) {
946              dTARGET;
947              AV* const av = PerlIO_get_layers(aTHX_ input ?
948                                         IoIFP(io) : IoOFP(io));
949              I32 i;
950              const I32 last = av_len(av);
951              I32 nitem = 0;
952              
953              for (i = last; i >= 0; i -= 3) {
954                   SV * const * const namsvp = av_fetch(av, i - 2, FALSE);
955                   SV * const * const argsvp = av_fetch(av, i - 1, FALSE);
956                   SV * const * const flgsvp = av_fetch(av, i,     FALSE);
957
958                   const bool namok = namsvp && *namsvp && SvPOK(*namsvp);
959                   const bool argok = argsvp && *argsvp && SvPOK(*argsvp);
960                   const bool flgok = flgsvp && *flgsvp && SvIOK(*flgsvp);
961
962                   if (details) {
963                        XPUSHs(namok
964                               ? newSVpvn(SvPVX_const(*namsvp), SvCUR(*namsvp))
965                               : &PL_sv_undef);
966                        XPUSHs(argok
967                               ? newSVpvn(SvPVX_const(*argsvp), SvCUR(*argsvp))
968                               : &PL_sv_undef);
969                        if (flgok)
970                             XPUSHi(SvIVX(*flgsvp));
971                        else
972                             XPUSHs(&PL_sv_undef);
973                        nitem += 3;
974                   }
975                   else {
976                        if (namok && argok)
977                             XPUSHs(Perl_newSVpvf(aTHX_ "%"SVf"(%"SVf")",
978                                                  SVfARG(*namsvp),
979                                                  SVfARG(*argsvp)));
980                        else if (namok)
981                             XPUSHs(Perl_newSVpvf(aTHX_ "%"SVf,
982                                                  SVfARG(*namsvp)));
983                        else
984                             XPUSHs(&PL_sv_undef);
985                        nitem++;
986                        if (flgok) {
987                             const IV flags = SvIVX(*flgsvp);
988
989                             if (flags & PERLIO_F_UTF8) {
990                                  XPUSHs(newSVpvs("utf8"));
991                                  nitem++;
992                             }
993                        }
994                   }
995              }
996
997              SvREFCNT_dec(av);
998
999              XSRETURN(nitem);
1000         }
1001     }
1002 #endif
1003
1004     XSRETURN(0);
1005 }
1006
1007 XS(XS_Internals_hash_seed)
1008 {
1009     dVAR;
1010     /* Using dXSARGS would also have dITEM and dSP,
1011      * which define 2 unused local variables.  */
1012     dAXMARK;
1013     PERL_UNUSED_ARG(cv);
1014     PERL_UNUSED_VAR(mark);
1015     XSRETURN_UV(PERL_HASH_SEED);
1016 }
1017
1018 XS(XS_Internals_rehash_seed)
1019 {
1020     dVAR;
1021     /* Using dXSARGS would also have dITEM and dSP,
1022      * which define 2 unused local variables.  */
1023     dAXMARK;
1024     PERL_UNUSED_ARG(cv);
1025     PERL_UNUSED_VAR(mark);
1026     XSRETURN_UV(PL_rehash_seed);
1027 }
1028
1029 XS(XS_Internals_HvREHASH)       /* Subject to change  */
1030 {
1031     dVAR;
1032     dXSARGS;
1033     PERL_UNUSED_ARG(cv);
1034     if (SvROK(ST(0))) {
1035         const HV * const hv = (HV *) SvRV(ST(0));
1036         if (items == 1 && SvTYPE(hv) == SVt_PVHV) {
1037             if (HvREHASH(hv))
1038                 XSRETURN_YES;
1039             else
1040                 XSRETURN_NO;
1041         }
1042     }
1043     Perl_croak(aTHX_ "Internals::HvREHASH $hashref");
1044 }
1045
1046 XS(XS_re_is_regexp)
1047 {
1048     dVAR; 
1049     dXSARGS;
1050     PERL_UNUSED_VAR(cv);
1051
1052     if (items != 1)
1053        Perl_croak(aTHX_ "Usage: %s(%s)", "re::is_regexp", "sv");
1054
1055     SP -= items;
1056
1057     if (SvRXOK(ST(0))) {
1058         XSRETURN_YES;
1059     } else {
1060         XSRETURN_NO;
1061     }
1062 }
1063
1064 XS(XS_re_regnames_count)
1065 {
1066     REGEXP *rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1067     SV * ret;
1068     dVAR; 
1069     dXSARGS;
1070     PERL_UNUSED_ARG(cv);
1071
1072     if (items != 0)
1073        Perl_croak(aTHX_ "Usage: %s(%s)", "re::regnames_count", "");
1074
1075     SP -= items;
1076
1077     if (!rx)
1078         XSRETURN_UNDEF;
1079
1080     ret = CALLREG_NAMED_BUFF_COUNT(rx);
1081
1082     SPAGAIN;
1083
1084     if (ret) {
1085         XPUSHs(ret);
1086         PUTBACK;
1087         return;
1088     } else {
1089         XSRETURN_UNDEF;
1090     }
1091 }
1092
1093 XS(XS_re_regname)
1094 {
1095     dVAR;
1096     dXSARGS;
1097     REGEXP * rx;
1098     U32 flags;
1099     SV * ret;
1100     PERL_UNUSED_ARG(cv);
1101
1102     if (items < 1 || items > 2)
1103         Perl_croak(aTHX_ "Usage: %s(%s)", "re::regname", "name[, all ]");
1104
1105     SP -= items;
1106
1107     rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1108
1109     if (!rx)
1110         XSRETURN_UNDEF;
1111
1112     if (items == 2 && SvTRUE(ST(1))) {
1113         flags = RXapif_ALL;
1114     } else {
1115         flags = RXapif_ONE;
1116     }
1117     ret = CALLREG_NAMED_BUFF_FETCH(rx, ST(0), (flags | RXapif_REGNAME));
1118
1119     if (ret) {
1120         if (SvROK(ret))
1121             XPUSHs(ret);
1122         else
1123             XPUSHs(SvREFCNT_inc(ret));
1124         XSRETURN(1);
1125     }
1126     XSRETURN_UNDEF;    
1127 }
1128
1129
1130 XS(XS_re_regnames)
1131 {
1132     dVAR;
1133     dXSARGS;
1134     REGEXP * rx;
1135     U32 flags;
1136     SV *ret;
1137     AV *av;
1138     I32 length;
1139     I32 i;
1140     SV **entry;
1141     PERL_UNUSED_ARG(cv);
1142
1143     if (items > 1)
1144         Perl_croak(aTHX_ "Usage: %s(%s)", "re::regnames", "[all]");
1145
1146     rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1147
1148     if (!rx)
1149         XSRETURN_UNDEF;
1150
1151     if (items == 1 && SvTRUE(ST(0))) {
1152         flags = RXapif_ALL;
1153     } else {
1154         flags = RXapif_ONE;
1155     }
1156
1157     SP -= items;
1158
1159     ret = CALLREG_NAMED_BUFF_ALL(rx, (flags | RXapif_REGNAMES));
1160
1161     SPAGAIN;
1162
1163     SP -= items;
1164
1165     if (!ret)
1166         XSRETURN_UNDEF;
1167
1168     av = (AV*)SvRV(ret);
1169     length = av_len(av);
1170
1171     for (i = 0; i <= length; i++) {
1172         entry = av_fetch(av, i, FALSE);
1173         
1174         if (!entry)
1175             Perl_croak(aTHX_ "NULL array element in re::regnames()");
1176
1177         XPUSHs(*entry);
1178     }
1179     PUTBACK;
1180     return;
1181 }
1182
1183 XS(XS_Tie_Hash_NamedCapture_FETCH)
1184 {
1185     dVAR;
1186     dXSARGS;
1187     REGEXP * rx;
1188     U32 flags;
1189     SV * ret;
1190     PERL_UNUSED_ARG(cv);
1191
1192     if (items != 2)
1193         Perl_croak(aTHX_ "Usage: Tie::Hash::NamedCapture::STORE($key, $flags)");
1194
1195     rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1196
1197     if (!rx)
1198         XSRETURN_UNDEF;
1199
1200     SP -= items;
1201
1202     flags = (U32)INT2PTR(IV,SvIV(SvRV((SV*)ST(0))));
1203     ret = CALLREG_NAMED_BUFF_FETCH(rx, ST(1), flags);
1204
1205     SPAGAIN;
1206
1207     if (ret) {
1208         if (SvROK(ret))
1209             XPUSHs(ret);
1210         else
1211             XPUSHs(SvREFCNT_inc(ret));
1212         PUTBACK;
1213         return;
1214     }
1215     XSRETURN_UNDEF;
1216 }
1217
1218 XS(XS_Tie_Hash_NamedCapture_STORE)
1219 {
1220     dVAR;
1221     dXSARGS;
1222     REGEXP * rx;
1223     U32 flags;
1224     PERL_UNUSED_ARG(cv);
1225
1226     if (items != 3)
1227         Perl_croak(aTHX_ "Usage: Tie::Hash::NamedCapture::STORE($key, $value, $flags)");
1228
1229     rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1230
1231     if (!rx) {
1232         if (!PL_localizing)
1233             Perl_croak(aTHX_ PL_no_modify);
1234         else
1235             XSRETURN_UNDEF;
1236     }
1237
1238     SP -= items;
1239
1240     flags = (U32)INT2PTR(IV,SvIV(SvRV((SV*)ST(0))));
1241     CALLREG_NAMED_BUFF_STORE(rx,ST(1), ST(2), flags);
1242 }
1243
1244 XS(XS_Tie_Hash_NamedCapture_DELETE)
1245 {
1246     dVAR;
1247     dXSARGS;
1248     REGEXP * rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1249     U32 flags;
1250     PERL_UNUSED_ARG(cv);
1251
1252     if (items != 2)
1253         Perl_croak(aTHX_ "Usage: Tie::Hash::NamedCapture::DELETE($key, $flags)");
1254
1255     if (!rx)
1256         Perl_croak(aTHX_ PL_no_modify);
1257
1258     SP -= items;
1259
1260     flags = (U32)INT2PTR(IV,SvIV(SvRV((SV*)ST(0))));
1261     CALLREG_NAMED_BUFF_DELETE(rx, ST(1), flags);
1262 }
1263
1264 XS(XS_Tie_Hash_NamedCapture_CLEAR)
1265 {
1266     dVAR;
1267     dXSARGS;
1268     REGEXP * rx;
1269     U32 flags;
1270     PERL_UNUSED_ARG(cv);
1271
1272     if (items != 1)
1273         Perl_croak(aTHX_ "Usage: Tie::Hash::NamedCapture::CLEAR($flags)");
1274
1275     rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1276
1277     if (!rx)
1278         Perl_croak(aTHX_ PL_no_modify);
1279
1280     SP -= items;
1281
1282     flags = (U32)INT2PTR(IV,SvIV(SvRV((SV*)ST(0))));
1283     CALLREG_NAMED_BUFF_CLEAR(rx, flags);
1284 }
1285
1286 XS(XS_Tie_Hash_NamedCapture_EXISTS)
1287 {
1288     dVAR;
1289     dXSARGS;
1290     REGEXP * rx;
1291     U32 flags;
1292     SV * ret;
1293     PERL_UNUSED_ARG(cv);
1294
1295     if (items != 2)
1296         Perl_croak(aTHX_ "Usage: Tie::Hash::NamedCapture::EXISTS($key, $flags)");
1297
1298     rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1299
1300     if (!rx)
1301         XSRETURN_UNDEF;
1302
1303     SP -= items;
1304
1305     flags = (U32)INT2PTR(IV,SvIV(SvRV((SV*)ST(0))));
1306     ret = CALLREG_NAMED_BUFF_EXISTS(rx, ST(1), flags);
1307
1308     SPAGAIN;
1309
1310         XPUSHs(ret);
1311         PUTBACK;
1312         return;
1313 }
1314
1315 XS(XS_Tie_Hash_NamedCapture_FIRSTK)
1316 {
1317     dVAR;
1318     dXSARGS;
1319     REGEXP * rx;
1320     U32 flags;
1321     SV * ret;
1322     PERL_UNUSED_ARG(cv);
1323
1324     if (items != 1)
1325         Perl_croak(aTHX_ "Usage: Tie::Hash::NamedCapture::FIRSTKEY()");
1326
1327     rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1328
1329     if (!rx)
1330         XSRETURN_UNDEF;
1331
1332     SP -= items;
1333
1334     flags = (U32)INT2PTR(IV,SvIV(SvRV((SV*)ST(0))));
1335     ret = CALLREG_NAMED_BUFF_FIRSTKEY(rx, flags);
1336
1337     SPAGAIN;
1338
1339     if (ret) {
1340         XPUSHs(SvREFCNT_inc(ret));
1341         PUTBACK;
1342     } else {
1343         XSRETURN_UNDEF;
1344     }
1345
1346 }
1347
1348 XS(XS_Tie_Hash_NamedCapture_NEXTK)
1349 {
1350     dVAR;
1351     dXSARGS;
1352     REGEXP * rx;
1353     U32 flags;
1354     SV * ret;
1355     PERL_UNUSED_ARG(cv);
1356
1357     if (items != 2)
1358         Perl_croak(aTHX_ "Usage: Tie::Hash::NamedCapture::NEXTKEY($lastkey)");
1359
1360     rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1361
1362     if (!rx)
1363         XSRETURN_UNDEF;
1364
1365     SP -= items;
1366
1367     flags = (U32)INT2PTR(IV,SvIV(SvRV((SV*)ST(0))));
1368     ret = CALLREG_NAMED_BUFF_NEXTKEY(rx, ST(1), flags);
1369
1370     SPAGAIN;
1371
1372     if (ret) {
1373         XPUSHs(ret);
1374     } else {
1375         XSRETURN_UNDEF;
1376     }  
1377     PUTBACK;
1378 }
1379
1380 XS(XS_Tie_Hash_NamedCapture_SCALAR)
1381 {
1382     dVAR;
1383     dXSARGS;
1384     REGEXP * rx;
1385     U32 flags;
1386     SV * ret;
1387     PERL_UNUSED_ARG(cv);
1388
1389     if (items != 1)
1390         Perl_croak(aTHX_ "Usage: Tie::Hash::NamedCapture::SCALAR()");
1391
1392     rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1393
1394     if (!rx)
1395         XSRETURN_UNDEF;
1396
1397     SP -= items;
1398
1399     flags = (U32)INT2PTR(IV,SvIV(SvRV((SV*)ST(0))));
1400     ret = CALLREG_NAMED_BUFF_SCALAR(rx, flags);
1401
1402     SPAGAIN;
1403
1404     if (ret) {
1405         XPUSHs(ret);
1406         PUTBACK;
1407         return;
1408     } else {
1409         XSRETURN_UNDEF;
1410     }
1411 }
1412
1413 XS(XS_Tie_Hash_NamedCapture_flags)
1414 {
1415     dVAR;
1416     dXSARGS;
1417     PERL_UNUSED_ARG(cv);
1418
1419     if (items != 0)
1420         Perl_croak(aTHX_ "Usage: Tie::Hash::NamedCapture::flags()");
1421
1422         XPUSHs(sv_2mortal(newSVuv(RXapif_ONE)));
1423         XPUSHs(sv_2mortal(newSVuv(RXapif_ALL)));
1424         PUTBACK;
1425         return;
1426 }
1427
1428
1429 /*
1430  * Local variables:
1431  * c-indentation-style: bsd
1432  * c-basic-offset: 4
1433  * indent-tabs-mode: t
1434  * End:
1435  *
1436  * ex: set ts=8 sts=4 sw=4 noet:
1437  */