develooper Front page | perl.perl5.changes | Postings from December 2008

Change 34989: Integrate:

From:
Nicholas Clark
Date:
December 3, 2008 03:00
Subject:
Change 34989: Integrate:
Change 34989 by nicholas@nicholas-plum on 2008/12/03 10:48:40

	Integrate:
	[ 34979]
	Add two more flags, PERLDBf_SAVESRC_NOSUBS and PERLDBf_SAVESRC_INVALID,
	which give total control over when source code from evals is stored.
	The debugger doesn't need them, but I forsee that profilers might.
	
	[ 34981]
	Followup to change 34979. Tests are good, m'kay. Particularly when they
	show you that something you thought worked doesn't.
	Sadly it's not possible to trivially make it work, so for now they're
	todo_skip().

Affected files ...

... //depot/maint-5.10/perl/perl.h#17 integrate
... //depot/maint-5.10/perl/pp_ctl.c#28 integrate
... //depot/maint-5.10/perl/t/comp/retainedlines.t#2 integrate

Differences ...

==== //depot/maint-5.10/perl/perl.h#17 (text) ====
Index: perl/perl.h
--- perl/perl.h#16~34715~	2008-11-04 00:28:29.000000000 -0800
+++ perl/perl.h	2008-12-03 02:48:40.000000000 -0800
@@ -5312,6 +5312,10 @@
 #define PERLDBf_NAMEEVAL	0x100	/* Informative names for evals */
 #define PERLDBf_NAMEANON	0x200	/* Informative names for anon subs */
 #define PERLDBf_SAVESRC  	0x400	/* Save source lines into @{"_<$filename"} */
+#define PERLDBf_SAVESRC_NOSUBS	0x800	/* Including evals that generate no subrouties */
+#if 0 /* Not yet working. */
+#define PERLDBf_SAVESRC_INVALID	0x1000	/* Save source that did not compile */
+#endif
 
 #define PERLDB_SUB	(PL_perldb && (PL_perldb & PERLDBf_SUB))
 #define PERLDB_LINE	(PL_perldb && (PL_perldb & PERLDBf_LINE))
@@ -5325,6 +5329,10 @@
 #define PERLDB_NAMEANON	(PL_perldb && (PL_perldb & PERLDBf_NAMEANON))
 #define PERLDB_ASSERTION (PL_perldb && (PL_perldb & PERLDBf_ASSERTION))
 #define PERLDB_SAVESRC 	(PL_perldb && (PL_perldb & PERLDBf_SAVESRC))
+#define PERLDB_SAVESRC_NOSUBS	(PL_perldb && (PL_perldb & PERLDBf_SAVESRC_NOSUBS))
+#if 0 /* Not yet working. */
+#define PERLDB_SAVESRC_INVALID	(PL_perldb && (PL_perldb & PERLDBf_SAVESRC_INVALID))
+#endif
 
 #ifdef USE_LOCALE_NUMERIC
 

==== //depot/maint-5.10/perl/pp_ctl.c#28 (text) ====
Index: perl/pp_ctl.c
--- perl/pp_ctl.c#27~34900~	2008-11-21 13:41:58.000000000 -0800
+++ perl/pp_ctl.c	2008-12-03 02:48:40.000000000 -0800
@@ -3652,9 +3652,19 @@
 	save_lines(CopFILEAV(&PL_compiling), PL_parser->linestr);
     PUTBACK;
     ok = doeval(gimme, NULL, runcv, seq);
-    if ((PERLDB_LINE || PERLDB_SAVESRC)
-	&& was != PL_breakable_sub_gen /* Some subs defined here. */
-	&& ok) {
+    if (ok ? (was != PL_breakable_sub_gen /* Some subs defined here. */
+	      ? (PERLDB_LINE || PERLDB_SAVESRC)
+	      :  PERLDB_SAVESRC_NOSUBS)
+	: 0 /* PERLDB_SAVESRC_INVALID */
+	/* Much that I'd like to think that it was this trivial to add this
+	   feature, it's not, due to
+	       lex_end();
+	       LEAVE;
+	   in S_doeval() for the failure case. So really we want a more
+	   sophisticated way of (optionally) clearing the source code.
+	   Particularly as the current way is buggy, as a syntactically
+	   invalid eval string can still define a subroutine that is retained,
+	   and the user may wish to breakpoint. */) {
 	/* Copy in anything fake and short. */
 	my_strlcpy(safestr, fakestr, fakelen);
     }

==== //depot/maint-5.10/perl/t/comp/retainedlines.t#2 (text) ====
Index: perl/t/comp/retainedlines.t
--- perl/t/comp/retainedlines.t#1~34898~	2008-11-21 02:22:59.000000000 -0800
+++ perl/t/comp/retainedlines.t	2008-12-03 02:48:40.000000000 -0800
@@ -10,7 +10,7 @@
 
 use strict;
 
-plan (tests => 21);
+plan (tests => 55);
 
 $^P = 0xA;
 
@@ -19,17 +19,9 @@
 is (@before, 0, "No evals");
 
 my %seen;
-my $name = 'foo';
-
-for my $sep (' ', "\0") {
-
-    my $prog = "sub $name {
-    'Perl${sep}Rules'
-};
-1;
-";
 
-    eval $prog or die;
+sub check_retained_lines {
+    my ($prog, $name) = @_;
     # Is there a more efficient way to write this?
     my @expect_lines = (undef, map ({"$_\n"} split "\n", $prog), "\n", ';');
 
@@ -39,19 +31,57 @@
 
     my @got_lines = @{$::{$keys[0]}};
 
-    is (@got_lines, @expect_lines, "Right number of lines for " . ord $sep);
+    is (@got_lines, @expect_lines, "Right number of lines for $name");
 
     for (0..$#expect_lines) {
 	is ($got_lines[$_], $expect_lines[$_], "Line $_ is correct");
     }
     $seen{$keys[0]}++;
+}
+
+my $name = 'foo';
+
+for my $sep (' ', "\0") {
+
+    my $prog = "sub $name {
+    'Perl${sep}Rules'
+};
+1;
+";
+
+    eval $prog or die;
+    check_retained_lines($prog, ord $sep);
     $name++;
 }
 
-is (eval '1 + 1', 2, 'String eval works');
+foreach my $flags (0x0, 0x800, 0x1000, 0x1800) {
+    local $^P = $^P | $flags;
+    # This is easier if we accept that the guts eval will add a trailing \n
+    # for us
+    my $prog = "1 + 1 + 1\n";
+    my $fail = "1 + \n";
+
+    is (eval $prog, 3, 'String eval works');
+    if ($flags & 0x800) {
+	check_retained_lines($prog, sprintf "%#X", $^P);
+    } else {
+	my @after = grep { /eval/ } keys %::;
+
+	is (@after, 0 + keys %seen,
+	    "evals that don't define subroutines are correctly cleaned up");
+    }
 
-my @after = grep { /eval/ } keys %::;
+    is (eval $fail, undef, 'Failed string eval fails');
 
-is (@after, 0 + keys %seen,
-    "evals that don't define subroutines are correctly cleaned up");
+    if ($flags & 0x1000) {
+    TODO: {
+	    todo_skip "Can't yet retain lines for evals with syntax errors", 6;
+	    check_retained_lines($fail, sprintf "%#X", $^P);
+	}
+    } else {
+	my @after = grep { /eval/ } keys %::;
 
+	is (@after, 0 + keys %seen,
+	    "evals that fail are correctly cleaned up");
+    }
+}
End of Patch.



nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About