slurping an empty file should return '' rather than undef, with
Gurusamy Sarathy [Sun, 14 Feb 1999 05:51:56 +0000 (05:51 +0000)]
commensurate effects on ARGV processing

p4raw-id: //depot/perl@2910

pod/perldelta.pod
pod/perlfunc.pod
pod/perlop.pod
pod/perlvar.pod
pp_hot.c
sv.h
t/io/argv.t

index efa52de..d858508 100644 (file)
@@ -125,6 +125,25 @@ now correctly prints "3|a", instead of "2|a".
 The new format type 'Z' is useful for packing and unpacking null-terminated
 strings.  See L<perlfunc/"pack">.
 
+=head1 Significant bug fixes
+
+=head2 E<lt>HANDLEE<gt> on empty files
+
+With C<$/> set to C<undef>, slurping an empty file returns a string of
+zero length (instead of C<undef>, as it used to) for the first time the
+HANDLE is read.  Subsequent reads yield C<undef>.
+
+This means that the following will append "foo" to an empty file (it used
+to not do anything before):
+
+    perl -0777 -pi -e 's/^/foo/' empty_file
+
+Note that the behavior of:
+
+    perl -pi -e 's/^/foo/' empty_file
+
+is unchanged (it continues to leave the file empty).
+
 =head1 Supported Platforms
 
 =over 4
@@ -225,8 +244,25 @@ stat(2) might lie, while access(2) knows better.
 
 =head1 Utility Changes
 
+=head2 New Modules
+
+=over
+
 Todo.
 
+=back
+
+=head2 Changes in existing modules
+
+=over
+
+=item Exporter
+
+Exporter::expand() takes an import list and returns the expanded
+list of names.
+
+=back
+
 =head1 Documentation Changes
 
 =over 4
index 1495514..0d09e85 100644 (file)
@@ -2841,10 +2841,17 @@ C<chdir()> there, it would have been testing the wrong file.
 
 =item readline EXPR
 
-Reads from the filehandle whose typeglob is contained in EXPR.  In scalar context, a single line
-is read and returned.  In list context, reads until end-of-file is
-reached and returns a list of lines (however you've defined lines
-with C<$/> or C<$INPUT_RECORD_SEPARATOR>).
+Reads from the filehandle whose typeglob is contained in EXPR.  In scalar
+context, each call reads and returns the next line, until end-of-file is
+reached, whereupon the subsequent call returns undef.  In list context,
+reads until end-of-file is reached and returns a list of lines.  Note that
+the notion of "line" used here is however you may have defined it
+with C<$/> or C<$INPUT_RECORD_SEPARATOR>).  See L<perlvar/"$/">.
+
+When C<$/> is set to C<undef> and when readline() is in a scalar
+context (i.e. file slurp mode), it returns C<''> the first time,
+followed by C<undef> subsequently.
+
 This is the internal function implementing the C<E<lt>EXPRE<gt>>
 operator, but you can use it directly.  The C<E<lt>EXPRE<gt>>
 operator is discussed in more detail in L<perlop/"I/O Operators">.
index b386651..73066c1 100644 (file)
@@ -1445,6 +1445,7 @@ to change.
 =head2 I/O Operators
 
 There are several I/O operators you should know about.
+
 A string enclosed by backticks (grave accents) first undergoes
 variable substitution just like a double quoted string.  It is then
 interpreted as a command, and the output of that command is the value
@@ -1462,9 +1463,12 @@ The generalized form of backticks is C<qx//>.  (Because backticks
 always undergo shell expansion as well, see L<perlsec> for
 security concerns.)
 
-Evaluating a filehandle in angle brackets yields the next line from
-that file (newline, if any, included), or C<undef> at end of file.
-Ordinarily you must assign that value to a variable, but there is one
+In a scalar context, evaluating a filehandle in angle brackets yields the
+next line from that file (newline, if any, included), or C<undef> at
+end-of-file.  When C<$/> is set to C<undef> (i.e. file slurp mode),
+it returns C<''> the first time, followed by C<undef> subsequently.
+
+Ordinarily you must assign the returned value to a variable, but there is one
 situation where an automatic assignment happens.  I<If and ONLY if> the
 input symbol is the only thing inside the conditional of a C<while> or
 C<for(;;)> loop, the value is automatically assigned to the variable
