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

# User Rev Content
1 root 1.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     */