This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Re: [ANNOUNCE] ExtUtils::MakeMaker 6.19
[perl5.git] / universal.c
CommitLineData
d6376244
JH
1/* universal.c
2 *
4bb101f2
JH
3 * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
4 * 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
AT
11/*
12 * "The roots of those mountains must be roots indeed; there must be
13 * great secrets buried there which have not been discovered since the
14 * beginning." --Gandalf, relating Gollum's story
15 */
16
6d4a7be2 17#include "EXTERN.h"
864dbfa3 18#define PERL_IN_UNIVERSAL_C
6d4a7be2 19#include "perl.h"
6d4a7be2 20
39f7a870
JH
21#ifdef USE_PERLIO
22#include "perliol.h" /* For the PERLIO_F_XXX */
23#endif
24
6d4a7be2 25/*
26 * Contributed by Graham Barr <Graham.Barr@tiuk.ti.com>
27 * The main guts of traverse_isa was actually copied from gv_fetchmeth
28 */
29
76e3520e 30STATIC SV *
301daebc
MS
31S_isa_lookup(pTHX_ HV *stash, const char *name, HV* name_stash,
32 int len, int level)
6d4a7be2 33{
34 AV* av;
35 GV* gv;
36 GV** gvp;
37 HV* hv = Nullhv;
46e4b22b 38 SV* subgen = Nullsv;
6d4a7be2 39
301daebc
MS
40 /* A stash/class can go by many names (ie. User == main::User), so
41 we compare the stash itself just in case */
42 if (name_stash && (stash == name_stash))
43 return &PL_sv_yes;
6d4a7be2 44
46e4b22b 45 if (strEQ(HvNAME(stash), name))
3280af22 46 return &PL_sv_yes;
6d4a7be2 47
a1d407e8
DM
48 if (strEQ(name, "UNIVERSAL"))
49 return &PL_sv_yes;
50
6d4a7be2 51 if (level > 100)
46e4b22b
GS
52 Perl_croak(aTHX_ "Recursive inheritance detected in package '%s'",
53 HvNAME(stash));
6d4a7be2 54
55 gvp = (GV**)hv_fetch(stash, "::ISA::CACHE::", 14, FALSE);
56
46e4b22b
GS
57 if (gvp && (gv = *gvp) != (GV*)&PL_sv_undef && (subgen = GvSV(gv))
58 && (hv = GvHV(gv)))
59 {
eb160463 60 if (SvIV(subgen) == (IV)PL_sub_generation) {
46e4b22b
GS
61 SV* sv;
62 SV** svp = (SV**)hv_fetch(hv, name, len, FALSE);
63 if (svp && (sv = *svp) != (SV*)&PL_sv_undef) {
64 DEBUG_o( Perl_deb(aTHX_ "Using cached ISA %s for package %s\n",
65 name, HvNAME(stash)) );
66 return sv;
67 }
68 }
69 else {
70 DEBUG_o( Perl_deb(aTHX_ "ISA Cache in package %s is stale\n",
71 HvNAME(stash)) );
72 hv_clear(hv);
73 sv_setiv(subgen, PL_sub_generation);
74 }
6d4a7be2 75 }
76
77 gvp = (GV**)hv_fetch(stash,"ISA",3,FALSE);
46e4b22b 78
3280af22 79 if (gvp && (gv = *gvp) != (GV*)&PL_sv_undef && (av = GvAV(gv))) {
46e4b22b 80 if (!hv || !subgen) {
6d4a7be2 81 gvp = (GV**)hv_fetch(stash, "::ISA::CACHE::", 14, TRUE);
82
83 gv = *gvp;
84
85 if (SvTYPE(gv) != SVt_PVGV)
86 gv_init(gv, stash, "::ISA::CACHE::", 14, TRUE);
87
46e4b22b
GS
88 if (!hv)
89 hv = GvHVn(gv);
90 if (!subgen) {
91 subgen = newSViv(PL_sub_generation);
92 GvSV(gv) = subgen;
93 }
6d4a7be2 94 }
46e4b22b 95 if (hv) {
6d4a7be2 96 SV** svp = AvARRAY(av);
93965878
NIS
97 /* NOTE: No support for tied ISA */
98 I32 items = AvFILLp(av) + 1;
6d4a7be2 99 while (items--) {
100 SV* sv = *svp++;
101 HV* basestash = gv_stashsv(sv, FALSE);
102 if (!basestash) {
599cee73 103 if (ckWARN(WARN_MISC))
9014280d 104 Perl_warner(aTHX_ packWARN(WARN_SYNTAX),
35c1215d
NC
105 "Can't locate package %"SVf" for @%s::ISA",
106 sv, HvNAME(stash));
6d4a7be2 107 continue;
108 }
301daebc
MS
109 if (&PL_sv_yes == isa_lookup(basestash, name, name_stash,
110 len, level + 1)) {
3280af22
NIS
111 (void)hv_store(hv,name,len,&PL_sv_yes,0);
112 return &PL_sv_yes;
6d4a7be2 113 }
114 }
3280af22 115 (void)hv_store(hv,name,len,&PL_sv_no,0);
6d4a7be2 116 }
117 }
a1d407e8 118 return &PL_sv_no;
6d4a7be2 119}
120
954c1994 121/*
ccfc67b7
JH
122=head1 SV Manipulation Functions
123
954c1994
GS
124=for apidoc sv_derived_from
125
126Returns a boolean indicating whether the SV is derived from the specified
127class. This is the function that implements C<UNIVERSAL::isa>. It works
128for class names as well as for objects.
129
130=cut
131*/
132
55497cff 133bool
864dbfa3 134Perl_sv_derived_from(pTHX_ SV *sv, const char *name)
55497cff 135{
55497cff 136 char *type;
137 HV *stash;
301daebc 138 HV *name_stash;
46e4b22b 139
55497cff 140 stash = Nullhv;
141 type = Nullch;
46e4b22b 142
55497cff 143 if (SvGMAGICAL(sv))
144 mg_get(sv) ;
145
146 if (SvROK(sv)) {
147 sv = SvRV(sv);
148 type = sv_reftype(sv,0);
46e4b22b 149 if (SvOBJECT(sv))
55497cff 150 stash = SvSTASH(sv);
151 }
152 else {
153 stash = gv_stashsv(sv, FALSE);
154 }
46e4b22b 155
301daebc
MS
156 name_stash = gv_stashpv(name, FALSE);
157
55497cff 158 return (type && strEQ(type,name)) ||
301daebc
MS
159 (stash && isa_lookup(stash, name, name_stash, strlen(name), 0)
160 == &PL_sv_yes)
55497cff 161 ? TRUE
162 : FALSE ;
55497cff 163}
164
1b026014
NIS
165#include "XSUB.h"
166
acfe0abc
GS
167void XS_UNIVERSAL_isa(pTHX_ CV *cv);
168void XS_UNIVERSAL_can(pTHX_ CV *cv);
169void XS_UNIVERSAL_VERSION(pTHX_ CV *cv);
439cb1c4
JP
170XS(XS_version_new);
171XS(XS_version_stringify);
172XS(XS_version_numify);
173XS(XS_version_vcmp);
174XS(XS_version_boolean);
175XS(XS_version_noop);
c8d69e4a 176XS(XS_version_is_alpha);
8800c35a 177XS(XS_utf8_is_utf8);
1b026014
NIS
178XS(XS_utf8_valid);
179XS(XS_utf8_encode);
180XS(XS_utf8_decode);
181XS(XS_utf8_upgrade);
182XS(XS_utf8_downgrade);
183XS(XS_utf8_unicode_to_native);
184XS(XS_utf8_native_to_unicode);
29569577
JH
185XS(XS_Internals_SvREADONLY);
186XS(XS_Internals_SvREFCNT);
f044d0d1 187XS(XS_Internals_hv_clear_placehold);
39f7a870 188XS(XS_PerlIO_get_layers);
39cff0d9 189XS(XS_Regexp_DESTROY);
9a7034eb 190XS(XS_Internals_hash_seed);
008fb0c0 191XS(XS_Internals_rehash_seed);
05619474 192XS(XS_Internals_HvREHASH);
0cb96387
GS
193
194void
195Perl_boot_core_UNIVERSAL(pTHX)
196{
197 char *file = __FILE__;
198
199 newXS("UNIVERSAL::isa", XS_UNIVERSAL_isa, file);
200 newXS("UNIVERSAL::can", XS_UNIVERSAL_can, file);
201 newXS("UNIVERSAL::VERSION", XS_UNIVERSAL_VERSION, file);
439cb1c4 202 {
ad63d80f
JP
203 /* register the overloading (type 'A') magic */
204 PL_amagic_generation++;
439cb1c4 205 /* Make it findable via fetchmethod */
be2ebcad 206 newXS("version::()", XS_version_noop, file);
439cb1c4
JP
207 newXS("version::new", XS_version_new, file);
208 newXS("version::(\"\"", XS_version_stringify, file);
209 newXS("version::stringify", XS_version_stringify, file);
210 newXS("version::(0+", XS_version_numify, file);
211 newXS("version::numify", XS_version_numify, file);
212 newXS("version::(cmp", XS_version_vcmp, file);
213 newXS("version::(<=>", XS_version_vcmp, file);
214 newXS("version::vcmp", XS_version_vcmp, file);
215 newXS("version::(bool", XS_version_boolean, file);
216 newXS("version::boolean", XS_version_boolean, file);
217 newXS("version::(nomethod", XS_version_noop, file);
218 newXS("version::noop", XS_version_noop, file);
c8d69e4a 219 newXS("version::is_alpha", XS_version_is_alpha, file);
439cb1c4 220 }
8800c35a 221 newXS("utf8::is_utf8", XS_utf8_is_utf8, file);
1b026014
NIS
222 newXS("utf8::valid", XS_utf8_valid, file);
223 newXS("utf8::encode", XS_utf8_encode, file);
224 newXS("utf8::decode", XS_utf8_decode, file);
225 newXS("utf8::upgrade", XS_utf8_upgrade, file);
226 newXS("utf8::downgrade", XS_utf8_downgrade, file);
227 newXS("utf8::native_to_unicode", XS_utf8_native_to_unicode, file);
228 newXS("utf8::unicode_to_native", XS_utf8_unicode_to_native, file);
29569577
JH
229 newXSproto("Internals::SvREADONLY",XS_Internals_SvREADONLY, file, "\\[$%@];$");
230 newXSproto("Internals::SvREFCNT",XS_Internals_SvREFCNT, file, "\\[$%@];$");
dfd4ef2f 231 newXSproto("Internals::hv_clear_placeholders",
f044d0d1 232 XS_Internals_hv_clear_placehold, file, "\\%");
9d569fce
JH
233 newXSproto("PerlIO::get_layers",
234 XS_PerlIO_get_layers, file, "*;@");
39cff0d9 235 newXS("Regexp::DESTROY", XS_Regexp_DESTROY, file);
9a7034eb 236 newXSproto("Internals::hash_seed",XS_Internals_hash_seed, file, "");
008fb0c0 237 newXSproto("Internals::rehash_seed",XS_Internals_rehash_seed, file, "");
05619474 238 newXSproto("Internals::HvREHASH", XS_Internals_HvREHASH, file, "\\%");
0cb96387
GS
239}
240
55497cff 241
6d4a7be2 242XS(XS_UNIVERSAL_isa)
243{
244 dXSARGS;
55497cff 245 SV *sv;
246 char *name;
2d8e6c8d 247 STRLEN n_a;
6d4a7be2 248
249 if (items != 2)
cea2e8a9 250 Perl_croak(aTHX_ "Usage: UNIVERSAL::isa(reference, kind)");
6d4a7be2 251
252 sv = ST(0);
f8f70380 253
d3f7f2b2
GS
254 if (SvGMAGICAL(sv))
255 mg_get(sv);
256
253ecd6d
RGS
257 if (!SvOK(sv) || !(SvROK(sv) || (SvPOK(sv) && SvCUR(sv))
258 || (SvGMAGICAL(sv) && SvPOKp(sv) && SvCUR(sv))))
f8f70380
GS
259 XSRETURN_UNDEF;
260
2d8e6c8d 261 name = (char *)SvPV(ST(1),n_a);
6d4a7be2 262
54310121 263 ST(0) = boolSV(sv_derived_from(sv, name));
6d4a7be2 264 XSRETURN(1);
265}
266
6d4a7be2 267XS(XS_UNIVERSAL_can)
268{
269 dXSARGS;
270 SV *sv;
271 char *name;
272 SV *rv;
6f08146e 273 HV *pkg = NULL;
2d8e6c8d 274 STRLEN n_a;
6d4a7be2 275
276 if (items != 2)
cea2e8a9 277 Perl_croak(aTHX_ "Usage: UNIVERSAL::can(object-ref, method)");
6d4a7be2 278
279 sv = ST(0);
f8f70380 280
d3f7f2b2
GS
281 if (SvGMAGICAL(sv))
282 mg_get(sv);
283
253ecd6d
RGS
284 if (!SvOK(sv) || !(SvROK(sv) || (SvPOK(sv) && SvCUR(sv))
285 || (SvGMAGICAL(sv) && SvPOKp(sv) && SvCUR(sv))))
f8f70380
GS
286 XSRETURN_UNDEF;
287
2d8e6c8d 288 name = (char *)SvPV(ST(1),n_a);
3280af22 289 rv = &PL_sv_undef;
6d4a7be2 290
46e4b22b 291 if (SvROK(sv)) {
6f08146e 292 sv = (SV*)SvRV(sv);
46e4b22b 293 if (SvOBJECT(sv))
6f08146e
NIS
294 pkg = SvSTASH(sv);
295 }
296 else {
297 pkg = gv_stashsv(sv, FALSE);
298 }
299
300 if (pkg) {
dc848c6f 301 GV *gv = gv_fetchmethod_autoload(pkg, name, FALSE);
302 if (gv && isGV(gv))
303 rv = sv_2mortal(newRV((SV*)GvCV(gv)));
6d4a7be2 304 }
305
306 ST(0) = rv;
307 XSRETURN(1);
308}
309
6d4a7be2 310XS(XS_UNIVERSAL_VERSION)
311{
312 dXSARGS;
313 HV *pkg;
314 GV **gvp;
315 GV *gv;
316 SV *sv;
317 char *undef;
318
1571675a 319 if (SvROK(ST(0))) {
6d4a7be2 320 sv = (SV*)SvRV(ST(0));
1571675a 321 if (!SvOBJECT(sv))
cea2e8a9 322 Perl_croak(aTHX_ "Cannot find version of an unblessed reference");
6d4a7be2 323 pkg = SvSTASH(sv);
324 }
325 else {
326 pkg = gv_stashsv(ST(0), FALSE);
327 }
328
329 gvp = pkg ? (GV**)hv_fetch(pkg,"VERSION",7,FALSE) : Null(GV**);
330
d4bea2fb 331 if (gvp && isGV(gv = *gvp) && SvOK(sv = GvSV(gv))) {
6d4a7be2 332 SV *nsv = sv_newmortal();
333 sv_setsv(nsv, sv);
334 sv = nsv;
335 undef = Nullch;
336 }
337 else {
3280af22 338 sv = (SV*)&PL_sv_undef;
6d4a7be2 339 undef = "(undef)";
340 }
341
1571675a
GS
342 if (items > 1) {
343 STRLEN len;
344 SV *req = ST(1);
345
62658f4d
PM
346 if (undef) {
347 if (pkg)
348 Perl_croak(aTHX_
349 "%s does not define $%s::VERSION--version check failed",
350 HvNAME(pkg), HvNAME(pkg));
351 else {
352 char *str = SvPVx(ST(0), len);
353
354 Perl_croak(aTHX_
355 "%s defines neither package nor VERSION--version check failed", str);
356 }
357 }
ad63d80f
JP
358 if ( !sv_derived_from(sv, "version"))
359 sv = new_version(sv);
360
361 if ( !sv_derived_from(req, "version"))
362 req = new_version(req);
1571675a 363
ad63d80f 364 if ( vcmp( SvRV(req), SvRV(sv) ) > 0 )
e3feee4e
RB
365 Perl_croak(aTHX_
366 "%s version %"SVf" required--this is only version %"SVf,
0773b1f0 367 HvNAME(pkg), req, sv);
2d8e6c8d 368 }
6d4a7be2 369
370 ST(0) = sv;
371
372 XSRETURN(1);
373}
374
439cb1c4
JP
375XS(XS_version_new)
376{
377 dXSARGS;
129318bd 378 if (items > 3)
439cb1c4
JP
379 Perl_croak(aTHX_ "Usage: version::new(class, version)");
380 SP -= items;
381 {
382/* char * class = (char *)SvPV_nolen(ST(0)); */
129318bd
JP
383 SV *version = ST(1);
384 if (items == 3 )
385 {
386 char *vs = savepvn(SvPVX(ST(2)),SvCUR(ST(2)));
9be22fdc 387 version = Perl_newSVpvf(aTHX_ "v%s",vs);
129318bd 388 }
439cb1c4 389
129318bd 390 PUSHs(new_version(version));
439cb1c4
JP
391 PUTBACK;
392 return;
393 }
394}
395
396XS(XS_version_stringify)
397{
41be1fbd
JH
398 dXSARGS;
399 if (items < 1)
400 Perl_croak(aTHX_ "Usage: version::stringify(lobj, ...)");
401 SP -= items;
402 {
403 SV * lobj;
404
405 if (sv_derived_from(ST(0), "version")) {
406 SV *tmp = SvRV(ST(0));
407 lobj = tmp;
408 }
409 else
410 Perl_croak(aTHX_ "lobj is not of type version");
411
412 {
413 PUSHs(vstringify(lobj));
414 }
415
416 PUTBACK;
417 return;
418 }
439cb1c4
JP
419}
420
421XS(XS_version_numify)
422{
41be1fbd
JH
423 dXSARGS;
424 if (items < 1)
425 Perl_croak(aTHX_ "Usage: version::numify(lobj, ...)");
426 SP -= items;
427 {
428 SV * lobj;
429
430 if (sv_derived_from(ST(0), "version")) {
431 SV *tmp = SvRV(ST(0));
432 lobj = tmp;
433 }
434 else
435 Perl_croak(aTHX_ "lobj is not of type version");
436
437 {
438 PUSHs(vnumify(lobj));
439 }
440
441 PUTBACK;
442 return;
443 }
439cb1c4
JP
444}
445
446XS(XS_version_vcmp)
447{
41be1fbd
JH
448 dXSARGS;
449 if (items < 1)
450 Perl_croak(aTHX_ "Usage: version::vcmp(lobj, ...)");
451 SP -= items;
452 {
453 SV * lobj;
454
455 if (sv_derived_from(ST(0), "version")) {
456 SV *tmp = SvRV(ST(0));
457 lobj = tmp;
458 }
459 else
460 Perl_croak(aTHX_ "lobj is not of type version");
461
462 {
463 SV *rs;
464 SV *rvs;
465 SV * robj = ST(1);
466 IV swap = (IV)SvIV(ST(2));
467
468 if ( ! sv_derived_from(robj, "version") )
469 {
470 robj = new_version(robj);
471 }
472 rvs = SvRV(robj);
473
474 if ( swap )
475 {
476 rs = newSViv(vcmp(rvs,lobj));
477 }
478 else
479 {
480 rs = newSViv(vcmp(lobj,rvs));
481 }
482
483 PUSHs(rs);
484 }
485
486 PUTBACK;
487 return;
488 }
439cb1c4
JP
489}
490
491XS(XS_version_boolean)
492{
41be1fbd
JH
493 dXSARGS;
494 if (items < 1)
495 Perl_croak(aTHX_ "Usage: version::boolean(lobj, ...)");
496 SP -= items;
497 {
498 SV * lobj;
499
500 if (sv_derived_from(ST(0), "version")) {
501 SV *tmp = SvRV(ST(0));
502 lobj = tmp;
503 }
504 else
505 Perl_croak(aTHX_ "lobj is not of type version");
506
507 {
508 SV *rs;
509 rs = newSViv( vcmp(lobj,new_version(newSVpvn("0",1))) );
510 PUSHs(rs);
511 }
512
513 PUTBACK;
514 return;
515 }
439cb1c4
JP
516}
517
518XS(XS_version_noop)
519{
41be1fbd
JH
520 dXSARGS;
521 if (items < 1)
522 Perl_croak(aTHX_ "Usage: version::noop(lobj, ...)");
523 {
524 SV * lobj;
525
526 if (sv_derived_from(ST(0), "version")) {
527 SV *tmp = SvRV(ST(0));
528 lobj = tmp;
529 }
530 else
531 Perl_croak(aTHX_ "lobj is not of type version");
532
533 {
534 Perl_croak(aTHX_ "operation not supported with version object");
535 }
536
537 }
538 XSRETURN_EMPTY;
439cb1c4
JP
539}
540
c8d69e4a
JP
541XS(XS_version_is_alpha)
542{
543 dXSARGS;
544 if (items != 1)
545 Perl_croak(aTHX_ "Usage: version::is_alpha(lobj)");
546 SP -= items;
547 {
548 SV *lobj;
549
550 if (sv_derived_from(ST(0), "version")) {
551 SV *tmp = SvRV(ST(0));
552 lobj = tmp;
553 }
554 else
555 Perl_croak(aTHX_ "lobj is not of type version");
556{
557 I32 len = av_len((AV *)lobj);
558 I32 digit = SvIVX(*av_fetch((AV *)lobj, len, 0));
559 if ( digit < 0 )
560 XSRETURN_YES;
561 else
562 XSRETURN_NO;
563}
564 PUTBACK;
565 return;
566 }
567}
568
8800c35a
JH
569XS(XS_utf8_is_utf8)
570{
41be1fbd
JH
571 dXSARGS;
572 if (items != 1)
573 Perl_croak(aTHX_ "Usage: utf8::is_utf8(sv)");
574 {
575 SV * sv = ST(0);
576 {
577 if (SvUTF8(sv))
578 XSRETURN_YES;
579 else
580 XSRETURN_NO;
581 }
582 }
583 XSRETURN_EMPTY;
8800c35a
JH
584}
585
1b026014
NIS
586XS(XS_utf8_valid)
587{
41be1fbd
JH
588 dXSARGS;
589 if (items != 1)
590 Perl_croak(aTHX_ "Usage: utf8::valid(sv)");
591 {
592 SV * sv = ST(0);
593 {
594 STRLEN len;
595 char *s = SvPV(sv,len);
596 if (!SvUTF8(sv) || is_utf8_string((U8*)s,len))
597 XSRETURN_YES;
598 else
599 XSRETURN_NO;
600 }
601 }
602 XSRETURN_EMPTY;
1b026014
NIS
603}
604
605XS(XS_utf8_encode)
606{
607 dXSARGS;
608 if (items != 1)
609 Perl_croak(aTHX_ "Usage: utf8::encode(sv)");
610 {
611 SV * sv = ST(0);
612
613 sv_utf8_encode(sv);
614 }
615 XSRETURN_EMPTY;
616}
617
618XS(XS_utf8_decode)
619{
620 dXSARGS;
621 if (items != 1)
622 Perl_croak(aTHX_ "Usage: utf8::decode(sv)");
623 {
624 SV * sv = ST(0);
625 bool RETVAL;
626
627 RETVAL = sv_utf8_decode(sv);
628 ST(0) = boolSV(RETVAL);
629 sv_2mortal(ST(0));
630 }
631 XSRETURN(1);
632}
633
634XS(XS_utf8_upgrade)
635{
636 dXSARGS;
637 if (items != 1)
638 Perl_croak(aTHX_ "Usage: utf8::upgrade(sv)");
639 {
640 SV * sv = ST(0);
641 STRLEN RETVAL;
642 dXSTARG;
643
644 RETVAL = sv_utf8_upgrade(sv);
645 XSprePUSH; PUSHi((IV)RETVAL);
646 }
647 XSRETURN(1);
648}
649
650XS(XS_utf8_downgrade)
651{
652 dXSARGS;
653 if (items < 1 || items > 2)
654 Perl_croak(aTHX_ "Usage: utf8::downgrade(sv, failok=0)");
655 {
656 SV * sv = ST(0);
657 bool failok;
658 bool RETVAL;
659
660 if (items < 2)
661 failok = 0;
662 else {
663 failok = (int)SvIV(ST(1));
664 }
665
666 RETVAL = sv_utf8_downgrade(sv, failok);
667 ST(0) = boolSV(RETVAL);
668 sv_2mortal(ST(0));
669 }
670 XSRETURN(1);
671}
672
673XS(XS_utf8_native_to_unicode)
674{
675 dXSARGS;
676 UV uv = SvUV(ST(0));
b7953727
JH
677
678 if (items > 1)
679 Perl_croak(aTHX_ "Usage: utf8::native_to_unicode(sv)");
680
1b026014
NIS
681 ST(0) = sv_2mortal(newSViv(NATIVE_TO_UNI(uv)));
682 XSRETURN(1);
683}
684
685XS(XS_utf8_unicode_to_native)
686{
687 dXSARGS;
688 UV uv = SvUV(ST(0));
b7953727
JH
689
690 if (items > 1)
691 Perl_croak(aTHX_ "Usage: utf8::unicode_to_native(sv)");
692
1b026014
NIS
693 ST(0) = sv_2mortal(newSViv(UNI_TO_NATIVE(uv)));
694 XSRETURN(1);
695}
696
14a976d6 697XS(XS_Internals_SvREADONLY) /* This is dangerous stuff. */
29569577
JH
698{
699 dXSARGS;
700 SV *sv = SvRV(ST(0));
701 if (items == 1) {
702 if (SvREADONLY(sv))
703 XSRETURN_YES;
704 else
705 XSRETURN_NO;
706 }
707 else if (items == 2) {
708 if (SvTRUE(ST(1))) {
709 SvREADONLY_on(sv);
710 XSRETURN_YES;
711 }
712 else {
14a976d6 713 /* I hope you really know what you are doing. */
29569577
JH
714 SvREADONLY_off(sv);
715 XSRETURN_NO;
716 }
717 }
14a976d6 718 XSRETURN_UNDEF; /* Can't happen. */
29569577
JH
719}
720
14a976d6 721XS(XS_Internals_SvREFCNT) /* This is dangerous stuff. */
29569577
JH
722{
723 dXSARGS;
724 SV *sv = SvRV(ST(0));
725 if (items == 1)
14a976d6 726 XSRETURN_IV(SvREFCNT(sv) - 1); /* Minus the ref created for us. */
29569577 727 else if (items == 2) {
14a976d6 728 /* I hope you really know what you are doing. */
29569577
JH
729 SvREFCNT(sv) = SvIV(ST(1));
730 XSRETURN_IV(SvREFCNT(sv));
731 }
14a976d6 732 XSRETURN_UNDEF; /* Can't happen. */
29569577
JH
733}
734
dfd4ef2f
NC
735/* Maybe this should return the number of placeholders found in scalar context,
736 and a list of them in list context. */
f044d0d1 737XS(XS_Internals_hv_clear_placehold)
dfd4ef2f
NC
738{
739 dXSARGS;
740 HV *hv = (HV *) SvRV(ST(0));
741
742 /* I don't care how many parameters were passed in, but I want to avoid
743 the unused variable warning. */
744
eb160463 745 items = (I32)HvPLACEHOLDERS(hv);
dfd4ef2f
NC
746
747 if (items) {
748 HE *entry;
749 I32 riter = HvRITER(hv);
750 HE *eiter = HvEITER(hv);
751 hv_iterinit(hv);
fe7bca90
NC
752 /* This may look suboptimal with the items *after* the iternext, but
753 it's quite deliberate. We only get here with items==0 if we've
754 just deleted the last placeholder in the hash. If we've just done
755 that then it means that the hash is in lazy delete mode, and the
756 HE is now only referenced in our iterator. If we just quit the loop
757 and discarded our iterator then the HE leaks. So we do the && the
758 other way to ensure iternext is called just one more time, which
759 has the side effect of triggering the lazy delete. */
760 while ((entry = hv_iternext_flags(hv, HV_ITERNEXT_WANTPLACEHOLDERS))
761 && items) {
dfd4ef2f
NC
762 SV *val = hv_iterval(hv, entry);
763
7996736c 764 if (val == &PL_sv_placeholder) {
dfd4ef2f
NC
765
766 /* It seems that I have to go back in the front of the hash
767 API to delete a hash, even though I have a HE structure
768 pointing to the very entry I want to delete, and could hold
769 onto the previous HE that points to it. And it's easier to
770 go in with SVs as I can then specify the precomputed hash,
771 and don't have fun and games with utf8 keys. */
772 SV *key = hv_iterkeysv(entry);
773
774 hv_delete_ent (hv, key, G_DISCARD, HeHASH(entry));
775 items--;
776 }
777 }
778 HvRITER(hv) = riter;
779 HvEITER(hv) = eiter;
780 }
781
782 XSRETURN(0);
783}
39f7a870 784
39cff0d9
AE
785XS(XS_Regexp_DESTROY)
786{
787
788}
789
39f7a870
JH
790XS(XS_PerlIO_get_layers)
791{
792 dXSARGS;
793 if (items < 1 || items % 2 == 0)
794 Perl_croak(aTHX_ "Usage: PerlIO_get_layers(filehandle[,args])");
5fef3b4a 795#ifdef USE_PERLIO
39f7a870
JH
796 {
797 SV * sv;
798 GV * gv;
799 IO * io;
800 bool input = TRUE;
801 bool details = FALSE;
802
803 if (items > 1) {
39f7a870
JH
804 SV **svp;
805
806 for (svp = MARK + 2; svp <= SP; svp += 2) {
807 SV **varp = svp;
808 SV **valp = svp + 1;
809 STRLEN klen;
810 char *key = SvPV(*varp, klen);
811
812 switch (*key) {
813 case 'i':
814 if (klen == 5 && memEQ(key, "input", 5)) {
815 input = SvTRUE(*valp);
816 break;
817 }
818 goto fail;
819 case 'o':
820 if (klen == 6 && memEQ(key, "output", 6)) {
821 input = !SvTRUE(*valp);
822 break;
823 }
824 goto fail;
825 case 'd':
826 if (klen == 7 && memEQ(key, "details", 7)) {
827 details = SvTRUE(*valp);
828 break;
829 }
830 goto fail;
831 default:
832 fail:
833 Perl_croak(aTHX_
834 "get_layers: unknown argument '%s'",
835 key);
836 }
837 }
838
839 SP -= (items - 1);
840 }
841
842 sv = POPs;
843 gv = (GV*)sv;
844
845 if (!isGV(sv)) {
846 if (SvROK(sv) && isGV(SvRV(sv)))
847 gv = (GV*)SvRV(sv);
848 else
849 gv = gv_fetchpv(SvPVX(sv), FALSE, SVt_PVIO);
850 }
851
852 if (gv && (io = GvIO(gv))) {
853 dTARGET;
854 AV* av = PerlIO_get_layers(aTHX_ input ?
855 IoIFP(io) : IoOFP(io));
856 I32 i;
857 I32 last = av_len(av);
858 I32 nitem = 0;
859
860 for (i = last; i >= 0; i -= 3) {
861 SV **namsvp;
862 SV **argsvp;
863 SV **flgsvp;
864 bool namok, argok, flgok;
865
866 namsvp = av_fetch(av, i - 2, FALSE);
867 argsvp = av_fetch(av, i - 1, FALSE);
868 flgsvp = av_fetch(av, i, FALSE);
869
870 namok = namsvp && *namsvp && SvPOK(*namsvp);
871 argok = argsvp && *argsvp && SvPOK(*argsvp);
872 flgok = flgsvp && *flgsvp && SvIOK(*flgsvp);
873
874 if (details) {
875 XPUSHs(namok ?
876 newSVpv(SvPVX(*namsvp), 0) : &PL_sv_undef);
877 XPUSHs(argok ?
878 newSVpv(SvPVX(*argsvp), 0) : &PL_sv_undef);
879 if (flgok)
880 XPUSHi(SvIVX(*flgsvp));
881 else
882 XPUSHs(&PL_sv_undef);
883 nitem += 3;
884 }
885 else {
886 if (namok && argok)
887 XPUSHs(Perl_newSVpvf(aTHX_ "%"SVf"(%"SVf")",
888 *namsvp, *argsvp));
889 else if (namok)
890 XPUSHs(Perl_newSVpvf(aTHX_ "%"SVf, *namsvp));
891 else
892 XPUSHs(&PL_sv_undef);
893 nitem++;
894 if (flgok) {
895 IV flags = SvIVX(*flgsvp);
896
897 if (flags & PERLIO_F_UTF8) {
898 XPUSHs(newSVpvn("utf8", 4));
899 nitem++;
900 }
901 }
902 }
903 }
904
905 SvREFCNT_dec(av);
906
907 XSRETURN(nitem);
908 }
909 }
5fef3b4a 910#endif
39f7a870
JH
911
912 XSRETURN(0);
913}
914
9a7034eb 915XS(XS_Internals_hash_seed)
c910b28a 916{
c85d3f85
NC
917 /* Using dXSARGS would also have dITEM and dSP,
918 * which define 2 unused local variables. */
919 dMARK; dAX;
81eaca17 920 XSRETURN_UV(PERL_HASH_SEED);
c910b28a
JH
921}
922
008fb0c0 923XS(XS_Internals_rehash_seed)
8e90d776
NC
924{
925 /* Using dXSARGS would also have dITEM and dSP,
926 * which define 2 unused local variables. */
927 dMARK; dAX;
008fb0c0 928 XSRETURN_UV(PL_rehash_seed);
8e90d776
NC
929}
930
05619474
NC
931XS(XS_Internals_HvREHASH) /* Subject to change */
932{
933 dXSARGS;
934 if (SvROK(ST(0))) {
935 HV *hv = (HV *) SvRV(ST(0));
936 if (items == 1 && SvTYPE(hv) == SVt_PVHV) {
937 if (HvREHASH(hv))
938 XSRETURN_YES;
939 else
940 XSRETURN_NO;
941 }
942 }
943 Perl_croak(aTHX_ "Internals::HvREHASH $hashref");
944}