This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Remove declaration of XS_Internals_inc_sub_generation
[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
24 * clever to move them to seperate XS files which would then be pulled
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
aea32303
NC
36static HV *
37S_get_isa_hash(pTHX_ HV *const stash)
00bf72ff
NC
38{
39 dVAR;
40 struct mro_meta *const meta = HvMROMETA(stash);
41
42 PERL_ARGS_ASSERT_GET_ISA_HASH;
43
44 if (!meta->isa) {
45 AV *const isa = mro_get_linear_isa(stash);
46 if (!meta->isa) {
47 HV *const isa_hash = newHV();
48 /* Linearisation didn't build it for us, so do it here. */
49 SV *const *svp = AvARRAY(isa);
50 SV *const *const svp_end = svp + AvFILLp(isa) + 1;
51 const HEK *const canon_name = HvNAME_HEK(stash);
52
53 while (svp < svp_end) {
54 (void) hv_store_ent(isa_hash, *svp++, &PL_sv_undef, 0);
55 }
56
57 (void) hv_common(isa_hash, NULL, HEK_KEY(canon_name),
58 HEK_LEN(canon_name), HEK_FLAGS(canon_name),
59 HV_FETCH_ISSTORE, &PL_sv_undef,
60 HEK_HASH(canon_name));
61 (void) hv_store(isa_hash, "UNIVERSAL", 9, &PL_sv_undef, 0);
62
63 SvREADONLY_on(isa_hash);
64
65 meta->isa = isa_hash;
66 }
67 }
68 return meta->isa;
69}
70
6d4a7be2 71/*
72 * Contributed by Graham Barr <Graham.Barr@tiuk.ti.com>
73 * The main guts of traverse_isa was actually copied from gv_fetchmeth
74 */
75
a9ec700e 76STATIC bool
515a4f72 77S_isa_lookup(pTHX_ HV *stash, const char * const name)
6d4a7be2 78{
97aff369 79 dVAR;
a49ba3fc 80 const struct mro_meta *const meta = HvMROMETA(stash);
aea32303 81 HV *const isa = meta->isa ? meta->isa : S_get_isa_hash(aTHX_ stash);
a49ba3fc
NC
82 STRLEN len = strlen(name);
83 const HV *our_stash;
6d4a7be2 84
7918f24d
NC
85 PERL_ARGS_ASSERT_ISA_LOOKUP;
86
a49ba3fc
NC
87 if (hv_common(isa, NULL, name, len, 0 /* No "UTF-8" flag possible with only
88 a char * argument*/,
89 HV_FETCH_ISEXISTS, NULL, 0)) {
90 /* Direct name lookup worked. */
a9ec700e 91 return TRUE;
a49ba3fc 92 }
6d4a7be2 93
a49ba3fc
NC
94 /* A stash/class can go by many names (ie. User == main::User), so
95 we use the name in the stash itself, which is canonical. */
96 our_stash = gv_stashpvn(name, len, 0);
97
98 if (our_stash) {
99 HEK *const canon_name = HvNAME_HEK(our_stash);
a1d407e8 100
a49ba3fc
NC
101 if (hv_common(isa, NULL, HEK_KEY(canon_name), HEK_LEN(canon_name),
102 HEK_FLAGS(canon_name),
103 HV_FETCH_ISEXISTS, NULL, HEK_HASH(canon_name))) {
e1a479c5 104 return TRUE;
a49ba3fc 105 }
6d4a7be2 106 }
107
a9ec700e 108 return FALSE;
6d4a7be2 109}
110
954c1994 111/*
ccfc67b7
JH
112=head1 SV Manipulation Functions
113
954c1994
GS
114=for apidoc sv_derived_from
115
6885da0e 116Returns a boolean indicating whether the SV is derived from the specified class
117I<at the C level>. To check derivation at the Perl level, call C<isa()> as a
118normal Perl method.
954c1994
GS
119
120=cut
121*/
122
55497cff 123bool
15f169a1 124Perl_sv_derived_from(pTHX_ SV *sv, const char *const name)
55497cff 125{
97aff369 126 dVAR;
0b6f4f5c 127 HV *stash;
46e4b22b 128
7918f24d
NC
129 PERL_ARGS_ASSERT_SV_DERIVED_FROM;
130
5b295bef 131 SvGETMAGIC(sv);
55497cff 132
133 if (SvROK(sv)) {
0b6f4f5c 134 const char *type;
55497cff 135 sv = SvRV(sv);
136 type = sv_reftype(sv,0);
0b6f4f5c
AL
137 if (type && strEQ(type,name))
138 return TRUE;
139 stash = SvOBJECT(sv) ? SvSTASH(sv) : NULL;
55497cff 140 }
141 else {
da51bb9b 142 stash = gv_stashsv(sv, 0);
55497cff 143 }
46e4b22b 144
4a9e32d8 145 return stash ? isa_lookup(stash, name) : FALSE;
55497cff 146}
147
cbc021f9 148/*
149=for apidoc sv_does
150
151Returns a boolean indicating whether the SV performs a specific, named role.
152The SV can be a Perl object or the name of a Perl class.
153
154=cut
155*/
156
1b026014
NIS
157#include "XSUB.h"
158
cbc021f9 159bool
15f169a1 160Perl_sv_does(pTHX_ SV *sv, const char *const name)
cbc021f9 161{
162 const char *classname;
163 bool does_it;
59e7186f 164 SV *methodname;
cbc021f9 165 dSP;
7918f24d
NC
166
167 PERL_ARGS_ASSERT_SV_DOES;
168
cbc021f9 169 ENTER;
170 SAVETMPS;
171
172 SvGETMAGIC(sv);
173
174 if (!SvOK(sv) || !(SvROK(sv) || (SvPOK(sv) && SvCUR(sv))
175 || (SvGMAGICAL(sv) && SvPOKp(sv) && SvCUR(sv))))
176 return FALSE;
177
178 if (sv_isobject(sv)) {
179 classname = sv_reftype(SvRV(sv),TRUE);
180 } else {
94707740 181 classname = SvPV_nolen(sv);
cbc021f9 182 }
183
184 if (strEQ(name,classname))
185 return TRUE;
186
187 PUSHMARK(SP);
188 XPUSHs(sv);
6e449a3a 189 mXPUSHs(newSVpv(name, 0));
cbc021f9 190 PUTBACK;
191
84bafc02 192 methodname = newSVpvs_flags("isa", SVs_TEMP);
59e7186f
RGS
193 /* ugly hack: use the SvSCREAM flag so S_method_common
194 * can figure out we're calling DOES() and not isa(),
195 * and report eventual errors correctly. --rgs */
196 SvSCREAM_on(methodname);
197 call_sv(methodname, G_SCALAR | G_METHOD);
cbc021f9 198 SPAGAIN;
199
200 does_it = SvTRUE( TOPs );
201 FREETMPS;
202 LEAVE;
203
204 return does_it;
205}
206
27da23d5
JH
207PERL_XS_EXPORT_C void XS_UNIVERSAL_isa(pTHX_ CV *cv);
208PERL_XS_EXPORT_C void XS_UNIVERSAL_can(pTHX_ CV *cv);
cbc021f9 209PERL_XS_EXPORT_C void XS_UNIVERSAL_DOES(pTHX_ CV *cv);
27da23d5 210PERL_XS_EXPORT_C void XS_UNIVERSAL_VERSION(pTHX_ CV *cv);
439cb1c4
JP
211XS(XS_version_new);
212XS(XS_version_stringify);
213XS(XS_version_numify);
9137345a 214XS(XS_version_normal);
439cb1c4
JP
215XS(XS_version_vcmp);
216XS(XS_version_boolean);
2dfd8427
AL
217#ifdef HASATTRIBUTE_NORETURN
218XS(XS_version_noop) __attribute__noreturn__;
219#else
439cb1c4 220XS(XS_version_noop);
2dfd8427 221#endif
c8d69e4a 222XS(XS_version_is_alpha);
137d6fc0 223XS(XS_version_qv);
8800c35a 224XS(XS_utf8_is_utf8);
1b026014
NIS
225XS(XS_utf8_valid);
226XS(XS_utf8_encode);
227XS(XS_utf8_decode);
228XS(XS_utf8_upgrade);
229XS(XS_utf8_downgrade);
230XS(XS_utf8_unicode_to_native);
231XS(XS_utf8_native_to_unicode);
29569577
JH
232XS(XS_Internals_SvREADONLY);
233XS(XS_Internals_SvREFCNT);
f044d0d1 234XS(XS_Internals_hv_clear_placehold);
39f7a870 235XS(XS_PerlIO_get_layers);
f63535fc 236XS(XS_Regexp_DESTROY);
9a7034eb 237XS(XS_Internals_hash_seed);
008fb0c0 238XS(XS_Internals_rehash_seed);
05619474 239XS(XS_Internals_HvREHASH);
80305961 240XS(XS_re_is_regexp);
192b9cd1
AB
241XS(XS_re_regname);
242XS(XS_re_regnames);
80305961 243XS(XS_re_regnames_count);
192c1e27 244XS(XS_re_regexp_pattern);
192b9cd1
AB
245XS(XS_Tie_Hash_NamedCapture_FETCH);
246XS(XS_Tie_Hash_NamedCapture_STORE);
247XS(XS_Tie_Hash_NamedCapture_DELETE);
248XS(XS_Tie_Hash_NamedCapture_CLEAR);
249XS(XS_Tie_Hash_NamedCapture_EXISTS);
86aa3d53
CB
250XS(XS_Tie_Hash_NamedCapture_FIRSTK);
251XS(XS_Tie_Hash_NamedCapture_NEXTK);
192b9cd1
AB
252XS(XS_Tie_Hash_NamedCapture_SCALAR);
253XS(XS_Tie_Hash_NamedCapture_flags);
0cb96387
GS
254
255void
256Perl_boot_core_UNIVERSAL(pTHX)
257{
97aff369 258 dVAR;
157e3fc8 259 static const char file[] = __FILE__;
0cb96387
GS
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
JP
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
JP
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
JP
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
NIS
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
JH
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
JH
298 newXSproto("PerlIO::get_layers",
299 XS_PerlIO_get_layers, file, "*;@");
f63535fc 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, "\\%");
80305961 304 newXSproto("re::is_regexp", XS_re_is_regexp, file, "$");
28d8d7f4
YO
305 newXSproto("re::regname", XS_re_regname, file, ";$$");
306 newXSproto("re::regnames", XS_re_regnames, file, ";$");
28d8d7f4 307 newXSproto("re::regnames_count", XS_re_regnames_count, file, "");
192c1e27 308 newXSproto("re::regexp_pattern", XS_re_regexp_pattern, file, "$");
192b9cd1
AB
309 newXS("Tie::Hash::NamedCapture::FETCH", XS_Tie_Hash_NamedCapture_FETCH, file);
310 newXS("Tie::Hash::NamedCapture::STORE", XS_Tie_Hash_NamedCapture_STORE, file);
311 newXS("Tie::Hash::NamedCapture::DELETE", XS_Tie_Hash_NamedCapture_DELETE, file);
312 newXS("Tie::Hash::NamedCapture::CLEAR", XS_Tie_Hash_NamedCapture_CLEAR, file);
313 newXS("Tie::Hash::NamedCapture::EXISTS", XS_Tie_Hash_NamedCapture_EXISTS, file);
86aa3d53
CB
314 newXS("Tie::Hash::NamedCapture::FIRSTKEY", XS_Tie_Hash_NamedCapture_FIRSTK, file);
315 newXS("Tie::Hash::NamedCapture::NEXTKEY", XS_Tie_Hash_NamedCapture_NEXTK, file);
192b9cd1
AB
316 newXS("Tie::Hash::NamedCapture::SCALAR", XS_Tie_Hash_NamedCapture_SCALAR, file);
317 newXS("Tie::Hash::NamedCapture::flags", XS_Tie_Hash_NamedCapture_flags, file);
0cb96387
GS
318}
319
afa74d42
NC
320/*
321=for apidoc croak_xs_usage
322
323A specialised variant of C<croak()> for emitting the usage message for xsubs
324
325 croak_xs_usage(cv, "eee_yow");
326
327works out the package name and subroutine name from C<cv>, and then calls
328C<croak()>. Hence if C<cv> is C<&ouch::awk>, it would call C<croak> as:
329
330 Perl_croak(aTHX_ "Usage %s::%s(%s)", "ouch" "awk", "eee_yow");
331
332=cut
333*/
334
335void
336Perl_croak_xs_usage(pTHX_ const CV *const cv, const char *const params)
337{
338 const GV *const gv = CvGV(cv);
339
340 PERL_ARGS_ASSERT_CROAK_XS_USAGE;
341
342 if (gv) {
343 const char *const gvname = GvNAME(gv);
344 const HV *const stash = GvSTASH(gv);
345 const char *const hvname = stash ? HvNAME_get(stash) : NULL;
346
347 if (hvname)
348 Perl_croak(aTHX_ "Usage: %s::%s(%s)", hvname, gvname, params);
349 else
350 Perl_croak(aTHX_ "Usage: %s(%s)", gvname, params);
351 } else {
352 /* Pants. I don't think that it should be possible to get here. */
93c51217 353 Perl_croak(aTHX_ "Usage: CODE(0x%"UVxf")(%s)", PTR2UV(cv), params);
afa74d42
NC
354 }
355}
55497cff 356
6d4a7be2 357XS(XS_UNIVERSAL_isa)
358{
97aff369 359 dVAR;
6d4a7be2 360 dXSARGS;
6d4a7be2 361
362 if (items != 2)
afa74d42 363 croak_xs_usage(cv, "reference, kind");
c4420975
AL
364 else {
365 SV * const sv = ST(0);
366 const char *name;
6d4a7be2 367
c4420975 368 SvGETMAGIC(sv);
d3f7f2b2 369
c4420975
AL
370 if (!SvOK(sv) || !(SvROK(sv) || (SvPOK(sv) && SvCUR(sv))
371 || (SvGMAGICAL(sv) && SvPOKp(sv) && SvCUR(sv))))
372 XSRETURN_UNDEF;
f8f70380 373
c4420975 374 name = SvPV_nolen_const(ST(1));
6d4a7be2 375
c4420975
AL
376 ST(0) = boolSV(sv_derived_from(sv, name));
377 XSRETURN(1);
378 }
6d4a7be2 379}
380
6d4a7be2 381XS(XS_UNIVERSAL_can)
382{
97aff369 383 dVAR;
6d4a7be2 384 dXSARGS;
385 SV *sv;
6867be6d 386 const char *name;
6d4a7be2 387 SV *rv;
6f08146e 388 HV *pkg = NULL;
6d4a7be2 389
390 if (items != 2)
afa74d42 391 croak_xs_usage(cv, "object-ref, method");
6d4a7be2 392
393 sv = ST(0);
f8f70380 394
5b295bef 395 SvGETMAGIC(sv);
d3f7f2b2 396
253ecd6d
RGS
397 if (!SvOK(sv) || !(SvROK(sv) || (SvPOK(sv) && SvCUR(sv))
398 || (SvGMAGICAL(sv) && SvPOKp(sv) && SvCUR(sv))))
f8f70380
GS
399 XSRETURN_UNDEF;
400
0510663f 401 name = SvPV_nolen_const(ST(1));
3280af22 402 rv = &PL_sv_undef;
6d4a7be2 403
46e4b22b 404 if (SvROK(sv)) {
daba3364 405 sv = MUTABLE_SV(SvRV(sv));
46e4b22b 406 if (SvOBJECT(sv))
6f08146e
NIS
407 pkg = SvSTASH(sv);
408 }
409 else {
da51bb9b 410 pkg = gv_stashsv(sv, 0);
6f08146e
NIS
411 }
412
413 if (pkg) {
c4420975 414 GV * const gv = gv_fetchmethod_autoload(pkg, name, FALSE);
dc848c6f 415 if (gv && isGV(gv))
daba3364 416 rv = sv_2mortal(newRV(MUTABLE_SV(GvCV(gv))));
6d4a7be2 417 }
418
419 ST(0) = rv;
420 XSRETURN(1);
421}
422
cbc021f9 423XS(XS_UNIVERSAL_DOES)
424{
425 dVAR;
426 dXSARGS;
58c0efa5 427 PERL_UNUSED_ARG(cv);
cbc021f9 428
429 if (items != 2)
26be3db7 430 Perl_croak(aTHX_ "Usage: invocant->DOES(kind)");
cbc021f9 431 else {
432 SV * const sv = ST(0);
433 const char *name;
434
435 name = SvPV_nolen_const(ST(1));
436 if (sv_does( sv, name ))
437 XSRETURN_YES;
438
439 XSRETURN_NO;
440 }
441}
442
6d4a7be2 443XS(XS_UNIVERSAL_VERSION)
444{
97aff369 445 dVAR;
6d4a7be2 446 dXSARGS;
447 HV *pkg;
448 GV **gvp;
449 GV *gv;
450 SV *sv;
e1ec3a88 451 const char *undef;
58c0efa5 452 PERL_UNUSED_ARG(cv);
6d4a7be2 453
1571675a 454 if (SvROK(ST(0))) {
daba3364 455 sv = MUTABLE_SV(SvRV(ST(0)));
1571675a 456 if (!SvOBJECT(sv))
cea2e8a9 457 Perl_croak(aTHX_ "Cannot find version of an unblessed reference");
6d4a7be2 458 pkg = SvSTASH(sv);
459 }
460 else {
da51bb9b 461 pkg = gv_stashsv(ST(0), 0);
6d4a7be2 462 }
463
4608196e 464 gvp = pkg ? (GV**)hv_fetchs(pkg, "VERSION", FALSE) : NULL;
6d4a7be2 465
0008872a 466 if (gvp && isGV(gv = *gvp) && (sv = GvSV(gv)) && SvOK(sv)) {
c4420975 467 SV * const nsv = sv_newmortal();
6d4a7be2 468 sv_setsv(nsv, sv);
469 sv = nsv;
137d6fc0 470 if ( !sv_derived_from(sv, "version"))
ac0e6a2f 471 upg_version(sv, FALSE);
c445ea15 472 undef = NULL;
6d4a7be2 473 }
474 else {
daba3364 475 sv = &PL_sv_undef;
6d4a7be2 476 undef = "(undef)";
477 }
478
1571675a 479 if (items > 1) {
1571675a
GS
480 SV *req = ST(1);
481
62658f4d 482 if (undef) {
bfcb3514 483 if (pkg) {
c4420975 484 const char * const name = HvNAME_get(pkg);
a3b680e6 485 Perl_croak(aTHX_
bfcb3514
NC
486 "%s does not define $%s::VERSION--version check failed",
487 name, name);
488 } else {
a3b680e6
AL
489 Perl_croak(aTHX_
490 "%s defines neither package nor VERSION--version check failed",
0510663f 491 SvPVx_nolen_const(ST(0)) );
62658f4d
PM
492 }
493 }
ad63d80f 494
137d6fc0
JP
495 if ( !sv_derived_from(req, "version")) {
496 /* req may very well be R/O, so create a new object */
ac0e6a2f 497 req = sv_2mortal( new_version(req) );
137d6fc0 498 }
1571675a 499
ac0e6a2f 500 if ( vcmp( req, sv ) > 0 ) {
ef8f7699 501 if ( hv_exists(MUTABLE_HV(SvRV(req)), "qv", 2 ) ) {
ac0e6a2f
RGS
502 Perl_croak(aTHX_ "%s version %"SVf" required--"
503 "this is only version %"SVf"", HvNAME_get(pkg),
be2597df 504 SVfARG(vnormal(req)),
be2597df 505 SVfARG(vnormal(sv)));
ac0e6a2f
RGS
506 } else {
507 Perl_croak(aTHX_ "%s version %"SVf" required--"
508 "this is only version %"SVf"", HvNAME_get(pkg),
8cb289bd
RGS
509 SVfARG(vstringify(req)),
510 SVfARG(vstringify(sv)));
ac0e6a2f
RGS
511 }
512 }
513
2d8e6c8d 514 }
6d4a7be2 515
2b140d5b 516 if ( SvOK(sv) && sv_derived_from(sv, "version") ) {
8cb289bd 517 ST(0) = vstringify(sv);
13f8f398
JP
518 } else {
519 ST(0) = sv;
b38a9dc5 520 }
6d4a7be2 521
522 XSRETURN(1);
523}
524
439cb1c4
JP
525XS(XS_version_new)
526{
97aff369 527 dVAR;
439cb1c4 528 dXSARGS;
129318bd 529 if (items > 3)
afa74d42 530 croak_xs_usage(cv, "class, version");
439cb1c4
JP
531 SP -= items;
532 {
137d6fc0
JP
533 SV *vs = ST(1);
534 SV *rv;
c4420975
AL
535 const char * const classname =
536 sv_isobject(ST(0)) /* get the class if called as an object method */
537 ? HvNAME(SvSTASH(SvRV(ST(0))))
538 : (char *)SvPV_nolen(ST(0));
9137345a 539
92dcf8ce
JP
540 if ( items == 1 || vs == &PL_sv_undef ) { /* no param or explicit undef */
541 /* create empty object */
542 vs = sv_newmortal();
76f68e9b 543 sv_setpvs(vs,"");
9137345a
JP
544 }
545 else if ( items == 3 ) {
546 vs = sv_newmortal();
cfd0369c 547 Perl_sv_setpvf(aTHX_ vs,"v%s",SvPV_nolen_const(ST(2)));
129318bd 548 }
439cb1c4 549
137d6fc0 550 rv = new_version(vs);
0723351e 551 if ( strcmp(classname,"version") != 0 ) /* inherited new() */
da51bb9b 552 sv_bless(rv, gv_stashpv(classname, GV_ADD));
137d6fc0 553
6e449a3a 554 mPUSHs(rv);
439cb1c4
JP
555 PUTBACK;
556 return;
557 }
558}
559
560XS(XS_version_stringify)
561{
97aff369 562 dVAR;
41be1fbd
JH
563 dXSARGS;
564 if (items < 1)
afa74d42 565 croak_xs_usage(cv, "lobj, ...");
41be1fbd
JH
566 SP -= items;
567 {
7452cf6a 568 SV * lobj;
41be1fbd
JH
569
570 if (sv_derived_from(ST(0), "version")) {
9137345a 571 lobj = SvRV(ST(0));
41be1fbd
JH
572 }
573 else
574 Perl_croak(aTHX_ "lobj is not of type version");
575
6e449a3a 576 mPUSHs(vstringify(lobj));
41be1fbd
JH
577
578 PUTBACK;
579 return;
580 }
439cb1c4
JP
581}
582
583XS(XS_version_numify)
584{
97aff369 585 dVAR;
41be1fbd
JH
586 dXSARGS;
587 if (items < 1)
afa74d42 588 croak_xs_usage(cv, "lobj, ...");
41be1fbd
JH
589 SP -= items;
590 {
7452cf6a 591 SV * lobj;
41be1fbd
JH
592
593 if (sv_derived_from(ST(0), "version")) {
9137345a 594 lobj = SvRV(ST(0));
41be1fbd
JH
595 }
596 else
597 Perl_croak(aTHX_ "lobj is not of type version");
598
6e449a3a 599 mPUSHs(vnumify(lobj));
41be1fbd
JH
600
601 PUTBACK;
602 return;
603 }
439cb1c4
JP
604}
605
9137345a
JP
606XS(XS_version_normal)
607{
97aff369 608 dVAR;
9137345a
JP
609 dXSARGS;
610 if (items < 1)
afa74d42 611 croak_xs_usage(cv, "lobj, ...");
9137345a
JP
612 SP -= items;
613 {
7452cf6a 614 SV * lobj;
9137345a
JP
615
616 if (sv_derived_from(ST(0), "version")) {
617 lobj = SvRV(ST(0));
618 }
619 else
620 Perl_croak(aTHX_ "lobj is not of type version");
621
6e449a3a 622 mPUSHs(vnormal(lobj));
9137345a
JP
623
624 PUTBACK;
625 return;
626 }
627}
628
439cb1c4
JP
629XS(XS_version_vcmp)
630{
97aff369 631 dVAR;
41be1fbd
JH
632 dXSARGS;
633 if (items < 1)
afa74d42 634 croak_xs_usage(cv, "lobj, ...");
41be1fbd
JH
635 SP -= items;
636 {
7452cf6a 637 SV * lobj;
41be1fbd
JH
638
639 if (sv_derived_from(ST(0), "version")) {
9137345a 640 lobj = SvRV(ST(0));
41be1fbd
JH
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);
7452cf6a 649 const IV swap = (IV)SvIV(ST(2));
41be1fbd
JH
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
6e449a3a 666 mPUSHs(rs);
41be1fbd
JH
667 }
668
669 PUTBACK;
670 return;
671 }
439cb1c4
JP
672}
673
674XS(XS_version_boolean)
675{
97aff369
JH
676 dVAR;
677 dXSARGS;
678 if (items < 1)
afa74d42 679 croak_xs_usage(cv, "lobj, ...");
97aff369 680 SP -= items;
c4420975
AL
681 if (sv_derived_from(ST(0), "version")) {
682 SV * const lobj = SvRV(ST(0));
396482e1 683 SV * const rs = newSViv( vcmp(lobj,new_version(newSVpvs("0"))) );
6e449a3a 684 mPUSHs(rs);
c4420975
AL
685 PUTBACK;
686 return;
687 }
688 else
689 Perl_croak(aTHX_ "lobj is not of type version");
439cb1c4
JP
690}
691
692XS(XS_version_noop)
693{
97aff369 694 dVAR;
2dfd8427
AL
695 dXSARGS;
696 if (items < 1)
afa74d42 697 croak_xs_usage(cv, "lobj, ...");
2dfd8427
AL
698 if (sv_derived_from(ST(0), "version"))
699 Perl_croak(aTHX_ "operation not supported with version object");
700 else
701 Perl_croak(aTHX_ "lobj is not of type version");
702#ifndef HASATTRIBUTE_NORETURN
703 XSRETURN_EMPTY;
704#endif
439cb1c4
JP
705}
706
c8d69e4a
JP
707XS(XS_version_is_alpha)
708{
97aff369 709 dVAR;
c8d69e4a
JP
710 dXSARGS;
711 if (items != 1)
afa74d42 712 croak_xs_usage(cv, "lobj");
c8d69e4a 713 SP -= items;
c4420975
AL
714 if (sv_derived_from(ST(0), "version")) {
715 SV * const lobj = ST(0);
ef8f7699 716 if ( hv_exists(MUTABLE_HV(SvRV(lobj)), "alpha", 5 ) )
c4420975
AL
717 XSRETURN_YES;
718 else
719 XSRETURN_NO;
c8d69e4a
JP
720 PUTBACK;
721 return;
722 }
c4420975
AL
723 else
724 Perl_croak(aTHX_ "lobj is not of type version");
c8d69e4a
JP
725}
726
137d6fc0
JP
727XS(XS_version_qv)
728{
97aff369 729 dVAR;
137d6fc0
JP
730 dXSARGS;
731 if (items != 1)
afa74d42 732 croak_xs_usage(cv, "ver");
137d6fc0
JP
733 SP -= items;
734 {
735 SV * ver = ST(0);
c4420975 736 if ( !SvVOK(ver) ) { /* only need to do with if not already v-string */
ac0e6a2f
RGS
737 SV * const rv = sv_newmortal();
738 sv_setsv(rv,ver); /* make a duplicate */
739 upg_version(rv, TRUE);
740 PUSHs(rv);
137d6fc0
JP
741 }
742 else
743 {
6e449a3a 744 mPUSHs(new_version(ver));
137d6fc0
JP
745 }
746
747 PUTBACK;
748 return;
749 }
750}
751
8800c35a
JH
752XS(XS_utf8_is_utf8)
753{
97aff369 754 dVAR;
41be1fbd
JH
755 dXSARGS;
756 if (items != 1)
afa74d42 757 croak_xs_usage(cv, "sv");
c4420975
AL
758 else {
759 const SV * const sv = ST(0);
760 if (SvUTF8(sv))
761 XSRETURN_YES;
762 else
763 XSRETURN_NO;
41be1fbd
JH
764 }
765 XSRETURN_EMPTY;
8800c35a
JH
766}
767
1b026014
NIS
768XS(XS_utf8_valid)
769{
97aff369 770 dVAR;
41be1fbd
JH
771 dXSARGS;
772 if (items != 1)
afa74d42 773 croak_xs_usage(cv, "sv");
c4420975
AL
774 else {
775 SV * const sv = ST(0);
776 STRLEN len;
777 const char * const s = SvPV_const(sv,len);
778 if (!SvUTF8(sv) || is_utf8_string((const U8*)s,len))
779 XSRETURN_YES;
780 else
781 XSRETURN_NO;
782 }
41be1fbd 783 XSRETURN_EMPTY;
1b026014
NIS
784}
785
786XS(XS_utf8_encode)
787{
97aff369 788 dVAR;
1b026014
NIS
789 dXSARGS;
790 if (items != 1)
afa74d42 791 croak_xs_usage(cv, "sv");
c4420975 792 sv_utf8_encode(ST(0));
1b026014
NIS
793 XSRETURN_EMPTY;
794}
795
796XS(XS_utf8_decode)
797{
97aff369 798 dVAR;
1b026014
NIS
799 dXSARGS;
800 if (items != 1)
afa74d42 801 croak_xs_usage(cv, "sv");
c4420975
AL
802 else {
803 SV * const sv = ST(0);
6867be6d 804 const bool RETVAL = sv_utf8_decode(sv);
1b026014
NIS
805 ST(0) = boolSV(RETVAL);
806 sv_2mortal(ST(0));
807 }
808 XSRETURN(1);
809}
810
811XS(XS_utf8_upgrade)
812{
97aff369 813 dVAR;
1b026014
NIS
814 dXSARGS;
815 if (items != 1)
afa74d42 816 croak_xs_usage(cv, "sv");
c4420975
AL
817 else {
818 SV * const sv = ST(0);
1b026014
NIS
819 STRLEN RETVAL;
820 dXSTARG;
821
822 RETVAL = sv_utf8_upgrade(sv);
823 XSprePUSH; PUSHi((IV)RETVAL);
824 }
825 XSRETURN(1);
826}
827
828XS(XS_utf8_downgrade)
829{
97aff369 830 dVAR;
1b026014
NIS
831 dXSARGS;
832 if (items < 1 || items > 2)
afa74d42 833 croak_xs_usage(cv, "sv, failok=0");
c4420975
AL
834 else {
835 SV * const sv = ST(0);
6867be6d
AL
836 const bool failok = (items < 2) ? 0 : (int)SvIV(ST(1));
837 const bool RETVAL = sv_utf8_downgrade(sv, failok);
1b026014 838
1b026014
NIS
839 ST(0) = boolSV(RETVAL);
840 sv_2mortal(ST(0));
841 }
842 XSRETURN(1);
843}
844
845XS(XS_utf8_native_to_unicode)
846{
97aff369 847 dVAR;
1b026014 848 dXSARGS;
6867be6d 849 const UV uv = SvUV(ST(0));
b7953727
JH
850
851 if (items > 1)
afa74d42 852 croak_xs_usage(cv, "sv");
b7953727 853
1b026014
NIS
854 ST(0) = sv_2mortal(newSViv(NATIVE_TO_UNI(uv)));
855 XSRETURN(1);
856}
857
858XS(XS_utf8_unicode_to_native)
859{
97aff369 860 dVAR;
1b026014 861 dXSARGS;
6867be6d 862 const UV uv = SvUV(ST(0));
b7953727
JH
863
864 if (items > 1)
afa74d42 865 croak_xs_usage(cv, "sv");
b7953727 866
1b026014
NIS
867 ST(0) = sv_2mortal(newSViv(UNI_TO_NATIVE(uv)));
868 XSRETURN(1);
869}
870
14a976d6 871XS(XS_Internals_SvREADONLY) /* This is dangerous stuff. */
29569577 872{
97aff369 873 dVAR;
29569577 874 dXSARGS;
c4420975 875 SV * const sv = SvRV(ST(0));
58c0efa5 876 PERL_UNUSED_ARG(cv);
6867be6d 877
29569577
JH
878 if (items == 1) {
879 if (SvREADONLY(sv))
880 XSRETURN_YES;
881 else
882 XSRETURN_NO;
883 }
884 else if (items == 2) {
885 if (SvTRUE(ST(1))) {
886 SvREADONLY_on(sv);
887 XSRETURN_YES;
888 }
889 else {
14a976d6 890 /* I hope you really know what you are doing. */
29569577
JH
891 SvREADONLY_off(sv);
892 XSRETURN_NO;
893 }
894 }
14a976d6 895 XSRETURN_UNDEF; /* Can't happen. */
29569577
JH
896}
897
14a976d6 898XS(XS_Internals_SvREFCNT) /* This is dangerous stuff. */
29569577 899{
97aff369 900 dVAR;
29569577 901 dXSARGS;
c4420975 902 SV * const sv = SvRV(ST(0));
58c0efa5 903 PERL_UNUSED_ARG(cv);
6867be6d 904
29569577 905 if (items == 1)
14a976d6 906 XSRETURN_IV(SvREFCNT(sv) - 1); /* Minus the ref created for us. */
29569577 907 else if (items == 2) {
14a976d6 908 /* I hope you really know what you are doing. */
29569577
JH
909 SvREFCNT(sv) = SvIV(ST(1));
910 XSRETURN_IV(SvREFCNT(sv));
911 }
14a976d6 912 XSRETURN_UNDEF; /* Can't happen. */
29569577
JH
913}
914
f044d0d1 915XS(XS_Internals_hv_clear_placehold)
dfd4ef2f 916{
97aff369 917 dVAR;
dfd4ef2f 918 dXSARGS;
6867be6d 919
3540d4ce 920 if (items != 1)
afa74d42 921 croak_xs_usage(cv, "hv");
c4420975 922 else {
ef8f7699 923 HV * const hv = MUTABLE_HV(SvRV(ST(0)));
c4420975
AL
924 hv_clear_placeholders(hv);
925 XSRETURN(0);
926 }
dfd4ef2f 927}
39f7a870 928
f63535fc
NC
929XS(XS_Regexp_DESTROY)
930{
931 PERL_UNUSED_CONTEXT;
932 PERL_UNUSED_ARG(cv);
933}
934
39f7a870
JH
935XS(XS_PerlIO_get_layers)
936{
97aff369 937 dVAR;
39f7a870
JH
938 dXSARGS;
939 if (items < 1 || items % 2 == 0)
afa74d42 940 croak_xs_usage(cv, "filehandle[,args]");
5fef3b4a 941#ifdef USE_PERLIO
39f7a870
JH
942 {
943 SV * sv;
944 GV * gv;
945 IO * io;
946 bool input = TRUE;
947 bool details = FALSE;
948
949 if (items > 1) {
c4420975 950 SV * const *svp;
39f7a870 951 for (svp = MARK + 2; svp <= SP; svp += 2) {
c4420975
AL
952 SV * const * const varp = svp;
953 SV * const * const valp = svp + 1;
39f7a870 954 STRLEN klen;
c4420975 955 const char * const key = SvPV_const(*varp, klen);
39f7a870
JH
956
957 switch (*key) {
958 case 'i':
959 if (klen == 5 && memEQ(key, "input", 5)) {
960 input = SvTRUE(*valp);
961 break;
962 }
963 goto fail;
964 case 'o':
965 if (klen == 6 && memEQ(key, "output", 6)) {
966 input = !SvTRUE(*valp);
967 break;
968 }
969 goto fail;
970 case 'd':
971 if (klen == 7 && memEQ(key, "details", 7)) {
972 details = SvTRUE(*valp);
973 break;
974 }
975 goto fail;
976 default:
977 fail:
978 Perl_croak(aTHX_
979 "get_layers: unknown argument '%s'",
980 key);
981 }
982 }
983
984 SP -= (items - 1);
985 }
986
987 sv = POPs;
159b6efe 988 gv = MUTABLE_GV(sv);
39f7a870
JH
989
990 if (!isGV(sv)) {
991 if (SvROK(sv) && isGV(SvRV(sv)))
159b6efe 992 gv = MUTABLE_GV(SvRV(sv));
671d49be 993 else if (SvPOKp(sv))
f776e3cd 994 gv = gv_fetchsv(sv, 0, SVt_PVIO);
39f7a870
JH
995 }
996
997 if (gv && (io = GvIO(gv))) {
c4420975 998 AV* const av = PerlIO_get_layers(aTHX_ input ?
39f7a870
JH
999 IoIFP(io) : IoOFP(io));
1000 I32 i;
c4420975 1001 const I32 last = av_len(av);
39f7a870
JH
1002 I32 nitem = 0;
1003
1004 for (i = last; i >= 0; i -= 3) {
c4420975
AL
1005 SV * const * const namsvp = av_fetch(av, i - 2, FALSE);
1006 SV * const * const argsvp = av_fetch(av, i - 1, FALSE);
1007 SV * const * const flgsvp = av_fetch(av, i, FALSE);
39f7a870 1008
c4420975
AL
1009 const bool namok = namsvp && *namsvp && SvPOK(*namsvp);
1010 const bool argok = argsvp && *argsvp && SvPOK(*argsvp);
1011 const bool flgok = flgsvp && *flgsvp && SvIOK(*flgsvp);
39f7a870
JH
1012
1013 if (details) {
92e45a3e
NC
1014 /* Indents of 5? Yuck. */
1015 /* We know that PerlIO_get_layers creates a new SV for
1016 the name and flags, so we can just take a reference
1017 and "steal" it when we free the AV below. */
ec3bab8e 1018 XPUSHs(namok
92e45a3e 1019 ? sv_2mortal(SvREFCNT_inc_simple_NN(*namsvp))
ec3bab8e
NC
1020 : &PL_sv_undef);
1021 XPUSHs(argok
92e45a3e
NC
1022 ? newSVpvn_flags(SvPVX_const(*argsvp),
1023 SvCUR(*argsvp),
1024 (SvUTF8(*argsvp) ? SVf_UTF8 : 0)
1025 | SVs_TEMP)
1026 : &PL_sv_undef);
96ccaf53 1027 XPUSHs(flgok
92e45a3e 1028 ? sv_2mortal(SvREFCNT_inc_simple_NN(*flgsvp))
ec3bab8e 1029 : &PL_sv_undef);
39f7a870
JH
1030 nitem += 3;
1031 }
1032 else {
1033 if (namok && argok)
1eb9e81d 1034 XPUSHs(sv_2mortal(Perl_newSVpvf(aTHX_ "%"SVf"(%"SVf")",
be2597df 1035 SVfARG(*namsvp),
1eb9e81d 1036 SVfARG(*argsvp))));
39f7a870 1037 else if (namok)
92e45a3e 1038 XPUSHs(sv_2mortal(SvREFCNT_inc_simple_NN(*namsvp)));
39f7a870
JH
1039 else
1040 XPUSHs(&PL_sv_undef);
1041 nitem++;
1042 if (flgok) {
c4420975 1043 const IV flags = SvIVX(*flgsvp);
39f7a870
JH
1044
1045 if (flags & PERLIO_F_UTF8) {
84bafc02 1046 XPUSHs(newSVpvs_flags("utf8", SVs_TEMP));
39f7a870
JH
1047 nitem++;
1048 }
1049 }
1050 }
1051 }
1052
1053 SvREFCNT_dec(av);
1054
1055 XSRETURN(nitem);
1056 }
1057 }
5fef3b4a 1058#endif
39f7a870
JH
1059
1060 XSRETURN(0);
1061}
1062
9a7034eb 1063XS(XS_Internals_hash_seed)
c910b28a 1064{
97aff369 1065 dVAR;
c85d3f85
NC
1066 /* Using dXSARGS would also have dITEM and dSP,
1067 * which define 2 unused local variables. */
557b887a 1068 dAXMARK;
53c1dcc0 1069 PERL_UNUSED_ARG(cv);
ad73156c 1070 PERL_UNUSED_VAR(mark);
81eaca17 1071 XSRETURN_UV(PERL_HASH_SEED);
c910b28a
JH
1072}
1073
008fb0c0 1074XS(XS_Internals_rehash_seed)
8e90d776 1075{
97aff369 1076 dVAR;
8e90d776
NC
1077 /* Using dXSARGS would also have dITEM and dSP,
1078 * which define 2 unused local variables. */
557b887a 1079 dAXMARK;
53c1dcc0 1080 PERL_UNUSED_ARG(cv);
ad73156c 1081 PERL_UNUSED_VAR(mark);
008fb0c0 1082 XSRETURN_UV(PL_rehash_seed);
8e90d776
NC
1083}
1084
05619474
NC
1085XS(XS_Internals_HvREHASH) /* Subject to change */
1086{
97aff369 1087 dVAR;
05619474 1088 dXSARGS;
93c51217 1089 PERL_UNUSED_ARG(cv);
05619474 1090 if (SvROK(ST(0))) {
ef8f7699 1091 const HV * const hv = (const HV *) SvRV(ST(0));
05619474
NC
1092 if (items == 1 && SvTYPE(hv) == SVt_PVHV) {
1093 if (HvREHASH(hv))
1094 XSRETURN_YES;
1095 else
1096 XSRETURN_NO;
1097 }
1098 }
1099 Perl_croak(aTHX_ "Internals::HvREHASH $hashref");
1100}
241d1a3b 1101
80305961
YO
1102XS(XS_re_is_regexp)
1103{
1104 dVAR;
1105 dXSARGS;
f7e71195
AB
1106 PERL_UNUSED_VAR(cv);
1107
80305961 1108 if (items != 1)
afa74d42 1109 croak_xs_usage(cv, "sv");
f7e71195 1110
80305961 1111 SP -= items;
f7e71195
AB
1112
1113 if (SvRXOK(ST(0))) {
1114 XSRETURN_YES;
1115 } else {
1116 XSRETURN_NO;
80305961
YO
1117 }
1118}
1119
192b9cd1 1120XS(XS_re_regnames_count)
80305961 1121{
192b9cd1
AB
1122 REGEXP *rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1123 SV * ret;
80305961
YO
1124 dVAR;
1125 dXSARGS;
192b9cd1
AB
1126
1127 if (items != 0)
afa74d42 1128 croak_xs_usage(cv, "");
192b9cd1
AB
1129
1130 SP -= items;
1131
1132 if (!rx)
1133 XSRETURN_UNDEF;
1134
1135 ret = CALLREG_NAMED_BUFF_COUNT(rx);
1136
1137 SPAGAIN;
1138
1139 if (ret) {
ec83ea38 1140 mXPUSHs(ret);
192b9cd1
AB
1141 PUTBACK;
1142 return;
1143 } else {
1144 XSRETURN_UNDEF;
1145 }
1146}
1147
1148XS(XS_re_regname)
1149{
1150 dVAR;
1151 dXSARGS;
1152 REGEXP * rx;
1153 U32 flags;
1154 SV * ret;
1155
28d8d7f4 1156 if (items < 1 || items > 2)
afa74d42 1157 croak_xs_usage(cv, "name[, all ]");
192b9cd1 1158
80305961 1159 SP -= items;
80305961 1160
192b9cd1
AB
1161 rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1162
1163 if (!rx)
1164 XSRETURN_UNDEF;
1165
1166 if (items == 2 && SvTRUE(ST(1))) {
f1b875a0 1167 flags = RXapif_ALL;
192b9cd1 1168 } else {
f1b875a0 1169 flags = RXapif_ONE;
80305961 1170 }
f1b875a0 1171 ret = CALLREG_NAMED_BUFF_FETCH(rx, ST(0), (flags | RXapif_REGNAME));
192b9cd1
AB
1172
1173 if (ret) {
ec83ea38 1174 mXPUSHs(ret);
192b9cd1
AB
1175 XSRETURN(1);
1176 }
1177 XSRETURN_UNDEF;
80305961
YO
1178}
1179
192b9cd1 1180
80305961
YO
1181XS(XS_re_regnames)
1182{
192b9cd1 1183 dVAR;
80305961 1184 dXSARGS;
192b9cd1
AB
1185 REGEXP * rx;
1186 U32 flags;
1187 SV *ret;
1188 AV *av;
1189 I32 length;
1190 I32 i;
1191 SV **entry;
1192
1193 if (items > 1)
afa74d42 1194 croak_xs_usage(cv, "[all]");
192b9cd1
AB
1195
1196 rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1197
1198 if (!rx)
1199 XSRETURN_UNDEF;
1200
1201 if (items == 1 && SvTRUE(ST(0))) {
f1b875a0 1202 flags = RXapif_ALL;
192b9cd1 1203 } else {
f1b875a0 1204 flags = RXapif_ONE;
192b9cd1
AB
1205 }
1206
80305961 1207 SP -= items;
80305961 1208
f1b875a0 1209 ret = CALLREG_NAMED_BUFF_ALL(rx, (flags | RXapif_REGNAMES));
192b9cd1
AB
1210
1211 SPAGAIN;
1212
1213 SP -= items;
1214
1215 if (!ret)
1216 XSRETURN_UNDEF;
1217
502c6561 1218 av = MUTABLE_AV(SvRV(ret));
192b9cd1
AB
1219 length = av_len(av);
1220
1221 for (i = 0; i <= length; i++) {
1222 entry = av_fetch(av, i, FALSE);
1223
1224 if (!entry)
1225 Perl_croak(aTHX_ "NULL array element in re::regnames()");
1226
ec83ea38 1227 mXPUSHs(SvREFCNT_inc_simple_NN(*entry));
80305961 1228 }
ec83ea38
MHM
1229
1230 SvREFCNT_dec(ret);
1231
192b9cd1
AB
1232 PUTBACK;
1233 return;
80305961
YO
1234}
1235
192c1e27
JH
1236XS(XS_re_regexp_pattern)
1237{
1238 dVAR;
1239 dXSARGS;
1240 REGEXP *re;
192c1e27
JH
1241
1242 if (items != 1)
afa74d42 1243 croak_xs_usage(cv, "sv");
192c1e27
JH
1244
1245 SP -= items;
1246
1247 /*
1248 Checks if a reference is a regex or not. If the parameter is
1249 not a ref, or is not the result of a qr// then returns false
1250 in scalar context and an empty list in list context.
1251 Otherwise in list context it returns the pattern and the
1252 modifiers, in scalar context it returns the pattern just as it
1253 would if the qr// was stringified normally, regardless as
1254 to the class of the variable and any strigification overloads
1255 on the object.
1256 */
1257
1258 if ((re = SvRX(ST(0)))) /* assign deliberate */
1259 {
1260 /* Housten, we have a regex! */
1261 SV *pattern;
1262 STRLEN left = 0;
1263 char reflags[6];
1264
1265 if ( GIMME_V == G_ARRAY ) {
1266 /*
1267 we are in list context so stringify
1268 the modifiers that apply. We ignore "negative
1269 modifiers" in this scenario.
1270 */
1271
1272 const char *fptr = INT_PAT_MODS;
1273 char ch;
1274 U16 match_flags = (U16)((RX_EXTFLAGS(re) & PMf_COMPILETIME)
1275 >> RXf_PMf_STD_PMMOD_SHIFT);
1276
1277 while((ch = *fptr++)) {
1278 if(match_flags & 1) {
1279 reflags[left++] = ch;
1280 }
1281 match_flags >>= 1;
1282 }
1283
fb632ce3
NC
1284 pattern = newSVpvn_flags(RX_PRECOMP(re),RX_PRELEN(re),
1285 (RX_UTF8(re) ? SVf_UTF8 : 0) | SVs_TEMP);
192c1e27
JH
1286
1287 /* return the pattern and the modifiers */
1288 XPUSHs(pattern);
fb632ce3 1289 XPUSHs(newSVpvn_flags(reflags, left, SVs_TEMP));
192c1e27
JH
1290 XSRETURN(2);
1291 } else {
1292 /* Scalar, so use the string that Perl would return */
1293 /* return the pattern in (?msix:..) format */
1294#if PERL_VERSION >= 11
daba3364 1295 pattern = sv_2mortal(newSVsv(MUTABLE_SV(re)));
192c1e27 1296#else
fb632ce3
NC
1297 pattern = newSVpvn_flags(RX_WRAPPED(re), RX_WRAPLEN(re),
1298 (RX_UTF8(re) ? SVf_UTF8 : 0) | SVs_TEMP);
192c1e27
JH
1299#endif
1300 XPUSHs(pattern);
1301 XSRETURN(1);
1302 }
1303 } else {
1304 /* It ain't a regexp folks */
1305 if ( GIMME_V == G_ARRAY ) {
1306 /* return the empty list */
1307 XSRETURN_UNDEF;
1308 } else {
1309 /* Because of the (?:..) wrapping involved in a
1310 stringified pattern it is impossible to get a
1311 result for a real regexp that would evaluate to
1312 false. Therefore we can return PL_sv_no to signify
1313 that the object is not a regex, this means that one
1314 can say
1315
1316 if (regex($might_be_a_regex) eq '(?:foo)') { }
1317
1318 and not worry about undefined values.
1319 */
1320 XSRETURN_NO;
1321 }
1322 }
1323 /* NOT-REACHED */
1324}
1325
192b9cd1 1326XS(XS_Tie_Hash_NamedCapture_FETCH)
80305961 1327{
192b9cd1 1328 dVAR;
80305961 1329 dXSARGS;
192b9cd1
AB
1330 REGEXP * rx;
1331 U32 flags;
1332 SV * ret;
1333
1334 if (items != 2)
afa74d42 1335 croak_xs_usage(cv, "$key, $flags");
192b9cd1
AB
1336
1337 rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1338
1339 if (!rx)
1340 XSRETURN_UNDEF;
1341
80305961 1342 SP -= items;
192b9cd1 1343
daba3364 1344 flags = (U32)INT2PTR(IV,SvIV(SvRV(MUTABLE_SV(ST(0)))));
192b9cd1
AB
1345 ret = CALLREG_NAMED_BUFF_FETCH(rx, ST(1), flags);
1346
1347 SPAGAIN;
1348
1349 if (ret) {
ec83ea38 1350 mXPUSHs(ret);
192b9cd1
AB
1351 PUTBACK;
1352 return;
1353 }
1354 XSRETURN_UNDEF;
1355}
1356
1357XS(XS_Tie_Hash_NamedCapture_STORE)
1358{
1359 dVAR;
1360 dXSARGS;
1361 REGEXP * rx;
1362 U32 flags;
1363
1364 if (items != 3)
afa74d42 1365 croak_xs_usage(cv, "$key, $value, $flags");
192b9cd1
AB
1366
1367 rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1368
1369 if (!rx) {
1370 if (!PL_localizing)
f1f66076 1371 Perl_croak(aTHX_ "%s", PL_no_modify);
192b9cd1 1372 else
28d8d7f4 1373 XSRETURN_UNDEF;
80305961 1374 }
192b9cd1
AB
1375
1376 SP -= items;
1377
daba3364 1378 flags = (U32)INT2PTR(IV,SvIV(SvRV(MUTABLE_SV(ST(0)))));
192b9cd1 1379 CALLREG_NAMED_BUFF_STORE(rx,ST(1), ST(2), flags);
80305961
YO
1380}
1381
192b9cd1
AB
1382XS(XS_Tie_Hash_NamedCapture_DELETE)
1383{
1384 dVAR;
1385 dXSARGS;
1386 REGEXP * rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1387 U32 flags;
80305961 1388
192b9cd1 1389 if (items != 2)
afa74d42 1390 croak_xs_usage(cv, "$key, $flags");
192b9cd1
AB
1391
1392 if (!rx)
f1f66076 1393 Perl_croak(aTHX_ "%s", PL_no_modify);
192b9cd1
AB
1394
1395 SP -= items;
1396
daba3364 1397 flags = (U32)INT2PTR(IV,SvIV(SvRV(MUTABLE_SV(ST(0)))));
192b9cd1
AB
1398 CALLREG_NAMED_BUFF_DELETE(rx, ST(1), flags);
1399}
1400
1401XS(XS_Tie_Hash_NamedCapture_CLEAR)
80305961 1402{
192b9cd1 1403 dVAR;
80305961 1404 dXSARGS;
192b9cd1
AB
1405 REGEXP * rx;
1406 U32 flags;
1407
1408 if (items != 1)
afa74d42 1409 croak_xs_usage(cv, "$flags");
192b9cd1
AB
1410
1411 rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1412
1413 if (!rx)
f1f66076 1414 Perl_croak(aTHX_ "%s", PL_no_modify);
192b9cd1 1415
80305961 1416 SP -= items;
80305961 1417
daba3364 1418 flags = (U32)INT2PTR(IV,SvIV(SvRV(MUTABLE_SV(ST(0)))));
192b9cd1
AB
1419 CALLREG_NAMED_BUFF_CLEAR(rx, flags);
1420}
1421
1422XS(XS_Tie_Hash_NamedCapture_EXISTS)
1423{
1424 dVAR;
1425 dXSARGS;
1426 REGEXP * rx;
1427 U32 flags;
1428 SV * ret;
1429
1430 if (items != 2)
afa74d42 1431 croak_xs_usage(cv, "$key, $flags");
192b9cd1
AB
1432
1433 rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1434
1435 if (!rx)
28d8d7f4 1436 XSRETURN_UNDEF;
192b9cd1
AB
1437
1438 SP -= items;
1439
daba3364 1440 flags = (U32)INT2PTR(IV,SvIV(SvRV(MUTABLE_SV(ST(0)))));
192b9cd1
AB
1441 ret = CALLREG_NAMED_BUFF_EXISTS(rx, ST(1), flags);
1442
1443 SPAGAIN;
1444
1445 XPUSHs(ret);
80305961
YO
1446 PUTBACK;
1447 return;
80305961
YO
1448}
1449
86aa3d53 1450XS(XS_Tie_Hash_NamedCapture_FIRSTK)
192b9cd1
AB
1451{
1452 dVAR;
1453 dXSARGS;
1454 REGEXP * rx;
1455 U32 flags;
1456 SV * ret;
80305961 1457
192b9cd1 1458 if (items != 1)
afa74d42 1459 croak_xs_usage(cv, "");
192b9cd1
AB
1460
1461 rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1462
1463 if (!rx)
1464 XSRETURN_UNDEF;
1465
1466 SP -= items;
1467
daba3364 1468 flags = (U32)INT2PTR(IV,SvIV(SvRV(MUTABLE_SV(ST(0)))));
192b9cd1
AB
1469 ret = CALLREG_NAMED_BUFF_FIRSTKEY(rx, flags);
1470
1471 SPAGAIN;
1472
1473 if (ret) {
ec83ea38 1474 mXPUSHs(ret);
192b9cd1
AB
1475 PUTBACK;
1476 } else {
1477 XSRETURN_UNDEF;
1478 }
1479
1480}
1481
86aa3d53 1482XS(XS_Tie_Hash_NamedCapture_NEXTK)
80305961 1483{
192b9cd1 1484 dVAR;
80305961 1485 dXSARGS;
192b9cd1
AB
1486 REGEXP * rx;
1487 U32 flags;
1488 SV * ret;
1489
1490 if (items != 2)
afa74d42 1491 croak_xs_usage(cv, "$lastkey");
192b9cd1
AB
1492
1493 rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1494
1495 if (!rx)
1496 XSRETURN_UNDEF;
80305961 1497
80305961 1498 SP -= items;
192b9cd1 1499
daba3364 1500 flags = (U32)INT2PTR(IV,SvIV(SvRV(MUTABLE_SV(ST(0)))));
192b9cd1
AB
1501 ret = CALLREG_NAMED_BUFF_NEXTKEY(rx, ST(1), flags);
1502
1503 SPAGAIN;
1504
1505 if (ret) {
ec83ea38 1506 mXPUSHs(ret);
80305961
YO
1507 } else {
1508 XSRETURN_UNDEF;
1509 }
1510 PUTBACK;
192b9cd1
AB
1511}
1512
1513XS(XS_Tie_Hash_NamedCapture_SCALAR)
1514{
1515 dVAR;
1516 dXSARGS;
1517 REGEXP * rx;
1518 U32 flags;
1519 SV * ret;
1520
1521 if (items != 1)
afa74d42 1522 croak_xs_usage(cv, "");
192b9cd1
AB
1523
1524 rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1525
1526 if (!rx)
1527 XSRETURN_UNDEF;
1528
1529 SP -= items;
1530
daba3364 1531 flags = (U32)INT2PTR(IV,SvIV(SvRV(MUTABLE_SV(ST(0)))));
192b9cd1
AB
1532 ret = CALLREG_NAMED_BUFF_SCALAR(rx, flags);
1533
1534 SPAGAIN;
1535
1536 if (ret) {
ec83ea38 1537 mXPUSHs(ret);
192b9cd1
AB
1538 PUTBACK;
1539 return;
1540 } else {
1541 XSRETURN_UNDEF;
1542 }
1543}
1544
1545XS(XS_Tie_Hash_NamedCapture_flags)
1546{
1547 dVAR;
1548 dXSARGS;
1549
1550 if (items != 0)
afa74d42 1551 croak_xs_usage(cv, "");
192b9cd1 1552
6e449a3a
MHM
1553 mXPUSHu(RXapif_ONE);
1554 mXPUSHu(RXapif_ALL);
192b9cd1
AB
1555 PUTBACK;
1556 return;
80305961
YO
1557}
1558
1559
241d1a3b
NC
1560/*
1561 * Local variables:
1562 * c-indentation-style: bsd
1563 * c-basic-offset: 4
1564 * indent-tabs-mode: t
1565 * End:
1566 *
37442d52
RGS
1567 * ex: set ts=8 sts=4 sw=4 noet:
1568 */