summaryrefslogtreecommitdiff
path: root/pp_sys.c
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2015-06-11 10:54:12 +0100
committerDavid Mitchell <davem@iabyn.com>2015-06-19 08:44:18 +0100
commit617a4f41d97982726e3623f6bc82502ee14d2403 (patch)
tree92335f7b9d0f2b3181c29b17ccb15d5bb35e044e /pp_sys.c
parent9c750db661e034b562ff95d055827d815c3f4cc1 (diff)
downloadperl-617a4f41d97982726e3623f6bc82502ee14d2403.tar.gz
pp_return(): tail call pp_leavewrite()
When 'return'ing from a format, rather than handling it ourselves, fall through to pp_leavewrite(). pp_return() is now only responsible for popping any extra contexts and junk from the stack. With this commit, *all* types of return are now handled by tail-calling the appropriate pp_leaveFOO() function, so this commit also cuts out big chunks of dead code. Note that the behaviour on using 'return' in a format is completely undocumented, and almost completely untested. In fact there is only a single format in the test suite that does a return, and the tests which use that are mainly there to ensure that extra stuff on the stack doesn't leak into the value(s) returned by write(). In particular, its not clear whether a return half-way through a format should cause the lines processed so far to be output, or to be discarded; currently it discards. Also, its not clear what (if anything) should be done with any args to the 'return' call. Currently they're just discarded. Also, the format in the test suite which does a return only does a 'return;', not a 'return x,y,z'. So that's still untested. So I decided to keep the current behaviour of return in format as close as possible rather than trying to change of fix anything.
Diffstat (limited to 'pp_sys.c')
-rw-r--r--pp_sys.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/pp_sys.c b/pp_sys.c
index 1c2ef9c1f2..6770063267 100644
--- a/pp_sys.c
+++ b/pp_sys.c
@@ -1437,8 +1437,9 @@ PP(pp_leavewrite)
I32 gimme;
PERL_CONTEXT *cx;
OP *retop;
+ bool is_return = cBOOL(PL_op->op_type == OP_RETURN);
- if (!io || !(ofp = IoOFP(io)))
+ if (is_return || !io || !(ofp = IoOFP(io)))
goto forget_top;
DEBUG_f(PerlIO_printf(Perl_debug_log, "left=%ld, todo=%ld\n",
@@ -1516,7 +1517,13 @@ PP(pp_leavewrite)
SP = newsp; /* ignore retval of formline */
LEAVE;
- if (!io || !(fp = IoOFP(io))) {
+ if (is_return)
+ /* XXX the semantics of doing 'return' in a format aren't documented.
+ * Currently we ignore any args to 'return' and just return
+ * a single undef in both scalar and list contexts
+ */
+ PUSHs(&PL_sv_undef);
+ else if (!io || !(fp = IoOFP(io))) {
if (io && IoIFP(io))
report_wrongway_fh(gv, '<');
else