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