----------------
____________________________________________________________________________
+[ 3655] By: gsar on 1999/07/07 18:55:45
+ Log: filetest.t and ByteLoader build tweaks from Peter Prymmer
+ <pvhp@forte.com>
+ Branch: perl
+ ! ext/ByteLoader/Makefile.PL t/op/filetest.t
+____________________________________________________________________________
+[ 3654] By: gsar on 1999/07/07 18:47:03
+ Log: change#1889 mistakenly removed F_SETLK
+ Branch: perl
+ ! ext/Fcntl/Fcntl.xs
+____________________________________________________________________________
+[ 3653] By: gsar on 1999/07/07 18:42:42
+ Log: B::Deparse update
+ From: Stephen McCamant <smccam@uclink4.berkeley.edu>
+ Date: Mon, 5 Jul 1999 17:57:03 -0500 (CDT)
+ Message-ID: <14209.13729.738691.610723@alias-2.pr.mcs.net>
+ Subject: [PATCH _57, long] B::Deparse 0.58
+ Branch: perl
+ ! ext/B/B/Deparse.pm
+____________________________________________________________________________
+[ 3652] By: gsar on 1999/07/07 18:41:07
+ Log: From: Ilya Zakharevich <ilya@math.ohio-state.edu>
+ Date: Mon, 5 Jul 1999 18:24:19 -0400 (EDT)
+ Message-Id: <199907052224.SAA10454@monk.mps.ohio-state.edu>
+ Subject: Re: [ID 19990705.001] Overloading boolean conversion
+ Branch: perl
+ ! gv.c t/pragma/overload.t
+____________________________________________________________________________
+[ 3651] By: gsar on 1999/07/07 17:47:30
+ Log: missing PerlIO_reopen() (suggested by sam@daemoninc.com)
+ Branch: perl
+ ! perlsfio.h
+____________________________________________________________________________
+[ 3650] By: gsar on 1999/07/07 17:45:52
+ Log: applied new parts of suggested patch
+ From: Charles Bailey <BAILEY@newman.upenn.edu>
+ Date: Fri, 02 Jul 1999 19:18:41 -0400 (EDT)
+ Message-id: <01JD3M8W1VXS000S5G@mail.newman.upenn.edu>
+ Subject: [PATCH 5.005_57] Consolidated VMS patch
+ Branch: perl
+ ! configure.com ext/IO/lib/IO/File.pm iperlsys.h
+ ! lib/ExtUtils/MM_VMS.pm lib/File/Basename.pm
+ ! lib/File/Spec/VMS.pm pod/perldiag.pod t/base/rs.t
+ ! t/lib/io_multihomed.t t/lib/textfill.t t/lib/textwrap.t
+ ! t/op/filetest.t t/op/mkdir.t thread.h vms/vms.c
+____________________________________________________________________________
+[ 3649] By: jhi on 1999/07/07 13:38:02
+ Log: Sync regcomp warn with reality.
+ Branch: cfgperl
+ ! t/pragma/warn/regcomp
+____________________________________________________________________________
+[ 3648] By: jhi on 1999/07/07 13:04:55
+ Log: Integrate with Sarathy; one conflict in t/pragma/warn/recgomp
+ resolved manually.
+ Branch: cfgperl
+ +> pod/perllexwarn.pod t/pragma/warn/6default t/pragma/warn/av
+ +> t/pragma/warn/doop t/pragma/warn/hv t/pragma/warn/malloc
+ +> t/pragma/warn/perlio t/pragma/warn/run t/pragma/warn/utf8
+ - README.lexwarn
+ !> (integrate 79 files)
+____________________________________________________________________________
+[ 3647] By: gsar on 1999/07/07 10:32:03
+ Log: From: jan.dubois@ibm.net (Jan Dubois)
+ Date: Thu, 01 Jul 1999 11:17:53 +0200
+ Message-ID: <377b2ca4.14467042@smtp1.ibm.net>
+ Subject: [PATCH 5.005_57] MakeMaker support for pod2html
+ Branch: perl
+ ! lib/ExtUtils/MM_Unix.pm lib/ExtUtils/MM_Win32.pm
+ ! lib/ExtUtils/MakeMaker.pm
+____________________________________________________________________________
+[ 3646] By: gsar on 1999/07/07 10:27:55
+ Log: fix undocumented IO::Handle functions as suggested
+ by cj10@cam.ac.uk
+ Branch: perl
+ ! ext/IO/lib/IO/Handle.pm
+____________________________________________________________________________
+[ 3645] By: gsar on 1999/07/07 10:18:55
+ Log: prohibit thread join()ing itself (from Dan Sugalski)
+ Branch: perl
+ ! ext/Thread/Thread.xs
+____________________________________________________________________________
+[ 3644] By: gsar on 1999/07/07 10:14:26
+ Log: From: "Vishal Bhatia" <vishalb@my-deja.com>
+ Date: Wed, 30 Jun 1999 14:02:42 -0700
+ Message-ID: <LJHFKBDHMHHJDAAA@my-deja.com>
+ Subject: [PATCH 5.005_57] Compiler and XSUBS
+ Branch: perl
+ ! ext/B/B/C.pm
+____________________________________________________________________________
+[ 3643] By: gsar on 1999/07/07 10:08:38
+ Log: mention C<foreach VAR (LIST) BLOCK continue BLOCK> syntax
+ (from François Désarménien <desar@club-internet.fr>)
+ Branch: perl
+ ! pod/perlsyn.pod
+____________________________________________________________________________
+[ 3642] By: gsar on 1999/07/07 10:03:24
+ Log: From: Doug MacEachern <dougm@cp.net>
+ Date: Sun, 27 Jun 1999 22:43:25 -0700 (PDT)
+ Message-ID: <Pine.LNX.4.10.9906272236430.389-100000@mojo.eng.cp.net>
+ Subject: [PATCH 5.005_57] add B::PV::{LEN,CUR}
+ Branch: perl
+ ! ext/B/B.xs
+____________________________________________________________________________
+[ 3641] By: gsar on 1999/07/07 10:00:57
+ Log: slightly modified version of suggested patch
+ From: Steven N. Hirsch <hirschs@stargate.btv.ibm.com>
+ Date: Mon, 28 Jun 1999 14:23:59 -0400
+ Message-Id: <199906281823.OAA24912@stargate.btv.ibm.com>
+ Subject: [ID 19990628.007] POSIX::tmpnam() broken for threaded 5.00503
+ Branch: perl
+ ! ext/POSIX/POSIX.xs
+____________________________________________________________________________
+[ 3640] By: gsar on 1999/07/07 09:45:43
+ Log: lexical warnings update (warning.t fails one test
+ due to leaked scalar, investigation pending)
+ From: paul.marquess@bt.com
+ Date: Sat, 26 Jun 1999 23:19:52 +0100
+ Message-ID: <5104D4DBC598D211B5FE0000F8FE7EB29C6C8E@mbtlipnt02.btlabs.bt.co.uk>
+ Subject: [PATCH 5.005_57] Lexical Warnings - mandatory warning are now default warnings
+ Branch: perl
+ + pod/perllexwarn.pod t/pragma/warn/6default t/pragma/warn/av
+ + t/pragma/warn/doop t/pragma/warn/hv t/pragma/warn/malloc
+ + t/pragma/warn/perlio t/pragma/warn/run t/pragma/warn/utf8
+ - README.lexwarn
+ ! Changes MANIFEST av.c djgpp/djgpp.c doio.c doop.c
+ ! ext/B/B/Asmdata.pm ext/ByteLoader/byterun.c
+ ! ext/ByteLoader/byterun.h gv.c hv.c jpl/JNI/JNI.xs
+ ! lib/warning.pm mg.c op.c os2/os2.c perl.c perlio.c
+ ! pod/perldelta.pod pod/perldiag.pod pod/perlfunc.pod
+ ! pod/perlmodlib.pod pod/perlrun.pod pod/perlvar.pod pp.c
+ ! pp_ctl.c run.c sv.c t/pragma/warn/3both t/pragma/warn/doio
+ ! t/pragma/warn/gv t/pragma/warn/mg t/pragma/warn/op
+ ! t/pragma/warn/perl t/pragma/warn/perly t/pragma/warn/pp
+ ! t/pragma/warn/pp_ctl t/pragma/warn/pp_hot t/pragma/warn/pp_sys
+ ! t/pragma/warn/regcomp t/pragma/warn/regexec t/pragma/warn/sv
+ ! t/pragma/warn/taint t/pragma/warn/toke t/pragma/warn/universal
+ ! t/pragma/warn/util t/pragma/warning.t toke.c utf8.c util.c
+ ! warning.h warning.pl win32/win32.c
+____________________________________________________________________________
[ 3639] By: gsar on 1999/07/07 08:09:30
Log: From: Brian Jepson <bjepson@home.com>
Date: Sat, 26 Jun 1999 10:47:45 -0500 (EST)
$ echo "SDBM_File if you have the GDBM library built on your machine
$ echo "
$ echo "Which modules do you want to build into perl?"
-$ dflt = "Fcntl Errno IO Opcode Data::Dumper attrs re VMS::Stdio VMS::DCLsym B SDBM_File"
+$ dflt = "Fcntl Errno IO Opcode Byteloader Devel::Peek Data::Dumper attrs re VMS::Stdio VMS::DCLsym B SDBM_File"
$ if Using_Dec_C.eqs."Yes"
$ THEN
$ dflt = dflt + " POSIX"
# but essentially none of his code remains.
package B::Deparse;
-use Carp 'cluck';
+use Carp 'cluck', 'croak';
use B qw(class main_root main_start main_cv svref_2object opnumber
OPf_WANT OPf_WANT_VOID OPf_WANT_SCALAR OPf_WANT_LIST
OPf_KIDS OPf_REF OPf_STACKED OPf_SPECIAL
SVf_IOK SVf_NOK SVf_ROK SVf_POK
PMf_KEEP PMf_GLOBAL PMf_CONTINUE PMf_EVAL PMf_ONCE
PMf_MULTILINE PMf_SINGLELINE PMf_FOLD PMf_EXTENDED);
-$VERSION = 0.57;
+$VERSION = 0.58;
use strict;
# Changes between 0.50 and 0.51:
# - added unquote option for expanding "" into concats, etc.
# - split method and proto parts of pp_entersub into separate functions
# - various minor cleanups
+# Changes after 0.57:
+# - added parens in \&foo (patch by Albert Dvornik)
+# Changes between 0.57 and 0.58:
+# - fixed `0' statements that weren't being printed
+# - added methods for use from other programs
+# (based on patches from James Duncan and Hugo van der Sanden)
+# - added -si and -sT to control indenting (also based on a patch from Hugo)
+# - added -sv to print something else instead of '???'
+# - preliminary version of utf8 tr/// handling
# Todo:
+# - finish tr/// changes
+# - add option for even more parens (generalize \&foo change)
# - {} around variables in strings ("${var}letters")
# base/lex.t 25-27
# comp/term.t 11
# - left/right context
# - recognize `use utf8', `use integer', etc
-# - handle swash-based utf8 tr/// (ick, looks hard)
+# - treat top-level block specially for incremental output
+# - interpret in high bit chars in string as utf8 \x{...} (when?)
+# - copy comments (look at real text with $^P)
# - avoid semis in one-statement blocks
# - associativity of &&=, ||=, ?:
# - ',' => '=>' (auto-unquote?)
# - break long lines ("\r" as discretionary break?)
-# - ANSI color syntax highlighting?
+# - configurable syntax highlighting: ANSI color, HTML, TeX, etc.
+# - more style options: brace style, hex vs. octal, quotes, ...
+# - print big ints as hex/octal instead of decimal (heuristic?)
# - include values of variables (e.g. set in BEGIN)
# - coordinate with Data::Dumper (both directions? see previous)
# - version using op_next instead of op_first/sibling?
# linenums: -l
# unquote: -q
# cuddle: ` ' or `\n', depending on -sC
+# indent_size: -si
+# use_tabs: -sT
+# ex_const: -sv
# A little explanation of how precedence contexts and associativity
# work:
while (length($opt = substr($opts, 0, 1))) {
if ($opt eq "C") {
$self->{'cuddle'} = " ";
+ $opts = substr($opts, 1);
+ } elsif ($opt eq "i") {
+ $opts =~ s/^i(\d+)//;
+ $self->{'indent_size'} = $1;
+ } elsif ($opt eq "T") {
+ $self->{'use_tabs'} = 1;
+ $opts = substr($opts, 1);
+ } elsif ($opt eq "v") {
+ $opts =~ s/^v([^.]*)(.|$)//;
+ $self->{'ex_const'} = $1;
}
- $opts = substr($opts, 1);
}
}
+sub new {
+ my $class = shift;
+ my $self = bless {}, $class;
+ $self->{'subs_todo'} = [];
+ $self->{'curstash'} = "main";
+ $self->{'cuddle'} = "\n";
+ $self->{'indent_size'} = 4;
+ $self->{'use_tabs'} = 0;
+ $self->{'ex_const'} = "'???'";
+ while (my $arg = shift @_) {
+ if (substr($arg, 0, 2) eq "-u") {
+ $self->stash_subs(substr($arg, 2));
+ } elsif ($arg eq "-p") {
+ $self->{'parens'} = 1;
+ } elsif ($arg eq "-l") {
+ $self->{'linenums'} = 1;
+ } elsif ($arg eq "-q") {
+ $self->{'unquote'} = 1;
+ } elsif (substr($arg, 0, 2) eq "-s") {
+ $self->style_opts(substr $arg, 2);
+ }
+ }
+ return $self;
+}
+
sub compile {
my(@args) = @_;
return sub {
- my $self = bless {};
- my $arg;
- $self->{'subs_todo'} = [];
+ my $self = B::Deparse->new(@args);
$self->stash_subs("main");
$self->{'curcv'} = main_cv;
- $self->{'curstash'} = "main";
- $self->{'cuddle'} = "\n";
- while ($arg = shift @args) {
- if (substr($arg, 0, 2) eq "-u") {
- $self->stash_subs(substr($arg, 2));
- } elsif ($arg eq "-p") {
- $self->{'parens'} = 1;
- } elsif ($arg eq "-l") {
- $self->{'linenums'} = 1;
- } elsif ($arg eq "-q") {
- $self->{'unquote'} = 1;
- } elsif (substr($arg, 0, 2) eq "-s") {
- $self->style_opts(substr $arg, 2);
- }
- }
$self->walk_sub(main_cv, main_start);
print $self->print_protos;
@{$self->{'subs_todo'}} =
- sort {$a->[0] <=> $b->[0]} @{$self->{'subs_todo'}};
- print indent($self->deparse(main_root, 0)), "\n" unless null main_root;
+ sort {$a->[0] <=> $b->[0]} @{$self->{'subs_todo'}};
+ print $self->indent($self->deparse(main_root, 0)), "\n"
+ unless null main_root;
my @text;
while (scalar(@{$self->{'subs_todo'}})) {
push @text, $self->next_todo;
}
}
+sub coderef2text {
+ my $self = shift;
+ my $sub = shift;
+ croak "Usage: ->coderef2text(CODEREF)" unless ref($sub) eq "CODE";
+ return $self->indent($self->deparse_sub(svref_2object($sub)));
+}
+
sub deparse {
my $self = shift;
my($op, $cx) = @_;
}
sub indent {
+ my $self = shift;
my $txt = shift;
my @lines = split(/\n/, $txt);
my $leader = "";
+ my $level = 0;
my $line;
for $line (@lines) {
- if (substr($line, 0, 1) eq "\t") {
- $leader = $leader . " ";
- $line = substr($line, 1);
- } elsif (substr($line, 0, 1) eq "\b") {
- $leader = substr($leader, 0, length($leader) - 4);
+ my $cmd = substr($line, 0, 1);
+ if ($cmd eq "\t" or $cmd eq "\b") {
+ $level += ($cmd eq "\t" ? 1 : -1) * $self->{'indent_size'};
+ if ($self->{'use_tabs'}) {
+ $leader = "\t" x ($level / 8) . " " x ($level % 8);
+ } else {
+ $leader = " " x $level;
+ }
$line = substr($line, 1);
}
if (substr($line, 0, 1) eq "\f") {
last if null $kid;
}
$expr .= $self->deparse($kid, 0);
- push @exprs, $expr if $expr;
+ push @exprs, $expr if length $expr;
}
if ($cx > 0) { # inside an expression
return "do { " . join(";\n", @exprs) . " }";
last if null $kid;
}
$expr .= $self->deparse($kid, 0);
- push @exprs, $expr if $expr;
+ push @exprs, $expr if length $expr;
}
if ($cx > 0) { # inside an expression, (a do {} while for lineseq)
return "do { " . join(";\n", @exprs) . " }";
sub unop {
my $self = shift;
- my($op, $cx, $name, $prec, $flags) = (@_, 0, 0);
+ my($op, $cx, $name) = @_;
my $kid;
if ($op->flags & OPf_KIDS) {
$kid = $op->first;
}
sub pp_and { logop(@_, "and", 3, "&&", 11, "if") }
-sub pp_or { logop(@_, "or", 2, "||", 10, "unless") }
+sub pp_or { logop(@_, "or", 2, "||", 10, "unless") }
sub pp_xor { logop(@_, "xor", 2, "", 0, "") }
sub logassignop {
$kid = $kid->first->sibling; # skip a pushmark
my $code = $kid->first; # skip a null
if (is_scope $code) {
- $code = "{" . $self->deparse($code, 1) . "} ";
+ $code = "{" . $self->deparse($code, 0) . "} ";
} else {
$code = $self->deparse($code, 24) . ", ";
}
my $self = shift;
my($op, $cx) = @_;
if (class($op) eq "OP") {
- return "'???'" if $op->targ == OP_CONST; # old value is lost
+ # old value is lost
+ return $self->{'ex_const'} if $op->targ == OP_CONST;
} elsif ($op->first->ppaddr eq "pp_pushmark") {
return $self->pp_list($op, $cx);
} elsif ($op->first->ppaddr eq "pp_enter") {
if ($c <= $#chars - 2 and $chars[$c + 1] == $tr + 1 and
$chars[$c + 2] == $tr + 2)
{
- for (; $c <= $#chars and $chars[$c + 1] == $chars[$c] + 1; $c++) {}
+ for (; $c <= $#chars-1 and $chars[$c + 1] == $chars[$c] + 1; $c++)
+ {}
$str .= "-";
$str .= pchr($chars[$c]);
}
return $str;
}
-sub pp_trans {
- my $self = shift;
- my($op, $cx) = @_;
- my(@table) = unpack("s256", $op->pv);
+# XXX This has trouble with hyphens in the replacement (tr/bac/-AC/),
+# and backslashes.
+
+sub tr_decode_byte {
+ my($table, $flags) = @_;
+ my(@table) = unpack("s256", $table);
my($c, $tr, @from, @to, @delfrom, $delhyphen);
if ($table[ord "-"] != -1 and
$table[ord("-") - 1] == -1 || $table[ord("-") + 1] == -1)
push @delfrom, $c;
}
}
- my $flags;
@from = (@from, @delfrom);
- if ($op->private & OPpTRANS_COMPLEMENT) {
- $flags .= "c";
+ if ($flags & OPpTRANS_COMPLEMENT) {
my @newfrom = ();
my %from;
@from{@from} = (1) x @from;
}
@from = @newfrom;
}
- if ($op->private & OPpTRANS_DELETE) {
- $flags .= "d";
- } else {
+ unless ($flags & OPpTRANS_DELETE) {
pop @to while $#to and $to[$#to] == $to[$#to -1];
}
- $flags .= "s" if $op->private & OPpTRANS_SQUASH;
my($from, $to);
$from = collapse(@from);
$to = collapse(@to);
$from .= "-" if $delhyphen;
+ return ($from, $to);
+}
+
+sub tr_chr {
+ my $x = shift;
+ if ($x == ord "-") {
+ return "\\-";
+ } else {
+ return chr $x;
+ }
+}
+
+# XXX This doesn't yet handle all cases correctly either
+
+sub tr_decode_utf8 {
+ my($swash_hv, $flags) = @_;
+ my %swash = $swash_hv->ARRAY;
+ my $final = undef;
+ $final = $swash{'FINAL'}->IV if exists $swash{'FINAL'};
+ my $none = $swash{"NONE"}->IV;
+ my $extra = $none + 1;
+ my(@from, @delfrom, @to);
+ my $line;
+ foreach $line (split /\n/, $swash{'LIST'}->PV) {
+ my($min, $max, $result) = split(/\t/, $line);
+ $min = hex $min;
+ if (length $max) {
+ $max = hex $max;
+ } else {
+ $max = $min;
+ }
+ $result = hex $result;
+ if ($result == $extra) {
+ push @delfrom, [$min, $max];
+ } else {
+ push @from, [$min, $max];
+ push @to, [$result, $result + $max - $min];
+ }
+ }
+ for my $i (0 .. $#from) {
+ if ($from[$i][0] == ord '-') {
+ unshift @from, splice(@from, $i, 1);
+ unshift @to, splice(@to, $i, 1);
+ last;
+ } elsif ($from[$i][1] == ord '-') {
+ $from[$i][1]--;
+ $to[$i][1]--;
+ unshift @from, ord '-';
+ unshift @to, ord '-';
+ last;
+ }
+ }
+ for my $i (0 .. $#delfrom) {
+ if ($delfrom[$i][0] == ord '-') {
+ push @delfrom, splice(@delfrom, $i, 1);
+ last;
+ } elsif ($delfrom[$i][1] == ord '-') {
+ $delfrom[$i][1]--;
+ push @delfrom, ord '-';
+ last;
+ }
+ }
+ if (defined $final and $to[$#to][1] != $final) {
+ push @to, [$final, $final];
+ }
+ push @from, @delfrom;
+ if ($flags & OPpTRANS_COMPLEMENT) {
+ my @newfrom;
+ my $next = 0;
+ for my $i (0 .. $#from) {
+ push @newfrom, [$next, $from[$i][0] - 1];
+ $next = $from[$i][1] + 1;
+ }
+ @from = ();
+ for my $range (@newfrom) {
+ if ($range->[0] <= $range->[1]) {
+ push @from, $range;
+ }
+ }
+ }
+ my($from, $to, $diff);
+ for my $chunk (@from) {
+ $diff = $chunk->[1] - $chunk->[0];
+ if ($diff > 1) {
+ $from .= tr_chr($chunk->[0]) . "-" . tr_chr($chunk->[1]);
+ } elsif ($diff == 1) {
+ $from .= tr_chr($chunk->[0]) . tr_chr($chunk->[1]);
+ } else {
+ $from .= tr_chr($chunk->[0]);
+ }
+ }
+ for my $chunk (@to) {
+ $diff = $chunk->[1] - $chunk->[0];
+ if ($diff > 1) {
+ $to .= tr_chr($chunk->[0]) . "-" . tr_chr($chunk->[1]);
+ } elsif ($diff == 1) {
+ $to .= tr_chr($chunk->[0]) . tr_chr($chunk->[1]);
+ } else {
+ $to .= tr_chr($chunk->[0]);
+ }
+ }
+ #$final = sprintf("%04x", $final) if defined $final;
+ #$none = sprintf("%04x", $none) if defined $none;
+ #$extra = sprintf("%04x", $extra) if defined $extra;
+ #print STDERR "final: $final\n none: $none\nextra: $extra\n";
+ #print STDERR $swash{'LIST'}->PV;
+ return (escape_str($from), escape_str($to));
+}
+
+sub pp_trans {
+ my $self = shift;
+ my($op, $cx) = @_;
+ my($from, $to);
+ if (class($op) eq "PVOP") {
+ ($from, $to) = tr_decode_byte($op->pv, $op->private);
+ } else { # class($op) eq "SVOP"
+ ($from, $to) = tr_decode_utf8($op->sv->RV, $op->private);
+ }
+ my $flags = "";
+ $flags .= "c" if $op->private & OPpTRANS_COMPLEMENT;
+ $flags .= "d" if $op->private & OPpTRANS_DELETE;
+ $to = "" if $from eq $to and $flags eq "";
+ $flags .= "s" if $op->private & OPpTRANS_SQUASH;
return "tr" . double_delim($from, $to) . $flags;
}
=head1 SYNOPSIS
-B<perl> B<-MO=Deparse>[B<,-u>I<PACKAGE>][B<,-p>][B<,-l>][B<,-s>I<LETTERS>] I<prog.pl>
+B<perl> B<-MO=Deparse>[B<,-u>I<PACKAGE>][B<,-p>][B<,-q>][B<,-l>][B<,-s>I<LETTERS>]
+ I<prog.pl>
=head1 DESCRIPTION
called by the main program (and all the subs called by them,
recursively), and any other subs in the main:: package. To include
subs in other packages that aren't called directly, such as AUTOLOAD,
-DESTROY, other subs called automatically by perl, and methods, which
-aren't resolved to subs until runtime, use the B<-u> option. The
+DESTROY, other subs called automatically by perl, and methods (which
+aren't resolved to subs until runtime), use the B<-u> option. The
argument to B<-u> is the name of a package, and should follow directly
after the 'u'. Multiple B<-u> options may be given, separated by
commas. Note that unlike some other backends, B::Deparse doesn't
=item B<-s>I<LETTERS>
-Tweak the style of B::Deparse's output. At the moment, only one style
-option is implemented:
+Tweak the style of B::Deparse's output. The letters should follow
+directly after the 's', with no space or punctuation. The following
+options are available:
=over 4
The default is not to cuddle.
+=item B<i>I<NUMBER>
+
+Indent lines by multiples of I<NUMBER> columns. The default is 4 columns.
+
+=item B<T>
+
+Use tabs for each 8 columns of indent. The default is to use only spaces.
+For instance, if the style options are B<-si4T>, a line that's indented
+3 times will be preceded by one tab and four spaces; if the options were
+B<-si8T>, the same line would be preceded by three tabs.
+
+=item B<v>I<STRING>B<.>
+
+Print I<STRING> for the value of a constant that can't be determined
+because it was optimized away (mnemonic: this happens when a constant
+is used in B<v>oid context). The end of the string is marked by a period.
+The string should be a valid perl expression, generally a constant.
+Note that unless it's a number, it probably needs to be quoted, and on
+a command line quotes need to be protected from the shell. Some
+conventional values include 0, 1, 42, '', 'foo', and
+'Useless use of constant omitted' (which may need to be
+B<-sv"'Useless use of constant omitted'.">
+or something similar depending on your shell). The default is '???'.
+If you're using B::Deparse on a module or other file that's require'd,
+you shouldn't use a value that evaluates to false, since the customary
+true constant at the end of a module will be in void context when the
+file is compiled as a main program.
+
=back
=back
+=head1 USING B::Deparse AS A MODULE
+
+=head2 Synopsis
+
+ use B::Deparse;
+ $deparse = B::Deparse->new("-p", "-sC");
+ $body = $deparse->coderef2text(\&func);
+ eval "sub func $body"; # the inverse operation
+
+=head2 Description
+
+B::Deparse can also be used on a sub-by-sub basis from other perl
+programs.
+
+=head2 new
+
+ $deparse = B::Deparse->new(OPTIONS)
+
+Create an object to store the state of a deparsing operation and any
+options. The options are the same as those that can be given on the
+command line (see L</OPTIONS>); options that are separated by commas
+after B<-MO=Deparse> should be given as separate strings. Some
+options, like B<-u>, don't make sense for a single subroutine, so
+don't pass them.
+
+=head2 coderef2text
+
+ $body = $deparse->coderef2text(\&func)
+ $body = $deparse->coderef2text(sub ($$) { ... })
+
+Return source code for the body of a subroutine (a block, optionally
+preceded by a prototype in parens), given a reference to the
+sub. Because a subroutine can have no names, or more than one name,
+this method doesn't return a complete subroutine definition -- if you
+want to eval the result, you should prepend "sub subname ", or "sub "
+for an anonymous function constructor. Unless the sub was defined in
+the main:: package, the code will include a package declaration.
+
=head1 BUGS
See the 'to do' list at the beginning of the module file.
=head1 AUTHOR
Stephen McCamant <smccam@uclink4.berkeley.edu>, based on an earlier
-version by Malcolm Beattie <mbeattie@sable.ox.ac.uk>.
+version by Malcolm Beattie <mbeattie@sable.ox.ac.uk>, with
+contributions from Gisle Aas, James Duncan, Albert Dvornik, Hugo van
+der Sanden, Gurusamy Sarathy, and Nick Ing-Simmons.
=cut
NAME => 'ByteLoader',
VERSION_FROM => 'ByteLoader.pm',
XSPROTOARG => '-noprototypes',
+ MAN3PODS => {}, # Pods will be built by installman.
OBJECT => 'byterun$(OBJ_EXT) ByteLoader$(OBJ_EXT)',
);
#else
goto not_there;
#endif
+ if (strEQ(name, "F_SETLK"))
+#ifdef F_SETLK
+ return F_SETLK;
+#else
+ goto not_there;
+#endif
if (strEQ(name, "F_SETLK64"))
#ifdef F_SETLK64
return F_SETLK64;
case dec_amg:
SvSetSV(left,res); return left;
case not_amg:
- ans=!SvOK(res); break;
+ ans=!SvTRUE(res); break;
}
return boolSV(ans);
} else if (method==copy_amg) {
#define PerlLIO_ioctl(fd, u, buf) ioctl((fd), (u), (buf))
#define PerlLIO_isatty(fd) isatty((fd))
#define PerlLIO_lseek(fd, offset, mode) lseek((fd), (offset), (mode))
+#define PerlLIO_stat(name, buf) Stat((name), (buf))
#ifdef HAS_LSTAT
-#define PerlLIO_lstat(name, buf) lstat((name), (buf))
+# define PerlLIO_lstat(name, buf) lstat((name), (buf))
#else
-#define PerlLIO_lstat(name, buf) PerlLIO_stat((name), (buf))
+# define PerlLIO_lstat(name, buf) PerlLIO_stat((name), (buf))
#endif
#define PerlLIO_mktemp(file) mktemp((file))
#define PerlLIO_mkstemp(file) mkstemp((file))
#define PerlLIO_read(fd, buf, count) read((fd), (buf), (count))
#define PerlLIO_rename(old, new) rename((old), (new))
#define PerlLIO_setmode(fd, mode) setmode((fd), (mode))
-#define PerlLIO_stat(name, buf) Stat((name), (buf))
#define PerlLIO_tmpnam(str) tmpnam((str))
#define PerlLIO_umask(mode) umask((mode))
#define PerlLIO_unlink(file) unlink((file))
use File::Basename;
use vars qw($Revision);
-$Revision = '5.52 (12-Sep-1998)';
+$Revision = '5.56 (27-Apr-1999)';
unshift @MM::ISA, 'ExtUtils::MM_VMS';
my(@m,$def,$macro);
if ($self->{DEFINE} ne '') {
- my(@defs) = split(/\s+/,$self->{DEFINE});
- foreach $def (@defs) {
+ my(@terms) = split(/\s+/,$self->{DEFINE});
+ my(@defs,@udefs);
+ foreach $def (@terms) {
next unless $def;
- if ($def =~ s/^-D//) { # If it was a Unix-style definition
+ my $targ = \@defs;
+ if ($def =~ s/^-([DU])//) { # If it was a Unix-style definition
+ if ($1 eq 'U') { $targ = \@udefs; }
$def =~ s/='(.*)'$/=$1/; # then remove shell-protection ''
$def =~ s/^'(.*)'$/$1/; # from entire term or argument
}
$def =~ s/"/""/g; # Protect existing " from DCL
$def = qq["$def"]; # and quote to prevent parsing of =
}
+ push @$targ, $def;
}
- $self->{DEFINE} = join ',',@defs;
+ $self->{DEFINE} = '';
+ if (@defs) { $self->{DEFINE} = '/Define=(' . join(',',@defs) . ')'; }
+ if (@udefs) { $self->{DEFINE} .= '/Undef=(' . join(',',@udefs) . ')'; }
}
if ($self->{OBJECT} =~ /\s/) {
# Deal with $self->{DEFINE} here since some C compilers pay attention
# to only one /Define clause on command line, so we have to
# conflate the ones from $Config{'ccflags'} and $self->{DEFINE}
- if ($quals =~ m:(.*)/define=\(?([^\(\/\)\s]+)\)?(.*)?:i) {
- $quals = "$1/Define=($2," . ($self->{DEFINE} ? "$self->{DEFINE}," : '') .
- "\$(DEFINE_VERSION),\$(XS_DEFINE_VERSION))$3";
- }
- else {
- $quals .= '/Define=(' . ($self->{DEFINE} ? "$self->{DEFINE}," : '') .
- '$(DEFINE_VERSION),$(XS_DEFINE_VERSION))';
+ # ($self->{DEFINE} has already been VMSified in constants() above)
+ if ($self->{DEFINE}) { $quals .= $self->{DEFINE}; }
+ for $type (qw(Def Undef)) {
+ my(@terms);
+ while ($quals =~ m:/${type}i?n?e?=([^/]+):ig) {
+ my $term = $1;
+ $term =~ s:^\((.+)\)$:$1:;
+ push @terms, $term;
+ }
+ if ($type eq 'Def') {
+ push @terms, qw[ $(DEFINE_VERSION) $(XS_DEFINE_VERSION) ];
+ }
+ if (@terms) {
+ $quals =~ s:/${type}i?n?e?=[^/]+::ig;
+ $quals .= "/${type}ine=(" . join(',',@terms) . ')';
+ }
}
$libperl or $libperl = $self->{LIBPERL_A} || "libperl.olb";
-# This whole section is commented out, since I don't think it's necessary (or applicable)
-# if ($libperl =~ s/^$Config{'dbgprefix'}//) { $libperl =~ s/perl([^Dd]*)\./perld$1./; }
-# if ($libperl =~ /libperl(\w+)\./i) {
-# my($type) = uc $1;
-# my(%map) = ( 'D' => 'DEBUGGING', 'E' => 'EMBED', 'M' => 'MULTIPLICITY',
-# 'DE' => 'DEBUGGING,EMBED', 'DM' => 'DEBUGGING,MULTIPLICITY',
-# 'EM' => 'EMBED,MULTIPLICITY', 'DEM' => 'DEBUGGING,EMBED,MULTIPLICITY' );
-# my($add) = join(',', grep { $quals !~ /\b$_\b/ } split(/,/,$map{$type}));
-# $quals =~ s:/define=\(([^\)]+)\):/Define=($1,$add):i if $add;
-# $self->{PERLTYPE} ||= $type;
-# }
# Likewise with $self->{INC} and /Include
if ($self->{'INC'}) {
}
}
$quals .= "$incstr)";
- $quals =~ s/\(,/\(/g;
+# $quals =~ s/,,/,/g; $quals =~ s/\(,/(/g;
$self->{CCFLAGS} = $quals;
$self->{OPTIMIZE} ||= $flagoptstr || $Config{'optimize'};
## use strict;
-# A bit of juggling to insure that C<use re 'taint';> awlays works, since
+# A bit of juggling to insure that C<use re 'taint';> always works, since
# File::Basename is used during the Perl build, when the re extension may
# not be available.
BEGIN {
there. This package overrides the implementation of these methods, not
the semantics.
+=cut
+
+sub eliminate_macros {
+ my($self,$path) = @_;
+ return '' unless $path;
+ $self = {} unless ref $self;
+ my($npath) = unixify($path);
+ my($complex) = 0;
+ my($head,$macro,$tail);
+
+ # perform m##g in scalar context so it acts as an iterator
+ while ($npath =~ m#(.*?)\$\((\S+?)\)(.*)#g) {
+ if ($self->{$2}) {
+ ($head,$macro,$tail) = ($1,$2,$3);
+ if (ref $self->{$macro}) {
+ if (ref $self->{$macro} eq 'ARRAY') {
+ $macro = join ' ', @{$self->{$macro}};
+ }
+ else {
+ print "Note: can't expand macro \$($macro) containing ",ref($self->{$macro}),
+ "\n\t(using MMK-specific deferred substitutuon; MMS will break)\n";
+ $macro = "\cB$macro\cB";
+ $complex = 1;
+ }
+ }
+ else { ($macro = unixify($self->{$macro})) =~ s#/$##; }
+ $npath = "$head$macro$tail";
+ }
+ }
+ if ($complex) { $npath =~ s#\cB(.*?)\cB#\${$1}#g; }
+ $npath;
+}
+
+sub fixpath {
+ my($self,$path,$force_path) = @_;
+ return '' unless $path;
+ $self = bless {} unless ref $self;
+ my($fixedpath,$prefix,$name);
+
+ if ($path =~ m#^\$\([^\)]+\)$# || $path =~ m#[/:>\]]#) {
+ if ($force_path or $path =~ /(?:DIR\)|\])$/) {
+ $fixedpath = vmspath($self->eliminate_macros($path));
+ }
+ else {
+ $fixedpath = vmsify($self->eliminate_macros($path));
+ }
+ }
+ elsif ((($prefix,$name) = ($path =~ m#^\$\(([^\)]+)\)(.+)#)) && $self->{$prefix}) {
+ my($vmspre) = $self->eliminate_macros("\$($prefix)");
+ # is it a dir or just a name?
+ $vmspre = ($vmspre =~ m|/| or $prefix =~ /DIR$/) ? vmspath($vmspre) : '';
+ $fixedpath = ($vmspre ? $vmspre : $self->{$prefix}) . $name;
+ $fixedpath = vmspath($fixedpath) if $force_path;
+ }
+ else {
+ $fixedpath = $path;
+ $fixedpath = vmspath($fixedpath) if $force_path;
+ }
+ # No hints, so we try to guess
+ if (!defined($force_path) and $fixedpath !~ /[:>(.\]]/) {
+ $fixedpath = vmspath($fixedpath) if -d $fixedpath;
+ }
+ # Trim off root dirname if it's had other dirs inserted in front of it.
+ $fixedpath =~ s/\.000000([\]>])/$1/;
+ $fixedpath;
+}
+
+
=head2 Methods always loaded
=over
#define PerlIO_write(f,buf,count) sfwrite(f,buf,count)
#define PerlIO_open(path,mode) sfopen(NULL,path,mode)
#define PerlIO_fdopen(fd,mode) _stdopen(fd,mode)
+#define PerlIO_reopen(path,mode,f) sfopen(f,path,mode)
#define PerlIO_close(f) sfclose(f)
#define PerlIO_puts(f,s) sfputr(f,s,-1)
#define PerlIO_putc(f,c) sfputc(f,c)
%ENV, it encountered a logical name or symbol definition which was too long,
so it was truncated to the string shown.
+=item Buffer overflow in prime_env_iter: %s
+
+(W) A warning peculiar to VMS. While Perl was preparing to iterate over
+%ENV, it encountered a logical name or symbol definition which was too long,
+so it was truncated to the string shown.
+
=item Callback called exit
(F) A subroutine invoked from an external package via perl_call_sv()
missing. You need to figure out where your CRTL misplaced its environ
or define F<PERL_ENV_TABLES> (see L<perlvms>) so that environ is not searched.
+=item Can't read CRTL environ
+
+(S) A warning peculiar to VMS. Perl tried to read an element of %ENV
+from the CRTL's internal environment array and discovered the array was
+missing. You need to figure out where your CRTL misplaced its environ
+or define F<PERL_ENV_TABLES> (see L<perlvms>) so that environ is not searched.
+
=item Can't "redo" outside a block
(F) A "redo" statement was executed to restart the current block, but
=item Character class syntax [%s] belongs inside character classes
(W) The character class constructs [: :], [= =], and [. .] go
-I<inside> character classes, the [] are part of the construct. For
-example: /[[:alpha:]]/
+I<inside> character classes, the [] are part of the construct,
+for example: /[012[:alpha:]345]/. Note that the last two constructs
+are not currently implemented, they are placeholders for future extensions.
-=item Character class syntax [ .] is reserved for future extensions
+=item Character class syntax [. .] is reserved for future extensions
(W) Within regular expression character classes ([]) the syntax beginning
with "[." and ending with ".]" is reserved for future extensions.
to translate to the number of seconds which need to be added to UTC to
get local time.
+=item no UTC offset information; assuming local time is UTC
+
+(S) A warning peculiar to VMS. Per was unable to find the local
+timezone offset, so it's assuming that local system time is equivalent
+to UTC. If it's not, define the logical name F<SYS$TIMEZONE_DIFFERENTIAL>
+to translate to the number of seconds which need to be added to UTC to
+get local time.
+
=item Not a CODE reference
(F) Perl was trying to evaluate a reference to a code value (that is, a
L<perlvms>) so that the environ array isn't the target of the change to
%ENV which produced the warning.
+=item This Perl can't reset CRTL eviron elements (%s)
+
+=item This Perl can't set CRTL environ elements (%s=%s)
+
+(W) Warnings peculiar to VMS. You tried to change or delete an element
+of the CRTL's internal environ array, but your copy of Perl wasn't
+built with a CRTL that contained the setenv() function. You'll need to
+rebuild Perl with a CRTL that does, or redefine F<PERL_ENV_TABLES> (see
+L<perlvms>) so that the environ array isn't the target of the change to
+%ENV which produced the warning.
+
=item times not implemented
(F) Your version of the C library apparently doesn't do times(). I suspect
data Perl expected. Someone's very confused, or perhaps trying to
subvert Perl's population of %ENV for nefarious purposes.
+=item Unknown process %x sent message to prime_env_iter: %s
+
+(P) An error peculiar to VMS. Perl was reading values for %ENV before
+iterating over it, and someone else stuck a message in the stream of
+data Perl expected. Someone's very confused, or perhaps trying to
+subvert Perl's population of %ENV for nefarious purposes.
+
=item unmatched () in regexp
(F) Unbackslashed parentheses must always be balanced in regular
than 1024 characters. The return value has been truncated to 1024
characters.
+=item Value of CLI symbol "%s" too long
+
+(W) A warning peculiar to VMS. Perl tried to read the value of an %ENV
+element from a CLI symbol table, and found a resultant string longer
+than 1024 characters. The return value has been truncated to 1024
+characters.
+
=item Variable "%s" is not imported%s
(F) While "use strict" in effect, you referred to a global variable
if ($bar eq "z\n") {print "ok 14\n";} else {print "not ok 14\n";}
close TESTFILE;
- unlink "./foo.bar";
- unlink "./foo.com";
+ 1 while unlink qw(foo.bar foo.com foo.fdl);
} else {
# Nobody else does this at the moment (well, maybe OS/390, but they can
# put their own tests in) so we just punt
elsif ($Config{'extensions'} !~ /\bIO\b/) {
$reason = 'IO extension unavailable';
}
- undef $reason if $^O eq 'VMS' and $Config{d_socket};
if ($reason) {
print "1..0 # Skip: $reason\n";
exit 0;
unshift @INC, '../lib';
}
+use Text::Wrap qw(&fill);
+
@tests = (split(/\nEND\n/s, <<DONE));
TEST1
Cyberdog Information
chdir 't' if -d 't';
unshift @INC, '../lib';
}
+use Text::Wrap qw(&wrap);
@tests = (split(/\nEND\n/s, <<DONE));
TEST1
print "# oldeuid = $oldeuid, euid = $>\n";
-if ($bad_chmod) {
+if (!$Config{d_seteuid}) {
+ print "ok 6 #skipped, no seteuid\n";
+}
+elsif ($bad_chmod) {
print "#[$@]\nok 6 #skipped\n";
}
else {
print "1..7\n";
-$^O eq 'MSWin32' ? `del /s /q blurfl 2>&1` : `rm -rf blurfl`;
+if ($^O eq 'VMS') { # May as well test the library too
+ unshift @INC, '../lib';
+ require File::Path;
+ File::Path::rmtree('blurfl');
+}
+else {
+ $^O eq 'MSWin32' ? `del /s /q blurfl 2>&1` : `rm -rf blurfl`;
+}
# tests 3 and 7 rather naughtily expect English error messages
$ENV{'LC_ALL'} = 'C';
$bar->{three} = 13;
test $bar->[3], 13; # 206
+{
+ package B;
+ use overload bool => sub { ${+shift} };
+}
+
+my $aaa;
+{ my $bbbb = 0; $aaa = bless \$bbbb, B }
+
+test !$aaa, 1;
+
+unless ($aaa) {
+ test 'ok', 'ok';
+} else {
+ test 'is not', 'ok';
+}
+
+
# Last test is:
-sub last {206}
+sub last {208}
key = cp1; keylen = cp2 - cp1;
if (keylen && hv_exists(seenhv,key,keylen)) continue;
while (*cp2 && *cp2 != '=') cp2++;
- while (*cp2 && *cp2 != '"') cp2++;
- for (cp1 = buf + retlen; *cp1 != '"'; cp1--) ;
- if ((!keylen || (cp1 - cp2 <= 0)) && ckWARN(WARN_INTERNAL)) {
+ while (*cp2 && *cp2 == '=') cp2++;
+ while (*cp2 && *cp2 == ' ') cp2++;
+ if (*cp2 == '"') { /* String translation; may embed "" */
+ for (cp1 = buf + retlen; *cp1 != '"'; cp1--) ;
+ cp2++; cp1--; /* Skip "" surrounding translation */
+ }
+ else { /* Numeric translation */
+ for (cp1 = cp2; *cp1 && *cp1 != ' '; cp1++) ;
+ cp1--; /* stop on last non-space char */
+ }
+ if ((!keylen || (cp1 - cp2 < -1)) && ckWARN(WARN_INTERNAL)) {
warner(WARN_INTERNAL,"Ill-formed message in prime_env_iter: |%s|",buf);
continue;
}
- /* Skip "" surrounding translation */
PERL_HASH(hash,key,keylen);
- hv_store(envhv,key,keylen,newSVpv(cp2+1,cp1 - cp2 - 1),hash);
+ hv_store(envhv,key,keylen,newSVpvn(cp2,cp1 - cp2 + 1),hash);
hv_store(seenhv,key,keylen,&PL_sv_yes,hash);
}
if (cmddsc.dsc$w_length == 14) { /* We just read LNM$FILE_DEV */
* to a mbx; that's the caller's responsibility.
*/
static unsigned long int
-pipe_eof(FILE *fp)
+pipe_eof(FILE *fp, int immediate)
{
char devnam[NAM$C_MAXRSS+1], *cp;
unsigned long int chan, iosb[2], retsts, retsts2;
if ((cp = strrchr(devnam,':')) != NULL) *(cp+1) = '\0';
devdsc.dsc$w_length = strlen(devnam);
_ckvmssts(sys$assign(&devdsc,&chan,0,0));
- retsts = sys$qiow(0,chan,IO$_WRITEOF,iosb,0,0,0,0,0,0,0,0);
+ retsts = sys$qiow(0,chan,IO$_WRITEOF|(immediate?IO$M_NOW|IO$M_NORSWAIT:0),
+ iosb,0,0,0,0,0,0,0,0);
if (retsts & 1) retsts = iosb[0];
retsts2 = sys$dassgn(chan); /* Be sure to deassign the channel */
if (retsts & 1) retsts = retsts2;
while (info) {
if (info->mode != 'r' && !info->done) {
- if (pipe_eof(info->fp) & 1) did_stuff = 1;
+ if (pipe_eof(info->fp, 1) & 1) did_stuff = 1;
}
info = info->next;
}
/* If we were writing to a subprocess, insure that someone reading from
* the mailbox gets an EOF. It looks like a simple fclose() doesn't
* produce an EOF record in the mailbox. */
- if (info->mode != 'r' && !info->done) pipe_eof(info->fp);
+ if (info->mode != 'r' && !info->done) pipe_eof(info->fp,0);
PerlIO_close(info->fp);
if (info->done) retsts = info->completion;