Change 28404 broke the construct s/foo/<<BAR/e. So, try to be more
[p5sagit/p5-mst-13.2.git] / universal.c
CommitLineData
d6376244 1/* universal.c
2 *
b5f8cc5c 3 * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
acde74e1 4 * 2005, 2006, by Larry Wall and others
d6376244 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
d31a8517 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
166f8a29 17/* This file contains the code that implements the functions in Perl's
18 * UNIVERSAL package, such as UNIVERSAL->can().
19 */
20
6d4a7be2 21#include "EXTERN.h"
864dbfa3 22#define PERL_IN_UNIVERSAL_C
6d4a7be2 23#include "perl.h"
6d4a7be2 24
39f7a870 25#ifdef USE_PERLIO
26#include "perliol.h" /* For the PERLIO_F_XXX */
27#endif
28
6d4a7be2 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
a9ec700e 34STATIC bool
301daebc 35S_isa_lookup(pTHX_ HV *stash, const char *name, HV* name_stash,
36 int len, int level)
6d4a7be2 37{
97aff369 38 dVAR;
6d4a7be2 39 AV* av;
40 GV* gv;
41 GV** gvp;
5c284bb0 42 HV* hv = NULL;
c445ea15 43 SV* subgen = NULL;
bfcb3514 44 const char *hvname;
6d4a7be2 45
301daebc 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 && (stash == name_stash))
a9ec700e 49 return TRUE;
6d4a7be2 50
bfcb3514 51 hvname = HvNAME_get(stash);
52
53 if (strEQ(hvname, name))
a9ec700e 54 return TRUE;
6d4a7be2 55
a1d407e8 56 if (strEQ(name, "UNIVERSAL"))
a9ec700e 57 return TRUE;
a1d407e8 58
6d4a7be2 59 if (level > 100)
46e4b22b 60 Perl_croak(aTHX_ "Recursive inheritance detected in package '%s'",
bfcb3514 61 hvname);
6d4a7be2 62
017a3ce5 63 gvp = (GV**)hv_fetchs(stash, "::ISA::CACHE::", FALSE);
6d4a7be2 64
46e4b22b 65 if (gvp && (gv = *gvp) != (GV*)&PL_sv_undef && (subgen = GvSV(gv))
66 && (hv = GvHV(gv)))
67 {
eb160463 68 if (SvIV(subgen) == (IV)PL_sub_generation) {
46e4b22b 69 SV* sv;
7452cf6a 70 SV** const svp = (SV**)hv_fetch(hv, name, len, FALSE);
46e4b22b 71 if (svp && (sv = *svp) != (SV*)&PL_sv_undef) {
72 DEBUG_o( Perl_deb(aTHX_ "Using cached ISA %s for package %s\n",
bfcb3514 73 name, hvname) );
a9ec700e 74 return (sv == &PL_sv_yes);
46e4b22b 75 }
76 }
77 else {
78 DEBUG_o( Perl_deb(aTHX_ "ISA Cache in package %s is stale\n",
bfcb3514 79 hvname) );
46e4b22b 80 hv_clear(hv);
81 sv_setiv(subgen, PL_sub_generation);
82 }
6d4a7be2 83 }
84
017a3ce5 85 gvp = (GV**)hv_fetchs(stash, "ISA", FALSE);
46e4b22b 86
3280af22 87 if (gvp && (gv = *gvp) != (GV*)&PL_sv_undef && (av = GvAV(gv))) {
46e4b22b 88 if (!hv || !subgen) {
017a3ce5 89 gvp = (GV**)hv_fetchs(stash, "::ISA::CACHE::", TRUE);
6d4a7be2 90
91 gv = *gvp;
92
93 if (SvTYPE(gv) != SVt_PVGV)
94 gv_init(gv, stash, "::ISA::CACHE::", 14, TRUE);
95
46e4b22b 96 if (!hv)
97 hv = GvHVn(gv);
98 if (!subgen) {
99 subgen = newSViv(PL_sub_generation);
100 GvSV(gv) = subgen;
101 }
6d4a7be2 102 }
46e4b22b 103 if (hv) {
6d4a7be2 104 SV** svp = AvARRAY(av);
93965878 105 /* NOTE: No support for tied ISA */
106 I32 items = AvFILLp(av) + 1;
6d4a7be2 107 while (items--) {
c4420975 108 SV* const sv = *svp++;
109 HV* const basestash = gv_stashsv(sv, FALSE);
6d4a7be2 110 if (!basestash) {
599cee73 111 if (ckWARN(WARN_MISC))
9014280d 112 Perl_warner(aTHX_ packWARN(WARN_SYNTAX),
bfcb3514 113 "Can't locate package %"SVf" for @%s::ISA",
95b63a38 114 (void*)sv, hvname);
6d4a7be2 115 continue;
116 }
a9ec700e 117 if (isa_lookup(basestash, name, name_stash, len, level + 1)) {
3280af22 118 (void)hv_store(hv,name,len,&PL_sv_yes,0);
a9ec700e 119 return TRUE;
6d4a7be2 120 }
121 }
3280af22 122 (void)hv_store(hv,name,len,&PL_sv_no,0);
6d4a7be2 123 }
124 }
a9ec700e 125 return FALSE;
6d4a7be2 126}
127
954c1994 128/*
ccfc67b7 129=head1 SV Manipulation Functions
130
954c1994 131=for apidoc sv_derived_from
132
6885da0e 133Returns a boolean indicating whether the SV is derived from the specified class
134I<at the C level>. To check derivation at the Perl level, call C<isa()> as a
135normal Perl method.
954c1994 136
137=cut
138*/
139
55497cff 140bool
864dbfa3 141Perl_sv_derived_from(pTHX_ SV *sv, const char *name)
55497cff 142{
97aff369 143 dVAR;
0b6f4f5c 144 HV *stash;
46e4b22b 145
5b295bef 146 SvGETMAGIC(sv);
55497cff 147
148 if (SvROK(sv)) {
0b6f4f5c 149 const char *type;
55497cff 150 sv = SvRV(sv);
151 type = sv_reftype(sv,0);
0b6f4f5c 152 if (type && strEQ(type,name))
153 return TRUE;
154 stash = SvOBJECT(sv) ? SvSTASH(sv) : NULL;
55497cff 155 }
156 else {
157 stash = gv_stashsv(sv, FALSE);
158 }
46e4b22b 159
0b6f4f5c 160 if (stash) {
161 HV * const name_stash = gv_stashpv(name, FALSE);
a9ec700e 162 return isa_lookup(stash, name, name_stash, strlen(name), 0);
0b6f4f5c 163 }
164 else
165 return FALSE;
301daebc 166
55497cff 167}
168
cbc021f9 169/*
170=for apidoc sv_does
171
172Returns a boolean indicating whether the SV performs a specific, named role.
173The SV can be a Perl object or the name of a Perl class.
174
175=cut
176*/
177
1b026014 178#include "XSUB.h"
179
cbc021f9 180bool
181Perl_sv_does(pTHX_ SV *sv, const char *name)
182{
183 const char *classname;
184 bool does_it;
185
186 dSP;
187 ENTER;
188 SAVETMPS;
189
190 SvGETMAGIC(sv);
191
192 if (!SvOK(sv) || !(SvROK(sv) || (SvPOK(sv) && SvCUR(sv))
193 || (SvGMAGICAL(sv) && SvPOKp(sv) && SvCUR(sv))))
194 return FALSE;
195
196 if (sv_isobject(sv)) {
197 classname = sv_reftype(SvRV(sv),TRUE);
198 } else {
199 classname = SvPV(sv,PL_na);
200 }
201
202 if (strEQ(name,classname))
203 return TRUE;
204
205 PUSHMARK(SP);
206 XPUSHs(sv);
207 XPUSHs(sv_2mortal(newSVpv(name, 0)));
208 PUTBACK;
209
210 call_method("isa", G_SCALAR);
211 SPAGAIN;
212
213 does_it = SvTRUE( TOPs );
214 FREETMPS;
215 LEAVE;
216
217 return does_it;
218}
219
27da23d5 220PERL_XS_EXPORT_C void XS_UNIVERSAL_isa(pTHX_ CV *cv);
221PERL_XS_EXPORT_C void XS_UNIVERSAL_can(pTHX_ CV *cv);
cbc021f9 222PERL_XS_EXPORT_C void XS_UNIVERSAL_DOES(pTHX_ CV *cv);
27da23d5 223PERL_XS_EXPORT_C void XS_UNIVERSAL_VERSION(pTHX_ CV *cv);
439cb1c4 224XS(XS_version_new);
225XS(XS_version_stringify);
226XS(XS_version_numify);
9137345a 227XS(XS_version_normal);
439cb1c4 228XS(XS_version_vcmp);
229XS(XS_version_boolean);
2dfd8427 230#ifdef HASATTRIBUTE_NORETURN
231XS(XS_version_noop) __attribute__noreturn__;
232#else
439cb1c4 233XS(XS_version_noop);
2dfd8427 234#endif
c8d69e4a 235XS(XS_version_is_alpha);
137d6fc0 236XS(XS_version_qv);
8800c35a 237XS(XS_utf8_is_utf8);
1b026014 238XS(XS_utf8_valid);
239XS(XS_utf8_encode);
240XS(XS_utf8_decode);
241XS(XS_utf8_upgrade);
242XS(XS_utf8_downgrade);
243XS(XS_utf8_unicode_to_native);
244XS(XS_utf8_native_to_unicode);
29569577 245XS(XS_Internals_SvREADONLY);
246XS(XS_Internals_SvREFCNT);
f044d0d1 247XS(XS_Internals_hv_clear_placehold);
39f7a870 248XS(XS_PerlIO_get_layers);
39cff0d9 249XS(XS_Regexp_DESTROY);
9a7034eb 250XS(XS_Internals_hash_seed);
008fb0c0 251XS(XS_Internals_rehash_seed);
05619474 252XS(XS_Internals_HvREHASH);
e1234d8e 253XS(XS_Internals_inc_sub_generation);
0cb96387 254
255void
256Perl_boot_core_UNIVERSAL(pTHX)
257{
97aff369 258 dVAR;
157e3fc8 259 static const char file[] = __FILE__;
0cb96387 260
261 newXS("UNIVERSAL::isa", XS_UNIVERSAL_isa, file);
262 newXS("UNIVERSAL::can", XS_UNIVERSAL_can, file);
cbc021f9 263 newXS("UNIVERSAL::DOES", XS_UNIVERSAL_DOES, file);
0cb96387 264 newXS("UNIVERSAL::VERSION", XS_UNIVERSAL_VERSION, file);
439cb1c4 265 {
ad63d80f 266 /* register the overloading (type 'A') magic */
267 PL_amagic_generation++;
439cb1c4 268 /* Make it findable via fetchmethod */
be2ebcad 269 newXS("version::()", XS_version_noop, file);
439cb1c4 270 newXS("version::new", XS_version_new, file);
271 newXS("version::(\"\"", XS_version_stringify, file);
272 newXS("version::stringify", XS_version_stringify, file);
273 newXS("version::(0+", XS_version_numify, file);
274 newXS("version::numify", XS_version_numify, file);
9137345a 275 newXS("version::normal", XS_version_normal, file);
439cb1c4 276 newXS("version::(cmp", XS_version_vcmp, file);
277 newXS("version::(<=>", XS_version_vcmp, file);
278 newXS("version::vcmp", XS_version_vcmp, file);
279 newXS("version::(bool", XS_version_boolean, file);
280 newXS("version::boolean", XS_version_boolean, file);
281 newXS("version::(nomethod", XS_version_noop, file);
282 newXS("version::noop", XS_version_noop, file);
c8d69e4a 283 newXS("version::is_alpha", XS_version_is_alpha, file);
137d6fc0 284 newXS("version::qv", XS_version_qv, file);
439cb1c4 285 }
8800c35a 286 newXS("utf8::is_utf8", XS_utf8_is_utf8, file);
1b026014 287 newXS("utf8::valid", XS_utf8_valid, file);
288 newXS("utf8::encode", XS_utf8_encode, file);
289 newXS("utf8::decode", XS_utf8_decode, file);
290 newXS("utf8::upgrade", XS_utf8_upgrade, file);
291 newXS("utf8::downgrade", XS_utf8_downgrade, file);
292 newXS("utf8::native_to_unicode", XS_utf8_native_to_unicode, file);
293 newXS("utf8::unicode_to_native", XS_utf8_unicode_to_native, file);
29569577 294 newXSproto("Internals::SvREADONLY",XS_Internals_SvREADONLY, file, "\\[$%@];$");
295 newXSproto("Internals::SvREFCNT",XS_Internals_SvREFCNT, file, "\\[$%@];$");
dfd4ef2f 296 newXSproto("Internals::hv_clear_placeholders",
f044d0d1 297 XS_Internals_hv_clear_placehold, file, "\\%");
9d569fce 298 newXSproto("PerlIO::get_layers",
299 XS_PerlIO_get_layers, file, "*;@");
39cff0d9 300 newXS("Regexp::DESTROY", XS_Regexp_DESTROY, file);
9a7034eb 301 newXSproto("Internals::hash_seed",XS_Internals_hash_seed, file, "");
008fb0c0 302 newXSproto("Internals::rehash_seed",XS_Internals_rehash_seed, file, "");
05619474 303 newXSproto("Internals::HvREHASH", XS_Internals_HvREHASH, file, "\\%");
e1234d8e 304 newXSproto("Internals::inc_sub_generation",XS_Internals_inc_sub_generation,
305 file, "");
0cb96387 306}
307
55497cff 308
6d4a7be2 309XS(XS_UNIVERSAL_isa)
310{
97aff369 311 dVAR;
6d4a7be2 312 dXSARGS;
6d4a7be2 313
314 if (items != 2)
cea2e8a9 315 Perl_croak(aTHX_ "Usage: UNIVERSAL::isa(reference, kind)");
c4420975 316 else {
317 SV * const sv = ST(0);
318 const char *name;
6d4a7be2 319
c4420975 320 SvGETMAGIC(sv);
d3f7f2b2 321
c4420975 322 if (!SvOK(sv) || !(SvROK(sv) || (SvPOK(sv) && SvCUR(sv))
323 || (SvGMAGICAL(sv) && SvPOKp(sv) && SvCUR(sv))))
324 XSRETURN_UNDEF;
f8f70380 325
c4420975 326 name = SvPV_nolen_const(ST(1));
6d4a7be2 327
c4420975 328 ST(0) = boolSV(sv_derived_from(sv, name));
329 XSRETURN(1);
330 }
6d4a7be2 331}
332
6d4a7be2 333XS(XS_UNIVERSAL_can)
334{
97aff369 335 dVAR;
6d4a7be2 336 dXSARGS;
337 SV *sv;
6867be6d 338 const char *name;
6d4a7be2 339 SV *rv;
6f08146e 340 HV *pkg = NULL;
6d4a7be2 341
342 if (items != 2)
cea2e8a9 343 Perl_croak(aTHX_ "Usage: UNIVERSAL::can(object-ref, method)");
6d4a7be2 344
345 sv = ST(0);
f8f70380 346
5b295bef 347 SvGETMAGIC(sv);
d3f7f2b2 348
253ecd6d 349 if (!SvOK(sv) || !(SvROK(sv) || (SvPOK(sv) && SvCUR(sv))
350 || (SvGMAGICAL(sv) && SvPOKp(sv) && SvCUR(sv))))
f8f70380 351 XSRETURN_UNDEF;
352
0510663f 353 name = SvPV_nolen_const(ST(1));
3280af22 354 rv = &PL_sv_undef;
6d4a7be2 355
46e4b22b 356 if (SvROK(sv)) {
6f08146e 357 sv = (SV*)SvRV(sv);
46e4b22b 358 if (SvOBJECT(sv))
6f08146e 359 pkg = SvSTASH(sv);
360 }
361 else {
362 pkg = gv_stashsv(sv, FALSE);
363 }
364
365 if (pkg) {
c4420975 366 GV * const gv = gv_fetchmethod_autoload(pkg, name, FALSE);
dc848c6f 367 if (gv && isGV(gv))
368 rv = sv_2mortal(newRV((SV*)GvCV(gv)));
6d4a7be2 369 }
370
371 ST(0) = rv;
372 XSRETURN(1);
373}
374
cbc021f9 375XS(XS_UNIVERSAL_DOES)
376{
377 dVAR;
378 dXSARGS;
379
380 if (items != 2)
381 Perl_croak(aTHX_ "Usage: invocant->does(kind)");
382 else {
383 SV * const sv = ST(0);
384 const char *name;
385
386 name = SvPV_nolen_const(ST(1));
387 if (sv_does( sv, name ))
388 XSRETURN_YES;
389
390 XSRETURN_NO;
391 }
392}
393
6d4a7be2 394XS(XS_UNIVERSAL_VERSION)
395{
97aff369 396 dVAR;
6d4a7be2 397 dXSARGS;
398 HV *pkg;
399 GV **gvp;
400 GV *gv;
401 SV *sv;
e1ec3a88 402 const char *undef;
6d4a7be2 403
1571675a 404 if (SvROK(ST(0))) {
6d4a7be2 405 sv = (SV*)SvRV(ST(0));
1571675a 406 if (!SvOBJECT(sv))
cea2e8a9 407 Perl_croak(aTHX_ "Cannot find version of an unblessed reference");
6d4a7be2 408 pkg = SvSTASH(sv);
409 }
410 else {
411 pkg = gv_stashsv(ST(0), FALSE);
412 }
413
4608196e 414 gvp = pkg ? (GV**)hv_fetchs(pkg, "VERSION", FALSE) : NULL;
6d4a7be2 415
0008872a 416 if (gvp && isGV(gv = *gvp) && (sv = GvSV(gv)) && SvOK(sv)) {
c4420975 417 SV * const nsv = sv_newmortal();
6d4a7be2 418 sv_setsv(nsv, sv);
419 sv = nsv;
137d6fc0 420 if ( !sv_derived_from(sv, "version"))
421 upg_version(sv);
c445ea15 422 undef = NULL;
6d4a7be2 423 }
424 else {
3280af22 425 sv = (SV*)&PL_sv_undef;
6d4a7be2 426 undef = "(undef)";
427 }
428
1571675a 429 if (items > 1) {
1571675a 430 SV *req = ST(1);
431
62658f4d 432 if (undef) {
bfcb3514 433 if (pkg) {
c4420975 434 const char * const name = HvNAME_get(pkg);
a3b680e6 435 Perl_croak(aTHX_
bfcb3514 436 "%s does not define $%s::VERSION--version check failed",
437 name, name);
438 } else {
a3b680e6 439 Perl_croak(aTHX_
440 "%s defines neither package nor VERSION--version check failed",
0510663f 441 SvPVx_nolen_const(ST(0)) );
62658f4d 442 }
443 }
ad63d80f 444
137d6fc0 445 if ( !sv_derived_from(req, "version")) {
446 /* req may very well be R/O, so create a new object */
c4420975 447 SV * const nsv = sv_newmortal();
137d6fc0 448 sv_setsv(nsv, req);
449 req = nsv;
450 upg_version(req);
451 }
1571675a 452
137d6fc0 453 if ( vcmp( req, sv ) > 0 )
b9381830 454 Perl_croak(aTHX_ "%s version %"SVf" (%"SVf") required--"
95b63a38 455 "this is only version %"SVf" (%"SVf")", HvNAME_get(pkg),
456 (void*)vnumify(req),
457 (void*)vnormal(req),
458 (void*)vnumify(sv),
459 (void*)vnormal(sv));
2d8e6c8d 460 }
6d4a7be2 461
2b140d5b 462 if ( SvOK(sv) && sv_derived_from(sv, "version") ) {
b38a9dc5 463 ST(0) = vnumify(sv);
13f8f398 464 } else {
465 ST(0) = sv;
b38a9dc5 466 }
6d4a7be2 467
468 XSRETURN(1);
469}
470
439cb1c4 471XS(XS_version_new)
472{
97aff369 473 dVAR;
439cb1c4 474 dXSARGS;
129318bd 475 if (items > 3)
439cb1c4 476 Perl_croak(aTHX_ "Usage: version::new(class, version)");
477 SP -= items;
478 {
137d6fc0 479 SV *vs = ST(1);
480 SV *rv;
c4420975 481 const char * const classname =
482 sv_isobject(ST(0)) /* get the class if called as an object method */
483 ? HvNAME(SvSTASH(SvRV(ST(0))))
484 : (char *)SvPV_nolen(ST(0));
9137345a 485
92dcf8ce 486 if ( items == 1 || vs == &PL_sv_undef ) { /* no param or explicit undef */
487 /* create empty object */
488 vs = sv_newmortal();
489 sv_setpvn(vs,"",0);
9137345a 490 }
491 else if ( items == 3 ) {
492 vs = sv_newmortal();
cfd0369c 493 Perl_sv_setpvf(aTHX_ vs,"v%s",SvPV_nolen_const(ST(2)));
129318bd 494 }
439cb1c4 495
137d6fc0 496 rv = new_version(vs);
0723351e 497 if ( strcmp(classname,"version") != 0 ) /* inherited new() */
498 sv_bless(rv, gv_stashpv(classname,TRUE));
137d6fc0 499
500 PUSHs(sv_2mortal(rv));
439cb1c4 501 PUTBACK;
502 return;
503 }
504}
505
506XS(XS_version_stringify)
507{
97aff369 508 dVAR;
41be1fbd 509 dXSARGS;
510 if (items < 1)
511 Perl_croak(aTHX_ "Usage: version::stringify(lobj, ...)");
512 SP -= items;
513 {
7452cf6a 514 SV * lobj;
41be1fbd 515
516 if (sv_derived_from(ST(0), "version")) {
9137345a 517 lobj = SvRV(ST(0));
41be1fbd 518 }
519 else
520 Perl_croak(aTHX_ "lobj is not of type version");
521
137d6fc0 522 PUSHs(sv_2mortal(vstringify(lobj)));
41be1fbd 523
524 PUTBACK;
525 return;
526 }
439cb1c4 527}
528
529XS(XS_version_numify)
530{
97aff369 531 dVAR;
41be1fbd 532 dXSARGS;
533 if (items < 1)
534 Perl_croak(aTHX_ "Usage: version::numify(lobj, ...)");
535 SP -= items;
536 {
7452cf6a 537 SV * lobj;
41be1fbd 538
539 if (sv_derived_from(ST(0), "version")) {
9137345a 540 lobj = SvRV(ST(0));
41be1fbd 541 }
542 else
543 Perl_croak(aTHX_ "lobj is not of type version");
544
137d6fc0 545 PUSHs(sv_2mortal(vnumify(lobj)));
41be1fbd 546
547 PUTBACK;
548 return;
549 }
439cb1c4 550}
551
9137345a 552XS(XS_version_normal)
553{
97aff369 554 dVAR;
9137345a 555 dXSARGS;
556 if (items < 1)
557 Perl_croak(aTHX_ "Usage: version::normal(lobj, ...)");
558 SP -= items;
559 {
7452cf6a 560 SV * lobj;
9137345a 561
562 if (sv_derived_from(ST(0), "version")) {
563 lobj = SvRV(ST(0));
564 }
565 else
566 Perl_croak(aTHX_ "lobj is not of type version");
567
568 PUSHs(sv_2mortal(vnormal(lobj)));
569
570 PUTBACK;
571 return;
572 }
573}
574
439cb1c4 575XS(XS_version_vcmp)
576{
97aff369 577 dVAR;
41be1fbd 578 dXSARGS;
579 if (items < 1)
580 Perl_croak(aTHX_ "Usage: version::vcmp(lobj, ...)");
581 SP -= items;
582 {
7452cf6a 583 SV * lobj;
41be1fbd 584
585 if (sv_derived_from(ST(0), "version")) {
9137345a 586 lobj = SvRV(ST(0));
41be1fbd 587 }
588 else
589 Perl_croak(aTHX_ "lobj is not of type version");
590
591 {
592 SV *rs;
593 SV *rvs;
594 SV * robj = ST(1);
7452cf6a 595 const IV swap = (IV)SvIV(ST(2));
41be1fbd 596
597 if ( ! sv_derived_from(robj, "version") )
598 {
599 robj = new_version(robj);
600 }
601 rvs = SvRV(robj);
602
603 if ( swap )
604 {
605 rs = newSViv(vcmp(rvs,lobj));
606 }
607 else
608 {
609 rs = newSViv(vcmp(lobj,rvs));
610 }
611
137d6fc0 612 PUSHs(sv_2mortal(rs));
41be1fbd 613 }
614
615 PUTBACK;
616 return;
617 }
439cb1c4 618}
619
620XS(XS_version_boolean)
621{
97aff369 622 dVAR;
623 dXSARGS;
624 if (items < 1)
625 Perl_croak(aTHX_ "Usage: version::boolean(lobj, ...)");
626 SP -= items;
c4420975 627 if (sv_derived_from(ST(0), "version")) {
628 SV * const lobj = SvRV(ST(0));
396482e1 629 SV * const rs = newSViv( vcmp(lobj,new_version(newSVpvs("0"))) );
c4420975 630 PUSHs(sv_2mortal(rs));
631 PUTBACK;
632 return;
633 }
634 else
635 Perl_croak(aTHX_ "lobj is not of type version");
439cb1c4 636}
637
638XS(XS_version_noop)
639{
97aff369 640 dVAR;
2dfd8427 641 dXSARGS;
642 if (items < 1)
643 Perl_croak(aTHX_ "Usage: version::noop(lobj, ...)");
644 if (sv_derived_from(ST(0), "version"))
645 Perl_croak(aTHX_ "operation not supported with version object");
646 else
647 Perl_croak(aTHX_ "lobj is not of type version");
648#ifndef HASATTRIBUTE_NORETURN
649 XSRETURN_EMPTY;
650#endif
439cb1c4 651}
652
c8d69e4a 653XS(XS_version_is_alpha)
654{
97aff369 655 dVAR;
c8d69e4a 656 dXSARGS;
657 if (items != 1)
658 Perl_croak(aTHX_ "Usage: version::is_alpha(lobj)");
659 SP -= items;
c4420975 660 if (sv_derived_from(ST(0), "version")) {
661 SV * const lobj = ST(0);
662 if ( hv_exists((HV*)SvRV(lobj), "alpha", 5 ) )
663 XSRETURN_YES;
664 else
665 XSRETURN_NO;
c8d69e4a 666 PUTBACK;
667 return;
668 }
c4420975 669 else
670 Perl_croak(aTHX_ "lobj is not of type version");
c8d69e4a 671}
672
137d6fc0 673XS(XS_version_qv)
674{
97aff369 675 dVAR;
137d6fc0 676 dXSARGS;
677 if (items != 1)
678 Perl_croak(aTHX_ "Usage: version::qv(ver)");
679 SP -= items;
680 {
681 SV * ver = ST(0);
c4420975 682 if ( !SvVOK(ver) ) { /* only need to do with if not already v-string */
683 SV * const vs = sv_newmortal();
137d6fc0 684 char *version;
685 if ( SvNOK(ver) ) /* may get too much accuracy */
686 {
687 char tbuf[64];
d9fad198 688 const STRLEN len = my_snprintf(tbuf, sizeof(tbuf), "%.9"NVgf, SvNVX(ver));
86c11942 689 version = savepvn(tbuf, len);
137d6fc0 690 }
691 else
692 {
2e0de35c 693 version = savesvpv(ver);
137d6fc0 694 }
695 (void)scan_version(version,vs,TRUE);
696 Safefree(version);
697
698 PUSHs(vs);
699 }
700 else
701 {
702 PUSHs(sv_2mortal(new_version(ver)));
703 }
704
705 PUTBACK;
706 return;
707 }
708}
709
8800c35a 710XS(XS_utf8_is_utf8)
711{
97aff369 712 dVAR;
41be1fbd 713 dXSARGS;
714 if (items != 1)
715 Perl_croak(aTHX_ "Usage: utf8::is_utf8(sv)");
c4420975 716 else {
717 const SV * const sv = ST(0);
718 if (SvUTF8(sv))
719 XSRETURN_YES;
720 else
721 XSRETURN_NO;
41be1fbd 722 }
723 XSRETURN_EMPTY;
8800c35a 724}
725
1b026014 726XS(XS_utf8_valid)
727{
97aff369 728 dVAR;
41be1fbd 729 dXSARGS;
730 if (items != 1)
731 Perl_croak(aTHX_ "Usage: utf8::valid(sv)");
c4420975 732 else {
733 SV * const sv = ST(0);
734 STRLEN len;
735 const char * const s = SvPV_const(sv,len);
736 if (!SvUTF8(sv) || is_utf8_string((const U8*)s,len))
737 XSRETURN_YES;
738 else
739 XSRETURN_NO;
740 }
41be1fbd 741 XSRETURN_EMPTY;
1b026014 742}
743
744XS(XS_utf8_encode)
745{
97aff369 746 dVAR;
1b026014 747 dXSARGS;
748 if (items != 1)
749 Perl_croak(aTHX_ "Usage: utf8::encode(sv)");
c4420975 750 sv_utf8_encode(ST(0));
1b026014 751 XSRETURN_EMPTY;
752}
753
754XS(XS_utf8_decode)
755{
97aff369 756 dVAR;
1b026014 757 dXSARGS;
758 if (items != 1)
759 Perl_croak(aTHX_ "Usage: utf8::decode(sv)");
c4420975 760 else {
761 SV * const sv = ST(0);
6867be6d 762 const bool RETVAL = sv_utf8_decode(sv);
1b026014 763 ST(0) = boolSV(RETVAL);
764 sv_2mortal(ST(0));
765 }
766 XSRETURN(1);
767}
768
769XS(XS_utf8_upgrade)
770{
97aff369 771 dVAR;
1b026014 772 dXSARGS;
773 if (items != 1)
774 Perl_croak(aTHX_ "Usage: utf8::upgrade(sv)");
c4420975 775 else {
776 SV * const sv = ST(0);
1b026014 777 STRLEN RETVAL;
778 dXSTARG;
779
780 RETVAL = sv_utf8_upgrade(sv);
781 XSprePUSH; PUSHi((IV)RETVAL);
782 }
783 XSRETURN(1);
784}
785
786XS(XS_utf8_downgrade)
787{
97aff369 788 dVAR;
1b026014 789 dXSARGS;
790 if (items < 1 || items > 2)
791 Perl_croak(aTHX_ "Usage: utf8::downgrade(sv, failok=0)");
c4420975 792 else {
793 SV * const sv = ST(0);
6867be6d 794 const bool failok = (items < 2) ? 0 : (int)SvIV(ST(1));
795 const bool RETVAL = sv_utf8_downgrade(sv, failok);
1b026014 796
1b026014 797 ST(0) = boolSV(RETVAL);
798 sv_2mortal(ST(0));
799 }
800 XSRETURN(1);
801}
802
803XS(XS_utf8_native_to_unicode)
804{
97aff369 805 dVAR;
1b026014 806 dXSARGS;
6867be6d 807 const UV uv = SvUV(ST(0));
b7953727 808
809 if (items > 1)
810 Perl_croak(aTHX_ "Usage: utf8::native_to_unicode(sv)");
811
1b026014 812 ST(0) = sv_2mortal(newSViv(NATIVE_TO_UNI(uv)));
813 XSRETURN(1);
814}
815
816XS(XS_utf8_unicode_to_native)
817{
97aff369 818 dVAR;
1b026014 819 dXSARGS;
6867be6d 820 const UV uv = SvUV(ST(0));
b7953727 821
822 if (items > 1)
823 Perl_croak(aTHX_ "Usage: utf8::unicode_to_native(sv)");
824
1b026014 825 ST(0) = sv_2mortal(newSViv(UNI_TO_NATIVE(uv)));
826 XSRETURN(1);
827}
828
14a976d6 829XS(XS_Internals_SvREADONLY) /* This is dangerous stuff. */
29569577 830{
97aff369 831 dVAR;
29569577 832 dXSARGS;
c4420975 833 SV * const sv = SvRV(ST(0));
6867be6d 834
29569577 835 if (items == 1) {
836 if (SvREADONLY(sv))
837 XSRETURN_YES;
838 else
839 XSRETURN_NO;
840 }
841 else if (items == 2) {
842 if (SvTRUE(ST(1))) {
843 SvREADONLY_on(sv);
844 XSRETURN_YES;
845 }
846 else {
14a976d6 847 /* I hope you really know what you are doing. */
29569577 848 SvREADONLY_off(sv);
849 XSRETURN_NO;
850 }
851 }
14a976d6 852 XSRETURN_UNDEF; /* Can't happen. */
29569577 853}
854
14a976d6 855XS(XS_Internals_SvREFCNT) /* This is dangerous stuff. */
29569577 856{
97aff369 857 dVAR;
29569577 858 dXSARGS;
c4420975 859 SV * const sv = SvRV(ST(0));
6867be6d 860
29569577 861 if (items == 1)
14a976d6 862 XSRETURN_IV(SvREFCNT(sv) - 1); /* Minus the ref created for us. */
29569577 863 else if (items == 2) {
14a976d6 864 /* I hope you really know what you are doing. */
29569577 865 SvREFCNT(sv) = SvIV(ST(1));
866 XSRETURN_IV(SvREFCNT(sv));
867 }
14a976d6 868 XSRETURN_UNDEF; /* Can't happen. */
29569577 869}
870
f044d0d1 871XS(XS_Internals_hv_clear_placehold)
dfd4ef2f 872{
97aff369 873 dVAR;
dfd4ef2f 874 dXSARGS;
6867be6d 875
3540d4ce 876 if (items != 1)
877 Perl_croak(aTHX_ "Usage: UNIVERSAL::hv_clear_placeholders(hv)");
c4420975 878 else {
879 HV * const hv = (HV *) SvRV(ST(0));
880 hv_clear_placeholders(hv);
881 XSRETURN(0);
882 }
dfd4ef2f 883}
39f7a870 884
39cff0d9 885XS(XS_Regexp_DESTROY)
886{
96a5add6 887 PERL_UNUSED_CONTEXT;
53c1dcc0 888 PERL_UNUSED_ARG(cv);
39cff0d9 889}
890
39f7a870 891XS(XS_PerlIO_get_layers)
892{
97aff369 893 dVAR;
39f7a870 894 dXSARGS;
895 if (items < 1 || items % 2 == 0)
896 Perl_croak(aTHX_ "Usage: PerlIO_get_layers(filehandle[,args])");
5fef3b4a 897#ifdef USE_PERLIO
39f7a870 898 {
899 SV * sv;
900 GV * gv;
901 IO * io;
902 bool input = TRUE;
903 bool details = FALSE;
904
905 if (items > 1) {
c4420975 906 SV * const *svp;
39f7a870 907 for (svp = MARK + 2; svp <= SP; svp += 2) {
c4420975 908 SV * const * const varp = svp;
909 SV * const * const valp = svp + 1;
39f7a870 910 STRLEN klen;
c4420975 911 const char * const key = SvPV_const(*varp, klen);
39f7a870 912
913 switch (*key) {
914 case 'i':
915 if (klen == 5 && memEQ(key, "input", 5)) {
916 input = SvTRUE(*valp);
917 break;
918 }
919 goto fail;
920 case 'o':
921 if (klen == 6 && memEQ(key, "output", 6)) {
922 input = !SvTRUE(*valp);
923 break;
924 }
925 goto fail;
926 case 'd':
927 if (klen == 7 && memEQ(key, "details", 7)) {
928 details = SvTRUE(*valp);
929 break;
930 }
931 goto fail;
932 default:
933 fail:
934 Perl_croak(aTHX_
935 "get_layers: unknown argument '%s'",
936 key);
937 }
938 }
939
940 SP -= (items - 1);
941 }
942
943 sv = POPs;
944 gv = (GV*)sv;
945
946 if (!isGV(sv)) {
947 if (SvROK(sv) && isGV(SvRV(sv)))
948 gv = (GV*)SvRV(sv);
671d49be 949 else if (SvPOKp(sv))
f776e3cd 950 gv = gv_fetchsv(sv, 0, SVt_PVIO);
39f7a870 951 }
952
953 if (gv && (io = GvIO(gv))) {
954 dTARGET;
c4420975 955 AV* const av = PerlIO_get_layers(aTHX_ input ?
39f7a870 956 IoIFP(io) : IoOFP(io));
957 I32 i;
c4420975 958 const I32 last = av_len(av);
39f7a870 959 I32 nitem = 0;
960
961 for (i = last; i >= 0; i -= 3) {
c4420975 962 SV * const * const namsvp = av_fetch(av, i - 2, FALSE);
963 SV * const * const argsvp = av_fetch(av, i - 1, FALSE);
964 SV * const * const flgsvp = av_fetch(av, i, FALSE);
39f7a870 965
c4420975 966 const bool namok = namsvp && *namsvp && SvPOK(*namsvp);
967 const bool argok = argsvp && *argsvp && SvPOK(*argsvp);
968 const bool flgok = flgsvp && *flgsvp && SvIOK(*flgsvp);
39f7a870 969
970 if (details) {
ec3bab8e 971 XPUSHs(namok
972 ? newSVpvn(SvPVX_const(*namsvp), SvCUR(*namsvp))
973 : &PL_sv_undef);
974 XPUSHs(argok
975 ? newSVpvn(SvPVX_const(*argsvp), SvCUR(*argsvp))
976 : &PL_sv_undef);
39f7a870 977 if (flgok)
978 XPUSHi(SvIVX(*flgsvp));
979 else
980 XPUSHs(&PL_sv_undef);
981 nitem += 3;
982 }
983 else {
984 if (namok && argok)
985 XPUSHs(Perl_newSVpvf(aTHX_ "%"SVf"(%"SVf")",
95b63a38 986 (void*)*namsvp,
987 (void*)*argsvp));
39f7a870 988 else if (namok)
95b63a38 989 XPUSHs(Perl_newSVpvf(aTHX_ "%"SVf,
990 (void*)*namsvp));
39f7a870 991 else
992 XPUSHs(&PL_sv_undef);
993 nitem++;
994 if (flgok) {
c4420975 995 const IV flags = SvIVX(*flgsvp);
39f7a870 996
997 if (flags & PERLIO_F_UTF8) {
396482e1 998 XPUSHs(newSVpvs("utf8"));
39f7a870 999 nitem++;
1000 }
1001 }
1002 }
1003 }
1004
1005 SvREFCNT_dec(av);
1006
1007 XSRETURN(nitem);
1008 }
1009 }
5fef3b4a 1010#endif
39f7a870 1011
1012 XSRETURN(0);
1013}
1014
9a7034eb 1015XS(XS_Internals_hash_seed)
c910b28a 1016{
97aff369 1017 dVAR;
c85d3f85 1018 /* Using dXSARGS would also have dITEM and dSP,
1019 * which define 2 unused local variables. */
557b887a 1020 dAXMARK;
53c1dcc0 1021 PERL_UNUSED_ARG(cv);
ad73156c 1022 PERL_UNUSED_VAR(mark);
81eaca17 1023 XSRETURN_UV(PERL_HASH_SEED);
c910b28a 1024}
1025
008fb0c0 1026XS(XS_Internals_rehash_seed)
8e90d776 1027{
97aff369 1028 dVAR;
8e90d776 1029 /* Using dXSARGS would also have dITEM and dSP,
1030 * which define 2 unused local variables. */
557b887a 1031 dAXMARK;
53c1dcc0 1032 PERL_UNUSED_ARG(cv);
ad73156c 1033 PERL_UNUSED_VAR(mark);
008fb0c0 1034 XSRETURN_UV(PL_rehash_seed);
8e90d776 1035}
1036
05619474 1037XS(XS_Internals_HvREHASH) /* Subject to change */
1038{
97aff369 1039 dVAR;
05619474 1040 dXSARGS;
1041 if (SvROK(ST(0))) {
c4420975 1042 const HV * const hv = (HV *) SvRV(ST(0));
05619474 1043 if (items == 1 && SvTYPE(hv) == SVt_PVHV) {
1044 if (HvREHASH(hv))
1045 XSRETURN_YES;
1046 else
1047 XSRETURN_NO;
1048 }
1049 }
1050 Perl_croak(aTHX_ "Internals::HvREHASH $hashref");
1051}
241d1a3b 1052
e1234d8e 1053XS(XS_Internals_inc_sub_generation)
1054{
97aff369 1055 dVAR;
e1234d8e 1056 /* Using dXSARGS would also have dITEM and dSP,
1057 * which define 2 unused local variables. */
1058 dAXMARK;
1059 PERL_UNUSED_ARG(cv);
1060 PERL_UNUSED_VAR(mark);
1061 ++PL_sub_generation;
1062 XSRETURN_EMPTY;
1063}
1064
241d1a3b 1065/*
1066 * Local variables:
1067 * c-indentation-style: bsd
1068 * c-basic-offset: 4
1069 * indent-tabs-mode: t
1070 * End:
1071 *
37442d52 1072 * ex: set ts=8 sts=4 sw=4 noet:
1073 */