ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/staticperl/perl/universal.c
Revision: 1.1
Committed: Thu Jun 30 14:26:43 2005 UTC (21 years, 3 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: PERL-5-8-7, HEAD
Branch point for: PERL
Log Message:
*** empty log message ***

File Contents

# Content
1 /* universal.c
2 *
3 * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
4 * 2005, 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 story
15 */
16
17 /* This file contains the code that implements the functions in Perl's
18 * UNIVERSAL package, such as UNIVERSAL->can().
19 */
20
21 #include "EXTERN.h"
22 #define PERL_IN_UNIVERSAL_C
23 #include "perl.h"
24
25 #ifdef USE_PERLIO
26 #include "perliol.h" /* For the PERLIO_F_XXX */
27 #endif
28
29 /*
30 * Contributed by Graham Barr <Graham.Barr@tiuk.ti.com>
31 * The main guts of traverse_isa was actually copied from gv_fetchmeth
32 */
33
34 STATIC SV *
35 S_isa_lookup(pTHX_ HV *stash, const char *name, HV* name_stash,
36 int len, int level)
37 {
38 AV* av;
39 GV* gv;
40 GV** gvp;
41 HV* hv = Nullhv;
42 SV* subgen = Nullsv;
43
44 /* A stash/class can go by many names (ie. User == main::User), so
45 we compare the stash itself just in case */
46 if (name_stash && (stash == name_stash))
47 return &PL_sv_yes;
48
49 if (strEQ(HvNAME(stash), name))
50 return &PL_sv_yes;
51
52 if (strEQ(name, "UNIVERSAL"))
53 return &PL_sv_yes;
54
55 if (level > 100)
56 Perl_croak(aTHX_ "Recursive inheritance detected in package '%s'",
57 HvNAME(stash));
58
59 gvp = (GV**)hv_fetch(stash, "::ISA::CACHE::", 14, FALSE);
60
61 if (gvp && (gv = *gvp) != (GV*)&PL_sv_undef && (subgen = GvSV(gv))
62 && (hv = GvHV(gv)))
63 {
64 if (SvIV(subgen) == (IV)PL_sub_generation) {
65 SV* sv;
66 SV** svp = (SV**)hv_fetch(hv, name, len, FALSE);
67 if (svp && (sv = *svp) != (SV*)&PL_sv_undef) {
68 DEBUG_o( Perl_deb(aTHX_ "Using cached ISA %s for package %s\n",
69 name, HvNAME(stash)) );
70 return sv;
71 }
72 }
73 else {
74 DEBUG_o( Perl_deb(aTHX_ "ISA Cache in package %s is stale\n",
75 HvNAME(stash)) );
76 hv_clear(hv);
77 sv_setiv(subgen, PL_sub_generation);
78 }
79 }
80
81 gvp = (GV**)hv_fetch(stash,"ISA",3,FALSE);
82
83 if (gvp && (gv = *gvp) != (GV*)&PL_sv_undef && (av = GvAV(gv))) {
84 if (!hv || !subgen) {
85 gvp = (GV**)hv_fetch(stash, "::ISA::CACHE::", 14, TRUE);
86
87 gv = *gvp;
88
89 if (SvTYPE(gv) != SVt_PVGV)
90 gv_init(gv, stash, "::ISA::CACHE::", 14, TRUE);
91
92 if (!hv)
93 hv = GvHVn(gv);
94 if (!subgen) {
95 subgen = newSViv(PL_sub_generation);
96 GvSV(gv) = subgen;
97 }
98 }
99 if (hv) {
100 SV** svp = AvARRAY(av);
101 /* NOTE: No support for tied ISA */
102 I32 items = AvFILLp(av) + 1;
103 while (items--) {
104 SV* sv = *svp++;
105 HV* basestash = gv_stashsv(sv, FALSE);
106 if (!basestash) {
107 if (ckWARN(WARN_MISC))
108 Perl_warner(aTHX_ packWARN(WARN_SYNTAX),
109 "Can't locate package %"SVf" for @%s::ISA",
110 sv, HvNAME(stash));
111 continue;
112 }
113 if (&PL_sv_yes == isa_lookup(basestash, name, name_stash,
114 len, level + 1)) {
115 (void)hv_store(hv,name,len,&PL_sv_yes,0);
116 return &PL_sv_yes;
117 }
118 }
119 (void)hv_store(hv,name,len,&PL_sv_no,0);
120 }
121 }
122 return &PL_sv_no;
123 }
124
125 /*
126 =head1 SV Manipulation Functions
127
128 =for apidoc sv_derived_from
129
130 Returns a boolean indicating whether the SV is derived from the specified
131 class. This is the function that implements C<UNIVERSAL::isa>. It works
132 for class names as well as for objects.
133
134 =cut
135 */
136
137 bool
138 Perl_sv_derived_from(pTHX_ SV *sv, const char *name)
139 {
140 char *type;
141 HV *stash;
142 HV *name_stash;
143
144 stash = Nullhv;
145 type = Nullch;
146
147 if (SvGMAGICAL(sv))
148 mg_get(sv) ;
149
150 if (SvROK(sv)) {
151 sv = SvRV(sv);
152 type = sv_reftype(sv,0);
153 if (SvOBJECT(sv))
154 stash = SvSTASH(sv);
155 }
156 else {
157 stash = gv_stashsv(sv, FALSE);
158 }
159
160 name_stash = gv_stashpv(name, FALSE);
161
162 return (type && strEQ(type,name)) ||
163 (stash && isa_lookup(stash, name, name_stash, strlen(name), 0)
164 == &PL_sv_yes)
165 ? TRUE
166 : FALSE ;
167 }
168
169 #include "XSUB.h"
170
171 void XS_UNIVERSAL_isa(pTHX_ CV *cv);
172 void XS_UNIVERSAL_can(pTHX_ CV *cv);
173 void XS_UNIVERSAL_VERSION(pTHX_ CV *cv);
174 XS(XS_utf8_is_utf8);
175 XS(XS_utf8_valid);
176 XS(XS_utf8_encode);
177 XS(XS_utf8_decode);
178 XS(XS_utf8_upgrade);
179 XS(XS_utf8_downgrade);
180 XS(XS_utf8_unicode_to_native);
181 XS(XS_utf8_native_to_unicode);
182 XS(XS_Internals_SvREADONLY);
183 XS(XS_Internals_SvREFCNT);
184 XS(XS_Internals_hv_clear_placehold);
185 XS(XS_PerlIO_get_layers);
186 XS(XS_Regexp_DESTROY);
187 XS(XS_Internals_hash_seed);
188 XS(XS_Internals_rehash_seed);
189 XS(XS_Internals_HvREHASH);
190
191 void
192 Perl_boot_core_UNIVERSAL(pTHX)
193 {
194 char *file = __FILE__;
195
196 newXS("UNIVERSAL::isa", XS_UNIVERSAL_isa, file);
197 newXS("UNIVERSAL::can", XS_UNIVERSAL_can, file);
198 newXS("UNIVERSAL::VERSION", XS_UNIVERSAL_VERSION, file);
199 newXS("utf8::is_utf8", XS_utf8_is_utf8, file);
200 newXS("utf8::valid", XS_utf8_valid, file);
201 newXS("utf8::encode", XS_utf8_encode, file);
202 newXS("utf8::decode", XS_utf8_decode, file);
203 newXS("utf8::upgrade", XS_utf8_upgrade, file);
204 newXS("utf8::downgrade", XS_utf8_downgrade, file);
205 newXS("utf8::native_to_unicode", XS_utf8_native_to_unicode, file);
206 newXS("utf8::unicode_to_native", XS_utf8_unicode_to_native, file);
207 newXSproto("Internals::SvREADONLY",XS_Internals_SvREADONLY, file, "\\[$%@];$");
208 newXSproto("Internals::SvREFCNT",XS_Internals_SvREFCNT, file, "\\[$%@];$");
209 newXSproto("Internals::hv_clear_placeholders",
210 XS_Internals_hv_clear_placehold, file, "\\%");
211 newXSproto("PerlIO::get_layers",
212 XS_PerlIO_get_layers, file, "*;@");
213 newXS("Regexp::DESTROY", XS_Regexp_DESTROY, file);
214 newXSproto("Internals::hash_seed",XS_Internals_hash_seed, file, "");
215 newXSproto("Internals::rehash_seed",XS_Internals_rehash_seed, file, "");
216 newXSproto("Internals::HvREHASH", XS_Internals_HvREHASH, file, "\\%");
217 }
218
219
220 XS(XS_UNIVERSAL_isa)
221 {
222 dXSARGS;
223 SV *sv;
224 char *name;
225 STRLEN n_a;
226
227 if (items != 2)
228 Perl_croak(aTHX_ "Usage: UNIVERSAL::isa(reference, kind)");
229
230 sv = ST(0);
231
232 if (SvGMAGICAL(sv))
233 mg_get(sv);
234
235 if (!SvOK(sv) || !(SvROK(sv) || (SvPOK(sv) && SvCUR(sv))
236 || (SvGMAGICAL(sv) && SvPOKp(sv) && SvCUR(sv))))
237 XSRETURN_UNDEF;
238
239 name = (char *)SvPV(ST(1),n_a);
240
241 ST(0) = boolSV(sv_derived_from(sv, name));
242 XSRETURN(1);
243 }
244
245 XS(XS_UNIVERSAL_can)
246 {
247 dXSARGS;
248 SV *sv;
249 char *name;
250 SV *rv;
251 HV *pkg = NULL;
252 STRLEN n_a;
253
254 if (items != 2)
255 Perl_croak(aTHX_ "Usage: UNIVERSAL::can(object-ref, method)");
256
257 sv = ST(0);
258
259 if (SvGMAGICAL(sv))
260 mg_get(sv);
261
262 if (!SvOK(sv) || !(SvROK(sv) || (SvPOK(sv) && SvCUR(sv))
263 || (SvGMAGICAL(sv) && SvPOKp(sv) && SvCUR(sv))))
264 XSRETURN_UNDEF;
265
266 name = (char *)SvPV(ST(1),n_a);
267 rv = &PL_sv_undef;
268
269 if (SvROK(sv)) {
270 sv = (SV*)SvRV(sv);
271 if (SvOBJECT(sv))
272 pkg = SvSTASH(sv);
273 }
274 else {
275 pkg = gv_stashsv(sv, FALSE);
276 }
277
278 if (pkg) {
279 GV *gv = gv_fetchmethod_autoload(pkg, name, FALSE);
280 if (gv && isGV(gv))
281 rv = sv_2mortal(newRV((SV*)GvCV(gv)));
282 }
283
284 ST(0) = rv;
285 XSRETURN(1);
286 }
287
288 XS(XS_UNIVERSAL_VERSION)
289 {
290 dXSARGS;
291 HV *pkg;
292 GV **gvp;
293 GV *gv;
294 SV *sv;
295 char *undef;
296
297 if (SvROK(ST(0))) {
298 sv = (SV*)SvRV(ST(0));
299 if (!SvOBJECT(sv))
300 Perl_croak(aTHX_ "Cannot find version of an unblessed reference");
301 pkg = SvSTASH(sv);
302 }
303 else {
304 pkg = gv_stashsv(ST(0), FALSE);
305 }
306
307 gvp = pkg ? (GV**)hv_fetch(pkg,"VERSION",7,FALSE) : Null(GV**);
308
309 if (gvp && isGV(gv = *gvp) && SvOK(sv = GvSV(gv))) {
310 SV *nsv = sv_newmortal();
311 sv_setsv(nsv, sv);
312 sv = nsv;
313 undef = Nullch;
314 }
315 else {
316 sv = (SV*)&PL_sv_undef;
317 undef = "(undef)";
318 }
319
320 if (items > 1) {
321 STRLEN len;
322 SV *req = ST(1);
323
324 if (undef) {
325 if (pkg)
326 Perl_croak(aTHX_
327 "%s does not define $%s::VERSION--version check failed",
328 HvNAME(pkg), HvNAME(pkg));
329 else {
330 char *str = SvPVx(ST(0), len);
331
332 Perl_croak(aTHX_
333 "%s defines neither package nor VERSION--version check failed", str);
334 }
335 }
336 if (!SvNIOK(sv) && SvPOK(sv)) {
337 char *str = SvPVx(sv,len);
338 while (len) {
339 --len;
340 /* XXX could DWIM "1.2.3" here */
341 if (!isDIGIT(str[len]) && str[len] != '.' && str[len] != '_')
342 break;
343 }
344 if (len) {
345 if (SvNOK(req) && SvPOK(req)) {
346 /* they said C<use Foo v1.2.3> and $Foo::VERSION
347 * doesn't look like a float: do string compare */
348 if (sv_cmp(req,sv) == 1) {
349 Perl_croak(aTHX_ "%s v%"VDf" required--"
350 "this is only v%"VDf,
351 HvNAME(pkg), req, sv);
352 }
353 goto finish;
354 }
355 /* they said C<use Foo 1.002_003> and $Foo::VERSION
356 * doesn't look like a float: force numeric compare */
357 (void)SvUPGRADE(sv, SVt_PVNV);
358 SvNVX(sv) = str_to_version(sv);
359 SvPOK_off(sv);
360 SvNOK_on(sv);
361 }
362 }
363 /* if we get here, we're looking for a numeric comparison,
364 * so force the required version into a float, even if they
365 * said C<use Foo v1.2.3> */
366 if (SvNOK(req) && SvPOK(req)) {
367 NV n = SvNV(req);
368 req = sv_newmortal();
369 sv_setnv(req, n);
370 }
371
372 if (SvNV(req) > SvNV(sv))
373 Perl_croak(aTHX_ "%s version %s required--this is only version %s",
374 HvNAME(pkg), SvPV_nolen(req), SvPV_nolen(sv));
375 }
376
377 finish:
378 ST(0) = sv;
379
380 XSRETURN(1);
381 }
382
383 XS(XS_utf8_is_utf8)
384 {
385 dXSARGS;
386 if (items != 1)
387 Perl_croak(aTHX_ "Usage: utf8::is_utf8(sv)");
388 {
389 SV * sv = ST(0);
390 {
391 if (SvUTF8(sv))
392 XSRETURN_YES;
393 else
394 XSRETURN_NO;
395 }
396 }
397 XSRETURN_EMPTY;
398 }
399
400 XS(XS_utf8_valid)
401 {
402 dXSARGS;
403 if (items != 1)
404 Perl_croak(aTHX_ "Usage: utf8::valid(sv)");
405 {
406 SV * sv = ST(0);
407 {
408 STRLEN len;
409 char *s = SvPV(sv,len);
410 if (!SvUTF8(sv) || is_utf8_string((U8*)s,len))
411 XSRETURN_YES;
412 else
413 XSRETURN_NO;
414 }
415 }
416 XSRETURN_EMPTY;
417 }
418
419 XS(XS_utf8_encode)
420 {
421 dXSARGS;
422 if (items != 1)
423 Perl_croak(aTHX_ "Usage: utf8::encode(sv)");
424 {
425 SV * sv = ST(0);
426
427 sv_utf8_encode(sv);
428 }
429 XSRETURN_EMPTY;
430 }
431
432 XS(XS_utf8_decode)
433 {
434 dXSARGS;
435 if (items != 1)
436 Perl_croak(aTHX_ "Usage: utf8::decode(sv)");
437 {
438 SV * sv = ST(0);
439 bool RETVAL;
440
441 RETVAL = sv_utf8_decode(sv);
442 ST(0) = boolSV(RETVAL);
443 sv_2mortal(ST(0));
444 }
445 XSRETURN(1);
446 }
447
448 XS(XS_utf8_upgrade)
449 {
450 dXSARGS;
451 if (items != 1)
452 Perl_croak(aTHX_ "Usage: utf8::upgrade(sv)");
453 {
454 SV * sv = ST(0);
455 STRLEN RETVAL;
456 dXSTARG;
457
458 RETVAL = sv_utf8_upgrade(sv);
459 XSprePUSH; PUSHi((IV)RETVAL);
460 }
461 XSRETURN(1);
462 }
463
464 XS(XS_utf8_downgrade)
465 {
466 dXSARGS;
467 if (items < 1 || items > 2)
468 Perl_croak(aTHX_ "Usage: utf8::downgrade(sv, failok=0)");
469 {
470 SV * sv = ST(0);
471 bool failok;
472 bool RETVAL;
473
474 if (items < 2)
475 failok = 0;
476 else {
477 failok = (int)SvIV(ST(1));
478 }
479
480 RETVAL = sv_utf8_downgrade(sv, failok);
481 ST(0) = boolSV(RETVAL);
482 sv_2mortal(ST(0));
483 }
484 XSRETURN(1);
485 }
486
487 XS(XS_utf8_native_to_unicode)
488 {
489 dXSARGS;
490 UV uv = SvUV(ST(0));
491
492 if (items > 1)
493 Perl_croak(aTHX_ "Usage: utf8::native_to_unicode(sv)");
494
495 ST(0) = sv_2mortal(newSViv(NATIVE_TO_UNI(uv)));
496 XSRETURN(1);
497 }
498
499 XS(XS_utf8_unicode_to_native)
500 {
501 dXSARGS;
502 UV uv = SvUV(ST(0));
503
504 if (items > 1)
505 Perl_croak(aTHX_ "Usage: utf8::unicode_to_native(sv)");
506
507 ST(0) = sv_2mortal(newSViv(UNI_TO_NATIVE(uv)));
508 XSRETURN(1);
509 }
510
511 XS(XS_Internals_SvREADONLY) /* This is dangerous stuff. */
512 {
513 dXSARGS;
514 SV *sv = SvRV(ST(0));
515 if (items == 1) {
516 if (SvREADONLY(sv))
517 XSRETURN_YES;
518 else
519 XSRETURN_NO;
520 }
521 else if (items == 2) {
522 if (SvTRUE(ST(1))) {
523 SvREADONLY_on(sv);
524 XSRETURN_YES;
525 }
526 else {
527 /* I hope you really know what you are doing. */
528 SvREADONLY_off(sv);
529 XSRETURN_NO;
530 }
531 }
532 XSRETURN_UNDEF; /* Can't happen. */
533 }
534
535 XS(XS_Internals_SvREFCNT) /* This is dangerous stuff. */
536 {
537 dXSARGS;
538 SV *sv = SvRV(ST(0));
539 if (items == 1)
540 XSRETURN_IV(SvREFCNT(sv) - 1); /* Minus the ref created for us. */
541 else if (items == 2) {
542 /* I hope you really know what you are doing. */
543 SvREFCNT(sv) = SvIV(ST(1));
544 XSRETURN_IV(SvREFCNT(sv));
545 }
546 XSRETURN_UNDEF; /* Can't happen. */
547 }
548
549 XS(XS_Internals_hv_clear_placehold)
550 {
551 dXSARGS;
552 HV *hv = (HV *) SvRV(ST(0));
553 if (items != 1)
554 Perl_croak(aTHX_ "Usage: UNIVERSAL::hv_clear_placeholders(hv)");
555 hv_clear_placeholders(hv);
556 XSRETURN(0);
557 }
558
559 XS(XS_Regexp_DESTROY)
560 {
561
562 }
563
564 XS(XS_PerlIO_get_layers)
565 {
566 dXSARGS;
567 if (items < 1 || items % 2 == 0)
568 Perl_croak(aTHX_ "Usage: PerlIO_get_layers(filehandle[,args])");
569 #ifdef USE_PERLIO
570 {
571 SV * sv;
572 GV * gv;
573 IO * io;
574 bool input = TRUE;
575 bool details = FALSE;
576
577 if (items > 1) {
578 SV **svp;
579
580 for (svp = MARK + 2; svp <= SP; svp += 2) {
581 SV **varp = svp;
582 SV **valp = svp + 1;
583 STRLEN klen;
584 char *key = SvPV(*varp, klen);
585
586 switch (*key) {
587 case 'i':
588 if (klen == 5 && memEQ(key, "input", 5)) {
589 input = SvTRUE(*valp);
590 break;
591 }
592 goto fail;
593 case 'o':
594 if (klen == 6 && memEQ(key, "output", 6)) {
595 input = !SvTRUE(*valp);
596 break;
597 }
598 goto fail;
599 case 'd':
600 if (klen == 7 && memEQ(key, "details", 7)) {
601 details = SvTRUE(*valp);
602 break;
603 }
604 goto fail;
605 default:
606 fail:
607 Perl_croak(aTHX_
608 "get_layers: unknown argument '%s'",
609 key);
610 }
611 }
612
613 SP -= (items - 1);
614 }
615
616 sv = POPs;
617 gv = (GV*)sv;
618
619 if (!isGV(sv)) {
620 if (SvROK(sv) && isGV(SvRV(sv)))
621 gv = (GV*)SvRV(sv);
622 else
623 gv = gv_fetchpv(SvPVX(sv), FALSE, SVt_PVIO);
624 }
625
626 if (gv && (io = GvIO(gv))) {
627 dTARGET;
628 AV* av = PerlIO_get_layers(aTHX_ input ?
629 IoIFP(io) : IoOFP(io));
630 I32 i;
631 I32 last = av_len(av);
632 I32 nitem = 0;
633
634 for (i = last; i >= 0; i -= 3) {
635 SV **namsvp;
636 SV **argsvp;
637 SV **flgsvp;
638 bool namok, argok, flgok;
639
640 namsvp = av_fetch(av, i - 2, FALSE);
641 argsvp = av_fetch(av, i - 1, FALSE);
642 flgsvp = av_fetch(av, i, FALSE);
643
644 namok = namsvp && *namsvp && SvPOK(*namsvp);
645 argok = argsvp && *argsvp && SvPOK(*argsvp);
646 flgok = flgsvp && *flgsvp && SvIOK(*flgsvp);
647
648 if (details) {
649 XPUSHs(namok ?
650 newSVpv(SvPVX(*namsvp), 0) : &PL_sv_undef);
651 XPUSHs(argok ?
652 newSVpv(SvPVX(*argsvp), 0) : &PL_sv_undef);
653 if (flgok)
654 XPUSHi(SvIVX(*flgsvp));
655 else
656 XPUSHs(&PL_sv_undef);
657 nitem += 3;
658 }
659 else {
660 if (namok && argok)
661 XPUSHs(Perl_newSVpvf(aTHX_ "%"SVf"(%"SVf")",
662 *namsvp, *argsvp));
663 else if (namok)
664 XPUSHs(Perl_newSVpvf(aTHX_ "%"SVf, *namsvp));
665 else
666 XPUSHs(&PL_sv_undef);
667 nitem++;
668 if (flgok) {
669 IV flags = SvIVX(*flgsvp);
670
671 if (flags & PERLIO_F_UTF8) {
672 XPUSHs(newSVpvn("utf8", 4));
673 nitem++;
674 }
675 }
676 }
677 }
678
679 SvREFCNT_dec(av);
680
681 XSRETURN(nitem);
682 }
683 }
684 #endif
685
686 XSRETURN(0);
687 }
688
689 XS(XS_Internals_hash_seed)
690 {
691 /* Using dXSARGS would also have dITEM and dSP,
692 * which define 2 unused local variables. */
693 dMARK; dAX;
694 XSRETURN_UV(PERL_HASH_SEED);
695 }
696
697 XS(XS_Internals_rehash_seed)
698 {
699 /* Using dXSARGS would also have dITEM and dSP,
700 * which define 2 unused local variables. */
701 dMARK; dAX;
702 XSRETURN_UV(PL_rehash_seed);
703 }
704
705 XS(XS_Internals_HvREHASH) /* Subject to change */
706 {
707 dXSARGS;
708 if (SvROK(ST(0))) {
709 HV *hv = (HV *) SvRV(ST(0));
710 if (items == 1 && SvTYPE(hv) == SVt_PVHV) {
711 if (HvREHASH(hv))
712 XSRETURN_YES;
713 else
714 XSRETURN_NO;
715 }
716 }
717 Perl_croak(aTHX_ "Internals::HvREHASH $hashref");
718 }
719
720 /*
721 * Local variables:
722 * c-indentation-style: bsd
723 * c-basic-offset: 4
724 * indent-tabs-mode: t
725 * End:
726 *
727 * vim: shiftwidth=4:
728 */