This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
regex: Remove FOLDCHAR regnode type
[perl5.git] / universal.c
CommitLineData
d6376244
JH
1/* universal.c
2 *
b5f8cc5c 3 * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
1129b882 4 * 2005, 2006, 2007, 2008 by Larry Wall and others
d6376244
JH
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/*
4ac71550
TC
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 history
15 *
16 * [p.54 of _The Lord of the Rings_, I/ii: "The Shadow of the Past"]
d31a8517
AT
17 */
18
166f8a29
DM
19/* This file contains the code that implements the functions in Perl's
20 * UNIVERSAL package, such as UNIVERSAL->can().
192b9cd1
AB
21 *
22 * It is also used to store XS functions that need to be present in
23 * miniperl for a lack of a better place to put them. It might be
486ec47a 24 * clever to move them to separate XS files which would then be pulled
192b9cd1 25 * in by some to-be-written build process.
166f8a29
DM
26 */
27
6d4a7be2 28#include "EXTERN.h"
864dbfa3 29#define PERL_IN_UNIVERSAL_C
6d4a7be2 30#include "perl.h"
6d4a7be2 31
39f7a870
JH
32#ifdef USE_PERLIO
33#include "perliol.h" /* For the PERLIO_F_XXX */
34#endif
35
6d4a7be2 36/*
37 * Contributed by Graham Barr <Graham.Barr@tiuk.ti.com>
38 * The main guts of traverse_isa was actually copied from gv_fetchmeth
39 */
40
a9ec700e 41STATIC bool
c7abbf64 42S_isa_lookup(pTHX_ HV *stash, const char * const name, STRLEN len, U32 flags)
6d4a7be2 43{
97aff369 44 dVAR;
a49ba3fc 45 const struct mro_meta *const meta = HvMROMETA(stash);
4340b386 46 HV *isa = meta->isa;
a49ba3fc 47 const HV *our_stash;
6d4a7be2 48
7918f24d
NC
49 PERL_ARGS_ASSERT_ISA_LOOKUP;
50
4340b386
FC
51 if (!isa) {
52 (void)mro_get_linear_isa(stash);
53 isa = meta->isa;
54 }
55
c7abbf64 56 if (hv_common(isa, NULL, name, len, ( flags & SVf_UTF8 ? HVhek_UTF8 : 0),
a49ba3fc
NC
57 HV_FETCH_ISEXISTS, NULL, 0)) {
58 /* Direct name lookup worked. */
a9ec700e 59 return TRUE;
a49ba3fc 60 }
6d4a7be2 61
a49ba3fc 62 /* A stash/class can go by many names (ie. User == main::User), so
81a5123c
FC
63 we use the HvENAME in the stash itself, which is canonical, falling
64 back to HvNAME if necessary. */
c7abbf64 65 our_stash = gv_stashpvn(name, len, flags);
a49ba3fc
NC
66
67 if (our_stash) {
81a5123c
FC
68 HEK *canon_name = HvENAME_HEK(our_stash);
69 if (!canon_name) canon_name = HvNAME_HEK(our_stash);
a1d407e8 70
a49ba3fc
NC
71 if (hv_common(isa, NULL, HEK_KEY(canon_name), HEK_LEN(canon_name),
72 HEK_FLAGS(canon_name),
73 HV_FETCH_ISEXISTS, NULL, HEK_HASH(canon_name))) {
e1a479c5 74 return TRUE;
a49ba3fc 75 }
6d4a7be2 76 }
77
a9ec700e 78 return FALSE;
6d4a7be2 79}
80
954c1994 81/*
ccfc67b7
JH
82=head1 SV Manipulation Functions
83
c7abbf64 84=for apidoc sv_derived_from_pvn
954c1994 85
6885da0e 86Returns a boolean indicating whether the SV is derived from the specified class
87I<at the C level>. To check derivation at the Perl level, call C<isa()> as a
88normal Perl method.
954c1994 89
c7abbf64
BF
90Currently, the only significant value for C<flags> is SVf_UTF8.
91
92=cut
93
94=for apidoc sv_derived_from_sv
95
96Exactly like L</sv_derived_from_pvn>, but takes the name string in the form
97of an SV instead of a string/length pair.
98
99=cut
100
101*/
102
103bool
104Perl_sv_derived_from_sv(pTHX_ SV *sv, SV *namesv, U32 flags)
105{
106 char *namepv;
107 STRLEN namelen;
108 PERL_ARGS_ASSERT_SV_DERIVED_FROM_SV;
109 namepv = SvPV(namesv, namelen);
110 if (SvUTF8(namesv))
111 flags |= SVf_UTF8;
112 return sv_derived_from_pvn(sv, namepv, namelen, flags);
113}
114
115/*
116=for apidoc sv_derived_from
117
118Exactly like L</sv_derived_from_pv>, but doesn't take a C<flags> parameter.
119
954c1994
GS
120=cut
121*/
122
55497cff 123bool
15f169a1 124Perl_sv_derived_from(pTHX_ SV *sv, const char *const name)
55497cff 125{
c7abbf64
BF
126 PERL_ARGS_ASSERT_SV_DERIVED_FROM;
127 return sv_derived_from_pvn(sv, name, strlen(name), 0);
128}
129
130/*
131=for apidoc sv_derived_from_pv
132
133Exactly like L</sv_derived_from_pvn>, but takes a nul-terminated string
134instead of a string/length pair.
135
136=cut
137*/
138
139
140bool
141Perl_sv_derived_from_pv(pTHX_ SV *sv, const char *const name, U32 flags)
142{
143 PERL_ARGS_ASSERT_SV_DERIVED_FROM_PV;
144 return sv_derived_from_pvn(sv, name, strlen(name), flags);
145}
146
147bool
148Perl_sv_derived_from_pvn(pTHX_ SV *sv, const char *const name, const STRLEN len, U32 flags)
149{
97aff369 150 dVAR;
0b6f4f5c 151 HV *stash;
46e4b22b 152
c7abbf64 153 PERL_ARGS_ASSERT_SV_DERIVED_FROM_PVN;
7918f24d 154
5b295bef 155 SvGETMAGIC(sv);
55497cff 156
bff39573 157 if (SvROK(sv)) {
0b6f4f5c 158 const char *type;
55497cff 159 sv = SvRV(sv);
160 type = sv_reftype(sv,0);
0b6f4f5c
AL
161 if (type && strEQ(type,name))
162 return TRUE;
163 stash = SvOBJECT(sv) ? SvSTASH(sv) : NULL;
55497cff 164 }
165 else {
da51bb9b 166 stash = gv_stashsv(sv, 0);
55497cff 167 }
46e4b22b 168
c7abbf64 169 return stash ? isa_lookup(stash, name, len, flags) : FALSE;
55497cff 170}
171
cbc021f9 172/*
d20c2c29 173=for apidoc sv_does_sv
cbc021f9 174
175Returns a boolean indicating whether the SV performs a specific, named role.
176The SV can be a Perl object or the name of a Perl class.
177
178=cut
179*/
180
1b026014
NIS
181#include "XSUB.h"
182
cbc021f9 183bool
f778bcfd 184Perl_sv_does_sv(pTHX_ SV *sv, SV *namesv, U32 flags)
cbc021f9 185{
f778bcfd 186 SV *classname;
cbc021f9 187 bool does_it;
59e7186f 188 SV *methodname;
cbc021f9 189 dSP;
7918f24d 190
f778bcfd
BF
191 PERL_ARGS_ASSERT_SV_DOES_SV;
192 PERL_UNUSED_ARG(flags);
7918f24d 193
cbc021f9 194 ENTER;
195 SAVETMPS;
196
197 SvGETMAGIC(sv);
198
199 if (!SvOK(sv) || !(SvROK(sv) || (SvPOK(sv) && SvCUR(sv))
7ce46f2a
GG
200 || (SvGMAGICAL(sv) && SvPOKp(sv) && SvCUR(sv)))) {
201 LEAVE;
cbc021f9 202 return FALSE;
7ce46f2a 203 }
cbc021f9 204
205 if (sv_isobject(sv)) {
f778bcfd 206 classname = sv_ref(NULL,SvRV(sv),TRUE);
cbc021f9 207 } else {
f778bcfd 208 classname = sv;
cbc021f9 209 }
210
f778bcfd 211 if (sv_eq(classname, namesv)) {
7ce46f2a 212 LEAVE;
cbc021f9 213 return TRUE;
7ce46f2a 214 }
cbc021f9 215
216 PUSHMARK(SP);
f778bcfd
BF
217 EXTEND(SP, 2);
218 PUSHs(sv);
219 PUSHs(namesv);
cbc021f9 220 PUTBACK;
221
84bafc02 222 methodname = newSVpvs_flags("isa", SVs_TEMP);
59e7186f
RGS
223 /* ugly hack: use the SvSCREAM flag so S_method_common
224 * can figure out we're calling DOES() and not isa(),
225 * and report eventual errors correctly. --rgs */
226 SvSCREAM_on(methodname);
227 call_sv(methodname, G_SCALAR | G_METHOD);
cbc021f9 228 SPAGAIN;
229
230 does_it = SvTRUE( TOPs );
231 FREETMPS;
232 LEAVE;
233
234 return does_it;
235}
236
afa74d42 237/*
f778bcfd
BF
238=for apidoc sv_does
239
d20c2c29 240Like L</sv_does_pv>, but doesn't take a C<flags> parameter.
f778bcfd
BF
241
242=cut
243*/
244
245bool
246Perl_sv_does(pTHX_ SV *sv, const char *const name)
247{
248 PERL_ARGS_ASSERT_SV_DOES;
249 return sv_does_sv(sv, newSVpvn_flags(name, strlen(name), SVs_TEMP), 0);
250}
251
252/*
253=for apidoc sv_does_pv
254
7d892b8c 255Like L</sv_does_sv>, but takes a nul-terminated string instead of an SV.
f778bcfd
BF
256
257=cut
258*/
259
260
261bool
262Perl_sv_does_pv(pTHX_ SV *sv, const char *const name, U32 flags)
263{
264 PERL_ARGS_ASSERT_SV_DOES_PV;
265 return sv_does_sv(sv, newSVpvn_flags(name, strlen(name), SVs_TEMP | flags), flags);
266}
267
7d892b8c
FC
268/*
269=for apidoc sv_does_pvn
270
271Like L</sv_does_sv>, but takes a string/length pair instead of an SV.
272
273=cut
274*/
275
f778bcfd
BF
276bool
277Perl_sv_does_pvn(pTHX_ SV *sv, const char *const name, const STRLEN len, U32 flags)
278{
279 PERL_ARGS_ASSERT_SV_DOES_PVN;
280
281 return sv_does_sv(sv, newSVpvn_flags(name, len, flags | SVs_TEMP), flags);
282}
283
284/*
afa74d42
NC
285=for apidoc croak_xs_usage
286
287A specialised variant of C<croak()> for emitting the usage message for xsubs
288
289 croak_xs_usage(cv, "eee_yow");
290
291works out the package name and subroutine name from C<cv>, and then calls
292C<croak()>. Hence if C<cv> is C<&ouch::awk>, it would call C<croak> as:
293
58cb15b3 294 Perl_croak(aTHX_ "Usage: %"SVf"::%"SVf"(%s)", "ouch" "awk", "eee_yow");
afa74d42
NC
295
296=cut
297*/
298
299void
300Perl_croak_xs_usage(pTHX_ const CV *const cv, const char *const params)
301{
302 const GV *const gv = CvGV(cv);
303
304 PERL_ARGS_ASSERT_CROAK_XS_USAGE;
305
306 if (gv) {
afa74d42 307 const HV *const stash = GvSTASH(gv);
afa74d42 308
58cb15b3 309 if (HvNAME_get(stash))
d0c0e7dd
FC
310 Perl_croak(aTHX_ "Usage: %"HEKf"::%"HEKf"(%s)",
311 HEKfARG(HvNAME_HEK(stash)),
312 HEKfARG(GvNAME_HEK(gv)),
58cb15b3 313 params);
afa74d42 314 else
d0c0e7dd
FC
315 Perl_croak(aTHX_ "Usage: %"HEKf"(%s)",
316 HEKfARG(GvNAME_HEK(gv)), params);
afa74d42
NC
317 } else {
318 /* Pants. I don't think that it should be possible to get here. */
93c51217 319 Perl_croak(aTHX_ "Usage: CODE(0x%"UVxf")(%s)", PTR2UV(cv), params);
afa74d42
NC
320 }
321}
55497cff 322
6d4a7be2 323XS(XS_UNIVERSAL_isa)
324{
97aff369 325 dVAR;
6d4a7be2 326 dXSARGS;
6d4a7be2 327
328 if (items != 2)
afa74d42 329 croak_xs_usage(cv, "reference, kind");
c4420975
AL
330 else {
331 SV * const sv = ST(0);
6d4a7be2 332
c4420975 333 SvGETMAGIC(sv);
d3f7f2b2 334
c4420975
AL
335 if (!SvOK(sv) || !(SvROK(sv) || (SvPOK(sv) && SvCUR(sv))
336 || (SvGMAGICAL(sv) && SvPOKp(sv) && SvCUR(sv))))
337 XSRETURN_UNDEF;
f8f70380 338
c7abbf64 339 ST(0) = boolSV(sv_derived_from_sv(sv, ST(1), 0));
c4420975
AL
340 XSRETURN(1);
341 }
6d4a7be2 342}
343
6d4a7be2 344XS(XS_UNIVERSAL_can)
345{
97aff369 346 dVAR;
6d4a7be2 347 dXSARGS;
348 SV *sv;
6d4a7be2 349 SV *rv;
6f08146e 350 HV *pkg = NULL;
6d4a7be2 351
352 if (items != 2)
afa74d42 353 croak_xs_usage(cv, "object-ref, method");
6d4a7be2 354
355 sv = ST(0);
f8f70380 356
5b295bef 357 SvGETMAGIC(sv);
d3f7f2b2 358
253ecd6d
RGS
359 if (!SvOK(sv) || !(SvROK(sv) || (SvPOK(sv) && SvCUR(sv))
360 || (SvGMAGICAL(sv) && SvPOKp(sv) && SvCUR(sv))))
f8f70380
GS
361 XSRETURN_UNDEF;
362
3280af22 363 rv = &PL_sv_undef;
6d4a7be2 364
46e4b22b 365 if (SvROK(sv)) {
daba3364 366 sv = MUTABLE_SV(SvRV(sv));
46e4b22b 367 if (SvOBJECT(sv))
6f08146e
NIS
368 pkg = SvSTASH(sv);
369 }
370 else {
da51bb9b 371 pkg = gv_stashsv(sv, 0);
6f08146e
NIS
372 }
373
374 if (pkg) {
a00b390b 375 GV * const gv = gv_fetchmethod_sv_flags(pkg, ST(1), 0);
dc848c6f 376 if (gv && isGV(gv))
daba3364 377 rv = sv_2mortal(newRV(MUTABLE_SV(GvCV(gv))));
6d4a7be2 378 }
379
380 ST(0) = rv;
381 XSRETURN(1);
382}
383
cbc021f9 384XS(XS_UNIVERSAL_DOES)
385{
386 dVAR;
387 dXSARGS;
58c0efa5 388 PERL_UNUSED_ARG(cv);
cbc021f9 389
390 if (items != 2)
46404226 391 Perl_croak(aTHX_ "Usage: invocant->DOES(kind)");
cbc021f9 392 else {
393 SV * const sv = ST(0);
f778bcfd 394 if (sv_does_sv( sv, ST(1), 0 ))
cbc021f9 395 XSRETURN_YES;
396
397 XSRETURN_NO;
398 }
399}
400
6d4a7be2 401XS(XS_UNIVERSAL_VERSION)
402{
97aff369 403 dVAR;
6d4a7be2 404 dXSARGS;
405 HV *pkg;
406 GV **gvp;
407 GV *gv;
408 SV *sv;
e1ec3a88 409 const char *undef;
58c0efa5 410 PERL_UNUSED_ARG(cv);
6d4a7be2 411
1571675a 412 if (SvROK(ST(0))) {
daba3364 413 sv = MUTABLE_SV(SvRV(ST(0)));
1571675a 414 if (!SvOBJECT(sv))
cea2e8a9 415 Perl_croak(aTHX_ "Cannot find version of an unblessed reference");
6d4a7be2 416 pkg = SvSTASH(sv);
417 }
418 else {
da51bb9b 419 pkg = gv_stashsv(ST(0), 0);
6d4a7be2 420 }
421
4608196e 422 gvp = pkg ? (GV**)hv_fetchs(pkg, "VERSION", FALSE) : NULL;
6d4a7be2 423
0008872a 424 if (gvp && isGV(gv = *gvp) && (sv = GvSV(gv)) && SvOK(sv)) {
a97f6d14
JP
425 SV * const nsv = sv_newmortal();
426 sv_setsv(nsv, sv);
427 sv = nsv;
573a19fb 428 if ( !sv_isobject(sv) || !sv_derived_from(sv, "version"))
a97f6d14
JP
429 upg_version(sv, FALSE);
430
c445ea15 431 undef = NULL;
6d4a7be2 432 }
433 else {
a97f6d14 434 sv = &PL_sv_undef;
6d4a7be2 435 undef = "(undef)";
436 }
437
1571675a 438 if (items > 1) {
1571675a
GS
439 SV *req = ST(1);
440
62658f4d 441 if (undef) {
bfcb3514 442 if (pkg) {
d0c0e7dd 443 const HEK * const name = HvNAME_HEK(pkg);
a3b680e6 444 Perl_croak(aTHX_
d0c0e7dd
FC
445 "%"HEKf" does not define $%"HEKf
446 "::VERSION--version check failed",
447 HEKfARG(name), HEKfARG(name));
bfcb3514 448 } else {
a3b680e6 449 Perl_croak(aTHX_
ed1db70e
BF
450 "%"SVf" defines neither package nor VERSION--version check failed",
451 SVfARG(ST(0)) );
62658f4d
PM
452 }
453 }
ad63d80f 454
573a19fb 455 if ( !sv_isobject(req) || !sv_derived_from(req, "version")) {
137d6fc0 456 /* req may very well be R/O, so create a new object */
ac0e6a2f 457 req = sv_2mortal( new_version(req) );
137d6fc0 458 }
1571675a 459
ac0e6a2f 460 if ( vcmp( req, sv ) > 0 ) {
ef8f7699 461 if ( hv_exists(MUTABLE_HV(SvRV(req)), "qv", 2 ) ) {
d0c0e7dd 462 Perl_croak(aTHX_ "%"HEKf" version %"SVf" required--"
ed1db70e 463 "this is only version %"SVf"",
d0c0e7dd 464 HEKfARG(HvNAME_HEK(pkg)),
e3a22e3f
GF
465 SVfARG(sv_2mortal(vnormal(req))),
466 SVfARG(sv_2mortal(vnormal(sv))));
ac0e6a2f 467 } else {
d0c0e7dd 468 Perl_croak(aTHX_ "%"HEKf" version %"SVf" required--"
ed1db70e 469 "this is only version %"SVf,
d0c0e7dd 470 HEKfARG(HvNAME_HEK(pkg)),
e3a22e3f
GF
471 SVfARG(sv_2mortal(vstringify(req))),
472 SVfARG(sv_2mortal(vstringify(sv))));
ac0e6a2f
RGS
473 }
474 }
475
2d8e6c8d 476 }
6d4a7be2 477
a97f6d14
JP
478 if ( SvOK(sv) && sv_derived_from(sv, "version") ) {
479 ST(0) = sv_2mortal(vstringify(sv));
480 } else {
481 ST(0) = sv;
482 }
6d4a7be2 483
484 XSRETURN(1);
485}
486
439cb1c4
JP
487XS(XS_version_new)
488{
97aff369 489 dVAR;
439cb1c4 490 dXSARGS;
129318bd 491 if (items > 3)
afa74d42 492 croak_xs_usage(cv, "class, version");
439cb1c4
JP
493 SP -= items;
494 {
137d6fc0
JP
495 SV *vs = ST(1);
496 SV *rv;
ed1db70e
BF
497 STRLEN len;
498 const char *classname;
499 U32 flags;
500 if ( sv_isobject(ST(0)) ) { /* get the class if called as an object method */
501 const HV * stash = SvSTASH(SvRV(ST(0)));
502 classname = HvNAME(stash);
503 len = HvNAMELEN(stash);
504 flags = HvNAMEUTF8(stash) ? SVf_UTF8 : 0;
505 }
506 else {
507 classname = SvPV(ST(0), len);
508 flags = SvUTF8(ST(0));
509 }
9137345a 510
91152fc1 511 if ( items == 1 || ! SvOK(vs) ) { /* no param or explicit undef */
92dcf8ce
JP
512 /* create empty object */
513 vs = sv_newmortal();
be5574c0 514 sv_setpvs(vs, "0");
9137345a
JP
515 }
516 else if ( items == 3 ) {
517 vs = sv_newmortal();
cfd0369c 518 Perl_sv_setpvf(aTHX_ vs,"v%s",SvPV_nolen_const(ST(2)));
129318bd 519 }
439cb1c4 520
137d6fc0 521 rv = new_version(vs);
ed1db70e
BF
522 if ( strnNE(classname,"version", len) ) /* inherited new() */
523 sv_bless(rv, gv_stashpvn(classname, len, GV_ADD | flags));
137d6fc0 524
6e449a3a 525 mPUSHs(rv);
439cb1c4
JP
526 PUTBACK;
527 return;
528 }
529}
530
531XS(XS_version_stringify)
532{
97aff369 533 dVAR;
41be1fbd
JH
534 dXSARGS;
535 if (items < 1)
afa74d42 536 croak_xs_usage(cv, "lobj, ...");
41be1fbd
JH
537 SP -= items;
538 {
d808b681 539 SV * lobj = ST(0);
41be1fbd 540
573a19fb 541 if (sv_isobject(lobj) && sv_derived_from(lobj, "version")) {
d808b681 542 lobj = SvRV(lobj);
41be1fbd
JH
543 }
544 else
545 Perl_croak(aTHX_ "lobj is not of type version");
546
6e449a3a 547 mPUSHs(vstringify(lobj));
41be1fbd
JH
548
549 PUTBACK;
550 return;
551 }
439cb1c4
JP
552}
553
554XS(XS_version_numify)
555{
97aff369 556 dVAR;
41be1fbd
JH
557 dXSARGS;
558 if (items < 1)
afa74d42 559 croak_xs_usage(cv, "lobj, ...");
41be1fbd
JH
560 SP -= items;
561 {
d808b681 562 SV * lobj = ST(0);
41be1fbd 563
573a19fb 564 if (sv_isobject(lobj) && sv_derived_from(lobj, "version")) {
d808b681 565 lobj = SvRV(lobj);
41be1fbd
JH
566 }
567 else
568 Perl_croak(aTHX_ "lobj is not of type version");
569
6e449a3a 570 mPUSHs(vnumify(lobj));
41be1fbd
JH
571
572 PUTBACK;
573 return;
574 }
439cb1c4
JP
575}
576
9137345a
JP
577XS(XS_version_normal)
578{
97aff369 579 dVAR;
9137345a
JP
580 dXSARGS;
581 if (items < 1)
afa74d42 582 croak_xs_usage(cv, "lobj, ...");
9137345a
JP
583 SP -= items;
584 {
d808b681 585 SV * lobj = ST(0);
9137345a 586
573a19fb 587 if (sv_isobject(lobj) && sv_derived_from(lobj, "version")) {
d808b681 588 lobj = SvRV(lobj);
9137345a
JP
589 }
590 else
591 Perl_croak(aTHX_ "lobj is not of type version");
592
6e449a3a 593 mPUSHs(vnormal(lobj));
9137345a
JP
594
595 PUTBACK;
596 return;
597 }
598}
599
439cb1c4
JP
600XS(XS_version_vcmp)
601{
97aff369 602 dVAR;
41be1fbd
JH
603 dXSARGS;
604 if (items < 1)
afa74d42 605 croak_xs_usage(cv, "lobj, ...");
41be1fbd
JH
606 SP -= items;
607 {
d808b681 608 SV * lobj = ST(0);
41be1fbd 609
573a19fb 610 if (sv_isobject(lobj) && sv_derived_from(lobj, "version")) {
d808b681 611 lobj = SvRV(lobj);
41be1fbd
JH
612 }
613 else
614 Perl_croak(aTHX_ "lobj is not of type version");
615
616 {
617 SV *rs;
618 SV *rvs;
619 SV * robj = ST(1);
7452cf6a 620 const IV swap = (IV)SvIV(ST(2));
41be1fbd 621
573a19fb 622 if ( !sv_isobject(robj) || !sv_derived_from(robj, "version") )
41be1fbd 623 {
e3a22e3f
GF
624 robj = new_version(SvOK(robj) ? robj : newSVpvs_flags("0", SVs_TEMP));
625 sv_2mortal(robj);
41be1fbd
JH
626 }
627 rvs = SvRV(robj);
628
629 if ( swap )
630 {
631 rs = newSViv(vcmp(rvs,lobj));
632 }
633 else
634 {
635 rs = newSViv(vcmp(lobj,rvs));
636 }
637
6e449a3a 638 mPUSHs(rs);
41be1fbd
JH
639 }
640
641 PUTBACK;
642 return;
643 }
439cb1c4
JP
644}
645
646XS(XS_version_boolean)
647{
97aff369
JH
648 dVAR;
649 dXSARGS;
650 if (items < 1)
afa74d42 651 croak_xs_usage(cv, "lobj, ...");
97aff369 652 SP -= items;
573a19fb 653 if (sv_isobject(ST(0)) && sv_derived_from(ST(0), "version")) {
c4420975 654 SV * const lobj = SvRV(ST(0));
396482e1 655 SV * const rs = newSViv( vcmp(lobj,new_version(newSVpvs("0"))) );
6e449a3a 656 mPUSHs(rs);
c4420975
AL
657 PUTBACK;
658 return;
659 }
660 else
661 Perl_croak(aTHX_ "lobj is not of type version");
439cb1c4
JP
662}
663
664XS(XS_version_noop)
665{
97aff369 666 dVAR;
2dfd8427
AL
667 dXSARGS;
668 if (items < 1)
afa74d42 669 croak_xs_usage(cv, "lobj, ...");
573a19fb 670 if (sv_isobject(ST(0)) && sv_derived_from(ST(0), "version"))
2dfd8427
AL
671 Perl_croak(aTHX_ "operation not supported with version object");
672 else
673 Perl_croak(aTHX_ "lobj is not of type version");
674#ifndef HASATTRIBUTE_NORETURN
675 XSRETURN_EMPTY;
676#endif
439cb1c4
JP
677}
678
c8d69e4a
JP
679XS(XS_version_is_alpha)
680{
97aff369 681 dVAR;
c8d69e4a
JP
682 dXSARGS;
683 if (items != 1)
afa74d42 684 croak_xs_usage(cv, "lobj");
c8d69e4a 685 SP -= items;
573a19fb 686 if (sv_isobject(ST(0)) && sv_derived_from(ST(0), "version")) {
c4420975 687 SV * const lobj = ST(0);
ef8f7699 688 if ( hv_exists(MUTABLE_HV(SvRV(lobj)), "alpha", 5 ) )
c4420975
AL
689 XSRETURN_YES;
690 else
691 XSRETURN_NO;
c8d69e4a
JP
692 PUTBACK;
693 return;
694 }
c4420975
AL
695 else
696 Perl_croak(aTHX_ "lobj is not of type version");
c8d69e4a
JP
697}
698
137d6fc0
JP
699XS(XS_version_qv)
700{
97aff369 701 dVAR;
137d6fc0 702 dXSARGS;
4ed3fda4 703 PERL_UNUSED_ARG(cv);
137d6fc0
JP
704 SP -= items;
705 {
f941e658
JP
706 SV * ver = ST(0);
707 SV * rv;
ed1db70e
BF
708 STRLEN len = 0;
709 const char * classname = "";
710 U32 flags = 0;
711 if ( items == 2 && SvOK(ST(1)) ) {
712 ver = ST(1);
713 if ( sv_isobject(ST(0)) ) { /* class called as an object method */
714 const HV * stash = SvSTASH(SvRV(ST(0)));
715 classname = HvNAME(stash);
716 len = HvNAMELEN(stash);
717 flags = HvNAMEUTF8(stash) ? SVf_UTF8 : 0;
718 }
719 else {
720 classname = SvPV(ST(0), len);
721 flags = SvUTF8(ST(0));
722 }
723 }
f941e658
JP
724 if ( !SvVOK(ver) ) { /* not already a v-string */
725 rv = sv_newmortal();
ac0e6a2f
RGS
726 sv_setsv(rv,ver); /* make a duplicate */
727 upg_version(rv, TRUE);
f941e658
JP
728 } else {
729 rv = sv_2mortal(new_version(ver));
137d6fc0 730 }
ed1db70e
BF
731 if ( items == 2
732 && strnNE(classname,"version", len) ) { /* inherited new() */
733 sv_bless(rv, gv_stashpvn(classname, len, GV_ADD | flags));
734 }
f941e658
JP
735 PUSHs(rv);
736 }
737 PUTBACK;
738 return;
739}
137d6fc0 740
f941e658
JP
741XS(XS_version_is_qv)
742{
743 dVAR;
744 dXSARGS;
745 if (items != 1)
746 croak_xs_usage(cv, "lobj");
747 SP -= items;
573a19fb 748 if (sv_isobject(ST(0)) && sv_derived_from(ST(0), "version")) {
f941e658
JP
749 SV * const lobj = ST(0);
750 if ( hv_exists(MUTABLE_HV(SvRV(lobj)), "qv", 2 ) )
751 XSRETURN_YES;
752 else
753 XSRETURN_NO;
137d6fc0
JP
754 PUTBACK;
755 return;
756 }
f941e658
JP
757 else
758 Perl_croak(aTHX_ "lobj is not of type version");
137d6fc0
JP
759}
760
8800c35a
JH
761XS(XS_utf8_is_utf8)
762{
97aff369 763 dVAR;
41be1fbd
JH
764 dXSARGS;
765 if (items != 1)
afa74d42 766 croak_xs_usage(cv, "sv");
c4420975 767 else {
76f73021
GF
768 SV * const sv = ST(0);
769 SvGETMAGIC(sv);
c4420975
AL
770 if (SvUTF8(sv))
771 XSRETURN_YES;
772 else
773 XSRETURN_NO;
41be1fbd
JH
774 }
775 XSRETURN_EMPTY;
8800c35a
JH
776}
777
1b026014
NIS
778XS(XS_utf8_valid)
779{
97aff369 780 dVAR;
41be1fbd
JH
781 dXSARGS;
782 if (items != 1)
afa74d42 783 croak_xs_usage(cv, "sv");
c4420975
AL
784 else {
785 SV * const sv = ST(0);
786 STRLEN len;
787 const char * const s = SvPV_const(sv,len);
788 if (!SvUTF8(sv) || is_utf8_string((const U8*)s,len))
789 XSRETURN_YES;
790 else
791 XSRETURN_NO;
792 }
41be1fbd 793 XSRETURN_EMPTY;
1b026014
NIS
794}
795
796XS(XS_utf8_encode)
797{
97aff369 798 dVAR;
1b026014
NIS
799 dXSARGS;
800 if (items != 1)
afa74d42 801 croak_xs_usage(cv, "sv");
c4420975 802 sv_utf8_encode(ST(0));
1b026014
NIS
803 XSRETURN_EMPTY;
804}
805
806XS(XS_utf8_decode)
807{
97aff369 808 dVAR;
1b026014
NIS
809 dXSARGS;
810 if (items != 1)
afa74d42 811 croak_xs_usage(cv, "sv");
c4420975
AL
812 else {
813 SV * const sv = ST(0);
b2b7346b 814 bool RETVAL;
492ebaba 815 if (SvREADONLY(sv)) sv_force_normal(sv);
c7102404 816 SvPV_force_nolen(sv);
b2b7346b 817 RETVAL = sv_utf8_decode(sv);
1b026014 818 ST(0) = boolSV(RETVAL);
1b026014
NIS
819 }
820 XSRETURN(1);
821}
822
823XS(XS_utf8_upgrade)
824{
97aff369 825 dVAR;
1b026014
NIS
826 dXSARGS;
827 if (items != 1)
afa74d42 828 croak_xs_usage(cv, "sv");
c4420975
AL
829 else {
830 SV * const sv = ST(0);
1b026014
NIS
831 STRLEN RETVAL;
832 dXSTARG;
833
834 RETVAL = sv_utf8_upgrade(sv);
835 XSprePUSH; PUSHi((IV)RETVAL);
836 }
837 XSRETURN(1);
838}
839
840XS(XS_utf8_downgrade)
841{
97aff369 842 dVAR;
1b026014
NIS
843 dXSARGS;
844 if (items < 1 || items > 2)
afa74d42 845 croak_xs_usage(cv, "sv, failok=0");
c4420975
AL
846 else {
847 SV * const sv = ST(0);
6867be6d
AL
848 const bool failok = (items < 2) ? 0 : (int)SvIV(ST(1));
849 const bool RETVAL = sv_utf8_downgrade(sv, failok);
1b026014 850
1b026014 851 ST(0) = boolSV(RETVAL);
1b026014
NIS
852 }
853 XSRETURN(1);
854}
855
856XS(XS_utf8_native_to_unicode)
857{
97aff369 858 dVAR;
1b026014 859 dXSARGS;
6867be6d 860 const UV uv = SvUV(ST(0));
b7953727
JH
861
862 if (items > 1)
afa74d42 863 croak_xs_usage(cv, "sv");
b7953727 864
1b026014
NIS
865 ST(0) = sv_2mortal(newSViv(NATIVE_TO_UNI(uv)));
866 XSRETURN(1);
867}
868
869XS(XS_utf8_unicode_to_native)
870{
97aff369 871 dVAR;
1b026014 872 dXSARGS;
6867be6d 873 const UV uv = SvUV(ST(0));
b7953727
JH
874
875 if (items > 1)
afa74d42 876 croak_xs_usage(cv, "sv");
b7953727 877
1b026014
NIS
878 ST(0) = sv_2mortal(newSViv(UNI_TO_NATIVE(uv)));
879 XSRETURN(1);
880}
881
14a976d6 882XS(XS_Internals_SvREADONLY) /* This is dangerous stuff. */
29569577 883{
97aff369 884 dVAR;
29569577 885 dXSARGS;
80b6a949
AB
886 SV * const svz = ST(0);
887 SV * sv;
58c0efa5 888 PERL_UNUSED_ARG(cv);
6867be6d 889
80b6a949
AB
890 /* [perl #77776] - called as &foo() not foo() */
891 if (!SvROK(svz))
892 croak_xs_usage(cv, "SCALAR[, ON]");
893
894 sv = SvRV(svz);
895
29569577 896 if (items == 1) {
3e89ba19 897 if (SvREADONLY(sv) && !SvIsCOW(sv))
29569577
JH
898 XSRETURN_YES;
899 else
900 XSRETURN_NO;
901 }
902 else if (items == 2) {
903 if (SvTRUE(ST(1))) {
3e89ba19 904 if (SvIsCOW(sv)) sv_force_normal(sv);
29569577
JH
905 SvREADONLY_on(sv);
906 XSRETURN_YES;
907 }
908 else {
14a976d6 909 /* I hope you really know what you are doing. */
3e89ba19 910 if (!SvIsCOW(sv)) SvREADONLY_off(sv);
29569577
JH
911 XSRETURN_NO;
912 }
913 }
14a976d6 914 XSRETURN_UNDEF; /* Can't happen. */
29569577
JH
915}
916
14a976d6 917XS(XS_Internals_SvREFCNT) /* This is dangerous stuff. */
29569577 918{
97aff369 919 dVAR;
29569577 920 dXSARGS;
80b6a949
AB
921 SV * const svz = ST(0);
922 SV * sv;
58c0efa5 923 PERL_UNUSED_ARG(cv);
6867be6d 924
80b6a949
AB
925 /* [perl #77776] - called as &foo() not foo() */
926 if (!SvROK(svz))
927 croak_xs_usage(cv, "SCALAR[, REFCOUNT]");
928
929 sv = SvRV(svz);
930
29569577 931 if (items == 1)
691f1758 932 XSRETURN_UV(SvREFCNT(sv) - 1); /* Minus the ref created for us. */
29569577 933 else if (items == 2) {
14a976d6 934 /* I hope you really know what you are doing. */
691f1758
TC
935 SvREFCNT(sv) = SvUV(ST(1)) + 1; /* we free one ref on exit */
936 XSRETURN_UV(SvREFCNT(sv) - 1);
29569577 937 }
14a976d6 938 XSRETURN_UNDEF; /* Can't happen. */
29569577
JH
939}
940
f044d0d1 941XS(XS_Internals_hv_clear_placehold)
dfd4ef2f 942{
97aff369 943 dVAR;
dfd4ef2f 944 dXSARGS;
6867be6d 945
80b6a949 946 if (items != 1 || !SvROK(ST(0)))
afa74d42 947 croak_xs_usage(cv, "hv");
c4420975 948 else {
ef8f7699 949 HV * const hv = MUTABLE_HV(SvRV(ST(0)));
c4420975
AL
950 hv_clear_placeholders(hv);
951 XSRETURN(0);
952 }
dfd4ef2f 953}
39f7a870
JH
954
955XS(XS_PerlIO_get_layers)
956{
97aff369 957 dVAR;
39f7a870
JH
958 dXSARGS;
959 if (items < 1 || items % 2 == 0)
afa74d42 960 croak_xs_usage(cv, "filehandle[,args]");
5fef3b4a 961#ifdef USE_PERLIO
39f7a870
JH
962 {
963 SV * sv;
964 GV * gv;
965 IO * io;
966 bool input = TRUE;
967 bool details = FALSE;
968
969 if (items > 1) {
c4420975 970 SV * const *svp;
39f7a870 971 for (svp = MARK + 2; svp <= SP; svp += 2) {
c4420975
AL
972 SV * const * const varp = svp;
973 SV * const * const valp = svp + 1;
39f7a870 974 STRLEN klen;
c4420975 975 const char * const key = SvPV_const(*varp, klen);
39f7a870
JH
976
977 switch (*key) {
978 case 'i':
979 if (klen == 5 && memEQ(key, "input", 5)) {
980 input = SvTRUE(*valp);
981 break;
982 }
983 goto fail;
984 case 'o':
985 if (klen == 6 && memEQ(key, "output", 6)) {
986 input = !SvTRUE(*valp);
987 break;
988 }
989 goto fail;
990 case 'd':
991 if (klen == 7 && memEQ(key, "details", 7)) {
992 details = SvTRUE(*valp);
993 break;
994 }
995 goto fail;
996 default:
997 fail:
998 Perl_croak(aTHX_
999 "get_layers: unknown argument '%s'",
1000 key);
1001 }
1002 }
1003
1004 SP -= (items - 1);
1005 }
1006
1007 sv = POPs;
7f9aa7d3 1008 gv = MAYBE_DEREF_GV(sv);
39f7a870 1009
3825652d 1010 if (!gv && !SvROK(sv))
7f9aa7d3 1011 gv = gv_fetchsv_nomg(sv, 0, SVt_PVIO);
39f7a870
JH
1012
1013 if (gv && (io = GvIO(gv))) {
c4420975 1014 AV* const av = PerlIO_get_layers(aTHX_ input ?
39f7a870
JH
1015 IoIFP(io) : IoOFP(io));
1016 I32 i;
c4420975 1017 const I32 last = av_len(av);
39f7a870
JH
1018 I32 nitem = 0;
1019
1020 for (i = last; i >= 0; i -= 3) {
c4420975
AL
1021 SV * const * const namsvp = av_fetch(av, i - 2, FALSE);
1022 SV * const * const argsvp = av_fetch(av, i - 1, FALSE);
1023 SV * const * const flgsvp = av_fetch(av, i, FALSE);
39f7a870 1024
c4420975
AL
1025 const bool namok = namsvp && *namsvp && SvPOK(*namsvp);
1026 const bool argok = argsvp && *argsvp && SvPOK(*argsvp);
1027 const bool flgok = flgsvp && *flgsvp && SvIOK(*flgsvp);
39f7a870
JH
1028
1029 if (details) {
92e45a3e
NC
1030 /* Indents of 5? Yuck. */
1031 /* We know that PerlIO_get_layers creates a new SV for
1032 the name and flags, so we can just take a reference
1033 and "steal" it when we free the AV below. */
ec3bab8e 1034 XPUSHs(namok
92e45a3e 1035 ? sv_2mortal(SvREFCNT_inc_simple_NN(*namsvp))
ec3bab8e
NC
1036 : &PL_sv_undef);
1037 XPUSHs(argok
92e45a3e
NC
1038 ? newSVpvn_flags(SvPVX_const(*argsvp),
1039 SvCUR(*argsvp),
1040 (SvUTF8(*argsvp) ? SVf_UTF8 : 0)
1041 | SVs_TEMP)
1042 : &PL_sv_undef);
96ccaf53 1043 XPUSHs(flgok
92e45a3e 1044 ? sv_2mortal(SvREFCNT_inc_simple_NN(*flgsvp))
ec3bab8e 1045 : &PL_sv_undef);
39f7a870
JH
1046 nitem += 3;
1047 }
1048 else {
1049 if (namok && argok)
1eb9e81d 1050 XPUSHs(sv_2mortal(Perl_newSVpvf(aTHX_ "%"SVf"(%"SVf")",
be2597df 1051 SVfARG(*namsvp),
1eb9e81d 1052 SVfARG(*argsvp))));
39f7a870 1053 else if (namok)
92e45a3e 1054 XPUSHs(sv_2mortal(SvREFCNT_inc_simple_NN(*namsvp)));
39f7a870
JH
1055 else
1056 XPUSHs(&PL_sv_undef);
1057 nitem++;
1058 if (flgok) {
c4420975 1059 const IV flags = SvIVX(*flgsvp);
39f7a870
JH
1060
1061 if (flags & PERLIO_F_UTF8) {
84bafc02 1062 XPUSHs(newSVpvs_flags("utf8", SVs_TEMP));
39f7a870
JH
1063 nitem++;
1064 }
1065 }
1066 }
1067 }
1068
1069 SvREFCNT_dec(av);
1070
1071 XSRETURN(nitem);
1072 }
1073 }
5fef3b4a 1074#endif
39f7a870
JH
1075
1076 XSRETURN(0);
1077}
1078
9a7034eb 1079XS(XS_Internals_hash_seed)
c910b28a 1080{
97aff369 1081 dVAR;
c85d3f85
NC
1082 /* Using dXSARGS would also have dITEM and dSP,
1083 * which define 2 unused local variables. */
557b887a 1084 dAXMARK;
53c1dcc0 1085 PERL_UNUSED_ARG(cv);
ad73156c 1086 PERL_UNUSED_VAR(mark);
81eaca17 1087 XSRETURN_UV(PERL_HASH_SEED);
c910b28a
JH
1088}
1089
008fb0c0 1090XS(XS_Internals_rehash_seed)
8e90d776 1091{
97aff369 1092 dVAR;
8e90d776
NC
1093 /* Using dXSARGS would also have dITEM and dSP,
1094 * which define 2 unused local variables. */
557b887a 1095 dAXMARK;
53c1dcc0 1096 PERL_UNUSED_ARG(cv);
ad73156c 1097 PERL_UNUSED_VAR(mark);
008fb0c0 1098 XSRETURN_UV(PL_rehash_seed);
8e90d776
NC
1099}
1100
05619474
NC
1101XS(XS_Internals_HvREHASH) /* Subject to change */
1102{
97aff369 1103 dVAR;
05619474 1104 dXSARGS;
93c51217 1105 PERL_UNUSED_ARG(cv);
05619474 1106 if (SvROK(ST(0))) {
ef8f7699 1107 const HV * const hv = (const HV *) SvRV(ST(0));
05619474
NC
1108 if (items == 1 && SvTYPE(hv) == SVt_PVHV) {
1109 if (HvREHASH(hv))
1110 XSRETURN_YES;
1111 else
1112 XSRETURN_NO;
1113 }
1114 }
1115 Perl_croak(aTHX_ "Internals::HvREHASH $hashref");
1116}
241d1a3b 1117
80305961
YO
1118XS(XS_re_is_regexp)
1119{
1120 dVAR;
1121 dXSARGS;
f7e71195
AB
1122 PERL_UNUSED_VAR(cv);
1123
80305961 1124 if (items != 1)
afa74d42 1125 croak_xs_usage(cv, "sv");
f7e71195 1126
f7e71195
AB
1127 if (SvRXOK(ST(0))) {
1128 XSRETURN_YES;
1129 } else {
1130 XSRETURN_NO;
80305961
YO
1131 }
1132}
1133
192b9cd1 1134XS(XS_re_regnames_count)
80305961 1135{
192b9cd1
AB
1136 REGEXP *rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1137 SV * ret;
80305961
YO
1138 dVAR;
1139 dXSARGS;
192b9cd1
AB
1140
1141 if (items != 0)
afa74d42 1142 croak_xs_usage(cv, "");
192b9cd1
AB
1143
1144 SP -= items;
fdae9473 1145 PUTBACK;
192b9cd1
AB
1146
1147 if (!rx)
1148 XSRETURN_UNDEF;
1149
1150 ret = CALLREG_NAMED_BUFF_COUNT(rx);
1151
1152 SPAGAIN;
fdae9473
NC
1153 PUSHs(ret ? sv_2mortal(ret) : &PL_sv_undef);
1154 XSRETURN(1);
192b9cd1
AB
1155}
1156
1157XS(XS_re_regname)
1158{
1159 dVAR;
1160 dXSARGS;
1161 REGEXP * rx;
1162 U32 flags;
1163 SV * ret;
1164
28d8d7f4 1165 if (items < 1 || items > 2)
afa74d42 1166 croak_xs_usage(cv, "name[, all ]");
192b9cd1 1167
80305961 1168 SP -= items;
fdae9473 1169 PUTBACK;
80305961 1170
192b9cd1
AB
1171 rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1172
1173 if (!rx)
1174 XSRETURN_UNDEF;
1175
1176 if (items == 2 && SvTRUE(ST(1))) {
f1b875a0 1177 flags = RXapif_ALL;
192b9cd1 1178 } else {
f1b875a0 1179 flags = RXapif_ONE;
80305961 1180 }
f1b875a0 1181 ret = CALLREG_NAMED_BUFF_FETCH(rx, ST(0), (flags | RXapif_REGNAME));
192b9cd1 1182
fdae9473
NC
1183 SPAGAIN;
1184 PUSHs(ret ? sv_2mortal(ret) : &PL_sv_undef);
1185 XSRETURN(1);
80305961
YO
1186}
1187
192b9cd1 1188
80305961
YO
1189XS(XS_re_regnames)
1190{
192b9cd1 1191 dVAR;
80305961 1192 dXSARGS;
192b9cd1
AB
1193 REGEXP * rx;
1194 U32 flags;
1195 SV *ret;
1196 AV *av;
1197 I32 length;
1198 I32 i;
1199 SV **entry;
1200
1201 if (items > 1)
afa74d42 1202 croak_xs_usage(cv, "[all]");
192b9cd1
AB
1203
1204 rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1205
1206 if (!rx)
1207 XSRETURN_UNDEF;
1208
1209 if (items == 1 && SvTRUE(ST(0))) {
f1b875a0 1210 flags = RXapif_ALL;
192b9cd1 1211 } else {
f1b875a0 1212 flags = RXapif_ONE;
192b9cd1
AB
1213 }
1214
80305961 1215 SP -= items;
fdae9473 1216 PUTBACK;
80305961 1217
f1b875a0 1218 ret = CALLREG_NAMED_BUFF_ALL(rx, (flags | RXapif_REGNAMES));
192b9cd1
AB
1219
1220 SPAGAIN;
1221
192b9cd1
AB
1222 if (!ret)
1223 XSRETURN_UNDEF;
1224
502c6561 1225 av = MUTABLE_AV(SvRV(ret));
192b9cd1
AB
1226 length = av_len(av);
1227
1228 for (i = 0; i <= length; i++) {
1229 entry = av_fetch(av, i, FALSE);
1230
1231 if (!entry)
1232 Perl_croak(aTHX_ "NULL array element in re::regnames()");
1233
ec83ea38 1234 mXPUSHs(SvREFCNT_inc_simple_NN(*entry));
80305961 1235 }
ec83ea38
MHM
1236
1237 SvREFCNT_dec(ret);
1238
192b9cd1
AB
1239 PUTBACK;
1240 return;
80305961
YO
1241}
1242
192c1e27
JH
1243XS(XS_re_regexp_pattern)
1244{
1245 dVAR;
1246 dXSARGS;
1247 REGEXP *re;
192c1e27
JH
1248
1249 if (items != 1)
afa74d42 1250 croak_xs_usage(cv, "sv");
192c1e27
JH
1251
1252 SP -= items;
1253
1254 /*
1255 Checks if a reference is a regex or not. If the parameter is
1256 not a ref, or is not the result of a qr// then returns false
1257 in scalar context and an empty list in list context.
1258 Otherwise in list context it returns the pattern and the
1259 modifiers, in scalar context it returns the pattern just as it
1260 would if the qr// was stringified normally, regardless as
486ec47a 1261 to the class of the variable and any stringification overloads
192c1e27
JH
1262 on the object.
1263 */
1264
1265 if ((re = SvRX(ST(0)))) /* assign deliberate */
1266 {
22c985d5 1267 /* Houston, we have a regex! */
192c1e27 1268 SV *pattern;
192c1e27
JH
1269
1270 if ( GIMME_V == G_ARRAY ) {
9de15fec 1271 STRLEN left = 0;
a62b1201 1272 char reflags[sizeof(INT_PAT_MODS) + MAX_CHARSET_NAME_LENGTH];
69af1167
SH
1273 const char *fptr;
1274 char ch;
1275 U16 match_flags;
1276
192c1e27
JH
1277 /*
1278 we are in list context so stringify
1279 the modifiers that apply. We ignore "negative
a62b1201 1280 modifiers" in this scenario, and the default character set
192c1e27
JH
1281 */
1282
a62b1201
KW
1283 if (get_regex_charset(RX_EXTFLAGS(re)) != REGEX_DEPENDS_CHARSET) {
1284 STRLEN len;
1285 const char* const name = get_regex_charset_name(RX_EXTFLAGS(re),
1286 &len);
1287 Copy(name, reflags + left, len, char);
1288 left += len;
9de15fec 1289 }
69af1167 1290 fptr = INT_PAT_MODS;
73134a2e 1291 match_flags = (U16)((RX_EXTFLAGS(re) & RXf_PMf_COMPILETIME)
192c1e27
JH
1292 >> RXf_PMf_STD_PMMOD_SHIFT);
1293
1294 while((ch = *fptr++)) {
1295 if(match_flags & 1) {
1296 reflags[left++] = ch;
1297 }
1298 match_flags >>= 1;
1299 }
1300
fb632ce3
NC
1301 pattern = newSVpvn_flags(RX_PRECOMP(re),RX_PRELEN(re),
1302 (RX_UTF8(re) ? SVf_UTF8 : 0) | SVs_TEMP);
192c1e27
JH
1303
1304 /* return the pattern and the modifiers */
1305 XPUSHs(pattern);
fb632ce3 1306 XPUSHs(newSVpvn_flags(reflags, left, SVs_TEMP));
192c1e27
JH
1307 XSRETURN(2);
1308 } else {
1309 /* Scalar, so use the string that Perl would return */
1310 /* return the pattern in (?msix:..) format */
1311#if PERL_VERSION >= 11
daba3364 1312 pattern = sv_2mortal(newSVsv(MUTABLE_SV(re)));
192c1e27 1313#else
fb632ce3
NC
1314 pattern = newSVpvn_flags(RX_WRAPPED(re), RX_WRAPLEN(re),
1315 (RX_UTF8(re) ? SVf_UTF8 : 0) | SVs_TEMP);
192c1e27
JH
1316#endif
1317 XPUSHs(pattern);
1318 XSRETURN(1);
1319 }
1320 } else {
1321 /* It ain't a regexp folks */
1322 if ( GIMME_V == G_ARRAY ) {
1323 /* return the empty list */
1324 XSRETURN_UNDEF;
1325 } else {
1326 /* Because of the (?:..) wrapping involved in a
1327 stringified pattern it is impossible to get a
1328 result for a real regexp that would evaluate to
1329 false. Therefore we can return PL_sv_no to signify
1330 that the object is not a regex, this means that one
1331 can say
1332
1333 if (regex($might_be_a_regex) eq '(?:foo)') { }
1334
1335 and not worry about undefined values.
1336 */
1337 XSRETURN_NO;
1338 }
1339 }
1340 /* NOT-REACHED */
1341}
1342
eff5b9d5
NC
1343struct xsub_details {
1344 const char *name;
1345 XSUBADDR_t xsub;
1346 const char *proto;
1347};
1348
1349struct xsub_details details[] = {
1350 {"UNIVERSAL::isa", XS_UNIVERSAL_isa, NULL},
1351 {"UNIVERSAL::can", XS_UNIVERSAL_can, NULL},
1352 {"UNIVERSAL::DOES", XS_UNIVERSAL_DOES, NULL},
1353 {"UNIVERSAL::VERSION", XS_UNIVERSAL_VERSION, NULL},
1354 {"version::()", XS_version_noop, NULL},
1355 {"version::new", XS_version_new, NULL},
1356 {"version::parse", XS_version_new, NULL},
1357 {"version::(\"\"", XS_version_stringify, NULL},
1358 {"version::stringify", XS_version_stringify, NULL},
1359 {"version::(0+", XS_version_numify, NULL},
1360 {"version::numify", XS_version_numify, NULL},
1361 {"version::normal", XS_version_normal, NULL},
1362 {"version::(cmp", XS_version_vcmp, NULL},
1363 {"version::(<=>", XS_version_vcmp, NULL},
1364 {"version::vcmp", XS_version_vcmp, NULL},
1365 {"version::(bool", XS_version_boolean, NULL},
1366 {"version::boolean", XS_version_boolean, NULL},
43d9ecf9
JP
1367 {"version::(+", XS_version_noop, NULL},
1368 {"version::(-", XS_version_noop, NULL},
1369 {"version::(*", XS_version_noop, NULL},
1370 {"version::(/", XS_version_noop, NULL},
1371 {"version::(+=", XS_version_noop, NULL},
1372 {"version::(-=", XS_version_noop, NULL},
1373 {"version::(*=", XS_version_noop, NULL},
1374 {"version::(/=", XS_version_noop, NULL},
1375 {"version::(abs", XS_version_noop, NULL},
eff5b9d5
NC
1376 {"version::(nomethod", XS_version_noop, NULL},
1377 {"version::noop", XS_version_noop, NULL},
1378 {"version::is_alpha", XS_version_is_alpha, NULL},
1379 {"version::qv", XS_version_qv, NULL},
1380 {"version::declare", XS_version_qv, NULL},
1381 {"version::is_qv", XS_version_is_qv, NULL},
1382 {"utf8::is_utf8", XS_utf8_is_utf8, NULL},
1383 {"utf8::valid", XS_utf8_valid, NULL},
1384 {"utf8::encode", XS_utf8_encode, NULL},
1385 {"utf8::decode", XS_utf8_decode, NULL},
1386 {"utf8::upgrade", XS_utf8_upgrade, NULL},
1387 {"utf8::downgrade", XS_utf8_downgrade, NULL},
1388 {"utf8::native_to_unicode", XS_utf8_native_to_unicode, NULL},
1389 {"utf8::unicode_to_native", XS_utf8_unicode_to_native, NULL},
1390 {"Internals::SvREADONLY", XS_Internals_SvREADONLY, "\\[$%@];$"},
1391 {"Internals::SvREFCNT", XS_Internals_SvREFCNT, "\\[$%@];$"},
1392 {"Internals::hv_clear_placeholders", XS_Internals_hv_clear_placehold, "\\%"},
1393 {"PerlIO::get_layers", XS_PerlIO_get_layers, "*;@"},
1394 {"Internals::hash_seed", XS_Internals_hash_seed, ""},
1395 {"Internals::rehash_seed", XS_Internals_rehash_seed, ""},
1396 {"Internals::HvREHASH", XS_Internals_HvREHASH, "\\%"},
1397 {"re::is_regexp", XS_re_is_regexp, "$"},
1398 {"re::regname", XS_re_regname, ";$$"},
1399 {"re::regnames", XS_re_regnames, ";$"},
1400 {"re::regnames_count", XS_re_regnames_count, ""},
1401 {"re::regexp_pattern", XS_re_regexp_pattern, "$"},
eff5b9d5
NC
1402};
1403
1404void
1405Perl_boot_core_UNIVERSAL(pTHX)
1406{
1407 dVAR;
1408 static const char file[] = __FILE__;
1409 struct xsub_details *xsub = details;
1410 const struct xsub_details *end
1411 = details + sizeof(details) / sizeof(details[0]);
1412
1413 do {
1414 newXS_flags(xsub->name, xsub->xsub, file, xsub->proto, 0);
1415 } while (++xsub < end);
1416
1417 /* register the overloading (type 'A') magic */
1418 PL_amagic_generation++;
1419
1420 /* Providing a Regexp::DESTROY fixes #21347. See test in t/op/ref.t */
bad4ae38
FC
1421 {
1422 CV * const cv =
1423 newCONSTSUB(get_hv("Regexp::", GV_ADD), "DESTROY", NULL);
1424 Safefree(CvFILE(cv));
1425 CvFILE(cv) = (char *)file;
1426 CvDYNFILE_off(cv);
1427 }
eff5b9d5 1428}
80305961 1429
241d1a3b
NC
1430/*
1431 * Local variables:
1432 * c-indentation-style: bsd
1433 * c-basic-offset: 4
1434 * indent-tabs-mode: t
1435 * End:
1436 *
37442d52
RGS
1437 * ex: set ts=8 sts=4 sw=4 noet:
1438 */