diff options
author | Perl 5 Porters <perl5-porters@africa.nicoh.com> | 1997-01-01 08:59:00 +1200 |
---|---|---|
committer | Chip Salzenberg <chip@atlantic.net> | 1997-01-01 08:59:00 +1200 |
commit | a60067777be62ee91d1318f9ae26d9ed713245de (patch) | |
tree | 9e312a824c6ef40aa10dd0e60451fd737098a965 /pod | |
parent | a034a98d8bfd0fd904012bd5227ce209aaaa0b26 (diff) | |
download | perl-a60067777be62ee91d1318f9ae26d9ed713245de.tar.gz |
[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 <ilya@math.ohio-state.edu>
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 <chip@atlantic.net>
Files: op.c
Subject: Warn on '{if,while} ($x = X)' where X is glob, readdir, or <FH>
From: Chip Salzenberg <chip@atlantic.net>
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 <roderick@gate.net>
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 <chip@atlantic.net>
Files: cop.h gv.c op.c
TESTS
Subject: Expanded locale.t and misc.t
From: Jarkko Hietaniemi <jhi@cc.hut.fi>
Files: t/lib/locale.t t/lib/misc.t
Subject: Expanded my.t
From: Chip Salzenberg <chip@atlantic.net>
Files: t/lib/my.t
Diffstat (limited to 'pod')
-rw-r--r-- | pod/perldiag.pod | 24 | ||||
-rw-r--r-- | pod/perldsc.pod | 4 | ||||
-rw-r--r-- | pod/perlembed.pod | 227 | ||||
-rw-r--r-- | pod/perllol.pod | 4 | ||||
-rw-r--r-- | pod/perlpod.pod | 12 | ||||
-rw-r--r-- | pod/perlref.pod | 10 | ||||
-rw-r--r-- | pod/perltoc.pod | 4 | ||||
-rw-r--r-- | pod/perltoot.pod | 8 | ||||
-rw-r--r-- | pod/perltrap.pod | 11 | ||||
-rw-r--r-- | pod/perlxs.pod | 2 | ||||
-rw-r--r-- | pod/perlxstut.pod | 10 |
11 files changed, 262 insertions, 54 deletions
diff --git a/pod/perldiag.pod b/pod/perldiag.pod index 49d30fcab0..6e4a3cf6c9 100644 --- a/pod/perldiag.pod +++ b/pod/perldiag.pod @@ -1815,7 +1815,7 @@ shifting or popping (for array variables). See L<perlform>. =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<perlref>. +=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<perlref>. + =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<perlref> for more on this. (W) A copy of the object returned from C<tie> (or C<tied>) was still valid when C<untie> was called. +=item Value of %s may be "0"; use "defined" + +(W) In a conditional expression, you used <HANDLE>, <*> (glob), or +C<readdir> 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<defined> 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 5beaa8bbe9..5a3a83ea5e 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<x> 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 ea0e8331f2..30c6e0a0a7 100644 --- a/pod/perlembed.pod +++ b/pod/perlembed.pod @@ -37,7 +37,7 @@ Read on... L<Compiling your C program> -There's one example in each of the six sections: +There's one example in each of the eight sections: L<Adding a Perl interpreter to your C program> @@ -49,6 +49,8 @@ L<Performing Perl pattern matches and substitutions from your C program> L<Fiddling with the Perl stack from your C program> +L<Maintaining a persistent interpreter> + L<Using Perl modules, which themselves use C libraries, from your C program> This documentation is UNIX specific. @@ -69,7 +71,7 @@ Your C program will--usually--allocate, "run", and deallocate a I<PerlInterpreter> 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<EXTERN.h> and +(version 5.002 or later), then the perl library (and I<EXTERN.h> and I<perl.h>, which you'll also need) will reside in a directory resembling this: @@ -225,13 +227,10 @@ L<Fiddling with the Perl stack from your C program> =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<perlguts/perl_eval_sv>). -Look for updates to this document soon. - -One way to evaluate a Perl string is to define a function (we'll call -ours I<perl_eval()>) that wraps around Perl's L<perlfunc/eval>. +One way to evaluate pieces of Perl code is to use L<perlguts/perl_eval_sv>. +We have wrapped this function with our own I<perl_eval()> function, which +converts a command string to an SV, passing this and the L<perlcall/G_DISCARD> +flag to L<perlguts/perl_eval_sv>. 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<float> from the second, and a C<char *> 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 <EXTERN.h> #include <perl.h> 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<main>. 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<perl_parse()>, compiled into a newly +constructed interpreter, then cleaned out with B<perl_destruct()> 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<perlfunc/eval>. +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<Embed::Persistent::eval_file> which lives in the file B<persistent.pl>, with +L<perlcall/perl_call_argv>, 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<perlfunc/require>, L<perlfunc/use> or +L<perlfunc/do>. In addition, there maybe B<AUTOLOAD>ed 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<perlfunc/my> 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 = <FH>; + 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 <EXTERN.h> + #include <perl.h> + + /* 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 37adac7ef5..b2d5dbe537 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<also> 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 5485f6c3b9..5c4466d398 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 - + <br>Figure 1.<IMG SRC="figure1.png"><br> - + =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 bbbe57feba..7b522eee4d 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<not> considered to be a symbolic reference when you're using strict refs: diff --git a/pod/perltoc.pod b/pod/perltoc.pod index 2821fa363a..8cac0fa7af 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 ff8e24fb3e..aae3b7393d 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 391c98b129..b8247a4208 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 cc83c8b843..26418b51a9 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 7371cb677d..afb018b28e 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: |