From: Perl 5 Porters Date: Tue, 31 Dec 1996 20:59:00 +0000 (+1200) Subject: [inseparable changes from patch from perl5.003_17 to perl5.003_18] X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=a60067777be62ee91d1318f9ae26d9ed713245de;p=p5sagit%2Fp5-mst-13.2.git [inseparable changes from patch from perl5.003_17 to perl5.003_18] CORE LANGUAGE CHANGES Subject: Inherited overloading Date: Sun, 29 Dec 1996 08:12:54 -0500 (EST) From: Ilya Zakharevich Files: gv.c lib/overload.pm perl.h sv.c sv.h t/op/overload.t Chip Salzenberg writes: > > Patch now, tarchive later: Below is the fixed overloading patch. Note that in between AMG_names got const on it (a good thing!), but as a corollary I needed to cast away const-ness to actually use it (since, say, newSVpv does not have const args). Enjoy, p5p-msgid: <199612291312.IAA02134@monk.mps.ohio-state.edu> Subject: Closures at file scope must be anonymous From: Chip Salzenberg Files: op.c Subject: Warn on '{if,while} ($x = X)' where X is glob, readdir, or From: Chip Salzenberg Files: op.c pod/perldiag.pod DOCUMENTATION Subject: Re: perldiag.pod entry for "Scalar value @%s{%s} ..." Date: Tue, 31 Dec 1996 11:50:19 -0500 From: Roderick Schertler Files: pod/perldiag.pod Msg-ID: <2043.852051019@eeyore.ibcinc.com> (applied based on p5p patch as commit c885792efecf3f527b3b5099727cc16b03eee1dc) OTHER CORE CHANGES Subject: Get rid of 'Leaked scalars' From: Chip Salzenberg Files: cop.h gv.c op.c TESTS Subject: Expanded locale.t and misc.t From: Jarkko Hietaniemi Files: t/lib/locale.t t/lib/misc.t Subject: Expanded my.t From: Chip Salzenberg Files: t/lib/my.t --- diff --git a/Changes b/Changes index 158a737..7eb79fe 100644 --- a/Changes +++ b/Changes @@ -9,6 +9,116 @@ releases.) ---------------- +Version 5.003_18 +---------------- + +Yet further down the road to 5.004.... + + CORE LANGUAGE CHANGES + + Title: "Inherited overloading" + From: Ilya Zakharevich + Msg-ID: <199612291312.IAA02134@monk.mps.ohio-state.edu> + Date: Sun, 29 Dec 1996 08:12:54 -0500 (EST) + Files: gv.c lib/overload.pm perl.h sv.c sv.h t/op/overload.t + + Title: "Hide lexicals from Cd or Cd module (!)" + From: Chip Salzenberg + Files: pp_ctl.c + + Title: "Closures at file scope must be anonymous" + From: Chip Salzenberg + Files: op.c + + Title: "Warn on '{if,while} ($x = X)' where X is glob, readdir, or " + From: Chip Salzenberg + Files: op.c pod/perldiag.pod + + Title: "Warn on 'undef $x; $x OP 1' where OP is *=, /=, %=, or **=" + From: Chip Salzenberg + Files: pp.c + + CORE PORTABILITY + + Title: "Ultrix setlocale() workaround" + From: Chip Salzenberg + Files: hints/ultrix_4.sh util.c + + OTHER CORE CHANGES + + Title: "Get rid of 'Leaked scalars'" + From: Chip Salzenberg + Files: cop.h gv.c op.c + + Title: "Don't forget $c in C<(($a,$b,$c)=(1,2))=(3,4,5)>" + From: Chip Salzenberg + Files: pp_hot.c + + Title: "Fix core dump on perl_construct()/perl_destruct() loop" + From: Chip Salzenberg + Files: perl.c + + Title: "Add missing syms to global.sym; update magic doc" + From: Chip Salzenberg + Files: global.sym pod/perlguts.pod + + TESTS + + Title: "Expanded locale.t and misc.t" + From: Jarkko Hietaniemi + Files: t/lib/locale.t t/lib/misc.t + + Title: "Expanded my.t" + From: Chip Salzenberg + Files: t/lib/my.t + + Title: "test harness for C" + From: Graham Barr + Msg-ID: <32C76882.3F3C7999@tiuk.ti.com> + Date: Mon, 30 Dec 1996 07:00:18 +0000 + Files: MANIFEST t/op/use.t + + Title: "More tests" + From: Tom Phoenix + Msg-ID: + Msg-ID: + Msg-ID: <199612280347.WAA00293@monk.mps.ohio-state.edu> + Date: Fri, 27 Dec 1996 22:47:24 -0500 (EST) + Files: lib/File/Copy.pm t/lib/filecopy.t + + DOCUMENTATION + + Title: "Updates to perllocale.pod" + From: Dominic Dunlop + Files: pod/perllocale.pod + + Title: "Locale-related pod patches, take 2" + From: Dominic Dunlop + Msg-ID: + Date: Sat, 28 Dec 1996 10:56:41 +0100 + Files: pod/perl.pod pod/perlform.pod pod/perlfunc.pod pod/perlop.pod + pod/perlre.pod pod/perlsec.pod + + Title: "Re: perldiag.pod entry for "Scalar value @%s{%s} ..."" + From: Roderick Schertler + Msg-ID: <2043.852051019@eeyore.ibcinc.com> + Date: Tue, 31 Dec 1996 11:50:19 -0500 + Files: pod/perldiag.pod + + +---------------- Version 5.003_17 ---------------- diff --git a/Configure b/Configure index 3ae746c..464e54c 100755 --- a/Configure +++ b/Configure @@ -5133,11 +5133,13 @@ case "$myhostname" in echo "(Attempting domain name extraction from $tans)" : Why was there an Egrep here, when Sed works? : Look for either a search or a domain directive. - dflt=.`$sed -n -e 's/^search[ ]*\(.*\)/\1/p' $tans \ - | ./tr '[A-Z]' '[a-z]' 2>/dev/null` + dflt=.`$sed -n -e 's/ / /g' \ + -e 's/^search.* \([^ ]*\) *$/\1/p' $tans \ + | ./tr '[A-Z]' '[a-z]' 2>/dev/null` case "$dflt" in - .) dflt=.`$sed -n -e 's/^domain[ ]*\(.*\)/\1/p' $tans \ - | ./tr '[A-Z]' '[a-z]' 2>/dev/null` + .) dflt=.`$sed -n -e 's/ / /g' \ + -e 's/^domain.* \([^ ]*\) *$/\1/p' $tans \ + | ./tr '[A-Z]' '[a-z]' 2>/dev/null` ;; esac fi diff --git a/INSTALL b/INSTALL index 876e2cd..3443d29 100644 --- a/INSTALL +++ b/INSTALL @@ -315,11 +315,11 @@ just put their local extensions in with the standard distribution. In order to support using things like #!/usr/local/bin/perl5.002 after a later version is released, architecture-dependent libraries are stored in a version-specific directory, such as -/usr/local/lib/perl5/archname/5.002/. In 5.000 and 5.001, these files -were just stored in /usr/local/lib/perl5/archname/. If you will not be -using 5.001 binaries, you can delete the standard extensions from the -/usr/local/lib/perl5/archname/ directory. Locally-added extensions can -be moved to the site_perl and site_perl/archname directories. +/usr/local/lib/perl5/archname/5.002/. In Perl 5.000 and 5.001, these +files were just stored in /usr/local/lib/perl5/archname/. If you will +not be using 5.001 binaries, you can delete the standard extensions from +the /usr/local/lib/perl5/archname/ directory. Locally-added extensions +can be moved to the site_perl and site_perl/archname directories. Again, these are just the defaults, and can be changed as you run Configure. @@ -406,7 +406,7 @@ Your system and typical applications may well give quite different results. The default name for the shared library is typically something like -libperl.so.3.2 (for perl5.003_02) or libperl.so.302 or simply +libperl.so.3.2 (for Perl 5.003_02) or libperl.so.302 or simply libperl.so. Configure tries to guess a sensible naming convention based on your C library name. Since the library gets installed in a version-specific architecture-dependent directory, the exact name @@ -436,8 +436,8 @@ LD_LIBRARY_PATH above. There is also an potential problem with the shared perl library if you want to have more than one "flavor" of the same version of perl (e.g. with and without -DDEBUGGING). For example, suppose you build and -install a standard perl5.004 with a shared library. Then, suppose you -try to build perl5.004 with -DDEBUGGING enabled, but everything else +install a standard Perl 5.004 with a shared library. Then, suppose you +try to build Perl 5.004 with -DDEBUGGING enabled, but everything else the same, including all the installation directories. How can you ensure that your newly built perl will link with your newly built libperl.so.4 rather with the installed libperl.so.4? The answer is @@ -645,7 +645,7 @@ various other operating systems. =back -=head1 Binary Compatibility With 5.003 +=head1 Binary Compatibility With Perl 5.003 Perl 5.003 turned on the EMBED feature by default, which tries to avoid possible symbol name conflict by prefixing all global symbols @@ -1012,14 +1012,14 @@ You can safely install the current version of perl5 and still run scripts under the old binaries for versions 5.003 and later ONLY. Instead of starting your script with #!/usr/local/bin/perl, just start it with #!/usr/local/bin/perl5.003 (or whatever version you want to run.) -If you want to retain a version of perl5 prior to perl5.003, you'll +If you want to retain a version of Perl 5 prior to 5.003, you'll need to install the current version in a separate directory tree, since some of the architecture-independent library files have changed in incompatible ways. The architecture-dependent files are stored in a version-specific directory (such as F) so that -they are still accessible. I perl5.000 and perl5.001 did not +they are still accessible. I Perl 5.000 and 5.001 did not put their architecture-dependent libraries in a version-specific directory. They are simply in F. If you will not be using 5.000 or 5.001, you may safely remove those @@ -1032,7 +1032,7 @@ Most extensions will probably not need to be recompiled to use with a newer version of perl. If you do run into problems, and you want to continue to use the old version of perl along with your extension, simply move those extension files to the appropriate version directory, such as -F. Then perl5.002 will find your +F. Then Perl 5.002 will find your files in the 5.002 directory, and newer versions of perl will find your newer extension in the site_perl directory. @@ -1046,7 +1046,7 @@ and adding /opt/perl5.002/bin to the shell PATH variable. Such users may also wish to add a symbolic link /usr/local/bin/perl so that scripts can still start with #!/usr/local/bin/perl. -B: Starting with 5.002_01, all functions in the perl C source +B: Starting with Perl 5.002_01, all functions in the perl C source code are protected by default by the prefix Perl_ (or perl_) so that you may link with third-party libraries without fear of namespace collisons. This breaks compatability with diff --git a/cop.h b/cop.h index 543c039..9728962 100644 --- a/cop.h +++ b/cop.h @@ -48,15 +48,12 @@ struct block_sub { #define POPSUB(cx) \ if (cx->blk_sub.hasargs) { /* put back old @_ */ \ + SvREFCNT_dec(GvAV(defgv)); \ GvAV(defgv) = cx->blk_sub.savearray; \ } \ if (cx->blk_sub.cv) { \ - if (!(CvDEPTH(cx->blk_sub.cv) = cx->blk_sub.olddepth)) { \ - if (cx->blk_sub.hasargs) { \ - SvREFCNT_inc((SV*)cx->blk_sub.argarray); \ - } \ + if (!(CvDEPTH(cx->blk_sub.cv) = cx->blk_sub.olddepth)) \ SvREFCNT_dec((SV*)cx->blk_sub.cv); \ - } \ } #define POPFORMAT(cx) \ diff --git a/embed.h b/embed.h index 84c3371..2399d0a 100644 --- a/embed.h +++ b/embed.h @@ -67,12 +67,14 @@ #define check_uni Perl_check_uni #define checkcomma Perl_checkcomma #define ck_aelem Perl_ck_aelem +#define ck_anoncode Perl_ck_anoncode #define ck_bitop Perl_ck_bitop #define ck_concat Perl_ck_concat #define ck_delete Perl_ck_delete #define ck_eof Perl_ck_eof #define ck_eval Perl_ck_eval #define ck_exec Perl_ck_exec +#define ck_exists Perl_ck_exists #define ck_ftst Perl_ck_ftst #define ck_fun Perl_ck_fun #define ck_fun_locale Perl_ck_fun_locale @@ -1073,6 +1075,7 @@ #define vtbl_glob Perl_vtbl_glob #define vtbl_isa Perl_vtbl_isa #define vtbl_isaelem Perl_vtbl_isaelem +#define vtbl_itervar Perl_vtbl_itervar #define vtbl_mglob Perl_vtbl_mglob #define vtbl_nkeys Perl_vtbl_nkeys #define vtbl_pack Perl_vtbl_pack diff --git a/ext/IO/lib/IO/Handle.pm b/ext/IO/lib/IO/Handle.pm index 59741c1..af706cf 100644 --- a/ext/IO/lib/IO/Handle.pm +++ b/ext/IO/lib/IO/Handle.pm @@ -76,7 +76,7 @@ result! See L for complete descriptions of each of the following supported C methods, which are just front ends for the corresponding built-in functions: - + close fileno getc diff --git a/ext/IO/lib/IO/Seekable.pm b/ext/IO/lib/IO/Seekable.pm index e8a9530..3bae914 100644 --- a/ext/IO/lib/IO/Seekable.pm +++ b/ext/IO/lib/IO/Seekable.pm @@ -26,7 +26,7 @@ that value to return to a previously visited position. See L for complete descriptions of each of the following supported C methods, which are just front ends for the corresponding built-in functions: - + clearerr seek tell diff --git a/gv.c b/gv.c index 6dd8ad0..45b6aec 100644 --- a/gv.c +++ b/gv.c @@ -818,8 +818,7 @@ GV* gv; SvREFCNT_dec(gp->gp_av); SvREFCNT_dec(gp->gp_hv); SvREFCNT_dec(gp->gp_io); - if ((cv = gp->gp_cv) && !GvCVGEN(gv)) - SvREFCNT_dec(cv); + SvREFCNT_dec(gp->gp_cv); SvREFCNT_dec(gp->gp_form); Safefree(gp); @@ -863,14 +862,14 @@ HV* stash; CV* cv; MAGIC* mg=mg_find((SV*)stash,'c'); AMT *amtp=mg ? (AMT*)mg->mg_ptr: NULL; + AMT amt; if (mg && (amtp=((AMT*)(mg->mg_ptr)))->was_ok_am == amagic_generation && amtp->was_ok_sub == sub_generation) - return HV_AMAGIC(stash)? TRUE: FALSE; - gvp=(GV**)hv_fetch(stash,"OVERLOAD",8,FALSE); - if (amtp && amtp->table) { + return AMT_AMAGIC(amtp); + if (amtp && AMT_AMAGIC(amtp)) { /* Have table. */ int i; - for (i=1;itable[i]) { SvREFCNT_dec(amtp->table[i]); } @@ -880,38 +879,32 @@ HV* stash; DEBUG_o( deb("Recalcing overload magic in package %s\n",HvNAME(stash)) ); + amt.was_ok_am = amagic_generation; + amt.was_ok_sub = sub_generation; + amt.fallback = AMGfallNO; + amt.flags = 0; + +#ifdef OVERLOAD_VIA_HASH + gvp=(GV**)hv_fetch(stash,"OVERLOAD",8,FALSE); /* A shortcut */ if (gvp && ((gv = *gvp) != (GV*)&sv_undef && (hv = GvHV(gv)))) { int filled=0; int i; char *cp; - AMT amt; SV* sv; SV** svp; - GV** gvp; - -/* if (*(svp)==(SV*)amagic_generation && *(svp+1)==(SV*)sub_generation) { - DEBUG_o( deb("Overload magic in package %s up-to-date\n",HvNAME(stash)) -); - return HV_AMAGIC(stash)? TRUE: FALSE; - }*/ - - amt.was_ok_am=amagic_generation; - amt.was_ok_sub=sub_generation; - amt.fallback=AMGfallNO; /* Work with "fallback" key, which we assume to be first in AMG_names */ - if ((cp=((char**)(*AMG_names))[0]) && - (svp=(SV**)hv_fetch(hv,cp,strlen(cp),FALSE)) && (sv = *svp)) { + if (( cp = (char *)AMG_names[0] ) && + (svp = (SV**)hv_fetch(hv,cp,strlen(cp),FALSE)) && (sv = *svp)) { if (SvTRUE(sv)) amt.fallback=AMGfallYES; else if (SvOK(sv)) amt.fallback=AMGfallNEVER; } - - for (i=1;img_ptr)->table)) + && (ocvp = cvp = (AMT_AMAGIC((AMT*)mg->mg_ptr) + ? (oamtp = amtp = (AMT*)mg->mg_ptr)->table + : NULL)) && ((cv = cvp[off=method+assignshift]) || (assign && amtp->fallback > AMGfallNEVER && /* fallback to * usual method */ @@ -1071,7 +1094,9 @@ int flags; if (!cv) goto not_found; } else if (!(AMGf_noright & flags) && SvAMAGIC(right) && (mg = mg_find((SV*)(stash=SvSTASH(SvRV(right))),'c')) - && (cvp = ((amtp=(AMT*)mg->mg_ptr)->table)) + && (cvp = (AMT_AMAGIC((AMT*)mg->mg_ptr) + ? (amtp = (AMT*)mg->mg_ptr)->table + : NULL)) && (cv = cvp[off=method])) { /* Method for right * argument found */ lr=1; @@ -1108,7 +1133,7 @@ int flags; goto not_found; } } else { - not_found: /* No method found, either report or die */ + not_found: /* No method found, either report or croak */ if (ocvp && (cv=ocvp[nomethod_amg])) { /* Call report method */ notfound = 1; lr = -1; } else if (cvp && (cv=cvp[nomethod_amg])) { @@ -1116,7 +1141,7 @@ int flags; } else { if (off==-1) off=method; sprintf(buf, "Operation `%s': no method found,\n\tleft argument %s%.256s,\n\tright argument %s%.256s", - ((char**)AMG_names)[method + assignshift], + AMG_names[method + assignshift], SvAMAGIC(left)? "in overloaded package ": "has no overloaded magic", @@ -1132,7 +1157,7 @@ int flags; if (amtp && amtp->fallback >= AMGfallYES) { DEBUG_o( deb(buf) ); } else { - die(buf); + croak(buf); } return NULL; } @@ -1140,11 +1165,11 @@ int flags; } if (!notfound) { DEBUG_o( deb("Overloaded operator `%s'%s%s%s:\n\tmethod%s found%s in package %.256s%s\n", - ((char**)AMG_names)[off], + AMG_names[off], method+assignshift==off? "" : " (initially `", method+assignshift==off? "" : - ((char**)AMG_names)[method+assignshift], + AMG_names[method+assignshift], method+assignshift==off? "" : "')", flags & AMGf_unary? "" : lr==1 ? " for right argument": " for left argument", @@ -1182,7 +1207,7 @@ int flags; PUSHs(lr>0? left: right); PUSHs( assign ? &sv_undef : (lr>0? &sv_yes: &sv_no)); if (notfound) { - PUSHs( sv_2mortal(newSVpv(((char**)AMG_names)[method + assignshift],0)) ); + PUSHs( sv_2mortal(newSVpv((char *)AMG_names[method + assignshift],0)) ); } PUSHs((SV*)cv); PUTBACK; @@ -1230,7 +1255,7 @@ ans=!SvOK(res); break; return ans? &sv_yes: &sv_no; } else if (method==copy_amg) { if (!SvROK(res)) { - die("Copy method did not return a reference"); + croak("Copy method did not return a reference"); } return SvREFCNT_inc(SvRV(res)); } else { diff --git a/lib/Class/Template.pm b/lib/Class/Template.pm index 311c72a..23a0d5b 100644 --- a/lib/Class/Template.pm +++ b/lib/Class/Template.pm @@ -84,7 +84,7 @@ This module uses perl5 classes to create nested data types. } =head1 NOTES - + Use '%' if the member should point to an anonymous hash. Use '@' if the member should point to an anonymous array. diff --git a/lib/ExtUtils/Embed.pm b/lib/ExtUtils/Embed.pm index fb2664c..c663d64 100644 --- a/lib/ExtUtils/Embed.pm +++ b/lib/ExtUtils/Embed.pm @@ -265,7 +265,7 @@ functions while building your application. =head1 @EXPORT ExtUtils::Embed exports the following functions: - + xsinit(), ldopts(), ccopts(), perl_inc(), ccflags(), ccdlflags(), xsi_header(), xsi_protos(), xsi_body() @@ -301,7 +301,7 @@ B<[@modules]> is an array ref, same as additional arguments mentioned above. =item Examples - + perl -MExtUtils::Embed -e xsinit -- -o xsinit.c Socket @@ -395,7 +395,7 @@ are picked up from the B file in the same directory. perl -MExtUtils::Embed -e ldopts -- -std Socket - + This will do the same as the above example, along with printing additional arguments for linking with the B extension. @@ -457,7 +457,7 @@ B uses the xsi_* functions to generate most of it's code. For examples on how to use B for building C/C++ applications with embedded perl, see the eg/ directory and L. - + =head1 SEE ALSO L diff --git a/lib/FileHandle.pm b/lib/FileHandle.pm index e2ce83d..aa8282b 100644 --- a/lib/FileHandle.pm +++ b/lib/FileHandle.pm @@ -184,7 +184,7 @@ result! See L for complete descriptions of each of the following supported C methods, which are just front ends for the corresponding built-in functions: - + close fileno getc diff --git a/lib/Net/netent.pm b/lib/Net/netent.pm index 9f385b0..c21096d 100644 --- a/lib/Net/netent.pm +++ b/lib/Net/netent.pm @@ -113,7 +113,7 @@ The gethost() functions do this in the Perl core: That means that the address comes back in binary for the host functions, and as a regular perl integer for the net ones. This seems a bug, but here's how to deal with it: - + use strict; use Socket; use Net::netent; @@ -154,7 +154,7 @@ This seems a bug, but here's how to deal with it: } } } - + =head1 NOTE While this class is currently implemented using the Class::Template diff --git a/lib/Tie/Hash.pm b/lib/Tie/Hash.pm index 20b6777..2117c54 100644 --- a/lib/Tie/Hash.pm +++ b/lib/Tie/Hash.pm @@ -98,7 +98,7 @@ L module. While these do not utilize B, they serve as good working examples. =cut - + use Carp; sub new { diff --git a/lib/diagnostics.pm b/lib/diagnostics.pm index 31e7670..3492bd3 100755 --- a/lib/diagnostics.pm +++ b/lib/diagnostics.pm @@ -150,8 +150,8 @@ You have to to this instead, and I you load the module. BEGIN { $diagnostics::PRETTY = 1 } I could start up faster by delaying compilation until it should be -needed, but this gets a "panic: top_level" -when using the pragma form in 5.001e. +needed, but this gets a "panic: top_level" when using the pragma form +in Perl 5.001e. While it's true that this documentation is somewhat subserious, if you use a program named I, you should expect a bit of whimsy. diff --git a/lib/overload.pm b/lib/overload.pm index 20411ea..ec874ec 100644 --- a/lib/overload.pm +++ b/lib/overload.pm @@ -1,12 +1,26 @@ package overload; +sub nil {} + sub OVERLOAD { $package = shift; my %arg = @_; - my $hash = \%{$package . "::OVERLOAD"}; + my ($sub, $fb); + $ {$package . "::OVERLOAD"}{dummy}++; # Register with magic by touching. + *{$package . "::()"} = \&nil; # Make it findable via fetchmethod. for (keys %arg) { - $hash->{$_} = $arg{$_}; + if ($_ eq 'fallback') { + $fb = $arg{$_}; + } else { + $sub = $arg{$_}; + if (not ref $sub and $sub !~ /::/) { + $sub = "${'package'}::$sub"; + } + #print STDERR "Setting `$ {'package'}::\cO$_' to \\&`$sub'.\n"; + *{$package . "::(" . $_} = \&{ $sub }; + } } + ${$package . "::()"} = $fb; # Make it findable too (fallback only). } sub import { @@ -18,41 +32,47 @@ sub import { sub unimport { $package = (caller())[0]; - my $hash = \%{$package . "::OVERLOAD"}; + ${$package . "::OVERLOAD"}{dummy}++; # Upgrade the table shift; for (@_) { - delete $hash->{$_}; + if ($_ eq 'fallback') { + undef $ {$package . "::()"}; + } else { + delete $ {$package . "::"}{"(" . $_}; + } } } sub Overloaded { - ($package = ref $_[0]) and defined %{$package . "::OVERLOAD"}; + my $package = shift; + $package = ref $package if ref $package; + $package->can('()'); } sub OverloadedStringify { - ($package = ref $_[0]) and - defined %{$package . "::OVERLOAD"} and - exists $ {$package . "::OVERLOAD"}{'""'} and - defined &{$ {$package . "::OVERLOAD"}{'""'}}; + my $package = shift; + $package = ref $package if ref $package; + $package->can('(""') } sub Method { - ($package = ref $_[0]) and - defined %{$package . "::OVERLOAD"} and - $ {$package . "::OVERLOAD"}{$_[1]}; + my $package = shift; + $package = ref $package if ref $package; + $package->can('(' . shift) } sub AddrRef { - $package = ref $_[0]; - bless $_[0], Overload::Fake; # Non-overloaded package + my $package = ref $_[0]; + return "$_[0]" unless $package; + bless $_[0], overload::Fake; # Non-overloaded package my $str = "$_[0]"; bless $_[0], $package; # Back - $str; + $package . substr $str, index $str, '='; } sub StrVal { - (OverloadedStringify) ? - (AddrRef) : + (OverloadedStringify($_[0])) ? + (AddrRef(shift)) : "$_[0]"; } @@ -486,9 +506,13 @@ induces diagnostic messages. =head1 BUGS Because it is used for overloading, the per-package associative array -%OVERLOAD now has a special meaning in Perl. +%OVERLOAD now has a special meaning in Perl. The symbol table is +filled with names looking like line-noise. -As shipped, mathemagical properties are not inherited via the @ISA tree. +For the purpose of inheritance every overloaded package behaves as if +C is present (possibly undefined). This may create +interesting effects if some package is not overloaded, but inherits +from two overloaded packages. This document is confusing. diff --git a/op.c b/op.c index eecde67..ac7b1a6 100644 --- a/op.c +++ b/op.c @@ -210,16 +210,14 @@ pad_findlex(char *name, PADOFFSET newoff, U32 seq, CV* startcv, I32 cx_ix) SvNVX(sv) = (double)curcop->cop_seq; SvIVX(sv) = 999999999; /* A ref, intro immediately */ SvFLAGS(sv) |= SVf_FAKE; - if (!CvUNIQUE(cv)) { - /* "It's closures all the way down." */ - CvCLONE_on(compcv); - if (cv != startcv) { - CV *bcv; - for (bcv = startcv; - bcv && bcv != cv && !CvCLONE(bcv); - bcv = CvOUTSIDE(bcv)) - CvCLONE_on(bcv); - } + /* "It's closures all the way down." */ + CvCLONE_on(compcv); + if (cv != startcv) { + CV *bcv; + for (bcv = startcv; + bcv && bcv != cv && !CvCLONE(bcv); + bcv = CvOUTSIDE(bcv)) + CvCLONE_on(bcv); } } av_store(comppad, newoff, SvREFCNT_inc(oldsv)); @@ -454,8 +452,13 @@ OP *op; case OP_ENTEREVAL: op->op_targ = 0; /* Was holding hints. */ break; + default: + if (!(op->op_flags & OPf_REF) || (check[op->op_type] != ck_ftst)) + break; + /* FALL THROUGH */ case OP_GVSV: case OP_GV: + case OP_AELEMFAST: SvREFCNT_dec(cGVOP->op_gv); break; case OP_NEXTSTATE: @@ -484,8 +487,6 @@ OP *op; pregfree(cPMOP->op_pmregexp); SvREFCNT_dec(cPMOP->op_pmshort); break; - default: - break; } if (op->op_targ > 0) @@ -2444,6 +2445,27 @@ OP* other; else scalar(other); } + else if (dowarn && (first->op_flags & OPf_KIDS)) { + OP *k1 = ((UNOP*)first)->op_first; + OP *k2 = k1->op_sibling; + OPCODE warnop = 0; + switch (first->op_type) + { + case OP_NULL: + if (k2 && k2->op_type == OP_READLINE + && (k2->op_flags & OPf_STACKED) + && (k1->op_type == OP_RV2SV || k1->op_type == OP_PADSV)) + warnop = k2->op_type; + break; + + case OP_SASSIGN: + if (k1->op_type == OP_READDIR || k1->op_type == OP_GLOB) + warnop = k1->op_type; + break; + } + if (warnop) + warn("Value of %s may be \"0\"; use \"defined\"", op_desc[warnop]); + } if (!other) return first; @@ -2982,8 +3004,11 @@ OP *block; if (op) sub_generation++; if (cv = GvCV(gv)) { - if (GvCVGEN(gv)) - cv = 0; /* just a cached method */ + if (GvCVGEN(gv)) { + /* just a cached method */ + SvREFCNT_dec(cv); + cv = 0; + } else if (CvROOT(cv) || CvXSUB(cv) || GvASSUMECV(gv)) { SV* const_sv = cv_const_sv(cv); @@ -3009,6 +3034,7 @@ OP *block; } if (cv) { /* must reuse cv if autoloaded */ cv_undef(cv); + CvFLAGS(cv) = (CvFLAGS(cv)&~CVf_CLONE) | (CvFLAGS(compcv)&CVf_CLONE); CvOUTSIDE(cv) = CvOUTSIDE(compcv); CvOUTSIDE(compcv) = 0; CvPADLIST(cv) = CvPADLIST(compcv); @@ -3044,6 +3070,10 @@ OP *block; return cv; } + /* XXX: Named functions at file scope cannot be closures */ + if (op && CvUNIQUE(CvOUTSIDE(cv))) + CvCLONE_off(cv); + av = newAV(); /* Will be @_ */ av_extend(av, 0); av_store(comppad, 0, (SV*)av); @@ -3061,40 +3091,37 @@ OP *block; CvSTART(cv) = LINKLIST(CvROOT(cv)); CvROOT(cv)->op_next = 0; peep(CvSTART(cv)); + if (s = strrchr(name,':')) s++; else s = name; if (strEQ(s, "BEGIN") && !error_count) { - line_t oldline = compiling.cop_line; - SV *oldrs = rs; - ENTER; SAVESPTR(compiling.cop_filegv); + SAVEI16(compiling.cop_line); SAVEI32(perldb); + save_svref(&rs); + sv_setsv(rs, nrs); + if (!beginav) beginav = newAV(); - av_push(beginav, (SV *)cv); DEBUG_x( dump_sub(gv) ); - rs = SvREFCNT_inc(nrs); - SvREFCNT_inc(cv); + av_push(beginav, (SV *)cv); + GvCV(gv) = 0; calllist(beginav); - if (GvCV(gv) == cv) { /* Detach it. */ - SvREFCNT_dec(cv); - GvCV(gv) = 0; /* Was above calllist, why? IZ */ - } - SvREFCNT_dec(rs); - rs = oldrs; + curcop = &compiling; - curcop->cop_line = oldline; /* might have recursed to yylex */ LEAVE; } else if (strEQ(s, "END") && !error_count) { if (!endav) endav = newAV(); av_unshift(endav, 1); - av_store(endav, 0, SvREFCNT_inc(cv)); + av_store(endav, 0, (SV *)cv); + GvCV(gv) = 0; } + if (perldb && curstash != debstash) { SV *sv; SV *tmpstr = sv_newmortal(); @@ -3122,13 +3149,14 @@ OP *block; perl_call_sv((SV*)cv, G_DISCARD); } } - op_free(op); - copline = NOLINE; - LEAVE_SCOPE(floor); + if (!op) { GvCV(gv) = 0; /* Will remember in SVOP instead. */ CvANON_on(cv); } + op_free(op); + copline = NOLINE; + LEAVE_SCOPE(floor); return cv; } @@ -4397,7 +4425,7 @@ register OP* o; o->op_type = OP_AELEMFAST; o->op_ppaddr = ppaddr[OP_AELEMFAST]; o->op_private = (U8)i; - GvAVn((GV*)(((SVOP*)o)->op_sv)); + GvAVn(((GVOP*)o)->op_gv); } } o->op_seq = op_seqmax++; diff --git a/patchlevel.h b/patchlevel.h index fcdf883..ccdc725 100644 --- a/patchlevel.h +++ b/patchlevel.h @@ -1,5 +1,5 @@ #define PATCHLEVEL 3 -#define SUBVERSION 17 +#define SUBVERSION 18 /* local_patches -- list of locally applied less-than-subversion patches. diff --git a/perl.h b/perl.h index 470a44d..f048d73 100644 --- a/perl.h +++ b/perl.h @@ -1950,55 +1950,67 @@ EXT MGVTBL vtbl_amagicelem; #ifdef OVERLOAD EXT long amagic_generation; -#define NofAMmeth 29 +#define NofAMmeth 58 #ifdef DOINIT -EXTCONST char * AMG_names[NofAMmeth][2] = { - {"fallback","abs"}, - {"bool", "nomethod"}, - {"\"\"", "0+"}, - {"+","+="}, - {"-","-="}, - {"*", "*="}, - {"/", "/="}, - {"%", "%="}, - {"**", "**="}, - {"<<", "<<="}, - {">>", ">>="}, - {"&", "&="}, - {"|", "|="}, - {"^", "^="}, - {"<", "<="}, - {">", ">="}, - {"==", "!="}, - {"<=>", "cmp"}, - {"lt", "le"}, - {"gt", "ge"}, - {"eq", "ne"}, - {"!", "~"}, - {"++", "--"}, - {"atan2", "cos"}, - {"sin", "exp"}, - {"log", "sqrt"}, - {"x","x="}, - {".",".="}, - {"=","neg"} +EXTCONST char * AMG_names[NofAMmeth] = { + "fallback", "abs", /* "fallback" should be the first. */ + "bool", "nomethod", + "\"\"", "0+", + "+", "+=", + "-", "-=", + "*", "*=", + "/", "/=", + "%", "%=", + "**", "**=", + "<<", "<<=", + ">>", ">>=", + "&", "&=", + "|", "|=", + "^", "^=", + "<", "<=", + ">", ">=", + "==", "!=", + "<=>", "cmp", + "lt", "le", + "gt", "ge", + "eq", "ne", + "!", "~", + "++", "--", + "atan2", "cos", + "sin", "exp", + "log", "sqrt", + "x", "x=", + ".", ".=", + "=", "neg" }; #else -EXTCONST char * AMG_names[NofAMmeth][2]; +EXTCONST char * AMG_names[NofAMmeth]; #endif /* def INITAMAGIC */ -struct am_table { +struct am_table { long was_ok_sub; long was_ok_am; - CV* table[NofAMmeth*2]; + U32 flags; + CV* table[NofAMmeth]; long fallback; }; +struct am_table_short { + long was_ok_sub; + long was_ok_am; + U32 flags; +}; typedef struct am_table AMT; +typedef struct am_table_short AMTS; #define AMGfallNEVER 1 #define AMGfallNO 2 #define AMGfallYES 3 +#define AMTf_AMAGIC 1 +#define AMT_AMAGIC(amt) ((amt)->flags & AMTf_AMAGIC) +#define AMT_AMAGIC_on(amt) ((amt)->flags |= AMTf_AMAGIC) +#define AMT_AMAGIC_off(amt) ((amt)->flags &= ~AMTf_AMAGIC) + enum { fallback_amg, abs_amg, bool__amg, nomethod_amg, diff --git a/pod/perldiag.pod b/pod/perldiag.pod index 49d30fc..6e4a3cf 100644 --- a/pod/perldiag.pod +++ b/pod/perldiag.pod @@ -1815,7 +1815,7 @@ shifting or popping (for array variables). See L. =item Scalar value @%s[%s] better written as $%s[%s] -(W) You've used an array slice (indicated by @) to select a single value of +(W) You've used an array slice (indicated by @) to select a single element of an array. Generally it's better to ask for a scalar value (indicated by $). The difference is that C<$foo[&bar]> always behaves like a scalar, both when assigning to it and when evaluating its argument, while C<@foo[&bar]> behaves @@ -1827,6 +1827,20 @@ element as a list, you need to look into how references work, because Perl will not magically convert between scalars and lists for you. See L. +=item Scalar value @%s{%s} better written as $%s{%s} + +(W) You've used a hash slice (indicated by @) to select a single element of +a hash. Generally it's better to ask for a scalar value (indicated by $). +The difference is that C<$foo{&bar}> always behaves like a scalar, both when +assigning to it and when evaluating its argument, while C<@foo{&bar}> behaves +like a list when you assign to it, and provides a list context to its +subscript, which can do weird things if you're expecting only one subscript. + +On the other hand, if you were actually hoping to treat the hash +element as a list, you need to look into how references work, because +Perl will not magically convert between scalars and lists for you. See +L. + =item Script is not setuid/setgid in suidperl (F) Oddly, the suidperl program was invoked on a script with its setuid @@ -2349,6 +2363,14 @@ L for more on this. (W) A copy of the object returned from C (or C) was still valid when C was called. +=item Value of %s may be "0"; use "defined" + +(W) In a conditional expression, you used , <*> (glob), or +C as a boolean value. Each of these operators may return a +value of "0"; that would make the conditional expression false, which +is probably not what you intended. So, when using these operators in +conditional expressions, test their values with the C operator. + =item Variable "%s" is not exported (F) While "use strict" in effect, you referred to a global variable diff --git a/pod/perldsc.pod b/pod/perldsc.pod index 5beaa8b..5a3a83e 100644 --- a/pod/perldsc.pod +++ b/pod/perldsc.pod @@ -303,8 +303,8 @@ variable, and it would thereby remind you to write instead: =head1 DEBUGGING -Before 5.002, the standard Perl debugger didn't do a very nice job of -printing out complex data structures. With version 5.002 or above, the +Before version 5.002, the standard Perl debugger didn't do a very nice job of +printing out complex data structures. With 5.002 or above, the debugger includes several new features, including command line editing as well as the C command to dump out complex data structures. For example, given the assignment to $LoL above, here's the debugger output: diff --git a/pod/perlembed.pod b/pod/perlembed.pod index ea0e833..30c6e0a 100644 --- a/pod/perlembed.pod +++ b/pod/perlembed.pod @@ -37,7 +37,7 @@ Read on... L -There's one example in each of the six sections: +There's one example in each of the eight sections: L @@ -49,6 +49,8 @@ L L +L + L This documentation is UNIX specific. @@ -69,7 +71,7 @@ Your C program will--usually--allocate, "run", and deallocate a I object, which is defined in the perl library. If your copy of Perl is recent enough to contain this documentation -(5.002 or later), then the perl library (and I and +(version 5.002 or later), then the perl library (and I and I, which you'll also need) will reside in a directory resembling this: @@ -225,13 +227,10 @@ L =head2 Evaluating a Perl statement from your C program -NOTE: This section, and the next, employ some very brittle techniques -for evaluating strings of Perl code. Perl 5.002 contains some nifty -features that enable A Better Way (such as with L). -Look for updates to this document soon. - -One way to evaluate a Perl string is to define a function (we'll call -ours I) that wraps around Perl's L. +One way to evaluate pieces of Perl code is to use L. +We have wrapped this function with our own I function, which +converts a command string to an SV, passing this and the L +flag to L. Arguably, this is the only routine you'll ever need to execute snippets of Perl code from within your C program. Your string can be @@ -250,17 +249,14 @@ the first, a C from the second, and a C from the third. static PerlInterpreter *my_perl; - int perl_eval(char *string) + I32 perl_eval(char *string) { - char *argv[2]; - argv[0] = string; - argv[1] = NULL; - perl_call_argv("_eval_", 0, argv); + return perl_eval_sv(newSVpv(string,0), G_DISCARD); } main (int argc, char **argv, char **env) { - char *embedding[] = { "", "-e", "sub _eval_ { eval $_[0] }" }; + char *embedding[] = { "", "-e", "0" }; STRLEN length; my_perl = perl_alloc(); @@ -328,12 +324,9 @@ been wrapped here): #include #include static PerlInterpreter *my_perl; - int perl_eval(char *string) + I32 perl_eval(char *string) { - char *argv[2]; - argv[0] = string; - argv[1] = NULL; - perl_call_argv("_eval_", 0, argv); + return perl_eval_sv(newSVpv(string,0), G_DISCARD); } /** match(string, pattern) ** @@ -401,7 +394,7 @@ been wrapped here): } main (int argc, char **argv, char **env) { - char *embedding[] = { "", "-e", "sub _eval_ { eval $_[0] }" }; + char *embedding[] = { "", "-e", "0" }; char *text, **match_list; int num_matches, i; int j; @@ -555,6 +548,198 @@ Compile and run: % power 3 to the 4th power is 81. +=head2 Maintaining a persistent interpreter + +When developing interactive, potentially long-running applications, it's +a good idea to maintain a persistent interpreter rather than allocating +and constructing a new interpreter multiple times. The major gain here is +speed, avoiding the penalty of Perl start-up time. However, a persistent +interpreter will require you to be more cautious in your use of namespace +and variable scoping. In previous examples we've been using global variables +in the default package B
. We knew exactly what code would be run, +making it safe to assume we'd avoid any variable collision or outrageous +symbol table growth. + +Let's say your application is a server, which must run perl code from an +arbitrary file during each transaction. Your server has no way of knowing +what code is inside anyone of these files. +If the file was pulled in by B, compiled into a newly +constructed interpreter, then cleaned out with B after the +the transaction, you'd be shielded from most namespace troubles. + +One way to avoid namespace collisions in this scenerio, is to translate the +file name into a valid Perl package name, which is most likely to be unique, +then compile the code into that package using L. +In the example below, each file will only be compiled once, unless it is +updated on disk. +Optionally, the application may choose to clean out the symbol table +associated with the file after we are done with it. We'll call the subroutine +B which lives in the file B, with +L, passing the filename and boolean cleanup/cache +flag as arguments. + +Note that the process will continue to grow for each file that is compiled, +and each file it pulls in via L, L or +L. In addition, there maybe Bed subroutines and +other conditions that cause Perl's symbol table to grow. You may wish to +add logic which keeps track of process size or restarts itself after n number +of requests to ensure memory consumption is kept to a minimum. You also need +to consider the importance of variable scoping with L to futher +reduce symbol table growth. + + + package Embed::Persistent; + #persistent.pl + + use strict; + use vars '%Cache'; + + #use Devel::Symdump (); + + sub valid_package_name { + my($string) = @_; + $string =~ s/([^A-Za-z0-9\/])/sprintf("_%2x",unpack("C",$1))/eg; + # second pass only for words starting with a digit + $string =~ s|/(\d)|sprintf("/_%2x",unpack("C",$1))|eg; + + # Dress it up as a real package name + $string =~ s|/|::|g; + return "Embed" . $string; + } + + #borrowed from Safe.pm + sub delete_package { + my $pkg = shift; + my ($stem, $leaf); + + no strict 'refs'; + $pkg = "main::$pkg\::"; # expand to full symbol table name + ($stem, $leaf) = $pkg =~ m/(.*::)(\w+::)$/; + + my $stem_symtab = *{$stem}{HASH}; + + delete $stem_symtab->{$leaf}; + } + + sub eval_file { + my($filename, $delete) = @_; + my $package = valid_package_name($filename); + my $mtime = -M $filename; + if(defined $Cache{$package}{mtime} + && + $Cache{$package}{mtime} <= $mtime) + { + # we have compiled this subroutine already, + # it has not been updated on disk, nothing left to do + print STDERR "already compiled $package->handler\n"; + } + else { + local *FH; + open FH, $filename or die "open '$filename' $!"; + local($/) = undef; + my $sub = ; + close FH; + + #wrap the code into a subroutine inside our unique package + my $eval = qq{package $package; sub handler { $sub; }}; + { + # hide our variables within this block + my($r,$filename,$mtime,$package,$sub); + eval $eval; + } + die $@ if $@; + + #cache it unless we're cleaning out each time + $Cache{$package}{mtime} = $mtime unless $delete; + } + + eval {$package->handler;}; + die $@ if $@; + + delete_package($package) if $delete; + + #take a look if you want + #print Devel::Symdump->rnew($package)->as_string, $/; + } + + 1; + + __END__ + + /* persistent.c */ + #include + #include + + /* 1 = clean out filename's symbol table after each request, 0 = don't */ + #ifndef DO_CLEAN + #define DO_CLEAN 0 + #endif + + static PerlInterpreter *perl = NULL; + + int + main(int argc, char **argv, char **env) + { + char *embedding[] = { "", "persistent.pl" }; + char *args[] = { "", DO_CLEAN, NULL }; + char filename [1024]; + int exitstatus = 0; + + if((perl = perl_alloc()) == NULL) { + fprintf(stderr, "no memory!"); + exit(1); + } + perl_construct(perl); + + exitstatus = perl_parse(perl, NULL, 2, embedding, NULL); + + if(!exitstatus) { + exitstatus = perl_run(perl); + + while(printf("Enter file name: ") && gets(filename)) { + + /* call the subroutine, passing it the filename as an argument */ + args[0] = filename; + perl_call_argv("Embed::Persistent::eval_file", + G_DISCARD | G_EVAL, args); + + /* check $@ */ + if(SvTRUE(GvSV(errgv))) + fprintf(stderr, "eval error: %s\n", SvPV(GvSV(errgv),na)); + } + } + + perl_destruct_level = 0; + perl_destruct(perl); + perl_free(perl); + exit(exitstatus); + } + + +Now compile: + + % cc -o persistent persistent.c `perl -MExtUtils::Embed -e ldopts` + +Here's a example script file: + + #test.pl + my $string = "hello"; + foo($string); + + sub foo { + print "foo says: @_\n"; + } + +Now run: + + % persistent + Enter file name: test.pl + foo says: hello + Enter file name: test.pl + already compiled Embed::test_2epl->handler + foo says: hello + Enter file name: ^C + =head2 Using Perl modules, which themselves use C libraries, from your C program If you've played with the examples above and tried to embed a script diff --git a/pod/perllol.pod b/pod/perllol.pod index 37adac7..b2d5dbe 100644 --- a/pod/perllol.pod +++ b/pod/perllol.pod @@ -146,8 +146,8 @@ you'd have to do something like this: Actually, if you were using strict, you'd have to declare not only $ref_to_LoL as you had to declare @LoL, but you'd I having to -initialize it to a reference to an empty list. (This was a bug in 5.001m -that's been fixed for the 5.002 release.) +initialize it to a reference to an empty list. (This was a bug in +perl version 5.001m that's been fixed for the 5.002 release.) my $ref_to_LoL = []; while (<>) { diff --git a/pod/perlpod.pod b/pod/perlpod.pod index 5485f6c..5c4466d 100644 --- a/pod/perlpod.pod +++ b/pod/perlpod.pod @@ -72,20 +72,20 @@ paragraph with a matching =end are treated as a particular format. Here are some examples of how to use these: =begin html - +
Figure 1.
- + =end html - + =begin text - + --------------- | foo | | bar | --------------- - + ^^^^ Figure 1. ^^^^ - + =end text Some format names that formatters currently are known to accept include diff --git a/pod/perlref.pod b/pod/perlref.pod index bbbe57f..7b522ee 100644 --- a/pod/perlref.pod +++ b/pod/perlref.pod @@ -236,8 +236,8 @@ open the filehandle for you, because *HANDLE{IO} will be undef if HANDLE hasn't been used yet. Use \*HANDLE for that sort of thing instead. Using \*HANDLE (or *HANDLE) is another way to use and store non-bareword -filehandles (before 5.002 it was the only way). The two methods are -largely interchangeable, you can do +filehandles (before perl version 5.002 it was the only way). The two +methods are largely interchangeable, you can do splutter(\*STDOUT); $rec = get_rec(\*STDIN); @@ -431,8 +431,8 @@ variables, which are all "global" to the package. =head2 Not-so-symbolic references -A new feature contributing to readability in 5.001 is that the brackets -around a symbolic reference behave more like quotes, just as they +A new feature contributing to readability in perl version 5.001 is that the +brackets around a symbolic reference behave more like quotes, just as they always have within a string. That is, $push = "pop on "; @@ -449,7 +449,7 @@ and even print ${ push } . "over"; will have the same effect. (This would have been a syntax error in -5.000, though Perl 4 allowed it in the spaceless form.) Note that this +Perl 5.000, though Perl 4 allowed it in the spaceless form.) Note that this construct is I considered to be a symbolic reference when you're using strict refs: diff --git a/pod/perltoc.pod b/pod/perltoc.pod index 2821fa3..8cac0fa 100644 --- a/pod/perltoc.pod +++ b/pod/perltoc.pod @@ -900,7 +900,7 @@ R, |dbcmd, ||dbcmd, = [alias value], command, p expr TTY, noTTY, ReadLine, NonStop, LineInfo - + =item Other resources @@ -936,7 +936,7 @@ TTY, noTTY, ReadLine, NonStop, LineInfo =item Security Bugs - + =back diff --git a/pod/perltoot.pod b/pod/perltoot.pod index ff8e24f..aae3b73 100644 --- a/pod/perltoot.pod +++ b/pod/perltoot.pod @@ -448,7 +448,7 @@ of magicalness to a C programmer. It's really just a mnemonic device to remind ourselves that this field is special and not to be used as a public data member in the same way that NAME, AGE, and PEERS are. (Because we've been developing this code under the strict pragma, prior -to 5.004 we'll have to quote the field name.) +to perl version 5.004 we'll have to quote the field name.) sub new { my $proto = shift; @@ -1087,10 +1087,10 @@ base class? That way you could give every object common methods without having to go and add it to each and every @ISA. Well, it turns out that you can. You don't see it, but Perl tacitly and irrevocably assumes that there's an extra element at the end of @ISA: the class UNIVERSAL. -In 5.003, there were no predefined methods there, but you could put +In version 5.003, there were no predefined methods there, but you could put whatever you felt like into it. -However, as of 5.004 (or some subversive releases, like 5.003_08), +However, as of version 5.004 (or some subversive releases, like 5.003_08), UNIVERSAL has some methods in it already. These are built-in to your Perl binary, so they don't take any extra time to load. Predefined methods include isa(), can(), and VERSION(). isa() tells you whether an object or @@ -1196,7 +1196,7 @@ replace the variables above like $AGE with literal numbers, like 1. A bigger difference between the two approaches can be found in memory use. A hash representation takes up more memory than an array representation because you have to allocation memory for the keys as well as the values. -However, it really isn't that bad, especially since as of 5.004, +However, it really isn't that bad, especially since as of version 5.004, memory is only allocated once for a given hash key, no matter how many hashes have that key. It's expected that sometime in the future, even these differences will fade into obscurity as more efficient underlying diff --git a/pod/perltrap.pod b/pod/perltrap.pod index 391c98b..b8247a4 100644 --- a/pod/perltrap.pod +++ b/pod/perltrap.pod @@ -654,7 +654,8 @@ Formatted output and significant digits This specific item has been deleted. It demonstrated how the auto-increment operator would not catch when a number went over the signed int limit. Fixed -in 5.003_04. But always be wary when using large integers. If in doubt: +in version 5.003_04. But always be wary when using large integers. +If in doubt: use Math::BigInt; @@ -663,10 +664,10 @@ in 5.003_04. But always be wary when using large integers. If in doubt: Assignment of return values from numeric equality tests does not work in perl5 when the test evaluates to false (0). Logical tests now return an null, instead of 0 - + $p = ($test == 1); print $p,"\n"; - + # perl4 prints: 0 # perl5 prints: @@ -934,7 +935,7 @@ of assignment. Perl 4 mistakenly gave them the precedence of the associated operator. So you now must parenthesize them in expressions like /foo/ ? ($a += 2) : ($a -= 2); - + Otherwise /foo/ ? $a += 2 : $a -= 2 @@ -1164,7 +1165,7 @@ within the signal handler function, each time a signal was handled with perl4. With perl5, the reset is now done correctly. Any code relying on the handler _not_ being reset will have to be reworked. -5.002 and beyond uses sigaction() under SysV +Since version 5.002, Perl uses sigaction() under SysV. sub gotit { print "Got @_... "; diff --git a/pod/perlxs.pod b/pod/perlxs.pod index cc83c8b..26418b5 100644 --- a/pod/perlxs.pod +++ b/pod/perlxs.pod @@ -953,7 +953,7 @@ example. # char* having the name of the package for the blessing. O_OBJECT sv_setref_pv( $arg, CLASS, (void*)$var ); - + INPUT O_OBJECT if( sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVMG) ) diff --git a/pod/perlxstut.pod b/pod/perlxstut.pod index 7371cb6..afb018b 100644 --- a/pod/perlxstut.pod +++ b/pod/perlxstut.pod @@ -25,21 +25,21 @@ features were added to Perl 5. =item * -In versions of 5.002 prior to the gamma version, the test script in Example -1 will not function properly. You need to change the "use lib" line to -read: +In versions of Perl 5.002 prior to the gamma version, the test script +in Example 1 will not function properly. You need to change the "use +lib" line to read: use lib './blib'; =item * -In versions of 5.002 prior to version beta 3, the line in the .xs file +In versions of Perl 5.002 prior to version beta 3, the line in the .xs file about "PROTOTYPES: DISABLE" will cause a compiler error. Simply remove that line from the file. =item * -In versions of 5.002 prior to version 5.002b1h, the test.pl file was not +In versions of Perl 5.002 prior to version 5.002b1h, the test.pl file was not automatically created by h2xs. This means that you cannot say "make test" to run the test script. You will need to add the following line before the "use extension" statement: diff --git a/sv.c b/sv.c index db34eb0..ab08ea9 100644 --- a/sv.c +++ b/sv.c @@ -4051,9 +4051,6 @@ SV* sv; strcat(d, " ),"); } } -#ifdef OVERLOAD - if (flags & SVpgv_AM) strcat(d, "withOVERLOAD,"); -#endif /* OVERLOAD */ } d += strlen(d); diff --git a/sv.h b/sv.h index 36fa72d..29342f0 100644 --- a/sv.h +++ b/sv.h @@ -131,11 +131,6 @@ struct io { #define SVphv_SHAREKEYS 0x20000000 /* keys live on shared string table */ #define SVphv_LAZYDEL 0x40000000 /* entry in xhv_eiter must be deleted */ -#ifdef OVERLOAD -#define SVpgv_AM 0x40000000 -/* #define SVpgv_badAM 0x20000000 */ -#endif /* OVERLOAD */ - struct xrv { SV * xrv_rv; /* pointer to another SV */ }; diff --git a/t/lib/locale.t b/t/lib/locale.t index 83fa46b..7f8c858 100755 --- a/t/lib/locale.t +++ b/t/lib/locale.t @@ -1,6 +1,6 @@ #!./perl -wT -print "1..67\n"; +print "1..104\n"; BEGIN { chdir 't' if -d 't'; @@ -74,15 +74,15 @@ check_taint 19, $+; check_taint 20, $1; check_taint_not 21, $2; -/(\W)/; # taint $&, $`, $', $+, $1. -check_taint 22, $&; -check_taint 23, $`; -check_taint 24, $'; -check_taint 25, $+; -check_taint 26, $1; +/(.)/; # untaint $&, $`, $', $+, $1. +check_taint_not 22, $&; +check_taint_not 23, $`; +check_taint_not 24, $'; +check_taint_not 25, $+; +check_taint_not 26, $1; check_taint_not 27, $2; -/(\s)/; # taint $&, $`, $', $+, $1. +/(\W)/; # taint $&, $`, $', $+, $1. check_taint 28, $&; check_taint 29, $`; check_taint 30, $'; @@ -90,7 +90,7 @@ check_taint 31, $+; check_taint 32, $1; check_taint_not 33, $2; -/(\S)/; # taint $&, $`, $', $+, $1. +/(\s)/; # taint $&, $`, $', $+, $1. check_taint 34, $&; check_taint 35, $`; check_taint 36, $'; @@ -98,45 +98,105 @@ check_taint 37, $+; check_taint 38, $1; check_taint_not 39, $2; +/(\S)/; # taint $&, $`, $', $+, $1. +check_taint 40, $&; +check_taint 41, $`; +check_taint 42, $'; +check_taint 43, $+; +check_taint 44, $1; +check_taint_not 45, $2; + $_ = $a; # untaint $_ -check_taint_not 40, $_; +check_taint_not 46, $_; /(b)/; # this must not taint -check_taint_not 41, $&; -check_taint_not 42, $`; -check_taint_not 43, $'; -check_taint_not 44, $+; -check_taint_not 45, $1; -check_taint_not 46, $2; +check_taint_not 47, $&; +check_taint_not 48, $`; +check_taint_not 49, $'; +check_taint_not 50, $+; +check_taint_not 51, $1; +check_taint_not 52, $2; $_ = $a; # untaint $_ -check_taint_not 47, $_; +check_taint_not 53, $_; $b = uc($a); # taint $b s/(.+)/$b/; # this must taint only the $_ -check_taint 48, $_; -check_taint_not 49, $&; -check_taint_not 50, $`; -check_taint_not 51, $'; -check_taint_not 52, $+; -check_taint_not 53, $1; -check_taint_not 54, $2; +check_taint 54, $_; +check_taint_not 55, $&; +check_taint_not 56, $`; +check_taint_not 57, $'; +check_taint_not 58, $+; +check_taint_not 59, $1; +check_taint_not 60, $2; $_ = $a; # untaint $_ s/(.+)/b/; # this must not taint -check_taint_not 55, $_; -check_taint_not 56, $&; -check_taint_not 57, $`; -check_taint_not 58, $'; -check_taint_not 59, $+; -check_taint_not 60, $1; -check_taint_not 61, $2; +check_taint_not 61, $_; +check_taint_not 62, $&; +check_taint_not 63, $`; +check_taint_not 64, $'; +check_taint_not 65, $+; +check_taint_not 66, $1; +check_taint_not 67, $2; + +$b = $a; # untaint $b + +($b = $a) =~ s/\w/$&/; +check_taint 68, $b; # $b should be tainted. +check_taint_not 69, $a; # $a should be not. + +$_ = $a; # untaint $_ + +s/(\w)/\l$1/; # this must taint +check_taint 70, $_; +check_taint 71, $&; +check_taint 72, $`; +check_taint 73, $'; +check_taint 74, $+; +check_taint 75, $1; +check_taint_not 76, $2; + +$_ = $a; # untaint $_ + +s/(\w)/\L$1/; # this must taint +check_taint 77, $_; +check_taint 78, $&; +check_taint 79, $`; +check_taint 80, $'; +check_taint 81, $+; +check_taint 82, $1; +check_taint_not 83, $2; + +$_ = $a; # untaint $_ + +s/(\w)/\u$1/; # this must taint +check_taint 84, $_; +check_taint 85, $&; +check_taint 86, $`; +check_taint 87, $'; +check_taint 88, $+; +check_taint 89, $1; +check_taint_not 90, $2; -check_taint_not 62, $a; +$_ = $a; # untaint $_ + +s/(\w)/\U$1/; # this must taint +check_taint 91, $_; +check_taint 92, $&; +check_taint 93, $`; +check_taint 94, $'; +check_taint 95, $+; +check_taint 96, $1; +check_taint_not 97, $2; + +# After all this tainting $a should be cool. + +check_taint_not 98, $a; # I think we've seen quite enough of taint. # Let us do some *real* locale work now. @@ -246,7 +306,8 @@ for (@Locale) { # Cross-check the upper and the lower. # Yes, this is broken when the upper<->lower changes the number of -# the glyphs (e.g. the German sharp-s aka double-s aka sz-ligature. +# the glyphs (e.g. the German sharp-s aka double-s aka sz-ligature, +# or the Dutch IJ or the Spanish LL or ...) # But so far all the implementations do this wrong so we can do it wrong too. for (keys %UPPER) { @@ -257,7 +318,7 @@ for (keys %UPPER) { } } } -print "ok 63\n"; +print "ok 99\n"; for (keys %lower) { if (defined $UPPER{$lower{$_}}) { @@ -267,7 +328,7 @@ for (keys %lower) { } } } -print "ok 64\n"; +print "ok 100\n"; # Find the alphabets that are not alphabets in the default locale. @@ -290,15 +351,18 @@ print "ok 64\n"; print 'not ' if ($1 ne $word); } -print "ok 65\n"; +print "ok 101\n"; # Find places where the collation order differs from the default locale. { - no locale; + my (@k, $i, $j, @d); - my @k = sort (keys %UPPER, keys %lower); - my ($i, $j, @d); + { + no locale; + + @k = sort (keys %UPPER, keys %lower); + } for ($i = 0; $i < @k; $i++) { for ($j = $i + 1; $j < @k; $j++) { @@ -312,10 +376,15 @@ print "ok 65\n"; for (@d) { ($i, $j) = @$_; - print 'not ' if ($i le $j or not (($i cmp $j) == 1)); + if ($i gt $j) { + print "# i = $i, j = $j, i ", + $i le $j ? 'le' : 'gt', " j\n"; + print 'not '; + last; + } } } -print "ok 66\n"; +print "ok 102\n"; # Cross-check whole character set. @@ -325,7 +394,47 @@ for (map { chr } 0..255) { if (/\s/ and /\S/) { print 'not '; last } if (/\w/ and /\D/ and not /_/ and not (exists $UPPER{$_} or exists $lower{$_})) { - print 'not '; last + print 'not '; + last; + } +} +print "ok 103\n"; + +# The @Locale should be internally consistent. + +{ + my ($from, $to, , $lesser, $greater); + + for (0..9) { + # Select a slice. + $from = int(($_*@Locale)/10); + $to = $from + int(@Locale/10); + $to = $#Locale if ($to > $#Locale); + $lesser = join('', @Locale[$from..$to]); + # Select a slice one character on. + $from++; $to++; + $to = $#Locale if ($to > $#Locale); + $greater = join('', @Locale[$from..$to]); + if (not ($lesser lt $greater) or + not ($lesser le $greater) or + not ($lesser ne $greater) or + ($lesser eq $greater) or + ($lesser ge $greater) or + ($lesser gt $greater) or + ($greater lt $lesser ) or + ($greater le $lesser ) or + not ($greater ne $lesser ) or + ($greater eq $lesser ) or + not ($greater ge $lesser ) or + not ($greater gt $lesser ) or + # Well, these two are sort of redundant because @Locale + # was derived using cmp. + not (($lesser cmp $greater) == -1) or + not (($greater cmp $lesser ) == 1) + ) { + print 'not '; + last; + } } } -print "ok 67\n"; +print "ok 104\n"; diff --git a/t/op/misc.t b/t/op/misc.t index 5bcc6a0..5b94e03 100755 --- a/t/op/misc.t +++ b/t/op/misc.t @@ -204,3 +204,54 @@ EXPECT This is a reversed sentence. -- Out of inspiration -- and destroyed as well +######## +my @a; $a[2] = 1; for (@a) { $_ = 2 } print "@a\n" +EXPECT +2 2 2 +######## +@a = ($a, $b, $c, $d) = (5, 6); +print "ok\n" + if ($a[0] == 5 and $a[1] == 6 and !defined $a[2] and !defined $a[3]); +EXPECT +ok +######## +print "ok\n" if (1E2<<1 == 200 and 3E4<<3 == 240000); +EXPECT +ok +######## +print "ok\n" if ("\0" cmp "\xFF"); +EXPECT +ok +######## +open(H,'op/misc.t'); # must be in the 't' directory +stat(H); +print "ok\n" if (-e _ and -f _ and -r _); +EXPECT +ok +######## +sub thing { 0 || return qw(now is the time) } +print thing(), "\n"; +EXPECT +nowisthetime +######## +$ren = 'joy'; +$stimpy = 'happy'; +{ local $main::{ren} = *stimpy; print $ren, ' ' } +print $ren, "\n"; +EXPECT +happy joy +######## +$stimpy = 'happy'; +{ local $main::{ren} = *stimpy; print ${'ren'}, ' ' } +print +(defined(${'ren'}) ? 'oops' : 'joy'), "\n"; +EXPECT +happy joy +######## +package p; +sub func { print 'really ' unless wantarray; 'p' } +sub groovy { 'groovy' } +package main; +print p::func()->groovy(), "\n" +EXPECT +really groovy +######## diff --git a/t/op/my.t b/t/op/my.t index 4ce020f..06c6963 100755 --- a/t/op/my.t +++ b/t/op/my.t @@ -1,8 +1,8 @@ #!./perl -# $RCSfile: local.t,v $$Revision: 4.1 $$Date: 92/08/07 18:28:04 $ +# $RCSfile: my.t,v $ -print "1..20\n"; +print "1..28\n"; sub foo { my($a, $b) = @_; @@ -44,3 +44,42 @@ $d{''} = "ok 18\n"; print &foo2("ok 11\n","ok 12\n"); print $a,@b,@c,%d,$x,$y; + +my $i = "outer"; + +if (my $i = "inner") { + print "not " if $i ne "inner"; +} +print "ok 21\n"; + +if ((my $i = 1) == 0) { + print "not "; +} +else { + print "not" if $i != 1; +} +print "ok 22\n"; + +my $j = 5; +while (my $i = --$j) { + print("not "), last unless $i > 0; +} +continue { + print("not "), last unless $i > 0; +} +print "ok 23\n"; + +$j = 5; +for (my $i = 0; (my $k = $i) < $j; ++$i) { + print("not "), last unless $i >= 0 && $i < $j && $i == $k; +} +print "ok 24\n"; +print "not " if defined $k; +print "ok 25\n"; + +foreach my $i (26, 27) { + print "ok $i\n"; +} + +print "not " if $i ne "outer"; +print "ok 28\n"; diff --git a/t/op/overload.t b/t/op/overload.t index fca26b4..9c897c3 100755 --- a/t/op/overload.t +++ b/t/op/overload.t @@ -33,7 +33,7 @@ qw( sub new { my $foo = $_[1]; - bless \$foo; + bless \$foo, $_[0]; } sub stringify { "${$_[0]}" } @@ -55,7 +55,9 @@ $a = new Oscalar "087"; $b= "$a"; # All test numbers in comments are off by 1. -# So much for hard-wiring them in :-) +# So much for hard-wiring them in :-) To fix this: +test(1); # 1 + test ($b eq $a); # 2 test ($b eq "087"); # 3 test (ref $a eq "Oscalar"); # 4 @@ -255,16 +257,89 @@ $a=new Oscalar "xx"; test ("b${a}c" eq "_._.b.__.xx._.__.c._"); # 88 +# Check inheritance of overloading; +{ + package OscalarI; + @ISA = 'Oscalar'; +} + +$aI = new OscalarI "$a"; +test (ref $aI eq "OscalarI"); # 89 +test ("$aI" eq "xx"); # 90 +test ($aI eq "xx"); # 91 +test ("b${aI}c" eq "_._.b.__.xx._.__.c._"); # 92 + # Here we test blessing to a package updates hash eval "package Oscalar; no overload '.'"; -test ("b${a}" eq "_.b.__.xx._"); # 89 +test ("b${a}" eq "_.b.__.xx._"); # 93 $x="1"; bless \$x, Oscalar; -test ("b${a}c" eq "bxxc"); # 90 +test ("b${a}c" eq "bxxc"); # 94 new Oscalar 1; -test ("b${a}c" eq "bxxc"); # 91 +test ("b${a}c" eq "bxxc"); # 95 + +# Negative overloading: + +$na = eval { ~$a }; +test($@ =~ /no method found/); # 96 + +# Check AUTOLOADING: + +*Oscalar::AUTOLOAD = + sub { *{"Oscalar::$AUTOLOAD"} = sub {"_!_" . shift() . "_!_"} ; + goto &{"Oscalar::$AUTOLOAD"}}; + +eval "package Oscalar; use overload '~' => 'comple'"; + +$na = eval { ~$a }; # Hash was not updated +test($@ =~ /no method found/); # 97 + +bless \$x, Oscalar; + +$na = eval { ~$a }; # Hash updated +test !$@; # 98 +test($na eq '_!_xx_!_'); # 99 + +$na = 0; + +$na = eval { ~$aI }; # Hash was not updated +test($@ =~ /no method found/); # 100 + +bless \$x, OscalarI; + +$na = eval { ~$aI }; +print $@; + +test !$@; # 101 +test($na eq '_!_xx_!_'); # 102 + +eval "package Oscalar; use overload '>>' => 'rshft'"; + +$na = eval { $aI >> 1 }; # Hash was not updated +test($@ =~ /no method found/); # 103 + +bless \$x, OscalarI; + +$na = 0; + +$na = eval { $aI >> 1 }; +print $@; + +test !$@; # 104 +test($na eq '_!_xx_!_'); # 105 + +test (overload::Method($a, '0+') eq \&Oscalar::numify); # 106 +test (overload::Method($aI,'0+') eq \&Oscalar::numify); # 107 +test (overload::Overloaded($aI)); # 108 +test (!overload::Overloaded('overload')); # 109 + +test (! defined overload::Method($aI, '<<')); # 110 +test (! defined overload::Method($a, '<')); # 111 + +test (overload::StrVal($aI) =~ /^OscalarI=SCALAR\(0x[\da-fA-F]+\)$/); # 112 +test (overload::StrVal(\$aI) eq "@{[\$aI]}"); # 113 -# Last test is number 90. -sub last {90} +# Last test is: +sub last {113}