@@ -1501,13 +1505,16 @@ The filehandles STDIN, STDOUT, and STDERR are predefined.  (The
 filehandles C<stdin>, C<stdout>, and C<stderr> will also work except in
 packages, where they would be interpreted as local identifiers rather
 than global.)  Additional filehandles may be created with the open()
-function.  See L<perlfunc/open()> for details on this.
+function.  See L<perlfunc/open> for details on this.
 
 If a E<lt>FILEHANDLEE<gt> is used in a context that is looking for a list, a
 list consisting of all the input lines is returned, one line per list
 element.  It's easy to make a I<LARGE> data space this way, so use with
 care.
 
+E<lt>FILEHANDLEE<gt> may also be spelt readline(FILEHANDLE).  See
+L<perlfunc/readline>.
+
 The null filehandle E<lt>E<gt> is special and can be used to emulate the
 behavior of B<sed> and B<awk>.  Input from E<lt>E<gt> comes either from
 standard input, or from each file listed on the command line.  Here's
index b9b0ce6..44124d6 100644 (file)
@@ -250,8 +250,8 @@ line.  Setting it to C<"\n\n"> will blindly assume that the next input
 character belongs to the next paragraph, even if it's a newline.
 (Mnemonic: / is used to delimit line boundaries when quoting poetry.)
 
-    undef $/;
-    $_ = <FH>;                 # whole file now here
+    undef $/;          # enable "slurp" mode
+    $_ = <FH>;         # whole file now here
     s/\n[ \t]+/ /g;
 
 Remember: the value of $/ is a string, not a regexp.  AWK has to be
index 27af29d..b1bf270 100644 (file)
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -1297,8 +1297,18 @@ do_readline(void)
        sv = sv_2mortal(NEWSV(57, 80));
        offset = 0;
     }
+
+/* flip-flop EOF state for a snarfed empty file */
+#define SNARF_EOF(gimme,rs,io,sv) \
+    ((gimme != G_SCALAR || SvCUR(sv)                                   \
+      || (IoFLAGS(io) & IOf_NOLINE) || IoLINES(io) || !RsSNARF(rs))    \
+       ? ((IoFLAGS(io) &= ~IOf_NOLINE), TRUE)                          \
+       : ((IoFLAGS(io) |= IOf_NOLINE), FALSE))
+
     for (;;) {
-       if (!sv_gets(sv, fp, offset)) {
+       if (!sv_gets(sv, fp, offset)
+           && (type == OP_GLOB || SNARF_EOF(gimme, PL_rs, io, sv)))
+       {
            PerlIO_clearerr(fp);
            if (IoFLAGS(io) & IOf_ARGV) {
                fp = nextargv(PL_last_in_gv);
diff --git a/sv.h b/sv.h
index a08a9c8..456d01c 100644 (file)
--- a/sv.h
+++ b/sv.h
@@ -313,6 +313,7 @@ struct xpvio {
 #define IOf_FLUSH 4    /* this fp wants a flush after write op */
 #define IOf_DIDTOP 8   /* just did top of form */
 #define IOf_UNTAINT 16  /* consider this fp (and its data) "safe" */
+#define IOf_NOLINE  32 /* slurped a pseudo-line from empty file */
 
 /* The following macros define implementation-independent predicates on SVs. */
 
index d99865e..cb2ffb3 100755 (executable)
@@ -1,10 +1,8 @@
 #!./perl
 
-# $RCSfile: argv.t,v $$Revision: 4.1 $$Date: 92/08/07 18:27:25 $
+print "1..6\n";
 
-print "1..5\n";
-
-open(try, '>Io.argv.tmp') || (die "Can't open temp file.");
+open(try, '>Io.argv.tmp') || (die "Can't open temp file: $!");
 print try "a line\n";
 close try;
 
@@ -45,4 +43,17 @@ if ($y eq "1a line\n2a line\n3a line\n")
 else
     {print "not ok 5\n";}
 
-unlink 'Io.argv.tmp';
+open(try, '>Io.argv.tmp') or die "Can't open temp file: $!";
+close try;
+@ARGV = 'Io.argv.tmp';
+$^I = '';
+$/ = undef;
+while (<>) {
+    s/^/ok 6\n/;
+    print;
+}
+open(try, '<Io.argv.tmp') or die "Can't open temp file: $!";
+print while <try>;
+close try;
+
+END { unlink 'Io.argv.tmp' }