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