summaryrefslogtreecommitdiffstats
path: root/contrib/perl5/utils
diff options
context:
space:
mode:
authormarkm <markm@FreeBSD.org>1998-09-09 07:00:04 +0000
committermarkm <markm@FreeBSD.org>1998-09-09 07:00:04 +0000
commit4fcbc3669aa997848e15198cc9fb856287a6788c (patch)
tree58b20e81687d6d5931f120b50802ed21225bf440 /contrib/perl5/utils
downloadFreeBSD-src-4fcbc3669aa997848e15198cc9fb856287a6788c.zip
FreeBSD-src-4fcbc3669aa997848e15198cc9fb856287a6788c.tar.gz
Initial import of Perl5. The king is dead; long live the king!
Diffstat (limited to 'contrib/perl5/utils')
-rw-r--r--contrib/perl5/utils/Makefile43
-rw-r--r--contrib/perl5/utils/c2ph.PL1403
-rw-r--r--contrib/perl5/utils/h2ph.PL636
-rw-r--r--contrib/perl5/utils/h2xs.PL905
-rw-r--r--contrib/perl5/utils/perlbug.PL1093
-rw-r--r--contrib/perl5/utils/perlcc.PL945
-rw-r--r--contrib/perl5/utils/perldoc.PL687
-rw-r--r--contrib/perl5/utils/pl2pm.PL389
-rw-r--r--contrib/perl5/utils/splain.PL49
9 files changed, 6150 insertions, 0 deletions
diff --git a/contrib/perl5/utils/Makefile b/contrib/perl5/utils/Makefile
new file mode 100644
index 0000000..2df16d8
--- /dev/null
+++ b/contrib/perl5/utils/Makefile
@@ -0,0 +1,43 @@
+
+PERL = ../miniperl
+REALPERL = ../perl
+
+# Files to be built with variable substitution after miniperl is
+# available. Dependencies handled manually below (for now).
+
+pl = c2ph.PL h2ph.PL h2xs.PL perlbug.PL perldoc.PL pl2pm.PL splain.PL perlcc.PL
+plextract = c2ph h2ph h2xs perlbug perldoc pl2pm splain perlcc
+plextractexe = c2ph.exe h2ph.exe h2xs.exe perlbug.exe perldoc.exe pl2pm.exe splain.exe perlcc.exe
+
+all: $(plextract)
+
+compile: all
+ $(REALPERL) -I../lib perlcc -regex 's/$$/.exe/' $(plextract) -prog -verbose dcf -log ../compilelog;
+
+$(plextract):
+ $(PERL) -I../lib $@.PL
+
+c2ph: c2ph.PL ../config.sh
+
+h2ph: h2ph.PL ../config.sh
+
+h2xs: h2xs.PL ../config.sh
+
+perlbug: perlbug.PL ../config.sh ../patchlevel.h
+
+perldoc: perldoc.PL ../config.sh
+
+pl2pm: pl2pm.PL ../config.sh
+
+splain: splain.PL ../config.sh ../lib/diagnostics.pm
+
+perlcc: perlcc.PL ../config.sh
+
+clean:
+
+realclean:
+ rm -rf $(plextract) pstruct $(plextractexe)
+
+clobber: realclean
+
+distclean: clobber
diff --git a/contrib/perl5/utils/c2ph.PL b/contrib/perl5/utils/c2ph.PL
new file mode 100644
index 0000000..38b259f
--- /dev/null
+++ b/contrib/perl5/utils/c2ph.PL
@@ -0,0 +1,1403 @@
+#!/usr/local/bin/perl
+
+use Config;
+use File::Basename qw(&basename &dirname);
+use Cwd;
+
+# List explicitly here the variables you want Configure to
+# generate. Metaconfig only looks for shell variables, so you
+# have to mention them as if they were shell variables, not
+# %Config entries. Thus you write
+# $startperl
+# to ensure Configure will look for $Config{startperl}.
+
+# This forces PL files to create target in same directory as PL file.
+# This is so that make depend always knows where to find PL derivatives.
+$origdir = cwd;
+chdir dirname($0);
+$file = basename($0, '.PL');
+$file .= '.com' if $^O eq 'VMS';
+
+open OUT,">$file" or die "Can't create $file: $!";
+
+print "Extracting $file (with variable substitutions)\n";
+
+# In this section, perl variables will be expanded during extraction.
+# You can use $Config{...} to use Configure variables.
+
+print OUT <<"!GROK!THIS!";
+$Config{startperl}
+ eval 'exec $Config{perlpath} -S \$0 \${1+"\$@"}'
+ if \$running_under_some_shell;
+!GROK!THIS!
+
+# In the following, perl variables are not expanded during extraction.
+
+print OUT <<'!NO!SUBS!';
+#
+#
+# c2ph (aka pstruct)
+# Tom Christiansen, <tchrist@convex.com>
+#
+# As pstruct, dump C structures as generated from 'cc -g -S' stabs.
+# As c2ph, do this PLUS generate perl code for getting at the structures.
+#
+# See the usage message for more. If this isn't enough, read the code.
+#
+
+=head1 NAME
+
+c2ph, pstruct - Dump C structures as generated from C<cc -g -S> stabs
+
+=head1 SYNOPSIS
+
+ c2ph [-dpnP] [var=val] [files ...]
+
+=head2 OPTIONS
+
+ Options:
+
+ -w wide; short for: type_width=45 member_width=35 offset_width=8
+ -x hex; short for: offset_fmt=x offset_width=08 size_fmt=x size_width=04
+
+ -n do not generate perl code (default when invoked as pstruct)
+ -p generate perl code (default when invoked as c2ph)
+ -v generate perl code, with C decls as comments
+
+ -i do NOT recompute sizes for intrinsic datatypes
+ -a dump information on intrinsics also
+
+ -t trace execution
+ -d spew reams of debugging output
+
+ -slist give comma-separated list a structures to dump
+
+=head1 DESCRIPTION
+
+The following is the old c2ph.doc documentation by Tom Christiansen
+<tchrist@perl.com>
+Date: 25 Jul 91 08:10:21 GMT
+
+Once upon a time, I wrote a program called pstruct. It was a perl
+program that tried to parse out C structures and display their member
+offsets for you. This was especially useful for people looking at
+binary dumps or poking around the kernel.
+
+Pstruct was not a pretty program. Neither was it particularly robust.
+The problem, you see, was that the C compiler was much better at parsing
+C than I could ever hope to be.
+
+So I got smart: I decided to be lazy and let the C compiler parse the C,
+which would spit out debugger stabs for me to read. These were much
+easier to parse. It's still not a pretty program, but at least it's more
+robust.
+
+Pstruct takes any .c or .h files, or preferably .s ones, since that's
+the format it is going to massage them into anyway, and spits out
+listings like this:
+
+ struct tty {
+ int tty.t_locker 000 4
+ int tty.t_mutex_index 004 4
+ struct tty * tty.t_tp_virt 008 4
+ struct clist tty.t_rawq 00c 20
+ int tty.t_rawq.c_cc 00c 4
+ int tty.t_rawq.c_cmax 010 4
+ int tty.t_rawq.c_cfx 014 4
+ int tty.t_rawq.c_clx 018 4
+ struct tty * tty.t_rawq.c_tp_cpu 01c 4
+ struct tty * tty.t_rawq.c_tp_iop 020 4
+ unsigned char * tty.t_rawq.c_buf_cpu 024 4
+ unsigned char * tty.t_rawq.c_buf_iop 028 4
+ struct clist tty.t_canq 02c 20
+ int tty.t_canq.c_cc 02c 4
+ int tty.t_canq.c_cmax 030 4
+ int tty.t_canq.c_cfx 034 4
+ int tty.t_canq.c_clx 038 4
+ struct tty * tty.t_canq.c_tp_cpu 03c 4
+ struct tty * tty.t_canq.c_tp_iop 040 4
+ unsigned char * tty.t_canq.c_buf_cpu 044 4
+ unsigned char * tty.t_canq.c_buf_iop 048 4
+ struct clist tty.t_outq 04c 20
+ int tty.t_outq.c_cc 04c 4
+ int tty.t_outq.c_cmax 050 4
+ int tty.t_outq.c_cfx 054 4
+ int tty.t_outq.c_clx 058 4
+ struct tty * tty.t_outq.c_tp_cpu 05c 4
+ struct tty * tty.t_outq.c_tp_iop 060 4
+ unsigned char * tty.t_outq.c_buf_cpu 064 4
+ unsigned char * tty.t_outq.c_buf_iop 068 4
+ (*int)() tty.t_oproc_cpu 06c 4
+ (*int)() tty.t_oproc_iop 070 4
+ (*int)() tty.t_stopproc_cpu 074 4
+ (*int)() tty.t_stopproc_iop 078 4
+ struct thread * tty.t_rsel 07c 4
+
+etc.
+
+
+Actually, this was generated by a particular set of options. You can control
+the formatting of each column, whether you prefer wide or fat, hex or decimal,
+leading zeroes or whatever.
+
+All you need to be able to use this is a C compiler than generates
+BSD/GCC-style stabs. The B<-g> option on native BSD compilers and GCC
+should get this for you.
+
+To learn more, just type a bogus option, like B<-\?>, and a long usage message
+will be provided. There are a fair number of possibilities.
+
+If you're only a C programmer, than this is the end of the message for you.
+You can quit right now, and if you care to, save off the source and run it
+when you feel like it. Or not.
+
+
+
+But if you're a perl programmer, then for you I have something much more
+wondrous than just a structure offset printer.
+
+You see, if you call pstruct by its other incybernation, c2ph, you have a code
+generator that translates C code into perl code! Well, structure and union
+declarations at least, but that's quite a bit.
+
+Prior to this point, anyone programming in perl who wanted to interact
+with C programs, like the kernel, was forced to guess the layouts of
+the C strutures, and then hardwire these into his program. Of course,
+when you took your wonderfully crafted program to a system where the
+sgtty structure was laid out differently, you program broke. Which is
+a shame.
+
+We've had Larry's h2ph translator, which helped, but that only works on
+cpp symbols, not real C, which was also very much needed. What I offer
+you is a symbolic way of getting at all the C structures. I've couched
+them in terms of packages and functions. Consider the following program:
+
+ #!/usr/local/bin/perl
+
+ require 'syscall.ph';
+ require 'sys/time.ph';
+ require 'sys/resource.ph';
+
+ $ru = "\0" x &rusage'sizeof();
+
+ syscall(&SYS_getrusage, &RUSAGE_SELF, $ru) && die "getrusage: $!";
+
+ @ru = unpack($t = &rusage'typedef(), $ru);
+
+ $utime = $ru[ &rusage'ru_utime + &timeval'tv_sec ]
+ + ($ru[ &rusage'ru_utime + &timeval'tv_usec ]) / 1e6;
+
+ $stime = $ru[ &rusage'ru_stime + &timeval'tv_sec ]
+ + ($ru[ &rusage'ru_stime + &timeval'tv_usec ]) / 1e6;
+
+ printf "you have used %8.3fs+%8.3fu seconds.\n", $utime, $stime;
+
+
+As you see, the name of the package is the name of the structure. Regular
+fields are just their own names. Plus the following accessor functions are
+provided for your convenience:
+
+ struct This takes no arguments, and is merely the number of first-level
+ elements in the structure. You would use this for indexing
+ into arrays of structures, perhaps like this
+
+
+ $usec = $u[ &user'u_utimer
+ + (&ITIMER_VIRTUAL * &itimerval'struct)
+ + &itimerval'it_value
+ + &timeval'tv_usec
+ ];
+
+ sizeof Returns the bytes in the structure, or the member if
+ you pass it an argument, such as
+
+ &rusage'sizeof(&rusage'ru_utime)
+
+ typedef This is the perl format definition for passing to pack and
+ unpack. If you ask for the typedef of a nothing, you get
+ the whole structure, otherwise you get that of the member
+ you ask for. Padding is taken care of, as is the magic to
+ guarantee that a union is unpacked into all its aliases.
+ Bitfields are not quite yet supported however.
+
+ offsetof This function is the byte offset into the array of that
+ member. You may wish to use this for indexing directly
+ into the packed structure with vec() if you're too lazy
+ to unpack it.
+
+ typeof Not to be confused with the typedef accessor function, this
+ one returns the C type of that field. This would allow
+ you to print out a nice structured pretty print of some
+ structure without knoning anything about it beforehand.
+ No args to this one is a noop. Someday I'll post such
+ a thing to dump out your u structure for you.
+
+
+The way I see this being used is like basically this:
+
+ % h2ph <some_include_file.h > /usr/lib/perl/tmp.ph
+ % c2ph some_include_file.h >> /usr/lib/perl/tmp.ph
+ % install
+
+It's a little tricker with c2ph because you have to get the includes right.
+I can't know this for your system, but it's not usually too terribly difficult.
+
+The code isn't pretty as I mentioned -- I never thought it would be a 1000-
+line program when I started, or I might not have begun. :-) But I would have
+been less cavalier in how the parts of the program communicated with each
+other, etc. It might also have helped if I didn't have to divine the makeup
+of the stabs on the fly, and then account for micro differences between my
+compiler and gcc.
+
+Anyway, here it is. Should run on perl v4 or greater. Maybe less.
+
+
+ --tom
+
+=cut
+
+$RCSID = '$Id: c2ph,v 1.7 95/10/28 10:41:47 tchrist Exp Locker: tchrist $';
+
+
+######################################################################
+
+# some handy data definitions. many of these can be reset later.
+
+$bitorder = 'b'; # ascending; set to B for descending bit fields
+
+%intrinsics =
+%template = (
+ 'char', 'c',
+ 'unsigned char', 'C',
+ 'short', 's',
+ 'short int', 's',
+ 'unsigned short', 'S',
+ 'unsigned short int', 'S',
+ 'short unsigned int', 'S',
+ 'int', 'i',
+ 'unsigned int', 'I',
+ 'long', 'l',
+ 'long int', 'l',
+ 'unsigned long', 'L',
+ 'unsigned long', 'L',
+ 'long unsigned int', 'L',
+ 'unsigned long int', 'L',
+ 'long long', 'q',
+ 'long long int', 'q',
+ 'unsigned long long', 'Q',
+ 'unsigned long long int', 'Q',
+ 'float', 'f',
+ 'double', 'd',
+ 'pointer', 'p',
+ 'null', 'x',
+ 'neganull', 'X',
+ 'bit', $bitorder,
+);
+
+&buildscrunchlist;
+delete $intrinsics{'neganull'};
+delete $intrinsics{'bit'};
+delete $intrinsics{'null'};
+
+# use -s to recompute sizes
+%sizeof = (
+ 'char', '1',
+ 'unsigned char', '1',
+ 'short', '2',
+ 'short int', '2',
+ 'unsigned short', '2',
+ 'unsigned short int', '2',
+ 'short unsigned int', '2',
+ 'int', '4',
+ 'unsigned int', '4',
+ 'long', '4',
+ 'long int', '4',
+ 'unsigned long', '4',
+ 'unsigned long int', '4',
+ 'long unsigned int', '4',
+ 'long long', '8',
+ 'long long int', '8',
+ 'unsigned long long', '8',
+ 'unsigned long long int', '8',
+ 'float', '4',
+ 'double', '8',
+ 'pointer', '4',
+);
+
+($type_width, $member_width, $offset_width, $size_width) = (20, 20, 6, 5);
+
+($offset_fmt, $size_fmt) = ('d', 'd');
+
+$indent = 2;
+
+$CC = 'cc';
+$CFLAGS = '-g -S';
+$DEFINES = '';
+
+$perl++ if $0 =~ m#/?c2ph$#;
+
+require 'getopts.pl';
+
+eval '$'.$1.'$2;' while $ARGV[0] =~ /^([A-Za-z_]+=)(.*)/ && shift;
+
+&Getopts('aixdpvtnws:') || &usage(0);
+
+$opt_d && $debug++;
+$opt_t && $trace++;
+$opt_p && $perl++;
+$opt_v && $verbose++;
+$opt_n && ($perl = 0);
+
+if ($opt_w) {
+ ($type_width, $member_width, $offset_width) = (45, 35, 8);
+}
+if ($opt_x) {
+ ($offset_fmt, $offset_width, $size_fmt, $size_width) = ( 'x', '08', 'x', 04 );
+}
+
+eval '$'.$1.'$2;' while $ARGV[0] =~ /^([A-Za-z_]+=)(.*)/ && shift;
+
+sub PLUMBER {
+ select(STDERR);
+ print "oops, apperent pager foulup\n";
+ $isatty++;
+ &usage(1);
+}
+
+sub usage {
+ local($oops) = @_;
+ unless (-t STDOUT) {
+ select(STDERR);
+ } elsif (!$oops) {
+ $isatty++;
+ $| = 1;
+ print "hit <RETURN> for further explanation: ";
+ <STDIN>;
+ open (PIPE, "|". ($ENV{PAGER} || 'more'));
+ $SIG{PIPE} = PLUMBER;
+ select(PIPE);
+ }
+
+ print "usage: $0 [-dpnP] [var=val] [files ...]\n";
+
+ exit unless $isatty;
+
+ print <<EOF;
+
+Options:
+
+-w wide; short for: type_width=45 member_width=35 offset_width=8
+-x hex; short for: offset_fmt=x offset_width=08 size_fmt=x size_width=04
+
+-n do not generate perl code (default when invoked as pstruct)
+-p generate perl code (default when invoked as c2ph)
+-v generate perl code, with C decls as comments
+
+-i do NOT recompute sizes for intrinsic datatypes
+-a dump information on intrinsics also
+
+-t trace execution
+-d spew reams of debugging output
+
+-slist give comma-separated list a structures to dump
+
+
+Var Name Default Value Meaning
+
+EOF
+
+ &defvar('CC', 'which_compiler to call');
+ &defvar('CFLAGS', 'how to generate *.s files with stabs');
+ &defvar('DEFINES','any extra cflags or cpp defines, like -I, -D, -U');
+
+ print "\n";
+
+ &defvar('type_width', 'width of type field (column 1)');
+ &defvar('member_width', 'width of member field (column 2)');
+ &defvar('offset_width', 'width of offset field (column 3)');
+ &defvar('size_width', 'width of size field (column 4)');
+
+ print "\n";
+
+ &defvar('offset_fmt', 'sprintf format type for offset');
+ &defvar('size_fmt', 'sprintf format type for size');
+
+ print "\n";
+
+ &defvar('indent', 'how far to indent each nesting level');
+
+ print <<'EOF';
+
+ If any *.[ch] files are given, these will be catted together into
+ a temporary *.c file and sent through:
+ $CC $CFLAGS $DEFINES
+ and the resulting *.s groped for stab information. If no files are
+ supplied, then stdin is read directly with the assumption that it
+ contains stab information. All other liens will be ignored. At
+ most one *.s file should be supplied.
+
+EOF
+ close PIPE;
+ exit 1;
+}
+
+sub defvar {
+ local($var, $msg) = @_;
+ printf "%-16s%-15s %s\n", $var, eval "\$$var", $msg;
+}
+
+$recurse = 1;
+
+if (@ARGV) {
+ if (grep(!/\.[csh]$/,@ARGV)) {
+ warn "Only *.[csh] files expected!\n";
+ &usage;
+ }
+ elsif (grep(/\.s$/,@ARGV)) {
+ if (@ARGV > 1) {
+ warn "Only one *.s file allowed!\n";
+ &usage;
+ }
+ }
+ elsif (@ARGV == 1 && $ARGV[0] =~ /\.c$/) {
+ local($dir, $file) = $ARGV[0] =~ m#(.*/)?(.*)$#;
+ $chdir = "cd $dir; " if $dir;
+ &system("$chdir$CC $CFLAGS $DEFINES $file") && exit 1;
+ $ARGV[0] =~ s/\.c$/.s/;
+ }
+ else {
+ $TMP = "/tmp/c2ph.$$.c";
+ &system("cat @ARGV > $TMP") && exit 1;
+ &system("cd /tmp; $CC $CFLAGS $DEFINES $TMP") && exit 1;
+ unlink $TMP;
+ $TMP =~ s/\.c$/.s/;
+ @ARGV = ($TMP);
+ }
+}
+
+if ($opt_s) {
+ for (split(/[\s,]+/, $opt_s)) {
+ $interested{$_}++;
+ }
+}
+
+
+$| = 1 if $debug;
+
+main: {
+
+ if ($trace) {
+ if (-t && !@ARGV) {
+ print STDERR "reading from your keyboard: ";
+ } else {
+ print STDERR "reading from " . (@ARGV ? "@ARGV" : "<STDIN>").": ";
+ }
+ }
+
+STAB: while (<>) {
+ if ($trace && !($. % 10)) {
+ $lineno = $..'';
+ print STDERR $lineno, "\b" x length($lineno);
+ }
+ next unless /^\s*\.stabs\s+/;
+ $line = $_;
+ s/^\s*\.stabs\s+//;
+ if (s/\\\\"[d,]+$//) {
+ $saveline .= $line;
+ $savebar = $_;
+ next STAB;
+ }
+ if ($saveline) {
+ s/^"//;
+ $_ = $savebar . $_;
+ $line = $saveline;
+ }
+ &stab;
+ $savebar = $saveline = undef;
+ }
+ print STDERR "$.\n" if $trace;
+ unlink $TMP if $TMP;
+
+ &compute_intrinsics if $perl && !$opt_i;
+
+ print STDERR "resolving types\n" if $trace;
+
+ &resolve_types;
+ &adjust_start_addrs;
+
+ $sum = 2 + $type_width + $member_width;
+ $pmask1 = "%-${type_width}s %-${member_width}s";
+ $pmask2 = "%-${sum}s %${offset_width}${offset_fmt}%s %${size_width}${size_fmt}%s";
+
+
+
+ if ($perl) {
+ # resolve template -- should be in stab define order, but even this isn't enough.
+ print STDERR "\nbuilding type templates: " if $trace;
+ for $i (reverse 0..$#type) {
+ next unless defined($name = $type[$i]);
+ next unless defined $struct{$name};
+ ($iname = $name) =~ s/\..*//;
+ $build_recursed = 0;
+ &build_template($name) unless defined $template{&psou($name)} ||
+ $opt_s && !$interested{$iname};
+ }
+ print STDERR "\n\n" if $trace;
+ }
+
+ print STDERR "dumping structs: " if $trace;
+
+ local($iam);
+
+
+
+ foreach $name (sort keys %struct) {
+ ($iname = $name) =~ s/\..*//;
+ next if $opt_s && !$interested{$iname};
+ print STDERR "$name " if $trace;
+
+ undef @sizeof;
+ undef @typedef;
+ undef @offsetof;
+ undef @indices;
+ undef @typeof;
+ undef @fieldnames;
+
+ $mname = &munge($name);
+
+ $fname = &psou($name);
+
+ print "# " if $perl && $verbose;
+ $pcode = '';
+ print "$fname {\n" if !$perl || $verbose;
+ $template{$fname} = &scrunch($template{$fname}) if $perl;
+ &pstruct($name,$name,0);
+ print "# " if $perl && $verbose;
+ print "}\n" if !$perl || $verbose;
+ print "\n" if $perl && $verbose;
+
+ if ($perl) {
+ print "$pcode";
+
+ printf("\nsub %-32s { %4d; }\n\n", "${mname}'struct", $countof{$name});
+
+ print <<EOF;
+sub ${mname}'typedef {
+ local(\$${mname}'index) = shift;
+ defined \$${mname}'index
+ ? \$${mname}'typedef[\$${mname}'index]
+ : \$${mname}'typedef;
+}
+EOF
+
+ print <<EOF;
+sub ${mname}'sizeof {
+ local(\$${mname}'index) = shift;
+ defined \$${mname}'index
+ ? \$${mname}'sizeof[\$${mname}'index]
+ : \$${mname}'sizeof;
+}
+EOF
+
+ print <<EOF;
+sub ${mname}'offsetof {
+ local(\$${mname}'index) = shift;
+ defined \$${mname}index
+ ? \$${mname}'offsetof[\$${mname}'index]
+ : \$${mname}'sizeof;
+}
+EOF
+
+ print <<EOF;
+sub ${mname}'typeof {
+ local(\$${mname}'index) = shift;
+ defined \$${mname}index
+ ? \$${mname}'typeof[\$${mname}'index]
+ : '$name';
+}
+EOF
+
+ print <<EOF;
+sub ${mname}'fieldnames {
+ \@${mname}'fieldnames;
+}
+EOF
+
+ $iam = ($isastruct{$name} && 's') || ($isaunion{$name} && 'u');
+
+ print <<EOF;
+sub ${mname}'isastruct {
+ '$iam';
+}
+EOF
+
+ print "\$${mname}'typedef = '" . &scrunch($template{$fname})
+ . "';\n";
+
+ print "\$${mname}'sizeof = $sizeof{$name};\n\n";
+
+
+ print "\@${mname}'indices = (", &squishseq(@indices), ");\n";
+
+ print "\n";
+
+ print "\@${mname}'typedef[\@${mname}'indices] = (",
+ join("\n\t", '', @typedef), "\n );\n\n";
+ print "\@${mname}'sizeof[\@${mname}'indices] = (",
+ join("\n\t", '', @sizeof), "\n );\n\n";
+ print "\@${mname}'offsetof[\@${mname}'indices] = (",
+ join("\n\t", '', @offsetof), "\n );\n\n";
+ print "\@${mname}'typeof[\@${mname}'indices] = (",
+ join("\n\t", '', @typeof), "\n );\n\n";
+ print "\@${mname}'fieldnames[\@${mname}'indices] = (",
+ join("\n\t", '', @fieldnames), "\n );\n\n";
+
+ $template_printed{$fname}++;
+ $size_printed{$fname}++;
+ }
+ print "\n";
+ }
+
+ print STDERR "\n" if $trace;
+
+ unless ($perl && $opt_a) {
+ print "\n1;\n" if $perl;
+ exit;
+ }
+
+
+
+ foreach $name (sort bysizevalue keys %intrinsics) {
+ next if $size_printed{$name};
+ print '$',&munge($name),"'sizeof = ", $sizeof{$name}, ";\n";
+ }
+
+ print "\n";
+
+ sub bysizevalue { $sizeof{$a} <=> $sizeof{$b}; }
+
+
+ foreach $name (sort keys %intrinsics) {
+ print '$',&munge($name),"'typedef = '", $template{$name}, "';\n";
+ }
+
+ print "\n1;\n" if $perl;
+
+ exit;
+}
+
+########################################################################################
+
+
+sub stab {
+ next unless $continued || /:[\$\w]+(\(\d+,\d+\))?=[\*\$\w]+/; # (\d+,\d+) is for sun
+ s/"// || next;
+ s/",([x\d]+),([x\d]+),([x\d]+),.*// || next;
+
+ next if /^\s*$/;
+
+ $size = $3 if $3;
+ $_ = $continued . $_ if length($continued);
+ if (s/\\\\$//) {
+ # if last 2 chars of string are '\\' then stab is continued
+ # in next stab entry
+ chop;
+ $continued = $_;
+ next;
+ }
+ $continued = '';
+
+
+ $line = $_;
+
+ if (($name, $pdecl) = /^([\$ \w]+):[tT]((\d+)(=[rufs*](\d+))+)$/) {
+ print "$name is a typedef for some funky pointers: $pdecl\n" if $debug;
+ &pdecl($pdecl);
+ next;
+ }
+
+
+
+ if (/(([ \w]+):t(\d+|\(\d+,\d+\)))=r?(\d+|\(\d+,\d+\))(;\d+;\d+;)?/) {
+ local($ident) = $2;
+ push(@intrinsics, $ident);
+ $typeno = &typeno($3);
+ $type[$typeno] = $ident;
+ print STDERR "intrinsic $ident in new type $typeno\n" if $debug;
+ next;
+ }
+
+ if (($name, $typeordef, $typeno, $extra, $struct, $_)
+ = /^([\$ \w]+):([ustT])(\d+|\(\d+,\d+\))(=[rufs*](\d+))?(.*)$/)
+ {
+ $typeno = &typeno($typeno); # sun foolery
+ }
+ elsif (/^[\$\w]+:/) {
+ next; # variable
+ }
+ else {
+ warn "can't grok stab: <$_> in: $line " if $_;
+ next;
+ }
+
+ #warn "got size $size for $name\n";
+ $sizeof{$name} = $size if $size;
+
+ s/;[-\d]*;[-\d]*;$//; # we don't care about ranges
+
+ $typenos{$name} = $typeno;
+
+ unless (defined $type[$typeno]) {
+ &panic("type 0??") unless $typeno;
+ $type[$typeno] = $name unless defined $type[$typeno];
+ printf "new type $typeno is $name" if $debug;
+ if ($extra =~ /\*/ && defined $type[$struct]) {
+ print ", a typedef for a pointer to " , $type[$struct] if $debug;
+ }
+ } else {
+ printf "%s is type %d", $name, $typeno if $debug;
+ print ", a typedef for " , $type[$typeno] if $debug;
+ }
+ print "\n" if $debug;
+ #next unless $extra =~ /[su*]/;
+
+ #$type[$struct] = $name;
+
+ if ($extra =~ /[us*]/) {
+ &sou($name, $extra);
+ $_ = &sdecl($name, $_, 0);
+ }
+ elsif (/^=ar/) {
+ print "it's a bare array typedef -- that's pretty sick\n" if $debug;
+ $_ = "$typeno$_";
+ $scripts = '';
+ $_ = &adecl($_,1);
+
+ }
+ elsif (s/((\w+):t(\d+|\(\d+,\d+\)))?=r?(;\d+;\d+;)?//) { # the ?'s are for gcc
+ push(@intrinsics, $2);
+ $typeno = &typeno($3);
+ $type[$typeno] = $2;
+ print STDERR "intrinsic $2 in new type $typeno\n" if $debug;
+ }
+ elsif (s/^=e//) { # blessed be thy compiler; mine won't do this
+ &edecl;
+ }
+ else {
+ warn "Funny remainder for $name on line $_ left in $line " if $_;
+ }
+}
+
+sub typeno { # sun thinks types are (0,27) instead of just 27
+ local($_) = @_;
+ s/\(\d+,(\d+)\)/$1/;
+ $_;
+}
+
+sub pstruct {
+ local($what,$prefix,$base) = @_;
+ local($field, $fieldname, $typeno, $count, $offset, $entry);
+ local($fieldtype);
+ local($type, $tname);
+ local($mytype, $mycount, $entry2);
+ local($struct_count) = 0;
+ local($pad, $revpad, $length, $prepad, $lastoffset, $lastlength, $fmt);
+ local($bits,$bytes);
+ local($template);
+
+
+ local($mname) = &munge($name);
+
+ sub munge {
+ local($_) = @_;
+ s/[\s\$\.]/_/g;
+ $_;
+ }
+
+ local($sname) = &psou($what);
+
+ $nesting++;
+
+ for $field (split(/;/, $struct{$what})) {
+ $pad = $prepad = 0;
+ $entry = '';
+ ($fieldname, $typeno, $count, $offset, $length) = split(/,/, $field);
+
+ $type = $type[$typeno];
+
+ $type =~ /([^[]*)(\[.*\])?/;
+ $mytype = $1;
+ $count .= $2;
+ $fieldtype = &psou($mytype);
+
+ local($fname) = &psou($name);
+
+ if ($build_templates) {
+
+ $pad = ($offset - ($lastoffset + $lastlength))/8
+ if defined $lastoffset;
+
+ if (! $finished_template{$sname}) {
+ if ($isaunion{$what}) {
+ $template{$sname} .= 'X' x $revpad . ' ' if $revpad;
+ } else {
+ $template{$sname} .= 'x' x $pad . ' ' if $pad;
+ }
+ }
+
+ $template = &fetch_template($type);
+ &repeat_template($template,$count);
+
+ if (! $finished_template{$sname}) {
+ $template{$sname} .= $template;
+ }
+
+ $revpad = $length/8 if $isaunion{$what};
+
+ ($lastoffset, $lastlength) = ($offset, $length);
+
+ } else {
+ print '# ' if $perl && $verbose;
+ $entry = sprintf($pmask1,
+ ' ' x ($nesting * $indent) . $fieldtype,
+ "$prefix.$fieldname" . $count);
+
+ $entry =~ s/(\*+)( )/$2$1/;
+
+ printf $pmask2,
+ $entry,
+ ($base+$offset)/8,
+ ($bits = ($base+$offset)%8) ? ".$bits" : " ",
+ $length/8,
+ ($bits = $length % 8) ? ".$bits": ""
+ if !$perl || $verbose;
+
+ if ($perl) {
+ $template = &fetch_template($type);
+ &repeat_template($template,$count);
+ }
+
+ if ($perl && $nesting == 1) {
+
+ push(@sizeof, int($length/8) .",\t# $fieldname");
+ push(@offsetof, int($offset/8) .",\t# $fieldname");
+ local($little) = &scrunch($template);
+ push(@typedef, "'$little', \t# $fieldname");
+ $type =~ s/(struct|union) //;
+ push(@typeof, "'$mytype" . ($count ? $count : '') .
+ "',\t# $fieldname");
+ push(@fieldnames, "'$fieldname',");
+ }
+
+ print ' ', ' ' x $indent x $nesting, $template
+ if $perl && $verbose;
+
+ print "\n" if !$perl || $verbose;
+
+ }
+ if ($perl) {
+ local($mycount) = defined $struct{$mytype} ? $countof{$mytype} : 1;
+ $mycount *= &scripts2count($count) if $count;
+ if ($nesting==1 && !$build_templates) {
+ $pcode .= sprintf("sub %-32s { %4d; }\n",
+ "${mname}'${fieldname}", $struct_count);
+ push(@indices, $struct_count);
+ }
+ $struct_count += $mycount;
+ }
+
+
+ &pstruct($type, "$prefix.$fieldname", $base+$offset)
+ if $recurse && defined $struct{$type};
+ }
+
+ $countof{$what} = $struct_count unless defined $countof{$whati};
+
+ $template{$sname} .= '$' if $build_templates;
+ $finished_template{$sname}++;
+
+ if ($build_templates && !defined $sizeof{$name}) {
+ local($fmt) = &scrunch($template{$sname});
+ print STDERR "no size for $name, punting with $fmt..." if $debug;
+ eval '$sizeof{$name} = length(pack($fmt, ()))';
+ if ($@) {
+ chop $@;
+ warn "couldn't get size for \$name: $@";
+ } else {
+ print STDERR $sizeof{$name}, "\n" if $debUg;
+ }
+ }
+
+ --$nesting;
+}
+
+
+sub psize {
+ local($me) = @_;
+ local($amstruct) = $struct{$me} ? 'struct ' : '';
+
+ print '$sizeof{\'', $amstruct, $me, '\'} = ';
+ printf "%d;\n", $sizeof{$me};
+}
+
+sub pdecl {
+ local($pdecl) = @_;
+ local(@pdecls);
+ local($tname);
+
+ warn "pdecl: $pdecl\n" if $debug;
+
+ $pdecl =~ s/\(\d+,(\d+)\)/$1/g;
+ $pdecl =~ s/\*//g;
+ @pdecls = split(/=/, $pdecl);
+ $typeno = $pdecls[0];
+ $tname = pop @pdecls;
+
+ if ($tname =~ s/^f//) { $tname = "$tname&"; }
+ #else { $tname = "$tname*"; }
+
+ for (reverse @pdecls) {
+ $tname .= s/^f// ? "&" : "*";
+ #$tname =~ s/^f(.*)/$1&/;
+ print "type[$_] is $tname\n" if $debug;
+ $type[$_] = $tname unless defined $type[$_];
+ }
+}
+
+
+
+sub adecl {
+ ($arraytype, $unknown, $lower, $upper) = ();
+ #local($typeno);
+ # global $typeno, @type
+ local($_, $typedef) = @_;
+
+ while (s/^((\d+|\(\d+,\d+\))=)?ar(\d+|\(\d+,\d+\));//) {
+ ($arraytype, $unknown) = ($2, $3);
+ $arraytype = &typeno($arraytype);
+ $unknown = &typeno($unknown);
+ if (s/^(\d+);(\d+);//) {
+ ($lower, $upper) = ($1, $2);
+ $scripts .= '[' . ($upper+1) . ']';
+ } else {
+ warn "can't find array bounds: $_";
+ }
+ }
+ if (s/^([(,)\d*f=]*),(\d+),(\d+);//) {
+ ($start, $length) = ($2, $3);
+ $whatis = $1;
+ if ($whatis =~ /^(\d+|\(\d+,\d+\))=/) {
+ $typeno = &typeno($1);
+ &pdecl($whatis);
+ } else {
+ $typeno = &typeno($whatis);
+ }
+ } elsif (s/^(\d+)(=[*suf]\d*)//) {
+ local($whatis) = $2;
+
+ if ($whatis =~ /[f*]/) {
+ &pdecl($whatis);
+ } elsif ($whatis =~ /[su]/) { #
+ print "$prefix.$fieldname is an array$scripts anon structs; disgusting\n"
+ if $debug;
+ #$type[$typeno] = $name unless defined $type[$typeno];
+ ##printf "new type $typeno is $name" if $debug;
+ $typeno = $1;
+ $type[$typeno] = "$prefix.$fieldname";
+ local($name) = $type[$typeno];
+ &sou($name, $whatis);
+ $_ = &sdecl($name, $_, $start+$offset);
+ 1;
+ $start = $start{$name};
+ $offset = $sizeof{$name};
+ $length = $offset;
+ } else {
+ warn "what's this? $whatis in $line ";
+ }
+ } elsif (/^\d+$/) {
+ $typeno = $_;
+ } else {
+ warn "bad array stab: $_ in $line ";
+ next STAB;
+ }
+ #local($wasdef) = defined($type[$typeno]) && $debug;
+ #if ($typedef) {
+ #print "redefining $type[$typeno] to " if $wasdef;
+ #$type[$typeno] = "$whatis$scripts"; # unless defined $type[$typeno];
+ #print "$type[$typeno]\n" if $wasdef;
+ #} else {
+ #$type[$arraytype] = $type[$typeno] unless defined $type[$arraytype];
+ #}
+ $type[$arraytype] = "$type[$typeno]$scripts" if defined $type[$typeno];
+ print "type[$arraytype] is $type[$arraytype]\n" if $debug;
+ print "$prefix.$fieldname is an array of $type[$arraytype]\n" if $debug;
+ $_;
+}
+
+
+
+sub sdecl {
+ local($prefix, $_, $offset) = @_;
+
+ local($fieldname, $scripts, $type, $arraytype, $unknown,
+ $whatis, $pdecl, $upper,$lower, $start,$length) = ();
+ local($typeno,$sou);
+
+
+SFIELD:
+ while (/^([^;]+);/) {
+ $scripts = '';
+ warn "sdecl $_\n" if $debug;
+ if (s/^([\$\w]+)://) {
+ $fieldname = $1;
+ } elsif (s/(\d+)=([us])(\d+|\(\d+,\d+\))//) { #
+ $typeno = &typeno($1);
+ $type[$typeno] = "$prefix.$fieldname";
+ local($name) = "$prefix.$fieldname";
+ &sou($name,$2);
+ $_ = &sdecl("$prefix.$fieldname", $_, $start+$offset);
+ $start = $start{$name};
+ $offset += $sizeof{$name};
+ #print "done with anon, start is $start, offset is $offset\n";
+ #next SFIELD;
+ } else {
+ warn "weird field $_ of $line" if $debug;
+ next STAB;
+ #$fieldname = &gensym;
+ #$_ = &sdecl("$prefix.$fieldname", $_, $start+$offset);
+ }
+
+ if (/^(\d+|\(\d+,\d+\))=ar/) {
+ $_ = &adecl($_);
+ }
+ elsif (s/^(\d+|\(\d+,\d+\))?,(\d+),(\d+);//) {
+ ($start, $length) = ($2, $3);
+ &panic("no length?") unless $length;
+ $typeno = &typeno($1) if $1;
+ }
+ elsif (s/^(\d+)=xs\w+:,(\d+),(\d+);//) {
+ ($start, $length) = ($2, $3);
+ &panic("no length?") unless $length;
+ $typeno = &typeno($1) if $1;
+ }
+ elsif (s/^((\d+|\(\d+,\d+\))(=[*f](\d+|\(\d+,\d+\)))+),(\d+),(\d+);//) {
+ ($pdecl, $start, $length) = ($1,$5,$6);
+ &pdecl($pdecl);
+ }
+ elsif (s/(\d+)=([us])(\d+|\(\d+,\d+\))//) { # the dratted anon struct
+ ($typeno, $sou) = ($1, $2);
+ $typeno = &typeno($typeno);
+ if (defined($type[$typeno])) {
+ warn "now how did we get type $1 in $fieldname of $line?";
+ } else {
+ print "anon type $typeno is $prefix.$fieldname\n" if $debug;
+ $type[$typeno] = "$prefix.$fieldname" unless defined $type[$typeno];
+ };
+ local($name) = "$prefix.$fieldname";
+ &sou($name,$sou);
+ print "anon ".($isastruct{$name}) ? "struct":"union"." for $prefix.$fieldname\n" if $debug;
+ $type[$typeno] = "$prefix.$fieldname";
+ $_ = &sdecl("$prefix.$fieldname", $_, $start+$offset);
+ $start = $start{$name};
+ $length = $sizeof{$name};
+ }
+ else {
+ warn "can't grok stab for $name ($_) in line $line ";
+ next STAB;
+ }
+
+ &panic("no length for $prefix.$fieldname") unless $length;
+ $struct{$name} .= join(',', $fieldname, $typeno, $scripts, $start, $length) . ';';
+ }
+ if (s/;\d*,(\d+),(\d+);//) {
+ local($start, $size) = ($1, $2);
+ $sizeof{$prefix} = $size;
+ print "start of $prefix is $start, size of $sizeof{$prefix}\n" if $debug;
+ $start{$prefix} = $start;
+ }
+ $_;
+}
+
+sub edecl {
+ s/;$//;
+ $enum{$name} = $_;
+ $_ = '';
+}
+
+sub resolve_types {
+ local($sou);
+ for $i (0 .. $#type) {
+ next unless defined $type[$i];
+ $_ = $type[$i];
+ unless (/\d/) {
+ print "type[$i] $type[$i]\n" if $debug;
+ next;
+ }
+ print "type[$i] $_ ==> " if $debug;
+ s/^(\d+)(\**)\&\*(\**)/"$2($3".&type($1) . ')()'/e;
+ s/^(\d+)\&/&type($1)/e;
+ s/^(\d+)/&type($1)/e;
+ s/(\*+)([^*]+)(\*+)/$1$3$2/;
+ s/\((\*+)(\w+)(\*+)\)/$3($1$2)/;
+ s/^(\d+)([\*\[].*)/&type($1).$2/e;
+ #s/(\d+)(\*|(\[[\[\]\d\*]+]\])+)/&type($1).$2/ge;
+ $type[$i] = $_;
+ print "$_\n" if $debug;
+ }
+}
+sub type { &psou($type[$_[0]] || "<UNDEFINED>"); }
+
+sub adjust_start_addrs {
+ for (sort keys %start) {
+ ($basename = $_) =~ s/\.[^.]+$//;
+ $start{$_} += $start{$basename};
+ print "start: $_ @ $start{$_}\n" if $debug;
+ }
+}
+
+sub sou {
+ local($what, $_) = @_;
+ /u/ && $isaunion{$what}++;
+ /s/ && $isastruct{$what}++;
+}
+
+sub psou {
+ local($what) = @_;
+ local($prefix) = '';
+ if ($isaunion{$what}) {
+ $prefix = 'union ';
+ } elsif ($isastruct{$what}) {
+ $prefix = 'struct ';
+ }
+ $prefix . $what;
+}
+
+sub scrunch {
+ local($_) = @_;
+
+ return '' if $_ eq '';
+
+ study;
+
+ s/\$//g;
+ s/ / /g;
+ 1 while s/(\w) \1/$1$1/g;
+
+ # i wanna say this, but perl resists my efforts:
+ # s/(\w)(\1+)/$2 . length($1)/ge;
+
+ &quick_scrunch;
+
+ s/ $//;
+
+ $_;
+}
+
+sub buildscrunchlist {
+ $scrunch_code = "sub quick_scrunch {\n";
+ for (values %intrinsics) {
+ $scrunch_code .= "\ts/(${_}{2,})/'$_' . length(\$1)/ge;\n";
+ }
+ $scrunch_code .= "}\n";
+ print "$scrunch_code" if $debug;
+ eval $scrunch_code;
+ &panic("can't eval scrunch_code $@ \nscrunch_code") if $@;
+}
+
+sub fetch_template {
+ local($mytype) = @_;
+ local($fmt);
+ local($count) = 1;
+
+ &panic("why do you care?") unless $perl;
+
+ if ($mytype =~ s/(\[\d+\])+$//) {
+ $count .= $1;
+ }
+
+ if ($mytype =~ /\*/) {
+ $fmt = $template{'pointer'};
+ }
+ elsif (defined $template{$mytype}) {
+ $fmt = $template{$mytype};
+ }
+ elsif (defined $struct{$mytype}) {
+ if (!defined $template{&psou($mytype)}) {
+ &build_template($mytype) unless $mytype eq $name;
+ }
+ elsif ($template{&psou($mytype)} !~ /\$$/) {
+ #warn "incomplete template for $mytype\n";
+ }
+ $fmt = $template{&psou($mytype)} || '?';
+ }
+ else {
+ warn "unknown fmt for $mytype\n";
+ $fmt = '?';
+ }
+
+ $fmt x $count . ' ';
+}
+
+sub compute_intrinsics {
+ local($TMP) = "/tmp/c2ph-i.$$.c";
+ open (TMP, ">$TMP") || die "can't open $TMP: $!";
+ select(TMP);
+
+ print STDERR "computing intrinsic sizes: " if $trace;
+
+ undef %intrinsics;
+
+ print <<'EOF';
+main() {
+ char *mask = "%d %s\n";
+EOF
+
+ for $type (@intrinsics) {
+ next if !$type || $type eq 'void' || $type =~ /complex/; # sun stuff
+ print <<"EOF";
+ printf(mask,sizeof($type), "$type");
+EOF
+ }
+
+ print <<'EOF';
+ printf(mask,sizeof(char *), "pointer");
+ exit(0);
+}
+EOF
+ close TMP;
+
+ select(STDOUT);
+ open(PIPE, "cd /tmp && $CC $TMP && /tmp/a.out|");
+ while (<PIPE>) {
+ chop;
+ split(' ',$_,2);;
+ print "intrinsic $_[1] is size $_[0]\n" if $debug;
+ $sizeof{$_[1]} = $_[0];
+ $intrinsics{$_[1]} = $template{$_[0]};
+ }
+ close(PIPE) || die "couldn't read intrinsics!";
+ unlink($TMP, '/tmp/a.out');
+ print STDERR "done\n" if $trace;
+}
+
+sub scripts2count {
+ local($_) = @_;
+
+ s/^\[//;
+ s/\]$//;
+ s/\]\[/*/g;
+ $_ = eval;
+ &panic("$_: $@") if $@;
+ $_;
+}
+
+sub system {
+ print STDERR "@_\n" if $trace;
+ system @_;
+}
+
+sub build_template {
+ local($name) = @_;
+
+ &panic("already got a template for $name") if defined $template{$name};
+
+ local($build_templates) = 1;
+
+ local($lparen) = '(' x $build_recursed;
+ local($rparen) = ')' x $build_recursed;
+
+ print STDERR "$lparen$name$rparen " if $trace;
+ $build_recursed++;
+ &pstruct($name,$name,0);
+ print STDERR "TEMPLATE for $name is ", $template{&psou($name)}, "\n" if $debug;
+ --$build_recursed;
+}
+
+
+sub panic {
+
+ select(STDERR);
+
+ print "\npanic: @_\n";
+
+ exit 1 if $] <= 4.003; # caller broken
+
+ local($i,$_);
+ local($p,$f,$l,$s,$h,$a,@a,@sub);
+ for ($i = 0; ($p,$f,$l,$s,$h,$w) = caller($i); $i++) {
+ @a = @DB'args;
+ for (@a) {
+ if (/^StB\000/ && length($_) == length($_main{'_main'})) {
+ $_ = sprintf("%s",$_);
+ }
+ else {
+ s/'/\\'/g;
+ s/([^\0]*)/'$1'/ unless /^-?[\d.]+$/;
+ s/([\200-\377])/sprintf("M-%c",ord($1)&0177)/eg;
+ s/([\0-\37\177])/sprintf("^%c",ord($1)^64)/eg;
+ }
+ }
+ $w = $w ? '@ = ' : '$ = ';
+ $a = $h ? '(' . join(', ', @a) . ')' : '';
+ push(@sub, "$w&$s$a from file $f line $l\n");
+ last if $signal;
+ }
+ for ($i=0; $i <= $#sub; $i++) {
+ last if $signal;
+ print $sub[$i];
+ }
+ exit 1;
+}
+
+sub squishseq {
+ local($num);
+ local($last) = -1e8;
+ local($string);
+ local($seq) = '..';
+
+ while (defined($num = shift)) {
+ if ($num == ($last + 1)) {
+ $string .= $seq unless $inseq++;
+ $last = $num;
+ next;
+ } elsif ($inseq) {
+ $string .= $last unless $last == -1e8;
+ }
+
+ $string .= ',' if defined $string;
+ $string .= $num;
+ $last = $num;
+ $inseq = 0;
+ }
+ $string .= $last if $inseq && $last != -e18;
+ $string;
+}
+
+sub repeat_template {
+ # local($template, $scripts) = @_; have to change caller's values
+
+ if ( $_[1] ) {
+ local($ncount) = &scripts2count($_[1]);
+ if ($_[0] =~ /^\s*c\s*$/i) {
+ $_[0] = "A$ncount ";
+ $_[1] = '';
+ } else {
+ $_[0] = $template x $ncount;
+ }
+ }
+}
+!NO!SUBS!
+
+close OUT or die "Can't close $file: $!";
+chmod 0755, $file or die "Can't reset permissions for $file: $!\n";
+unlink 'pstruct';
+print "Linking c2ph to pstruct.\n";
+if (defined $Config{d_link}) {
+ link 'c2ph', 'pstruct';
+} else {
+ unshift @INC, '../lib';
+ require File::Copy;
+ File::Copy::syscopy('c2ph', 'pstruct');
+}
+exec("$Config{'eunicefix'} $file") if $Config{'eunicefix'} ne ':';
+chdir $origdir;
diff --git a/contrib/perl5/utils/h2ph.PL b/contrib/perl5/utils/h2ph.PL
new file mode 100644
index 0000000..066f2c9
--- /dev/null
+++ b/contrib/perl5/utils/h2ph.PL
@@ -0,0 +1,636 @@
+#!/usr/local/bin/perl
+
+use Config;
+use File::Basename qw(basename dirname);
+use Cwd;
+
+# List explicitly here the variables you want Configure to
+# generate. Metaconfig only looks for shell variables, so you
+# have to mention them as if they were shell variables, not
+# %Config entries. Thus you write
+# $startperl
+# to ensure Configure will look for $Config{startperl}.
+# Wanted: $archlibexp
+
+# This forces PL files to create target in same directory as PL file.
+# This is so that make depend always knows where to find PL derivatives.
+$origdir = cwd;
+chdir dirname($0);
+$file = basename($0, '.PL');
+$file .= '.com' if $^O eq 'VMS';
+
+open OUT,">$file" or die "Can't create $file: $!";
+
+print "Extracting $file (with variable substitutions)\n";
+
+# In this section, perl variables will be expanded during extraction.
+# You can use $Config{...} to use Configure variables.
+
+print OUT <<"!GROK!THIS!";
+$Config{startperl}
+ eval 'exec $Config{perlpath} -S \$0 \${1+"\$@"}'
+ if \$running_under_some_shell;
+!GROK!THIS!
+
+# In the following, perl variables are not expanded during extraction.
+
+print OUT <<'!NO!SUBS!';
+
+use Config;
+use File::Path qw(mkpath);
+use Getopt::Std;
+
+getopts('Dd:rlhaQ');
+die "-r and -a options are mutually exclusive\n" if ($opt_r and $opt_a);
+@inc_dirs = inc_dirs() if $opt_a;
+
+my $Exit = 0;
+
+my $Dest_dir = $opt_d || $Config{installsitearch};
+die "Destination directory $Dest_dir doesn't exist or isn't a directory\n"
+ unless -d $Dest_dir;
+
+@isatype = split(' ',<<END);
+ char uchar u_char
+ short ushort u_short
+ int uint u_int
+ long ulong u_long
+ FILE key_t caddr_t
+END
+
+@isatype{@isatype} = (1) x @isatype;
+$inif = 0;
+
+@ARGV = ('-') unless @ARGV;
+
+while (defined ($file = next_file())) {
+ if (-l $file and -d $file) {
+ link_if_possible($file) if ($opt_l);
+ next;
+ }
+
+ # Recover from header files with unbalanced cpp directives
+ $t = '';
+ $tab = 0;
+
+ # $eval_index goes into ``#line'' directives, to help locate syntax errors:
+ $eval_index = 1;
+
+ if ($file eq '-') {
+ open(IN, "-");
+ open(OUT, ">-");
+ } else {
+ ($outfile = $file) =~ s/\.h$/.ph/ || next;
+ print "$file -> $outfile\n" unless $opt_Q;
+ if ($file =~ m|^(.*)/|) {
+ $dir = $1;
+ mkpath "$Dest_dir/$dir";
+ }
+
+ if ($opt_a) { # automagic mode: locate header file in @inc_dirs
+ foreach (@inc_dirs) {
+ chdir $_;
+ last if -f $file;
+ }
+ }
+
+ open(IN,"$file") || (($Exit = 1),(warn "Can't open $file: $!\n"),next);
+ open(OUT,">$Dest_dir/$outfile") || die "Can't create $outfile: $!\n";
+ }
+ while (<IN>) {
+ chop;
+ while (/\\$/) {
+ chop;
+ $_ .= <IN>;
+ chop;
+ }
+ print OUT "# $_\n" if $opt_D;
+ if (s:/\*:\200:g) {
+ s:\*/:\201:g;
+ s/\200[^\201]*\201//g; # delete single line comments
+ if (s/\200.*//) { # begin multi-line comment?
+ $_ .= '/*';
+ $_ .= <IN>;
+ redo;
+ }
+ }
+ if (s/^\s*\#\s*//) {
+ if (s/^define\s+(\w+)//) {
+ $name = $1;
+ $new = '';
+ s/\s+$//;
+ if (s/^\(([\w,\s]*)\)//) {
+ $args = $1;
+ my $proto = '() ';
+ if ($args ne '') {
+ $proto = '';
+ foreach $arg (split(/,\s*/,$args)) {
+ $arg =~ s/^\s*([^\s].*[^\s])\s*$/$1/;
+ $curargs{$arg} = 1;
+ }
+ $args =~ s/\b(\w)/\$$1/g;
+ $args = "local($args) = \@_;\n$t ";
+ }
+ s/^\s+//;
+ expr();
+ $new =~ s/(["\\])/\\$1/g; #"]);
+ $new = reindent($new);
+ $args = reindent($args);
+ if ($t ne '') {
+ $new =~ s/(['\\])/\\$1/g; #']);
+ if ($opt_h) {
+ print OUT $t,
+ "eval \"\\n#line $eval_index $outfile\\n\" . 'sub $name $proto\{\n$t ${args}eval q($new);\n$t}' unless defined(\&$name);\n";
+ $eval_index++;
+ } else {
+ print OUT $t,
+ "eval 'sub $name $proto\{\n$t ${args}eval q($new);\n$t}' unless defined(\&$name);\n";
+ }
+ } else {
+ print OUT "unless(defined(\&$name)) {\n sub $name $proto\{\n\t${args}eval q($new);\n }\n}\n";
+ }
+ %curargs = ();
+ } else {
+ s/^\s+//;
+ expr();
+ $new = 1 if $new eq '';
+ $new = reindent($new);
+ $args = reindent($args);
+ if ($t ne '') {
+ $new =~ s/(['\\])/\\$1/g; #']);
+ if ($opt_h) {
+ print OUT $t,"eval \"\\n#line $eval_index $outfile\\n\" . 'sub $name () {",$new,";}' unless defined(\&$name);\n";
+ $eval_index++;
+ } else {
+ print OUT $t,"eval 'sub $name () {",$new,";}' unless defined(\&$name);\n";
+ }
+ } else {
+ print OUT $t,"unless(defined(\&$name)) {\n sub $name () {\t",$new,";}\n}\n";
+ }
+ }
+ } elsif (/^(include|import)\s*[<"](.*)[>"]/) {
+ ($incl = $2) =~ s/\.h$/.ph/;
+ print OUT $t,"require '$incl';\n";
+ } elsif(/^include_next\s*[<"](.*)[>"]/) {
+ ($incl = $1) =~ s/\.h$/.ph/;
+ print OUT ($t,
+ "eval {\n");
+ $tab += 4;
+ $t = "\t" x ($tab / 8) . ' ' x ($tab % 8);
+ print OUT ($t,
+ "my(\%INCD) = map { \$INC{\$_} => 1 } ",
+ "(grep { \$_ eq \"$incl\" } keys(\%INC));\n");
+ print OUT ($t,
+ "my(\@REM) = map { \"\$_/$incl\" } ",
+ "(grep { not exists(\$INCD{\"\$_/$incl\"})",
+ "and -f \"\$_/$incl\" } \@INC);\n");
+ print OUT ($t,
+ "require \"\$REM[0]\" if \@REM;\n");
+ $tab -= 4;
+ $t = "\t" x ($tab / 8) . ' ' x ($tab % 8);
+ print OUT ($t,
+ "};\n");
+ print OUT ($t,
+ "warn(\$\@) if \$\@;\n");
+ } elsif (/^ifdef\s+(\w+)/) {
+ print OUT $t,"if(defined(&$1)) {\n";
+ $tab += 4;
+ $t = "\t" x ($tab / 8) . ' ' x ($tab % 8);
+ } elsif (/^ifndef\s+(\w+)/) {
+ print OUT $t,"unless(defined(&$1)) {\n";
+ $tab += 4;
+ $t = "\t" x ($tab / 8) . ' ' x ($tab % 8);
+ } elsif (s/^if\s+//) {
+ $new = '';
+ $inif = 1;
+ expr();
+ $inif = 0;
+ print OUT $t,"if($new) {\n";
+ $tab += 4;
+ $t = "\t" x ($tab / 8) . ' ' x ($tab % 8);
+ } elsif (s/^elif\s+//) {
+ $new = '';
+ $inif = 1;
+ expr();
+ $inif = 0;
+ $tab -= 4;
+ $t = "\t" x ($tab / 8) . ' ' x ($tab % 8);
+ print OUT $t,"}\n elsif($new) {\n";
+ $tab += 4;
+ $t = "\t" x ($tab / 8) . ' ' x ($tab % 8);
+ } elsif (/^else/) {
+ $tab -= 4;
+ $t = "\t" x ($tab / 8) . ' ' x ($tab % 8);
+ print OUT $t,"} else {\n";
+ $tab += 4;
+ $t = "\t" x ($tab / 8) . ' ' x ($tab % 8);
+ } elsif (/^endif/) {
+ $tab -= 4;
+ $t = "\t" x ($tab / 8) . ' ' x ($tab % 8);
+ print OUT $t,"}\n";
+ } elsif(/^undef\s+(\w+)/) {
+ print OUT $t, "undef(&$1) if defined(&$1);\n";
+ } elsif(/^error\s+(.*)/) {
+ print OUT $t, "die(\"$1\");\n";
+ } elsif(/^warning\s+(.*)/) {
+ print OUT $t, "warn(\"$1\");\n";
+ } elsif(/^ident\s+(.*)/) {
+ print OUT $t, "# $1\n";
+ }
+ } elsif(/^\s*(typedef\s*)?enum\s*(\s+[a-zA-Z_]\w*\s*)?\{/) {
+ until(/\}.*?;/) {
+ chomp($next = <IN>);
+ $_ .= $next;
+ print OUT "# $next\n" if $opt_D;
+ }
+ s@/\*.*?\*/@@g;
+ s/\s+/ /g;
+ /^\s?(typedef\s?)?enum\s?([a-zA-Z_]\w*)?\s?\{(.*)\}\s?([a-zA-Z_]\w*)?\s?;/;
+ ($enum_subs = $3) =~ s/\s//g;
+ @enum_subs = split(/,/, $enum_subs);
+ $enum_val = -1;
+ for $enum (@enum_subs) {
+ ($enum_name, $enum_value) = $enum =~ /^([a-zA-Z_]\w*)(=.+)?$/;
+ $enum_value =~ s/^=//;
+ $enum_val = (length($enum_value) ? $enum_value : $enum_val + 1);
+ if ($opt_h) {
+ print OUT ($t,
+ "eval(\"\\n#line $eval_index $outfile\\n",
+ "sub $enum_name () \{ $enum_val; \}\") ",
+ "unless defined(\&$enum_name);\n");
+ ++ $eval_index;
+ } else {
+ print OUT ($t,
+ "eval(\"sub $enum_name () \{ $enum_val; \}\") ",
+ "unless defined(\&$enum_name);\n");
+ }
+ }
+ }
+ }
+ print OUT "1;\n";
+
+ $is_converted{$file} = 1;
+ queue_includes_from($file) if ($opt_a);
+}
+
+exit $Exit;
+
+sub reindent($) {
+ my($text) = shift;
+ $text =~ s/\n/\n /g;
+ $text =~ s/ /\t/g;
+ $text;
+}
+
+sub expr {
+ if(keys(%curargs)) {
+ my($joined_args) = join('|', keys(%curargs));
+ }
+ while ($_ ne '') {
+ s/^\&\&// && do { $new .= " &&"; next;}; # handle && operator
+ s/^\&([\(a-z\)]+)/$1/i; # hack for things that take the address of
+ s/^(\s+)// && do {$new .= ' '; next;};
+ s/^(0X[0-9A-F]+)[UL]*//i && do {$new .= lc($1); next;};
+ s/^(-?\d+\.\d+E[-+]\d+)F?//i && do {$new .= $1; next;};
+ s/^(\d+)\s*[LU]*//i && do {$new .= $1; next;};
+ s/^("(\\"|[^"])*")// && do {$new .= $1; next;};
+ s/^'((\\"|[^"])*)'// && do {
+ if ($curargs{$1}) {
+ $new .= "ord('\$$1')";
+ } else {
+ $new .= "ord('$1')";
+ }
+ next;
+ };
+ # replace "sizeof(foo)" with "{foo}"
+ # also, remove * (C dereference operator) to avoid perl syntax
+ # problems. Where the %sizeof array comes from is anyone's
+ # guess (c2ph?), but this at least avoids fatal syntax errors.
+ # Behavior is undefined if sizeof() delimiters are unbalanced.
+ # This code was modified to able to handle constructs like this:
+ # sizeof(*(p)), which appear in the HP-UX 10.01 header files.
+ s/^sizeof\s*\(// && do {
+ $new .= '$sizeof';
+ my $lvl = 1; # already saw one open paren
+ # tack { on the front, and skip it in the loop
+ $_ = "{" . "$_";
+ my $index = 1;
+ # find balanced closing paren
+ while ($index <= length($_) && $lvl > 0) {
+ $lvl++ if substr($_, $index, 1) eq "(";
+ $lvl-- if substr($_, $index, 1) eq ")";
+ $index++;
+ }
+ # tack } on the end, replacing )
+ substr($_, $index - 1, 1) = "}";
+ # remove pesky * operators within the sizeof argument
+ substr($_, 0, $index - 1) =~ s/\*//g;
+ next;
+ };
+ # Eliminate typedefs
+ /\(([\w\s]+)[\*\s]*\)\s*[\w\(]/ && do {
+ foreach (split /\s+/, $1) { # Make sure all the words are types,
+ last unless ($isatype{$_} or $_ eq 'struct');
+ }
+ s/\([\w\s]+[\*\s]*\)// && next; # then eliminate them.
+ };
+ # struct/union member, including arrays:
+ s/^([_A-Z]\w*(\[[^\]]+\])?((\.|->)[_A-Z]\w*(\[[^\]]+\])?)+)//i && do {
+ $id = $1;
+ $id =~ s/(\.|(->))([^\.\-]*)/->\{$3\}/g;
+ $id =~ s/\b([^\$])($joined_args)/$1\$$2/g if length($joined_args);
+ while($id =~ /\[\s*([^\$\&\d\]]+)\]/) {
+ my($index) = $1;
+ $index =~ s/\s//g;
+ if(exists($curargs{$index})) {
+ $index = "\$$index";
+ } else {
+ $index = "&$index";
+ }
+ $id =~ s/\[\s*([^\$\&\d\]]+)\]/[$index]/;
+ }
+ $new .= " (\$$id)";
+ };
+ s/^([_a-zA-Z]\w*)// && do {
+ $id = $1;
+ if ($id eq 'struct') {
+ s/^\s+(\w+)//;
+ $id .= ' ' . $1;
+ $isatype{$id} = 1;
+ } elsif ($id =~ /^((un)?signed)|(long)|(short)$/) {
+ while (s/^\s+(\w+)//) { $id .= ' ' . $1; }
+ $isatype{$id} = 1;
+ }
+ if ($curargs{$id}) {
+ $new .= "\$$id";
+ $new .= '->' if /^[\[\{]/;
+ } elsif ($id eq 'defined') {
+ $new .= 'defined';
+ } elsif (/^\(/) {
+ s/^\((\w),/("$1",/ if $id =~ /^_IO[WR]*$/i; # cheat
+ $new .= " &$id";
+ } elsif ($isatype{$id}) {
+ if ($new =~ /{\s*$/) {
+ $new .= "'$id'";
+ } elsif ($new =~ /\(\s*$/ && /^[\s*]*\)/) {
+ $new =~ s/\(\s*$//;
+ s/^[\s*]*\)//;
+ } else {
+ $new .= q(').$id.q(');
+ }
+ } else {
+ if ($inif && $new !~ /defined\s*\($/) {
+ $new .= '(defined(&' . $id . ') ? &' . $id . ' : 0)';
+ } elsif (/^\[/) {
+ $new .= " \$$id";
+ } else {
+ $new .= ' &' . $id;
+ }
+ }
+ next;
+ };
+ s/^(.)// && do { if ($1 ne '#') { $new .= $1; } next;};
+ }
+}
+
+
+# Handle recursive subdirectories without getting a grotesquely big stack.
+# Could this be implemented using File::Find?
+sub next_file
+{
+ my $file;
+
+ while (@ARGV) {
+ $file = shift @ARGV;
+
+ if ($file eq '-' or -f $file or -l $file) {
+ return $file;
+ } elsif (-d $file) {
+ if ($opt_r) {
+ expand_glob($file);
+ } else {
+ print STDERR "Skipping directory `$file'\n";
+ }
+ } elsif ($opt_a) {
+ return $file;
+ } else {
+ print STDERR "Skipping `$file': not a file or directory\n";
+ }
+ }
+
+ return undef;
+}
+
+
+# Put all the files in $directory into @ARGV for processing.
+sub expand_glob
+{
+ my ($directory) = @_;
+
+ $directory =~ s:/$::;
+
+ opendir DIR, $directory;
+ foreach (readdir DIR) {
+ next if ($_ eq '.' or $_ eq '..');
+
+ # expand_glob() is going to be called until $ARGV[0] isn't a
+ # directory; so push directories, and unshift everything else.
+ if (-d "$directory/$_") { push @ARGV, "$directory/$_" }
+ else { unshift @ARGV, "$directory/$_" }
+ }
+ closedir DIR;
+}
+
+
+# Given $file, a symbolic link to a directory in the C include directory,
+# make an equivalent symbolic link in $Dest_dir, if we can figure out how.
+# Otherwise, just duplicate the file or directory.
+sub link_if_possible
+{
+ my ($dirlink) = @_;
+ my $target = eval 'readlink($dirlink)';
+
+ if ($target =~ m:^\.\./: or $target =~ m:^/:) {
+ # The target of a parent or absolute link could leave the $Dest_dir
+ # hierarchy, so let's put all of the contents of $dirlink (actually,
+ # the contents of $target) into @ARGV; as a side effect down the
+ # line, $dirlink will get created as an _actual_ directory.
+ expand_glob($dirlink);
+ } else {
+ if (-l "$Dest_dir/$dirlink") {
+ unlink "$Dest_dir/$dirlink" or
+ print STDERR "Could not remove link $Dest_dir/$dirlink: $!\n";
+ }
+
+ if (eval 'symlink($target, "$Dest_dir/$dirlink")') {
+ print "Linking $target -> $Dest_dir/$dirlink\n";
+
+ # Make sure that the link _links_ to something:
+ if (! -e "$Dest_dir/$target") {
+ mkpath("$Dest_dir/$target", 0755) or
+ print STDERR "Could not create $Dest_dir/$target/\n";
+ }
+ } else {
+ print STDERR "Could not symlink $target -> $Dest_dir/$dirlink: $!\n";
+ }
+ }
+}
+
+
+# Push all #included files in $file onto our stack, except for STDIN
+# and files we've already processed.
+sub queue_includes_from
+{
+ my ($file) = @_;
+ my $line;
+
+ return if ($file eq "-");
+
+ open HEADER, $file or return;
+ while (defined($line = <HEADER>)) {
+ while (/\\$/) { # Handle continuation lines
+ chop $line;
+ $line .= <HEADER>;
+ }
+
+ if ($line =~ /^#\s*include\s+<(.*?)>/) {
+ push(@ARGV, $1) unless $is_converted{$1};
+ }
+ }
+ close HEADER;
+}
+
+
+# Determine include directories; $Config{usrinc} should be enough for (all
+# non-GCC?) C compilers, but gcc uses an additional include directory.
+sub inc_dirs
+{
+ my $from_gcc = `$Config{cc} -v 2>&1`;
+ $from_gcc =~ s:^Reading specs from (.*?)/specs\b.*:$1/include:s;
+
+ length($from_gcc) ? ($from_gcc, $Config{usrinc}) : ($Config{usrinc});
+}
+
+
+1;
+
+##############################################################################
+__END__
+
+=head1 NAME
+
+h2ph - convert .h C header files to .ph Perl header files
+
+=head1 SYNOPSIS
+
+B<h2ph [-d destination directory] [-r | -a] [-l] [headerfiles]>
+
+=head1 DESCRIPTION
+
+I<h2ph>
+converts any C header files specified to the corresponding Perl header file
+format.
+It is most easily run while in /usr/include:
+
+ cd /usr/include; h2ph * sys/*
+
+or
+
+ cd /usr/include; h2ph -r -l .
+
+The output files are placed in the hierarchy rooted at Perl's
+architecture dependent library directory. You can specify a different
+hierarchy with a B<-d> switch.
+
+If run with no arguments, filters standard input to standard output.
+
+=head1 OPTIONS
+
+=over 4
+
+=item -d destination_dir
+
+Put the resulting B<.ph> files beneath B<destination_dir>, instead of
+beneath the default Perl library location (C<$Config{'installsitsearch'}>).
+
+=item -r
+
+Run recursively; if any of B<headerfiles> are directories, then run I<h2ph>
+on all files in those directories (and their subdirectories, etc.). B<-r>
+and B<-a> are mutually exclusive.
+
+=item -a
+
+Run automagically; convert B<headerfiles>, as well as any B<.h> files
+which they include. This option will search for B<.h> files in all
+directories which your C compiler ordinarily uses. B<-a> and B<-r> are
+mutually exclusive.
+
+=item -l
+
+Symbolic links will be replicated in the destination directory. If B<-l>
+is not specified, then links are skipped over.
+
+=item -h
+
+Put ``hints'' in the .ph files which will help in locating problems with
+I<h2ph>. In those cases when you B<require> a B<.ph> file containing syntax
+errors, instead of the cryptic
+
+ [ some error condition ] at (eval mmm) line nnn
+
+you will see the slightly more helpful
+
+ [ some error condition ] at filename.ph line nnn
+
+However, the B<.ph> files almost double in size when built using B<-h>.
+
+=item -D
+
+Include the code from the B<.h> file as a comment in the B<.ph> file.
+This is primarily used for debugging I<h2ph>.
+
+=back
+
+=head1 ENVIRONMENT
+
+No environment variables are used.
+
+=head1 FILES
+
+ /usr/include/*.h
+ /usr/include/sys/*.h
+
+etc.
+
+=head1 AUTHOR
+
+Larry Wall
+
+=head1 SEE ALSO
+
+perl(1)
+
+=head1 DIAGNOSTICS
+
+The usual warnings if it can't read or write the files involved.
+
+=head1 BUGS
+
+Doesn't construct the %sizeof array for you.
+
+It doesn't handle all C constructs, but it does attempt to isolate
+definitions inside evals so that you can get at the definitions
+that it can translate.
+
+It's only intended as a rough tool.
+You may need to dicker with the files produced.
+
+=cut
+
+!NO!SUBS!
+
+close OUT or die "Can't close $file: $!";
+chmod 0755, $file or die "Can't reset permissions for $file: $!\n";
+exec("$Config{'eunicefix'} $file") if $Config{'eunicefix'} ne ':';
+chdir $origdir;
diff --git a/contrib/perl5/utils/h2xs.PL b/contrib/perl5/utils/h2xs.PL
new file mode 100644
index 0000000..52f590b
--- /dev/null
+++ b/contrib/perl5/utils/h2xs.PL
@@ -0,0 +1,905 @@
+#!/usr/local/bin/perl
+
+use Config;
+use File::Basename qw(&basename &dirname);
+use Cwd;
+
+# List explicitly here the variables you want Configure to
+# generate. Metaconfig only looks for shell variables, so you
+# have to mention them as if they were shell variables, not
+# %Config entries. Thus you write
+# $startperl
+# to ensure Configure will look for $Config{startperl}.
+
+# This forces PL files to create target in same directory as PL file.
+# This is so that make depend always knows where to find PL derivatives.
+$origdir = cwd;
+chdir dirname($0);
+$file = basename($0, '.PL');
+$file .= '.com' if $^O eq 'VMS';
+
+open OUT,">$file" or die "Can't create $file: $!";
+
+print "Extracting $file (with variable substitutions)\n";
+
+# In this section, perl variables will be expanded during extraction.
+# You can use $Config{...} to use Configure variables.
+
+print OUT <<"!GROK!THIS!";
+$Config{startperl}
+ eval 'exec $Config{perlpath} -S \$0 \${1+"\$@"}'
+ if \$running_under_some_shell;
+!GROK!THIS!
+
+# In the following, perl variables are not expanded during extraction.
+
+print OUT <<'!NO!SUBS!';
+
+=head1 NAME
+
+h2xs - convert .h C header files to Perl extensions
+
+=head1 SYNOPSIS
+
+B<h2xs> [B<-AOPXcdf>] [B<-v> version] [B<-n> module_name] [B<-p> prefix] [B<-s> sub] [headerfile ... [extra_libraries]]
+
+B<h2xs> B<-h>
+
+=head1 DESCRIPTION
+
+I<h2xs> builds a Perl extension from C header files. The extension
+will include functions which can be used to retrieve the value of any
+#define statement which was in the C header files.
+
+The I<module_name> will be used for the name of the extension. If
+module_name is not supplied then the name of the first header file
+will be used, with the first character capitalized.
+
+If the extension might need extra libraries, they should be included
+here. The extension Makefile.PL will take care of checking whether
+the libraries actually exist and how they should be loaded.
+The extra libraries should be specified in the form -lm -lposix, etc,
+just as on the cc command line. By default, the Makefile.PL will
+search through the library path determined by Configure. That path
+can be augmented by including arguments of the form B<-L/another/library/path>
+in the extra-libraries argument.
+
+=head1 OPTIONS
+
+=over 5
+
+=item B<-A>
+
+Omit all autoload facilities. This is the same as B<-c> but also removes the
+S<C<require AutoLoader>> statement from the .pm file.
+
+=item B<-F>
+
+Additional flags to specify to C preprocessor when scanning header for
+function declarations. Should not be used without B<-x>.
+
+=item B<-O>
+
+Allows a pre-existing extension directory to be overwritten.
+
+=item B<-P>
+
+Omit the autogenerated stub POD section.
+
+=item B<-X>
+
+Omit the XS portion. Used to generate templates for a module which is not
+XS-based.
+
+=item B<-c>
+
+Omit C<constant()> from the .xs file and corresponding specialised
+C<AUTOLOAD> from the .pm file.
+
+=item B<-d>
+
+Turn on debugging messages.
+
+=item B<-f>
+
+Allows an extension to be created for a header even if that header is
+not found in /usr/include.
+
+=item B<-h>
+
+Print the usage, help and version for this h2xs and exit.
+
+=item B<-n> I<module_name>
+
+Specifies a name to be used for the extension, e.g., S<-n RPC::DCE>
+
+=item B<-p> I<prefix>
+
+Specify a prefix which should be removed from the Perl function names, e.g., S<-p sec_rgy_>
+This sets up the XS B<PREFIX> keyword and removes the prefix from functions that are
+autoloaded via the C<constant()> mechansim.
+
+=item B<-s> I<sub1,sub2>
+
+Create a perl subroutine for the specified macros rather than autoload with the constant() subroutine.
+These macros are assumed to have a return type of B<char *>, e.g., S<-s sec_rgy_wildcard_name,sec_rgy_wildcard_sid>.
+
+=item B<-v> I<version>
+
+Specify a version number for this extension. This version number is added
+to the templates. The default is 0.01.
+
+=item B<-x>
+
+Automatically generate XSUBs basing on function declarations in the
+header file. The package C<C::Scan> should be installed. If this
+option is specified, the name of the header file may look like
+C<NAME1,NAME2>. In this case NAME1 is used instead of the specified string,
+but XSUBs are emitted only for the declarations included from file NAME2.
+
+Note that some types of arguments/return-values for functions may
+result in XSUB-declarations/typemap-entries which need
+hand-editing. Such may be objects which cannot be converted from/to a
+pointer (like C<long long>), pointers to functions, or arrays.
+
+=back
+
+=head1 EXAMPLES
+
+
+ # Default behavior, extension is Rusers
+ h2xs rpcsvc/rusers
+
+ # Same, but extension is RUSERS
+ h2xs -n RUSERS rpcsvc/rusers
+
+ # Extension is rpcsvc::rusers. Still finds <rpcsvc/rusers.h>
+ h2xs rpcsvc::rusers
+
+ # Extension is ONC::RPC. Still finds <rpcsvc/rusers.h>
+ h2xs -n ONC::RPC rpcsvc/rusers
+
+ # Without constant() or AUTOLOAD
+ h2xs -c rpcsvc/rusers
+
+ # Creates templates for an extension named RPC
+ h2xs -cfn RPC
+
+ # Extension is ONC::RPC.
+ h2xs -cfn ONC::RPC
+
+ # Makefile.PL will look for library -lrpc in
+ # additional directory /opt/net/lib
+ h2xs rpcsvc/rusers -L/opt/net/lib -lrpc
+
+ # Extension is DCE::rgynbase
+ # prefix "sec_rgy_" is dropped from perl function names
+ h2xs -n DCE::rgynbase -p sec_rgy_ dce/rgynbase
+
+ # Extension is DCE::rgynbase
+ # prefix "sec_rgy_" is dropped from perl function names
+ # subroutines are created for sec_rgy_wildcard_name and sec_rgy_wildcard_sid
+ h2xs -n DCE::rgynbase -p sec_rgy_ \
+ -s sec_rgy_wildcard_name,sec_rgy_wildcard_sid dce/rgynbase
+
+ # Make XS without defines in perl.h, but with function declarations
+ # visible from perl.h. Name of the extension is perl1.
+ # When scanning perl.h, define -DEXT=extern -DdEXT= -DINIT(x)=
+ # Extra backslashes below because the string is passed to shell.
+ # Note that a directory with perl header files would
+ # be added automatically to include path.
+ h2xs -xAn perl1 -F "-DEXT=extern -DdEXT= -DINIT\(x\)=" perl.h
+
+ # Same with function declaration in proto.h as visible from perl.h.
+ h2xs -xAn perl2 perl.h,proto.h
+
+=head1 ENVIRONMENT
+
+No environment variables are used.
+
+=head1 AUTHOR
+
+Larry Wall and others
+
+=head1 SEE ALSO
+
+L<perl>, L<perlxstut>, L<ExtUtils::MakeMaker>, and L<AutoLoader>.
+
+=head1 DIAGNOSTICS
+
+The usual warnings if it cannot read or write the files involved.
+
+=cut
+
+my( $H2XS_VERSION ) = ' $Revision: 1.18 $ ' =~ /\$Revision:\s+([^\s]+)/;
+my $TEMPLATE_VERSION = '0.01';
+
+use Getopt::Std;
+
+sub usage{
+ warn "@_\n" if @_;
+ die "h2xs [-AOPXcdfh] [-v version] [-n module_name] [-p prefix] [-s subs] [headerfile [extra_libraries]]
+version: $H2XS_VERSION
+ -A Omit all autoloading facilities (implies -c).
+ -F Additional flags for C preprocessor (used with -x).
+ -O Allow overwriting of a pre-existing extension directory.
+ -P Omit the stub POD section.
+ -X Omit the XS portion.
+ -c Omit the constant() function and specialised AUTOLOAD from the XS file.
+ -d Turn on debugging messages.
+ -f Force creation of the extension even if the C header does not exist.
+ -h Display this help message
+ -n Specify a name to use for the extension (recommended).
+ -p Specify a prefix which should be removed from the Perl function names.
+ -s Create subroutines for specified macros.
+ -v Specify a version number for this extension.
+ -x Autogenerate XSUBs using C::Scan.
+extra_libraries
+ are any libraries that might be needed for loading the
+ extension, e.g. -lm would try to link in the math library.
+";
+}
+
+
+getopts("AF:OPXcdfhn:p:s:v:x") || usage;
+
+usage if $opt_h;
+
+if( $opt_v ){
+ $TEMPLATE_VERSION = $opt_v;
+}
+$opt_c = 1 if $opt_A;
+%const_xsub = map { $_,1 } split(/,+/, $opt_s) if $opt_s;
+
+while (my $arg = shift) {
+ if ($arg =~ /^-l/i) {
+ $extralibs = "$arg @ARGV";
+ last;
+ }
+ push(@path_h, $arg);
+}
+
+usage "Must supply header file or module name\n"
+ unless (@path_h or $opt_n);
+
+
+if( @path_h ){
+ foreach my $path_h (@path_h) {
+ $name ||= $path_h;
+ if( $path_h =~ s#::#/#g && $opt_n ){
+ warn "Nesting of headerfile ignored with -n\n";
+ }
+ $path_h .= ".h" unless $path_h =~ /\.h$/;
+ $fullpath = $path_h;
+ $path_h =~ s/,.*$// if $opt_x;
+ if ($^O eq 'VMS') { # Consider overrides of default location
+ if ($path_h !~ m![:>\[]!) {
+ my($hadsys) = ($path_h =~ s!^sys/!!i);
+ if ($ENV{'DECC$System_Include'}) { $path_h = "DECC\$System_Include:$path_h"; }
+ elsif ($ENV{'DECC$Library_Include'}) { $path_h = "DECC\$Library_Include:$path_h"; }
+ elsif ($ENV{'GNU_CC_Include'}) { $path_h = 'GNU_CC_Include:' .
+ ($hadsys ? '[vms]' : '[000000]') . $path_h; }
+ elsif ($ENV{'VAXC$Include'}) { $path_h = "VAXC\$_Include:$path_h"; }
+ else { $path_h = "Sys\$Library:$path_h"; }
+ }
+ }
+ elsif ($^O eq 'os2') {
+ $path_h = "/usr/include/$path_h"
+ if $path_h !~ m#^([a-z]:)?[./]#i and -r "/usr/include/$path_h";
+ }
+ else {
+ $path_h = "/usr/include/$path_h"
+ if $path_h !~ m#^[./]# and -r "/usr/include/$path_h";
+ }
+
+ if (!$opt_c) {
+ die "Can't find $path_h\n" if ( ! $opt_f && ! -f $path_h );
+ # Scan the header file (we should deal with nested header files)
+ # Record the names of simple #define constants into const_names
+ # Function prototypes are processed below.
+ open(CH, "<$path_h") || die "Can't open $path_h: $!\n";
+ while (<CH>) {
+ if (/^#[ \t]*define\s+([\$\w]+)\b\s*[^("]/) {
+ print "Matched $_ ($1)\n" if $opt_d;
+ $_ = $1;
+ next if /^_.*_h_*$/i; # special case, but for what?
+ if (defined $opt_p) {
+ if (!/^$opt_p(\d)/) {
+ ++$prefix{$_} if s/^$opt_p//;
+ }
+ else {
+ warn "can't remove $opt_p prefix from '$_'!\n";
+ }
+ }
+ $const_names{$_}++;
+ }
+ }
+ close(CH);
+ }
+ }
+ @const_names = sort keys %const_names;
+}
+
+
+$module = $opt_n || do {
+ $name =~ s/\.h$//;
+ if( $name !~ /::/ ){
+ $name =~ s#^.*/##;
+ $name = "\u$name";
+ }
+ $name;
+};
+
+(chdir 'ext', $ext = 'ext/') if -d 'ext';
+
+if( $module =~ /::/ ){
+ $nested = 1;
+ @modparts = split(/::/,$module);
+ $modfname = $modparts[-1];
+ $modpname = join('/',@modparts);
+}
+else {
+ $nested = 0;
+ @modparts = ();
+ $modfname = $modpname = $module;
+}
+
+
+if ($opt_O) {
+ warn "Overwriting existing $ext$modpname!!!\n" if -e $modpname;
+} else {
+ die "Won't overwrite existing $ext$modpname\n" if -e $modpname;
+}
+if( $nested ){
+ $modpath = "";
+ foreach (@modparts){
+ mkdir("$modpath$_", 0777);
+ $modpath .= "$_/";
+ }
+}
+mkdir($modpname, 0777);
+chdir($modpname) || die "Can't chdir $ext$modpname: $!\n";
+
+my %types_seen;
+my %std_types;
+my $fdecls;
+my $fdecls_parsed;
+
+if( ! $opt_X ){ # use XS, unless it was disabled
+ open(XS, ">$modfname.xs") || die "Can't create $ext$modpname/$modfname.xs: $!\n";
+ if ($opt_x) {
+ require C::Scan; # Run-time directive
+ require Config; # Run-time directive
+ warn "Scanning typemaps...\n";
+ get_typemap();
+ my $c;
+ my $filter;
+ my @fdecls;
+ foreach my $filename (@path_h) {
+ my $addflags = $opt_F || '';
+ if ($fullpath =~ /,/) {
+ $filename = $`;
+ $filter = $';
+ }
+ warn "Scanning $filename for functions...\n";
+ $c = new C::Scan 'filename' => $filename, 'filename_filter' => $filter,
+ 'add_cppflags' => $addflags;
+ $c->set('includeDirs' => ["$Config::Config{archlib}/CORE"]);
+
+ $fdecls_parsed = $c->get('parsed_fdecls');
+ push(@fdecls, @{$c->get('fdecls')});
+ }
+ $fdecls = [ @fdecls ];
+ }
+}
+
+open(PM, ">$modfname.pm") || die "Can't create $ext$modpname/$modfname.pm: $!\n";
+
+$" = "\n\t";
+warn "Writing $ext$modpname/$modfname.pm\n";
+
+print PM <<"END";
+package $module;
+
+use strict;
+END
+
+if( $opt_X || $opt_c || $opt_A ){
+ # we won't have our own AUTOLOAD(), so won't have $AUTOLOAD
+ print PM <<'END';
+use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
+END
+}
+else{
+ # we'll have an AUTOLOAD(), and it will have $AUTOLOAD and
+ # will want Carp.
+ print PM <<'END';
+use Carp;
+use vars qw($VERSION @ISA @EXPORT @EXPORT_OK $AUTOLOAD);
+END
+}
+
+print PM <<'END';
+
+require Exporter;
+END
+
+print PM <<"END" if ! $opt_X; # use DynaLoader, unless XS was disabled
+require DynaLoader;
+END
+
+# require autoloader if XS is disabled.
+# if XS is enabled, require autoloader unless autoloading is disabled.
+if( ($opt_X && (! $opt_A)) || (!$opt_X) ) {
+ print PM <<"END";
+require AutoLoader;
+END
+}
+
+if( $opt_X || ($opt_c && ! $opt_A) ){
+ # we won't have our own AUTOLOAD(), so we'll inherit it.
+ if( ! $opt_X ) { # use DynaLoader, unless XS was disabled
+ print PM <<"END";
+
+\@ISA = qw(Exporter AutoLoader DynaLoader);
+END
+ }
+ else{
+ print PM <<"END";
+
+\@ISA = qw(Exporter AutoLoader);
+END
+ }
+}
+else{
+ # 1) we have our own AUTOLOAD(), so don't need to inherit it.
+ # or
+ # 2) we don't want autoloading mentioned.
+ if( ! $opt_X ){ # use DynaLoader, unless XS was disabled
+ print PM <<"END";
+
+\@ISA = qw(Exporter DynaLoader);
+END
+ }
+ else{
+ print PM <<"END";
+
+\@ISA = qw(Exporter);
+END
+ }
+}
+
+print PM<<"END";
+# Items to export into callers namespace by default. Note: do not export
+# names by default without a very good reason. Use EXPORT_OK instead.
+# Do not simply export all your public functions/methods/constants.
+\@EXPORT = qw(
+ @const_names
+);
+\$VERSION = '$TEMPLATE_VERSION';
+
+END
+
+print PM <<"END" unless $opt_c or $opt_X;
+sub AUTOLOAD {
+ # This AUTOLOAD is used to 'autoload' constants from the constant()
+ # XS function. If a constant is not found then control is passed
+ # to the AUTOLOAD in AutoLoader.
+
+ my \$constname;
+ (\$constname = \$AUTOLOAD) =~ s/.*:://;
+ croak "&$module::constant not defined" if \$constname eq 'constant';
+ my \$val = constant(\$constname, \@_ ? \$_[0] : 0);
+ if (\$! != 0) {
+ if (\$! =~ /Invalid/) {
+ \$AutoLoader::AUTOLOAD = \$AUTOLOAD;
+ goto &AutoLoader::AUTOLOAD;
+ }
+ else {
+ croak "Your vendor has not defined $module macro \$constname";
+ }
+ }
+ *\$AUTOLOAD = sub () { \$val };
+ goto &\$AUTOLOAD;
+}
+
+END
+
+if( ! $opt_X ){ # print bootstrap, unless XS is disabled
+ print PM <<"END";
+bootstrap $module \$VERSION;
+END
+}
+
+if( $opt_P ){ # if POD is disabled
+ $after = '__END__';
+}
+else {
+ $after = '=cut';
+}
+
+print PM <<"END";
+
+# Preloaded methods go here.
+
+# Autoload methods go after $after, and are processed by the autosplit program.
+
+1;
+__END__
+END
+
+$author = "A. U. Thor";
+$email = 'a.u.thor@a.galaxy.far.far.away';
+
+my $const_doc = '';
+my $fdecl_doc = '';
+if (@const_names and not $opt_P) {
+ $const_doc = <<EOD;
+\n=head1 Exported constants
+
+ @{[join "\n ", @const_names]}
+
+EOD
+}
+if (defined $fdecls and @$fdecls and not $opt_P) {
+ $fdecl_doc = <<EOD;
+\n=head1 Exported functions
+
+ @{[join "\n ", @$fdecls]}
+
+EOD
+}
+
+$pod = <<"END" unless $opt_P;
+## Below is the stub of documentation for your module. You better edit it!
+#
+#=head1 NAME
+#
+#$module - Perl extension for blah blah blah
+#
+#=head1 SYNOPSIS
+#
+# use $module;
+# blah blah blah
+#
+#=head1 DESCRIPTION
+#
+#Stub documentation for $module was created by h2xs. It looks like the
+#author of the extension was negligent enough to leave the stub
+#unedited.
+#
+#Blah blah blah.
+#$const_doc$fdecl_doc
+#=head1 AUTHOR
+#
+#$author, $email
+#
+#=head1 SEE ALSO
+#
+#perl(1).
+#
+#=cut
+END
+
+$pod =~ s/^\#//gm unless $opt_P;
+print PM $pod unless $opt_P;
+
+close PM;
+
+
+if( ! $opt_X ){ # print XS, unless it is disabled
+warn "Writing $ext$modpname/$modfname.xs\n";
+
+print XS <<"END";
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+#ifdef __cplusplus
+}
+#endif
+
+END
+if( @path_h ){
+ foreach my $path_h (@path_h) {
+ my($h) = $path_h;
+ $h =~ s#^/usr/include/##;
+ if ($^O eq 'VMS') { $h =~ s#.*vms\]#sys/# or $h =~ s#.*[:>\]]##; }
+ print XS qq{#include <$h>\n};
+ }
+ print XS "\n";
+}
+
+if( ! $opt_c ){
+print XS <<"END";
+static int
+not_here(s)
+char *s;
+{
+ croak("$module::%s not implemented on this architecture", s);
+ return -1;
+}
+
+static double
+constant(name, arg)
+char *name;
+int arg;
+{
+ errno = 0;
+ switch (*name) {
+END
+
+my(@AZ, @az, @under);
+
+foreach(@const_names){
+ @AZ = 'A' .. 'Z' if !@AZ && /^[A-Z]/;
+ @az = 'a' .. 'z' if !@az && /^[a-z]/;
+ @under = '_' if !@under && /^_/;
+}
+
+foreach $letter (@AZ, @az, @under) {
+
+ last if $letter eq 'a' && !@const_names;
+
+ print XS " case '$letter':\n";
+ my($name);
+ while (substr($const_names[0],0,1) eq $letter) {
+ $name = shift(@const_names);
+ $macro = $prefix{$name} ? "$opt_p$name" : $name;
+ next if $const_xsub{$macro};
+ print XS <<"END";
+ if (strEQ(name, "$name"))
+#ifdef $macro
+ return $macro;
+#else
+ goto not_there;
+#endif
+END
+ }
+ print XS <<"END";
+ break;
+END
+}
+print XS <<"END";
+ }
+ errno = EINVAL;
+ return 0;
+
+not_there:
+ errno = ENOENT;
+ return 0;
+}
+
+END
+}
+
+$prefix = "PREFIX = $opt_p" if defined $opt_p;
+# Now switch from C to XS by issuing the first MODULE declaration:
+print XS <<"END";
+
+MODULE = $module PACKAGE = $module $prefix
+
+END
+
+foreach (sort keys %const_xsub) {
+ print XS <<"END";
+char *
+$_()
+
+ CODE:
+#ifdef $_
+ RETVAL = $_;
+#else
+ croak("Your vendor has not defined the $module macro $_");
+#endif
+
+ OUTPUT:
+ RETVAL
+
+END
+}
+
+# If a constant() function was written then output a corresponding
+# XS declaration:
+print XS <<"END" unless $opt_c;
+
+double
+constant(name,arg)
+ char * name
+ int arg
+
+END
+
+my %seen_decl;
+
+
+sub print_decl {
+ my $fh = shift;
+ my $decl = shift;
+ my ($type, $name, $args) = @$decl;
+ return if $seen_decl{$name}++; # Need to do the same for docs as well?
+
+ my @argnames = map {$_->[1]} @$args;
+ my @argtypes = map { normalize_type( $_->[0] ) } @$args;
+ my @argarrays = map { $_->[4] || '' } @$args;
+ my $numargs = @$args;
+ if ($numargs and $argtypes[-1] eq '...') {
+ $numargs--;
+ $argnames[-1] = '...';
+ }
+ local $" = ', ';
+ $type = normalize_type($type);
+
+ print $fh <<"EOP";
+
+$type
+$name(@argnames)
+EOP
+
+ for $arg (0 .. $numargs - 1) {
+ print $fh <<"EOP";
+ $argtypes[$arg] $argnames[$arg]$argarrays[$arg]
+EOP
+ }
+}
+
+# Should be called before any actual call to normalize_type().
+sub get_typemap {
+ # We do not want to read ./typemap by obvios reasons.
+ my @tm = qw(../../../typemap ../../typemap ../typemap);
+ my $stdtypemap = "$Config::Config{privlib}/ExtUtils/typemap";
+ unshift @tm, $stdtypemap;
+ my $proto_re = "[" . quotemeta('\$%&*@;') . "]" ;
+ my $image;
+
+ foreach $typemap (@tm) {
+ next unless -e $typemap ;
+ # skip directories, binary files etc.
+ warn " Scanning $typemap\n";
+ warn("Warning: ignoring non-text typemap file '$typemap'\n"), next
+ unless -T $typemap ;
+ open(TYPEMAP, $typemap)
+ or warn ("Warning: could not open typemap file '$typemap': $!\n"), next;
+ my $mode = 'Typemap';
+ while (<TYPEMAP>) {
+ next if /^\s*\#/;
+ if (/^INPUT\s*$/) { $mode = 'Input'; next; }
+ elsif (/^OUTPUT\s*$/) { $mode = 'Output'; next; }
+ elsif (/^TYPEMAP\s*$/) { $mode = 'Typemap'; next; }
+ elsif ($mode eq 'Typemap') {
+ next if /^\s*($|\#)/ ;
+ if ( ($type, $image) =
+ /^\s*(.*?\S)\s+(\S+)\s*($proto_re*)\s*$/o
+ # This may reference undefined functions:
+ and not ($image eq 'T_PACKED' and $typemap eq $stdtypemap)) {
+ normalize_type($type);
+ }
+ }
+ }
+ close(TYPEMAP) or die "Cannot close $typemap: $!";
+ }
+ %std_types = %types_seen;
+ %types_seen = ();
+}
+
+
+sub normalize_type {
+ my $ignore_mods = '(?:\b(?:__const__|static|inline|__inline__)\b\s*)*';
+ my $type = shift;
+ $type =~ s/$ignore_mods//go;
+ $type =~ s/([\]\[()])/ \1 /g;
+ $type =~ s/\s+/ /g;
+ $type =~ s/\s+$//;
+ $type =~ s/^\s+//;
+ $type =~ s/\b\*/ */g;
+ $type =~ s/\*\b/* /g;
+ $type =~ s/\*\s+(?=\*)/*/g;
+ $types_seen{$type}++
+ unless $type eq '...' or $type eq 'void' or $std_types{$type};
+ $type;
+}
+
+if ($opt_x) {
+ for $decl (@$fdecls_parsed) { print_decl(\*XS, $decl) }
+}
+
+close XS;
+
+if (%types_seen) {
+ my $type;
+ warn "Writing $ext$modpname/typemap\n";
+ open TM, ">typemap" or die "Cannot open typemap file for write: $!";
+
+ for $type (keys %types_seen) {
+ print TM $type, "\t" x (6 - int((length $type)/8)), "T_PTROBJ\n"
+ }
+
+ close TM or die "Cannot close typemap file for write: $!";
+}
+
+} # if( ! $opt_X )
+
+warn "Writing $ext$modpname/Makefile.PL\n";
+open(PL, ">Makefile.PL") || die "Can't create $ext$modpname/Makefile.PL: $!\n";
+
+print PL <<'END';
+use ExtUtils::MakeMaker;
+# See lib/ExtUtils/MakeMaker.pm for details of how to influence
+# the contents of the Makefile that is written.
+END
+print PL "WriteMakefile(\n";
+print PL " 'NAME' => '$module',\n";
+print PL " 'VERSION_FROM' => '$modfname.pm', # finds \$VERSION\n";
+if( ! $opt_X ){ # print C stuff, unless XS is disabled
+ print PL " 'LIBS' => ['$extralibs'], # e.g., '-lm' \n";
+ print PL " 'DEFINE' => '', # e.g., '-DHAVE_SOMETHING' \n";
+ print PL " 'INC' => '', # e.g., '-I/usr/include/other' \n";
+}
+print PL ");\n";
+close(PL) || die "Can't close $ext$modpname/Makefile.PL: $!\n";
+
+warn "Writing $ext$modpname/test.pl\n";
+open(EX, ">test.pl") || die "Can't create $ext$modpname/test.pl: $!\n";
+print EX <<'_END_';
+# Before `make install' is performed this script should be runnable with
+# `make test'. After `make install' it should work as `perl test.pl'
+
+######################### We start with some black magic to print on failure.
+
+# Change 1..1 below to 1..last_test_to_print .
+# (It may become useful if the test is moved to ./t subdirectory.)
+
+BEGIN { $| = 1; print "1..1\n"; }
+END {print "not ok 1\n" unless $loaded;}
+_END_
+print EX <<_END_;
+use $module;
+_END_
+print EX <<'_END_';
+$loaded = 1;
+print "ok 1\n";
+
+######################### End of black magic.
+
+# Insert your test code below (better if it prints "ok 13"
+# (correspondingly "not ok 13") depending on the success of chunk 13
+# of the test code):
+
+_END_
+close(EX) || die "Can't close $ext$modpname/test.pl: $!\n";
+
+warn "Writing $ext$modpname/Changes\n";
+open(EX, ">Changes") || die "Can't create $ext$modpname/Changes: $!\n";
+print EX "Revision history for Perl extension $module.\n\n";
+print EX "$TEMPLATE_VERSION ",scalar localtime,"\n";
+print EX "\t- original version; created by h2xs $H2XS_VERSION\n\n";
+close(EX) || die "Can't close $ext$modpname/Changes: $!\n";
+
+warn "Writing $ext$modpname/MANIFEST\n";
+open(MANI,'>MANIFEST') or die "Can't create MANIFEST: $!";
+@files = <*>;
+if (!@files) {
+ eval {opendir(D,'.');};
+ unless ($@) { @files = readdir(D); closedir(D); }
+}
+if (!@files) { @files = map {chomp && $_} `ls`; }
+if ($^O eq 'VMS') {
+ foreach (@files) {
+ # Clip trailing '.' for portability -- non-VMS OSs don't expect it
+ s%\.$%%;
+ # Fix up for case-sensitive file systems
+ s/$modfname/$modfname/i && next;
+ $_ = "\U$_" if $_ eq 'manifest' or $_ eq 'changes';
+ $_ = 'Makefile.PL' if $_ eq 'makefile.pl';
+ }
+}
+print MANI join("\n",@files), "\n";
+close MANI;
+!NO!SUBS!
+
+close OUT or die "Can't close $file: $!";
+chmod 0755, $file or die "Can't reset permissions for $file: $!\n";
+exec("$Config{'eunicefix'} $file") if $Config{'eunicefix'} ne ':';
+chdir $origdir;
diff --git a/contrib/perl5/utils/perlbug.PL b/contrib/perl5/utils/perlbug.PL
new file mode 100644
index 0000000..589e7e6
--- /dev/null
+++ b/contrib/perl5/utils/perlbug.PL
@@ -0,0 +1,1093 @@
+#!/usr/local/bin/perl
+
+use Config;
+use File::Basename qw(&basename &dirname);
+use Cwd;
+
+# List explicitly here the variables you want Configure to
+# generate. Metaconfig only looks for shell variables, so you
+# have to mention them as if they were shell variables, not
+# %Config entries. Thus you write
+# $startperl
+# to ensure Configure will look for $Config{startperl}.
+# $perlpath
+
+# This forces PL files to create target in same directory as PL file.
+# This is so that make depend always knows where to find PL derivatives.
+$origdir = cwd;
+chdir dirname($0);
+$file = basename($0, '.PL');
+$file .= '.com' if $^O eq 'VMS';
+
+open OUT, ">$file" or die "Can't create $file: $!";
+
+# extract patchlevel.h information
+
+open PATCH_LEVEL, "<../patchlevel.h" or die "Can't open patchlevel.h: $!";
+
+my $patchlevel_date = (stat PATCH_LEVEL)[9];
+
+while (<PATCH_LEVEL>) {
+ last if $_ =~ /^\s*static\s+char.*?local_patches\[\]\s*=\s*{\s*$/;
+}
+
+my @patches;
+while (<PATCH_LEVEL>) {
+ last if /^\s*}/;
+ chomp;
+ s/^\s+,?"?//;
+ s/"?,?$//;
+ s/(['\\])/\\$1/g;
+ push @patches, $_ unless $_ eq 'NULL';
+}
+my $patch_desc = "'" . join("',\n '", @patches) . "'";
+my $patch_tags = join "", map /(\S+)/ ? "+$1 " : (), @patches;
+
+close PATCH_LEVEL;
+
+# TO DO (prehaps): store/embed $Config::config_sh into perlbug. When perlbug is
+# used, compare $Config::config_sh with the stored version. If they differ then
+# append a list of individual differences to the bug report.
+
+
+print "Extracting $file (with variable substitutions)\n";
+
+# In this section, perl variables will be expanded during extraction.
+# You can use $Config{...} to use Configure variables.
+
+print OUT <<"!GROK!THIS!";
+$Config{startperl}
+ eval 'exec $Config{perlpath} -S \$0 \${1+"\$@"}'
+ if \$running_under_some_shell;
+
+my \$config_tag1 = '$] - $Config{cf_time}';
+
+my \$patchlevel_date = $patchlevel_date;
+my \$patch_tags = '$patch_tags';
+my \@patches = (
+ $patch_desc
+);
+!GROK!THIS!
+
+# In the following, perl variables are not expanded during extraction.
+
+print OUT <<'!NO!SUBS!';
+
+use Config;
+use Getopt::Std;
+use strict;
+
+sub paraprint;
+
+BEGIN {
+ eval "use Mail::Send;";
+ $::HaveSend = ($@ eq "");
+ eval "use Mail::Util;";
+ $::HaveUtil = ($@ eq "");
+};
+
+my $Version = "1.26";
+
+# Changed in 1.06 to skip Mail::Send and Mail::Util if not available.
+# Changed in 1.07 to see more sendmail execs, and added pipe output.
+# Changed in 1.08 to use correct address for sendmail.
+# Changed in 1.09 to close the REP file before calling it up in the editor.
+# Also removed some old comments duplicated elsewhere.
+# Changed in 1.10 to run under VMS without Mail::Send; also fixed
+# temp filename generation.
+# Changed in 1.11 to clean up some text and removed Mail::Send deactivator.
+# Changed in 1.12 to check for editor errors, make save/send distinction
+# clearer and add $ENV{REPLYTO}.
+# Changed in 1.13 to hopefully make it more difficult to accidentally
+# send mail
+# Changed in 1.14 to make the prompts a little more clear on providing
+# helpful information. Also let file read fail gracefully.
+# Changed in 1.15 to add warnings to stop people using perlbug for non-bugs.
+# Also report selected environment variables.
+# Changed in 1.16 to include @INC, and allow user to re-edit if no changes.
+# Changed in 1.17 Win32 support added. GSAR 97-04-12
+# Changed in 1.18 add '-ok' option for reporting build success. CFR 97-06-18
+# Changed in 1.19 '-ok' default not '-v'
+# add local patch information
+# warn on '-ok' if this is an old system; add '-okay'
+# Changed in 1.20 Added patchlevel.h reading and version/config checks
+# Changed in 1.21 Added '-nok' for reporting build failure DFD 98-05-05
+# Changed in 1.22 Heavy reformatting & minor bugfixes HVDS 98-05-10
+# Changed in 1.23 Restore -ok(ay): say 'success'; don't prompt
+# Changed in 1.24 Added '-F<file>' to save report HVDS 98-07-01
+# Changed in 1.25 Warn on failure to open save file. HVDS 98-07-12
+# Changed in 1.26 Don't require -t STDIN for -ok. HVDS 98-07-15
+
+# TODO: - Allow the user to re-name the file on mail failure, and
+# make sure failure (transmission-wise) of Mail::Send is
+# accounted for.
+# - Test -b option
+
+my( $file, $usefile, $cc, $address, $perlbug, $testaddress, $filename,
+ $subject, $from, $verbose, $ed, $outfile,
+ $fh, $me, $Is_MSWin32, $Is_VMS, $msg, $body, $andcc, %REP, $ok);
+
+my $config_tag2 = "$] - $Config{cf_time}";
+
+Init();
+
+if ($::opt_h) { Help(); exit; }
+if ($::opt_d) { Dump(*STDOUT); exit; }
+if (!-t STDIN && !($ok and not $::opt_n)) {
+ paraprint <<EOF;
+Please use perlbug interactively. If you want to
+include a file, you can use the -f switch.
+EOF
+ die "\n";
+}
+if (!-t STDOUT && !$outfile) { Dump(*STDOUT); exit; }
+
+Query();
+Edit() unless $usefile || ($ok and not $::opt_n);
+NowWhat();
+Send();
+
+exit;
+
+sub Init {
+ # -------- Setup --------
+
+ $Is_MSWin32 = $^O eq 'MSWin32';
+ $Is_VMS = $^O eq 'VMS';
+
+ if (!getopts("dhva:s:b:f:F:r:e:SCc:to:n:")) { Help(); exit; };
+
+ # This comment is needed to notify metaconfig that we are
+ # using the $perladmin, $cf_by, and $cf_time definitions.
+
+ # -------- Configuration ---------
+
+ # perlbug address
+ $perlbug = 'perlbug@perl.com';
+
+ # Test address
+ $testaddress = 'perlbug-test@perl.com';
+
+ # Target address
+ $address = $::opt_a || ($::opt_t ? $testaddress : $perlbug);
+
+ # Users address, used in message and in Reply-To header
+ $from = $::opt_r || "";
+
+ # Include verbose configuration information
+ $verbose = $::opt_v || 0;
+
+ # Subject of bug-report message
+ $subject = $::opt_s || "";
+
+ # Send a file
+ $usefile = ($::opt_f || 0);
+
+ # File to send as report
+ $file = $::opt_f || "";
+
+ # File to output to
+ $outfile = $::opt_F || "";
+
+ # Body of report
+ $body = $::opt_b || "";
+
+ # Editor
+ $ed = $::opt_e || $ENV{VISUAL} || $ENV{EDITOR} || $ENV{EDIT}
+ || ($Is_VMS && "edit/tpu")
+ || ($Is_MSWin32 && "notepad")
+ || "vi";
+
+ # Not OK - provide build failure template by finessing OK report
+ if ($::opt_n) {
+ if (substr($::opt_n, 0, 2) eq 'ok' ) {
+ $::opt_o = substr($::opt_n, 1);
+ } else {
+ Help();
+ exit();
+ }
+ }
+
+ # OK - send "OK" report for build on this system
+ $ok = 0;
+ if ($::opt_o) {
+ if ($::opt_o eq 'k' or $::opt_o eq 'kay') {
+ my $age = time - $patchlevel_date;
+ if ($::opt_o eq 'k' and $age > 60 * 24 * 60 * 60 ) {
+ my $date = localtime $patchlevel_date;
+ print <<"EOF";
+"perlbug -ok" and "perlbug -nok" do not report on Perl versions which
+are more than 60 days old. This Perl version was constructed on
+$date. If you really want to report this, use
+"perlbug -okay" or "perlbug -nokay".
+EOF
+ exit();
+ }
+ # force these options
+ unless ($::opt_n) {
+ $::opt_S = 1; # don't prompt for send
+ $::opt_b = 1; # we have a body
+ $body = "Perl reported to build OK on this system.\n";
+ }
+ $::opt_C = 1; # don't send a copy to the local admin
+ $::opt_s = 1; # we have a subject line
+ $subject = ($::opt_n ? 'Not ' : '')
+ . "OK: perl $] ${patch_tags}on"
+ ." $::Config{'archname'} $::Config{'osvers'} $subject";
+ $ok = 1;
+ } else {
+ Help();
+ exit();
+ }
+ }
+
+ # Possible administrator addresses, in order of confidence
+ # (Note that cf_email is not mentioned to metaconfig, since
+ # we don't really want it. We'll just take it if we have to.)
+ #
+ # This has to be after the $ok stuff above because of the way
+ # that $::opt_C is forced.
+ $cc = $::opt_C ? "" : (
+ $::opt_c || $::Config{'perladmin'}
+ || $::Config{'cf_email'} || $::Config{'cf_by'}
+ );
+
+ # My username
+ $me = $Is_MSWin32 ? $ENV{'USERNAME'}
+ : $^O eq 'os2' ? $ENV{'USER'} || $ENV{'LOGNAME'}
+ : eval { getpwuid($<) }; # May be missing
+
+ $from = $::Config{'cf_email'}
+ if !$from && $::Config{'cf_email'} && $::Config{'cf_by'} && $me &&
+ ($me eq $::Config{'cf_by'});
+} # sub Init
+
+sub Query {
+ # Explain what perlbug is
+ unless ($ok) {
+ paraprint <<EOF;
+This program provides an easy way to create a message reporting a bug
+in perl, and e-mail it to $address. It is *NOT* intended for
+sending test messages or simply verifying that perl works, *NOR* is it
+intended for reporting bugs in third-party perl modules. It is *ONLY*
+a means of reporting verifiable problems with the core perl distribution,
+and any solutions to such problems, to the people who maintain perl.
+
+If you're just looking for help with perl, try posting to the Usenet
+newsgroup comp.lang.perl.misc. If you're looking for help with using
+perl with CGI, try posting to comp.infosystems.www.programming.cgi.
+EOF
+ }
+
+ # Prompt for subject of message, if needed
+ unless ($subject) {
+ paraprint <<EOF;
+First of all, please provide a subject for the
+message. It should be a concise description of
+the bug or problem. "perl bug" or "perl problem"
+is not a concise description.
+EOF
+ print "Subject: ";
+ $subject = <>;
+
+ my $err = 0;
+ while ($subject !~ /\S/) {
+ print "\nPlease enter a subject: ";
+ $subject = <>;
+ if ($err++ > 5) {
+ die "Aborting.\n";
+ }
+ }
+ chop $subject;
+ }
+
+ # Prompt for return address, if needed
+ unless ($from) {
+ # Try and guess return address
+ my $guess;
+
+ $guess = $ENV{'REPLY-TO'} || $ENV{'REPLYTO'} || '';
+ unless ($guess) {
+ my $domain;
+ if ($::HaveUtil) {
+ $domain = Mail::Util::maildomain();
+ } elsif ($Is_MSWin32) {
+ $domain = $ENV{'USERDOMAIN'};
+ } else {
+ require Sys::Hostname;
+ $domain = Sys::Hostname::hostname();
+ }
+ if ($domain) {
+ if ($Is_VMS && !$::Config{'d_socket'}) {
+ $guess = "$domain\:\:$me";
+ } else {
+ $guess = "$me\@$domain" if $domain;
+ }
+ }
+ }
+
+ if ($guess) {
+ unless ($ok) {
+ paraprint <<EOF;
+Your e-mail address will be useful if you need to be contacted. If the
+default shown is not your full internet e-mail address, please correct it.
+EOF
+ }
+ } else {
+ paraprint <<EOF;
+So that you may be contacted if necessary, please enter
+your full internet e-mail address here.
+EOF
+ }
+
+ if ($ok && $guess) {
+ # use it
+ $from = $guess;
+ } else {
+ # verify it
+ print "Your address [$guess]: ";
+ $from = <>;
+ chop $from;
+ $from = $guess if $from eq '';
+ }
+ }
+
+ if ($from eq $cc or $me eq $cc) {
+ # Try not to copy ourselves
+ $cc = "yourself";
+ }
+
+ # Prompt for administrator address, unless an override was given
+ if( !$::opt_C and !$::opt_c ) {
+ paraprint <<EOF;
+A copy of this report can be sent to your local
+perl administrator. If the address is wrong, please
+correct it, or enter 'none' or 'yourself' to not send
+a copy.
+EOF
+ print "Local perl administrator [$cc]: ";
+ my $entry = scalar <>;
+ chop $entry;
+
+ if ($entry ne "") {
+ $cc = $entry;
+ $cc = '' if $me eq $cc;
+ }
+ }
+
+ $cc = '' if $cc =~ /^(none|yourself|me|myself|ourselves)$/i;
+ $andcc = " and $cc" if $cc;
+
+ # Prompt for editor, if no override is given
+editor:
+ unless ($::opt_e || $::opt_f || $::opt_b) {
+ paraprint <<EOF;
+Now you need to supply the bug report. Try to make
+the report concise but descriptive. Include any
+relevant detail. If you are reporting something
+that does not work as you think it should, please
+try to include example of both the actual
+result, and what you expected.
+
+Some information about your local
+perl configuration will automatically be included
+at the end of the report. If you are using any
+unusual version of perl, please try and confirm
+exactly which versions are relevant.
+
+You will probably want to use an editor to enter
+the report. If "$ed" is the editor you want
+to use, then just press Enter, otherwise type in
+the name of the editor you would like to use.
+
+If you would like to use a prepared file, type
+"file", and you will be asked for the filename.
+EOF
+ print "Editor [$ed]: ";
+ my $entry =scalar <>;
+ chop $entry;
+
+ $usefile = 0;
+ if ($entry eq "file") {
+ $usefile = 1;
+ } elsif ($entry ne "") {
+ $ed = $entry;
+ }
+ }
+
+ # Generate scratch file to edit report in
+ $filename = filename();
+
+ # Prompt for file to read report from, if needed
+ if ($usefile and !$file) {
+filename:
+ paraprint <<EOF;
+What is the name of the file that contains your report?
+EOF
+ print "Filename: ";
+ my $entry = scalar <>;
+ chop $entry;
+
+ if ($entry eq "") {
+ paraprint <<EOF;
+No filename? I'll let you go back and choose an editor again.
+EOF
+ goto editor;
+ }
+
+ unless (-f $entry and -r $entry) {
+ paraprint <<EOF;
+I'm sorry, but I can't read from `$entry'. Maybe you mistyped the name of
+the file? If you don't want to send a file, just enter a blank line and you
+can get back to the editor selection.
+EOF
+ goto filename;
+ }
+ $file = $entry;
+ }
+
+ # Generate report
+ open(REP,">$filename");
+ my $reptype = !$ok ? "bug" : $::opt_n ? "build failure" : "success";
+
+ print REP <<EOF;
+This is a $reptype report for perl from $from,
+generated with the help of perlbug $Version running under perl $].
+
+EOF
+
+ if ($body) {
+ print REP $body;
+ } elsif ($usefile) {
+ open(F, "<$file")
+ or die "Unable to read report file from `$file': $!\n";
+ while (<F>) {
+ print REP $_
+ }
+ close(F);
+ } else {
+ print REP <<EOF;
+
+-----------------------------------------------------------------
+[Please enter your report here]
+
+
+
+[Please do not change anything below this line]
+-----------------------------------------------------------------
+EOF
+ }
+ Dump(*REP);
+ close(REP);
+
+ # read in the report template once so that
+ # we can track whether the user does any editing.
+ # yes, *all* whitespace is ignored.
+ open(REP, "<$filename");
+ while (<REP>) {
+ s/\s+//g;
+ $REP{$_}++;
+ }
+ close(REP);
+} # sub Query
+
+sub Dump {
+ local(*OUT) = @_;
+
+ print REP "\n---\n";
+ print REP "This perlbug was built using Perl $config_tag1\n",
+ "It is being executed now by Perl $config_tag2.\n\n"
+ if $config_tag2 ne $config_tag1;
+
+ print OUT <<EOF;
+Site configuration information for perl $]:
+
+EOF
+ if ($::Config{cf_by} and $::Config{cf_time}) {
+ print OUT "Configured by $::Config{cf_by} at $::Config{cf_time}.\n\n";
+ }
+ print OUT Config::myconfig;
+
+ if (@patches) {
+ print OUT join "\n ", "Locally applied patches:", @patches;
+ print OUT "\n";
+ };
+
+ print OUT <<EOF;
+
+---
+\@INC for perl $]:
+EOF
+ for my $i (@INC) {
+ print OUT " $i\n";
+ }
+
+ print OUT <<EOF;
+
+---
+Environment for perl $]:
+EOF
+ for my $env (sort
+ (qw(PATH LD_LIBRARY_PATH LANG PERL_BADLANG SHELL HOME LOGDIR),
+ grep /^(?:PERL|LC_)/, keys %ENV)
+ ) {
+ print OUT " $env",
+ exists $ENV{$env} ? "=$ENV{$env}" : ' (unset)',
+ "\n";
+ }
+ if ($verbose) {
+ print OUT "\nComplete configuration data for perl $]:\n\n";
+ my $value;
+ foreach (sort keys %::Config) {
+ $value = $::Config{$_};
+ $value =~ s/'/\\'/g;
+ print OUT "$_='$value'\n";
+ }
+ }
+} # sub Dump
+
+sub Edit {
+ # Edit the report
+ if ($usefile || $body) {
+ paraprint <<EOF;
+Please make sure that the name of the editor you want to use is correct.
+EOF
+ print "Editor [$ed]: ";
+ my $entry =scalar <>;
+ chop $entry;
+ $ed = $entry unless $entry eq '';
+ }
+
+tryagain:
+ my $sts = system("$ed $filename");
+ if ($sts) {
+ paraprint <<EOF;
+The editor you chose (`$ed') could apparently not be run!
+Did you mistype the name of your editor? If so, please
+correct it here, otherwise just press Enter.
+EOF
+ print "Editor [$ed]: ";
+ my $entry =scalar <>;
+ chop $entry;
+
+ if ($entry ne "") {
+ $ed = $entry;
+ goto tryagain;
+ } else {
+ paraprint <<EOF;
+You may want to save your report to a file, so you can edit and mail it
+yourself.
+EOF
+ }
+ }
+
+ return if ($ok and not $::opt_n) || $body;
+ # Check that we have a report that has some, eh, report in it.
+ my $unseen = 0;
+
+ open(REP, "<$filename");
+ # a strange way to check whether any significant editing
+ # have been done: check whether any new non-empty lines
+ # have been added. Yes, the below code ignores *any* space
+ # in *any* line.
+ while (<REP>) {
+ s/\s+//g;
+ $unseen++ if $_ ne '' and not exists $REP{$_};
+ }
+
+ while ($unseen == 0) {
+ paraprint <<EOF;
+I am sorry but it looks like you did not report anything.
+EOF
+ print "Action (Retry Edit/Cancel) ";
+ my ($action) = scalar(<>);
+ if ($action =~ /^[re]/i) { # <R>etry <E>dit
+ goto tryagain;
+ } elsif ($action =~ /^[cq]/i) { # <C>ancel, <Q>uit
+ Cancel();
+ }
+ }
+} # sub Edit
+
+sub Cancel {
+ 1 while unlink($filename); # remove all versions under VMS
+ print "\nCancelling.\n";
+ exit(0);
+}
+
+sub NowWhat {
+ # Report is done, prompt for further action
+ if( !$::opt_S ) {
+ while(1) {
+ paraprint <<EOF;
+Now that you have completed your report, would you like to send
+the message to $address$andcc, display the message on
+the screen, re-edit it, or cancel without sending anything?
+You may also save the message as a file to mail at another time.
+EOF
+ retry:
+ print "Action (Send/Display/Edit/Cancel/Save to File): ";
+ my $action = scalar <>;
+ chop $action;
+
+ if ($action =~ /^(f|sa)/i) { # <F>ile/<Sa>ve
+ print "\n\nName of file to save message in [perlbug.rep]: ";
+ my $file = scalar <>;
+ chop $file;
+ $file = "perlbug.rep" if $file eq "";
+
+ unless (open(FILE, ">$file")) {
+ print "\nError opening $file: $!\n\n";
+ goto retry;
+ }
+ open(REP, "<$filename");
+ print FILE "To: $address\nSubject: $subject\n";
+ print FILE "Cc: $cc\n" if $cc;
+ print FILE "Reply-To: $from\n" if $from;
+ print FILE "\n";
+ while (<REP>) { print FILE }
+ close(REP);
+ close(FILE);
+
+ print "\nMessage saved in `$file'.\n";
+ exit;
+ } elsif ($action =~ /^(d|l|sh)/i ) { # <D>isplay, <L>ist, <Sh>ow
+ # Display the message
+ open(REP, "<$filename");
+ while (<REP>) { print $_ }
+ close(REP);
+ } elsif ($action =~ /^se/i) { # <S>end
+ # Send the message
+ print "Are you certain you want to send this message?\n"
+ . 'Please type "yes" if you are: ';
+ my $reply = scalar <STDIN>;
+ chop $reply;
+ if ($reply eq "yes") {
+ last;
+ } else {
+ paraprint <<EOF;
+That wasn't a clear "yes", so I won't send your message. If you are sure
+your message should be sent, type in "yes" (without the quotes) at the
+confirmation prompt.
+EOF
+ }
+ } elsif ($action =~ /^[er]/i) { # <E>dit, <R>e-edit
+ # edit the message
+ Edit();
+ } elsif ($action =~ /^[qc]/i) { # <C>ancel, <Q>uit
+ Cancel();
+ } elsif ($action =~ /^s/) {
+ paraprint <<EOF;
+I'm sorry, but I didn't understand that. Please type "send" or "save".
+EOF
+ }
+ }
+ }
+} # sub NowWhat
+
+sub Send {
+ # Message has been accepted for transmission -- Send the message
+ if ($outfile) {
+ open SENDMAIL, ">$outfile" or die "Couldn't open '$outfile': $!\n";
+ goto sendout;
+ }
+ if ($::HaveSend) {
+ $msg = new Mail::Send Subject => $subject, To => $address;
+ $msg->cc($cc) if $cc;
+ $msg->add("Reply-To",$from) if $from;
+
+ $fh = $msg->open;
+ open(REP, "<$filename");
+ while (<REP>) { print $fh $_ }
+ close(REP);
+ $fh->close;
+
+ print "\nMessage sent.\n";
+ } elsif ($Is_VMS) {
+ if ( ($address =~ /@/ and $address !~ /^\w+%"/) or
+ ($cc =~ /@/ and $cc !~ /^\w+%"/) ) {
+ my $prefix;
+ foreach (qw[ IN MX SMTP UCX PONY WINS ], '') {
+ $prefix = "$_%", last if $ENV{"MAIL\$PROTOCOL_$_"};
+ }
+ $address = qq[${prefix}"$address"] unless $address =~ /^\w+%"/;
+ $cc = qq[${prefix}"$cc"] unless !$cc || $cc =~ /^\w+%"/;
+ }
+ $subject =~ s/"/""/g; $address =~ s/"/""/g; $cc =~ s/"/""/g;
+ my $sts = system(qq[mail/Subject="$subject" $filename. "$address","$cc"]);
+ if ($sts) {
+ die <<EOF;
+Can't spawn off mail
+ (leaving bug report in $filename): $sts
+EOF
+ }
+ } else {
+ my $sendmail = "";
+ for (qw(/usr/lib/sendmail /usr/sbin/sendmail /usr/ucblib/sendmail)) {
+ $sendmail = $_, last if -e $_;
+ }
+ if ($^O eq 'os2' and $sendmail eq "") {
+ my $path = $ENV{PATH};
+ $path =~ s:\\:/: ;
+ my @path = split /$Config{'path_sep'}/, $path;
+ for (@path) {
+ $sendmail = "$_/sendmail", last if -e "$_/sendmail";
+ $sendmail = "$_/sendmail.exe", last if -e "$_/sendmail.exe";
+ }
+ }
+
+ paraprint(<<"EOF"), die "\n" if $sendmail eq "";
+I am terribly sorry, but I cannot find sendmail, or a close equivalent, and
+the perl package Mail::Send has not been installed, so I can't send your bug
+report. We apologize for the inconvenience.
+
+So you may attempt to find some way of sending your message, it has
+been left in the file `$filename'.
+EOF
+ open(SENDMAIL, "|$sendmail -t") || die "'|$sendmail -t' failed: $!";
+sendout:
+ print SENDMAIL "To: $address\n";
+ print SENDMAIL "Subject: $subject\n";
+ print SENDMAIL "Cc: $cc\n" if $cc;
+ print SENDMAIL "Reply-To: $from\n" if $from;
+ print SENDMAIL "\n\n";
+ open(REP, "<$filename");
+ while (<REP>) { print SENDMAIL $_ }
+ close(REP);
+
+ if (close(SENDMAIL)) {
+ printf "\nMessage %s.\n", $outfile ? "saved" : "sent";
+ } else {
+ warn "\nSendmail returned status '", $? >> 8, "'\n";
+ }
+ }
+ 1 while unlink($filename); # remove all versions under VMS
+} # sub Send
+
+sub Help {
+ print <<EOF;
+
+A program to help generate bug reports about perl5, and mail them.
+It is designed to be used interactively. Normally no arguments will
+be needed.
+
+Usage:
+$0 [-v] [-a address] [-s subject] [-b body | -f inpufile ] [ -F outputfile ]
+ [-r returnaddress] [-e editor] [-c adminaddress | -C] [-S] [-t] [-h]
+$0 [-v] [-r returnaddress] [-ok | -okay | -nok | -nokay]
+
+Simplest usage: run "$0", and follow the prompts.
+
+Options:
+
+ -v Include Verbose configuration data in the report
+ -f File containing the body of the report. Use this to
+ quickly send a prepared message.
+ -F File to output the resulting mail message to, instead of mailing.
+ -S Send without asking for confirmation.
+ -a Address to send the report to. Defaults to `$address'.
+ -c Address to send copy of report to. Defaults to `$cc'.
+ -C Don't send copy to administrator.
+ -s Subject to include with the message. You will be prompted
+ if you don't supply one on the command line.
+ -b Body of the report. If not included on the command line, or
+ in a file with -f, you will get a chance to edit the message.
+ -r Your return address. The program will ask you to confirm
+ this if you don't give it here.
+ -e Editor to use.
+ -t Test mode. The target address defaults to `$testaddress'.
+ -d Data mode (the default if you redirect or pipe output.)
+ This prints out your configuration data, without mailing
+ anything. You can use this with -v to get more complete data.
+ -ok Report successful build on this system to perl porters
+ (use alone or with -v). Only use -ok if *everything* was ok:
+ if there were *any* problems at all, use -nok.
+ -okay As -ok but allow report from old builds.
+ -nok Report unsuccessful build on this system to perl porters
+ (use alone or with -v). You must describe what went wrong
+ in the body of the report which you will be asked to edit.
+ -nokay As -nok but allow report from old builds.
+ -h Print this help message.
+
+EOF
+}
+
+sub filename {
+ my $dir = $Is_VMS ? 'sys$scratch:'
+ : ($Is_MSWin32 && $ENV{'TEMP'}) ? $ENV{'TEMP'}
+ : '/tmp/';
+ $filename = "bugrep0$$";
+ $dir .= "\\" if $Is_MSWin32 and $dir !~ m|[\\/]$|;
+ $filename++ while -e "$dir$filename";
+ $filename = "$dir$filename";
+}
+
+sub paraprint {
+ my @paragraphs = split /\n{2,}/, "@_";
+ print "\n\n";
+ for (@paragraphs) { # implicit local $_
+ s/(\S)\s*\n/$1 /g;
+ write;
+ print "\n";
+ }
+}
+
+format STDOUT =
+^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ~~
+$_
+.
+
+__END__
+
+=head1 NAME
+
+perlbug - how to submit bug reports on Perl
+
+=head1 SYNOPSIS
+
+B<perlbug> S<[ B<-v> ]> S<[ B<-a> I<address> ]> S<[ B<-s> I<subject> ]>
+S<[ B<-b> I<body> | B<-f> I<inputfile> ]> S<[ B<-F> I<outputfile> ]>
+S<[ B<-r> I<returnaddress> ]>
+S<[ B<-e> I<editor> ]> S<[ B<-c> I<adminaddress> | B<-C> ]>
+S<[ B<-S> ]> S<[ B<-t> ]> S<[ B<-d> ]> S<[ B<-h> ]>
+
+B<perlbug> S<[ B<-v> ]> S<[ B<-r> I<returnaddress> ]>
+S<[ B<-ok> | B<-okay> | B<-nok> | B<-nokay> ]>
+
+=head1 DESCRIPTION
+
+A program to help generate bug reports about perl or the modules that
+come with it, and mail them.
+
+If you have found a bug with a non-standard port (one that was not part
+of the I<standard distribution>), a binary distribution, or a
+non-standard module (such as Tk, CGI, etc), then please see the
+documentation that came with that distribution to determine the correct
+place to report bugs.
+
+C<perlbug> is designed to be used interactively. Normally no arguments
+will be needed. Simply run it, and follow the prompts.
+
+If you are unable to run B<perlbug> (most likely because you don't have
+a working setup to send mail that perlbug recognizes), you may have to
+compose your own report, and email it to B<perlbug@perl.com>. You might
+find the B<-d> option useful to get summary information in that case.
+
+In any case, when reporting a bug, please make sure you have run through
+this checklist:
+
+=over 4
+
+=item What version of perl you are running?
+
+Type C<perl -v> at the command line to find out.
+
+=item Are you running the latest released version of perl?
+
+Look at http://www.perl.com/ to find out. If it is not the latest
+released version, get that one and see whether your bug has been
+fixed. Note that bug reports about old versions of perl, especially
+those prior to the 5.0 release, are likely to fall upon deaf ears.
+You are on your own if you continue to use perl1 .. perl4.
+
+=item Are you sure what you have is a bug?
+
+A significant number of the bug reports we get turn out to be documented
+features in perl. Make sure the behavior you are witnessing doesn't fall
+under that category, by glancing through the documentation that comes
+with perl (we'll admit this is no mean task, given the sheer volume of
+it all, but at least have a look at the sections that I<seem> relevant).
+
+Be aware of the familiar traps that perl programmers of various hues
+fall into. See L<perltrap>.
+
+Try to study the problem under the perl debugger, if necessary.
+See L<perldebug>.
+
+=item Do you have a proper test case?
+
+The easier it is to reproduce your bug, the more likely it will be
+fixed, because if no one can duplicate the problem, no one can fix it.
+A good test case has most of these attributes: fewest possible number
+of lines; few dependencies on external commands, modules, or
+libraries; runs on most platforms unimpeded; and is self-documenting.
+
+A good test case is almost always a good candidate to be on the perl
+test suite. If you have the time, consider making your test case so
+that it will readily fit into the standard test suite.
+
+=item Can you describe the bug in plain English?
+
+The easier it is to understand a reproducible bug, the more likely it
+will be fixed. Anything you can provide by way of insight into the
+problem helps a great deal. In other words, try to analyse the
+problem to the extent you feel qualified and report your discoveries.
+
+=item Can you fix the bug yourself?
+
+A bug report which I<includes a patch to fix it> will almost
+definitely be fixed. Use the C<diff> program to generate your patches
+(C<diff> is being maintained by the GNU folks as part of the B<diffutils>
+package, so you should be able to get it from any of the GNU software
+repositories). If you do submit a patch, the cool-dude counter at
+perlbug@perl.com will register you as a savior of the world. Your
+patch may be returned with requests for changes, or requests for more
+detailed explanations about your fix.
+
+Here are some clues for creating quality patches: Use the B<-c> or
+B<-u> switches to the diff program (to create a so-called context or
+unified diff). Make sure the patch is not reversed (the first
+argument to diff is typically the original file, the second argument
+your changed file). Make sure you test your patch by applying it with
+the C<patch> program before you send it on its way. Try to follow the
+same style as the code you are trying to patch. Make sure your patch
+really does work (C<make test>, if the thing you're patching supports
+it).
+
+=item Can you use C<perlbug> to submit the report?
+
+B<perlbug> will, amongst other things, ensure your report includes
+crucial information about your version of perl. If C<perlbug> is unable
+to mail your report after you have typed it in, you may have to compose
+the message yourself, add the output produced by C<perlbug -d> and email
+it to B<perlbug@perl.com>. If, for some reason, you cannot run
+C<perlbug> at all on your system, be sure to include the entire output
+produced by running C<perl -V> (note the uppercase V).
+
+=back
+
+Having done your bit, please be prepared to wait, to be told the bug
+is in your code, or even to get no reply at all. The perl maintainers
+are busy folks, so if your problem is a small one or if it is difficult
+to understand or already known, they may not respond with a personal reply.
+If it is important to you that your bug be fixed, do monitor the
+C<Changes> file in any development releases since the time you submitted
+the bug, and encourage the maintainers with kind words (but never any
+flames!). Feel free to resend your bug report if the next released
+version of perl comes out and your bug is still present.
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<-a>
+
+Address to send the report to. Defaults to `perlbug@perl.com'.
+
+=item B<-b>
+
+Body of the report. If not included on the command line, or
+in a file with B<-f>, you will get a chance to edit the message.
+
+=item B<-C>
+
+Don't send copy to administrator.
+
+=item B<-c>
+
+Address to send copy of report to. Defaults to the address of the
+local perl administrator (recorded when perl was built).
+
+=item B<-d>
+
+Data mode (the default if you redirect or pipe output). This prints out
+your configuration data, without mailing anything. You can use this
+with B<-v> to get more complete data.
+
+=item B<-e>
+
+Editor to use.
+
+=item B<-f>
+
+File containing the body of the report. Use this to quickly send a
+prepared message.
+
+=item B<-F>
+
+File to output the results to instead of sending as an email. Useful
+particularly when running perlbug on a machine with no direct internet
+connection.
+
+=item B<-h>
+
+Prints a brief summary of the options.
+
+=item B<-ok>
+
+Report successful build on this system to perl porters. Forces B<-S>
+and B<-C>. Forces and supplies values for B<-s> and B<-b>. Only
+prompts for a return address if it cannot guess it (for use with
+B<make>). Honors return address specified with B<-r>. You can use this
+with B<-v> to get more complete data. Only makes a report if this
+system is less than 60 days old.
+
+=item B<-okay>
+
+As B<-ok> except it will report on older systems.
+
+=item B<-nok>
+
+Report unsuccessful build on this system. Forces B<-C>. Forces and
+supplies a value for B<-s>, then requires you to edit the report
+and say what went wrong. Alternatively, a prepared report may be
+supplied using B<-f>. Only prompts for a return address if it
+cannot guess it (for use with B<make>). Honors return address
+specified with B<-r>. You can use this with B<-v> to get more
+complete data. Only makes a report if this system is less than 60
+days old.
+
+=item B<-nokay>
+
+As B<-nok> except it will report on older systems.
+
+=item B<-r>
+
+Your return address. The program will ask you to confirm its default
+if you don't use this option.
+
+=item B<-S>
+
+Send without asking for confirmation.
+
+=item B<-s>
+
+Subject to include with the message. You will be prompted if you don't
+supply one on the command line.
+
+=item B<-t>
+
+Test mode. The target address defaults to `perlbug-test@perl.com'.
+
+=item B<-v>
+
+Include verbose configuration data in the report.
+
+=back
+
+=head1 AUTHORS
+
+Kenneth Albanowski (E<lt>kjahds@kjahds.comE<gt>), subsequently I<doc>tored
+by Gurusamy Sarathy (E<lt>gsar@umich.eduE<gt>), Tom Christiansen
+(E<lt>tchrist@perl.comE<gt>), Nathan Torkington (E<lt>gnat@frii.comE<gt>),
+Charles F. Randall (E<lt>cfr@pobox.comE<gt>), Mike Guy
+(E<lt>mjtg@cam.a.ukE<gt>), Dominic Dunlop (E<lt>domo@computer.orgE<gt>)
+and Hugo van der Sanden (E<lt>hv@crypt0.demon.co.ukE<gt>).
+
+=head1 SEE ALSO
+
+perl(1), perldebug(1), perltrap(1), diff(1), patch(1)
+
+=head1 BUGS
+
+None known (guess what must have been used to report them?)
+
+=cut
+
+!NO!SUBS!
+
+close OUT or die "Can't close $file: $!";
+chmod 0755, $file or die "Can't reset permissions for $file: $!\n";
+exec("$Config{'eunicefix'} $file") if $Config{'eunicefix'} ne ':';
+chdir $origdir;
+
diff --git a/contrib/perl5/utils/perlcc.PL b/contrib/perl5/utils/perlcc.PL
new file mode 100644
index 0000000..b214645
--- /dev/null
+++ b/contrib/perl5/utils/perlcc.PL
@@ -0,0 +1,945 @@
+#!/usr/local/bin/perl
+
+use Config;
+use File::Basename qw(&basename &dirname);
+use Cwd;
+
+# List explicitly here the variables you want Configure to
+# generate. Metaconfig only looks for shell variables, so you
+# have to mention them as if they were shell variables, not
+# %Config entries. Thus you write
+# $startperl
+# to ensure Configure will look for $Config{startperl}.
+# Wanted: $archlibexp
+
+# This forces PL files to create target in same directory as PL file.
+# This is so that make depend always knows where to find PL derivatives.
+$origdir = cwd;
+chdir dirname($0);
+$file = basename($0, '.PL');
+$file .= '.com' if $^O eq 'VMS';
+
+open OUT,">$file" or die "Can't create $file: $!";
+
+print "Extracting $file (with variable substitutions)\n";
+
+# In this section, perl variables will be expanded during extraction.
+# You can use $Config{...} to use Configure variables.
+
+print OUT <<"!GROK!THIS!";
+$Config{startperl}
+ eval 'exec $Config{perlpath} -S \$0 \${1+"\$@"}'
+ if \$running_under_some_shell;
+!GROK!THIS!
+
+# In the following, perl variables are not expanded during extraction.
+
+print OUT <<'!NO!SUBS!';
+
+use Config;
+use strict;
+use FileHandle;
+use File::Basename qw(&basename &dirname);
+use Cwd;
+
+use Getopt::Long;
+
+$Getopt::Long::bundling_override = 1;
+$Getopt::Long::passthrough = 0;
+$Getopt::Long::ignore_case = 0;
+
+my $options = {};
+my $_fh;
+
+main();
+
+sub main
+{
+
+ GetOptions
+ (
+ $options, "L:s",
+ "I:s",
+ "C:s",
+ "o:s",
+ "e:s",
+ "regex:s",
+ "verbose:s",
+ "log:s",
+ "argv:s",
+ "gen",
+ "sav",
+ "run",
+ "prog",
+ "mod"
+ );
+
+
+ my $key;
+
+ local($") = "|";
+
+ _usage() if (!_checkopts());
+ push(@ARGV, _maketempfile()) if ($options->{'e'});
+
+ _usage() if (!@ARGV);
+
+ my $file;
+ foreach $file (@ARGV)
+ {
+ _print("
+--------------------------------------------------------------------------------
+Compiling $file:
+--------------------------------------------------------------------------------
+", 36 );
+ _doit($file);
+ }
+}
+
+sub _doit
+{
+ my ($file) = @_;
+
+ my ($program_ext, $module_ext) = _getRegexps();
+ my ($obj, $objfile, $so, $type);
+
+ if (
+ (($file =~ m"@$program_ext") && ($file !~ m"@$module_ext"))
+ || (defined($options->{'prog'}) || defined($options->{'run'}))
+ )
+ {
+ $objfile = ($options->{'C'}) ? $options->{'C'} : "$file.c";
+ $type = 'program';
+
+ $obj = ($options->{'o'})? $options->{'o'} :
+ _getExecutable( $file,$program_ext);
+
+ return() if (!$obj);
+
+ }
+ elsif (($file =~ m"@$module_ext") || ($options->{'mod'}))
+ {
+ die "Shared objects are not supported on Win32 yet!!!!\n"
+ if ($Config{'osname'} eq 'MSWin32');
+
+ $obj = ($options->{'o'})? $options->{'o'} :
+ _getExecutable($file, $module_ext);
+ $so = "$obj.$Config{so}";
+ $type = 'sharedlib';
+ return() if (!$obj);
+ $objfile = ($options->{'C'}) ? $options->{'C'} : "$file.c";
+ }
+ else
+ {
+ _error("noextension", $file, $program_ext, $module_ext);
+ return();
+ }
+
+ if ($type eq 'program')
+ {
+ _print("Making C($objfile) for $file!\n", 36 );
+
+ my $errcode = _createCode($objfile, $file);
+ (_print( "ERROR: In generating code for $file!\n", -1), return())
+ if ($errcode);
+
+ _print("Compiling C($obj) for $file!\n", 36 ) if (!$options->{'gen'});
+ $errcode = _compileCode($file, $objfile, $obj)
+ if (!$options->{'gen'});
+
+ if ($errcode)
+ {
+ _print( "ERROR: In compiling code for $objfile !\n", -1);
+ my $ofile = File::Basename::basename($objfile);
+ $ofile =~ s"\.c$"\.o"s;
+
+ _removeCode("$ofile");
+ return()
+ }
+
+ _runCode($obj) if ($options->{'run'});
+
+ _removeCode($objfile) if (!$options->{'sav'} ||
+ ($options->{'e'} && !$options->{'C'}));
+
+ _removeCode($file) if ($options->{'e'});
+
+ _removeCode($obj) if (($options->{'e'}
+ && !$options->{'sav'}
+ && !$options->{'o'})
+ || ($options->{'run'} && !$options->{'sav'}));
+ }
+ else
+ {
+ _print( "Making C($objfile) for $file!\n", 36 );
+ my $errcode = _createCode($objfile, $file, $obj);
+ (_print( "ERROR: In generating code for $file!\n", -1), return())
+ if ($errcode);
+
+ _print( "Compiling C($so) for $file!\n", 36 ) if (!$options->{'gen'});
+
+ my $errorcode =
+ _compileCode($file, $objfile, $obj, $so ) if (!$options->{'gen'});
+
+ (_print( "ERROR: In compiling code for $objfile!\n", -1), return())
+ if ($errcode);
+ }
+}
+
+sub _getExecutable
+{
+ my ($sourceprog, $ext) = @_;
+ my ($obj);
+
+ if (defined($options->{'regex'}))
+ {
+ eval("(\$obj = \$sourceprog) =~ $options->{'regex'}");
+ return(0) if (_error('badeval', $@));
+ return(0) if (_error('equal', $obj, $sourceprog));
+ }
+ elsif (defined ($options->{'ext'}))
+ {
+ ($obj = $sourceprog) =~ s"@$ext"$options->{ext}"g;
+ return(0) if (_error('equal', $obj, $sourceprog));
+ }
+ elsif (defined ($options->{'run'}))
+ {
+ $obj = "perlc$$";
+ }
+ else
+ {
+ ($obj = $sourceprog) =~ s"@$ext""g;
+ return(0) if (_error('equal', $obj, $sourceprog));
+ }
+ return($obj);
+}
+
+sub _createCode
+{
+ my ( $generated_cfile, $file, $final_output ) = @_;
+ my $return;
+
+ local($") = " -I";
+
+ if (@_ == 2) # compiling a program
+ {
+ _print( "$^X -I@INC -MO=CC,-o$generated_cfile $file\n", 36);
+ $return = _run("$ -I@INC -MO=CC,-o$generated_cfile $file", 9);
+ $return;
+ }
+ else # compiling a shared object
+ {
+ _print(
+ "$ -I@INC -MO=CC,-m$final_output,-o$generated_cfile $file\n", 36);
+ $return =
+ _run("$ -I@INC -MO=CC,-m$final_output,-o$generated_cfile $file", 9);
+ $return;
+ }
+}
+
+sub _compileCode
+{
+ my ($sourceprog, $generated_cfile, $output_executable, $shared_object) = @_;
+ my @return;
+
+ if (@_ == 3) # just compiling a program
+ {
+ $return[0] =
+ _ccharness('static', $sourceprog, "-o", $output_executable, $generated_cfile);
+ $return[0];
+ }
+ else
+ {
+ my $object_file = $generated_cfile;
+ $object_file =~ s"\.c$"$Config{_o}";
+
+ $return[0] = _ccharness('compile', $sourceprog, "-c", $generated_cfile);
+ $return[1] = _ccharness
+ (
+ 'dynamic',
+ $sourceprog, "-o",
+ $shared_object, $object_file
+ );
+ return(1) if (grep ($_, @return));
+ return(0);
+ }
+}
+
+sub _runCode
+{
+ my ($executable) = @_;
+ _print("$executable $options->{'argv'}\n", 36);
+ _run("$executable $options->{'argv'}", -1 );
+}
+
+sub _removeCode
+{
+ my ($file) = @_;
+ unlink($file) if (-e $file);
+}
+
+sub _ccharness
+{
+ my $type = shift;
+ my (@args) = @_;
+ local($") = " ";
+
+ my $sourceprog = shift(@args);
+ my ($libdir, $incdir);
+
+ if (-d "$Config{installarchlib}/CORE")
+ {
+ $libdir = "-L$Config{installarchlib}/CORE";
+ $incdir = "-I$Config{installarchlib}/CORE";
+ }
+ else
+ {
+ $libdir = "-L.. -L.";
+ $incdir = "-I.. -I.";
+ }
+
+ $libdir .= " -L$options->{L}" if (defined($options->{L}));
+ $incdir .= " -I$options->{L}" if (defined($options->{L}));
+
+ my $linkargs = '';
+
+ if (!grep(/^-[cS]$/, @args))
+ {
+ my $lperl = $^O eq 'os2' ? '-llibperl' : '-lperl';
+ my $flags = $type eq 'dynamic' ? $Config{lddlflags} : $Config{ldflags};
+ $linkargs = "$flags $libdir $lperl @Config{libs}";
+ }
+
+ my @sharedobjects = _getSharedObjects($sourceprog);
+
+ my $cccmd =
+ "$Config{cc} @Config{qw(ccflags optimize)} $incdir @sharedobjects @args $linkargs";
+
+
+ _print ("$cccmd\n", 36);
+ _run("$cccmd", 18 );
+}
+
+sub _getSharedObjects
+{
+ my ($sourceprog) = @_;
+ my ($tmpfile, $incfile);
+ my (@return);
+ local($") = " -I";
+
+ if ($Config{'osname'} eq 'MSWin32')
+ {
+ # _addstuff;
+ }
+ else
+ {
+ my ($tmpprog);
+ ($tmpprog = $sourceprog) =~ s"(.*)[\/\\](.*)"$2";
+ $tmpfile = "/tmp/$tmpprog.tst";
+ $incfile = "/tmp/$tmpprog.val";
+ }
+
+ my $fd = new FileHandle("> $tmpfile") || die "Couldn't open $tmpfile!\n";
+ my $fd2 =
+ new FileHandle("$sourceprog") || die "Couldn't open $sourceprog!\n";
+
+ my $perl = <$fd2>; # strip off header;
+
+ print $fd
+<<"EOF";
+ use FileHandle;
+ my \$fh3 = new FileHandle("> $incfile")
+ || die "Couldn't open $incfile\\n";
+
+ my \$key;
+ foreach \$key (keys(\%INC)) { print \$fh3 "\$key:\$INC{\$key}\\n"; }
+ close(\$fh3);
+ exit();
+EOF
+
+ print $fd ( <$fd2> );
+ close($fd);
+
+ _print("$ -I@INC $tmpfile\n", 36);
+ _run("$ -I@INC $tmpfile", 9 );
+
+ $fd = new FileHandle ("$incfile");
+ my @lines = <$fd>;
+
+ unlink($tmpfile);
+ unlink($incfile);
+
+ my $line;
+ my $autolib;
+
+ foreach $line (@lines)
+ {
+ chomp($line);
+ my ($modname, $modpath) = split(':', $line);
+ my ($dir, $file) = ($modpath=~ m"(.*)[\\/]($modname)");
+
+ if ($autolib = _lookforAuto($dir, $file))
+ {
+ push(@return, $autolib);
+ }
+ }
+
+ return(@return);
+}
+
+sub _maketempfile
+{
+ my $return;
+
+# if ($Config{'osname'} eq 'MSWin32')
+# { $return = "C:\\TEMP\\comp$$.p"; }
+# else
+# { $return = "/tmp/comp$$.p"; }
+
+ $return = "comp$$.p";
+
+ my $fd = new FileHandle( "> $return") || die "Couldn't open $return!\n";
+ print $fd $options->{'e'};
+ close($fd);
+
+ return($return);
+}
+
+
+sub _lookforAuto
+{
+ my ($dir, $file) = @_;
+
+ my $relshared;
+ my $return;
+
+ ($relshared = $file) =~ s"(.*)\.pm"$1";
+
+ my ($tmp, $modname) = ($relshared =~ m"(?:(.*)[\\/]){0,1}(.*)"s);
+
+ $relshared .=
+ ($Config{'osname'} eq 'MSWin32')? "\\$modname.dll" : "/$modname.so";
+
+
+
+ if (-e ($return = "$Config{'installarchlib'}/auto/$relshared") )
+ {
+ return($return);
+ }
+ elsif (-e ($return = "$Config{'installsitearch'}/auto/$relshared"))
+ {
+ return($return);
+ }
+ elsif (-e ($return = "$dir/arch/auto/$relshared"))
+ {
+ return($return);
+ }
+ else
+ {
+ return(undef);
+ }
+}
+
+sub _getRegexps # make the appropriate regexps for making executables,
+{ # shared libs
+
+ my ($program_ext, $module_ext) = ([],[]);
+
+
+ @$program_ext = ($ENV{PERL_SCRIPT_EXT})? split(':', $ENV{PERL_SCRIPT_EXT}) :
+ ('.p$', '.pl$', '.bat$');
+
+
+ @$module_ext = ($ENV{PERL_MODULE_EXT})? split(':', $ENV{PERL_MODULE_EXT}) :
+ ('.pm$');
+
+
+ _mungeRegexp( $program_ext );
+ _mungeRegexp( $module_ext );
+
+ return($program_ext, $module_ext);
+}
+
+sub _mungeRegexp
+{
+ my ($regexp) = @_;
+
+ grep(s:(^|[^\\])\.:$1\x00\\.:g, @$regexp);
+ grep(s:(^|[^\x00])\\\.:$1\.:g, @$regexp);
+ grep(s:\x00::g, @$regexp);
+}
+
+
+sub _error
+{
+ my ($type, @args) = @_;
+
+ if ($type eq 'equal')
+ {
+
+ if ($args[0] eq $args[1])
+ {
+ _print ("ERROR: The object file '$args[0]' does not generate a legitimate executable file! Skipping!\n", -1);
+ return(1);
+ }
+ }
+ elsif ($type eq 'badeval')
+ {
+ if ($args[0])
+ {
+ _print ("ERROR: $args[0]\n", -1);
+ return(1);
+ }
+ }
+ elsif ($type eq 'noextension')
+ {
+ my $progext = join(',', @{$args[1]});
+ my $modext = join(',', @{$args[2]});
+
+ $progext =~ s"\\""g;
+ $modext =~ s"\\""g;
+
+ $progext =~ s"\$""g;
+ $modext =~ s"\$""g;
+
+ _print
+ (
+"
+ERROR: '$args[0]' does not have a proper extension! Proper extensions are:
+
+ PROGRAM: $progext
+ SHARED OBJECT: $modext
+
+Use the '-prog' flag to force your files to be interpreted as programs.
+Use the '-mod' flag to force your files to be interpreted as modules.
+", -1
+ );
+ return(1);
+ }
+
+ return(0);
+}
+
+sub _checkopts
+{
+ my @errors;
+ local($") = "\n";
+
+ if ($options->{'log'})
+ {
+ $_fh = new FileHandle(">> $options->{'log'}") || push(@errors, "ERROR: Couldn't open $options->{'log'}\n");
+ }
+
+ if (($options->{'c'}) && (@ARGV > 1) && ($options->{'sav'} ))
+ {
+ push(@errors,
+"ERROR: The '-sav' and '-C' options are incompatible when you have more than
+ one input file! ('-C' explicitly names resulting C code, '-sav' saves it,
+ and hence, with more than one file, the c code will be overwritten for
+ each file that you compile)\n");
+ }
+ if (($options->{'o'}) && (@ARGV > 1))
+ {
+ push(@errors,
+"ERROR: The '-o' option is incompatible when you have more than one input file!
+ (-o explicitly names the resulting executable, hence, with more than
+ one file the names clash)\n");
+ }
+
+ if ($options->{'e'} && $options->{'sav'} && !$options->{'o'} &&
+ !$options->{'C'})
+ {
+ push(@errors,
+"ERROR: You need to specify where you are going to save the resulting
+ executable or C code, when using '-sav' and '-e'. Use '-o' or '-C'.\n");
+ }
+
+ if (($options->{'regex'} || $options->{'run'} || $options->{'o'})
+ && $options->{'gen'})
+ {
+ push(@errors,
+"ERROR: The options '-regex', '-run', and '-o' are incompatible with '-gen'.
+ '-gen' says to stop at C generation, and the other three modify the
+ compilation and/or running process!\n");
+ }
+
+ if ($options->{'run'} && $options->{'mod'})
+ {
+ push(@errors,
+"ERROR: Can't run modules that you are compiling! '-run' and '-mod' are
+ incompatible!\n");
+ }
+
+ if ($options->{'e'} && @ARGV)
+ {
+ push (@errors,
+"ERROR: The option '-e' needs to be all by itself without any other
+ file arguments!\n");
+ }
+ if ($options->{'e'} && !($options->{'o'} || $options->{'run'}))
+ {
+ $options->{'run'} = 1;
+ }
+
+ if (!defined($options->{'verbose'}))
+ {
+ $options->{'verbose'} = ($options->{'log'})? 64 : 7;
+ }
+
+ my $verbose_error;
+
+ if ($options->{'verbose'} =~ m"[^tagfcd]" &&
+ !( $options->{'verbose'} eq '0' ||
+ ($options->{'verbose'} < 64 && $options->{'verbose'} > 0)))
+ {
+ $verbose_error = 1;
+ push(@errors,
+"ERROR: Illegal verbosity level. Needs to have either the letters
+ 't','a','g','f','c', or 'd' in it or be between 0 and 63, inclusive.\n");
+ }
+
+ $options->{'verbose'} = ($options->{'verbose'} =~ m"[tagfcd]")?
+ ($options->{'verbose'} =~ m"d") * 32 +
+ ($options->{'verbose'} =~ m"c") * 16 +
+ ($options->{'verbose'} =~ m"f") * 8 +
+ ($options->{'verbose'} =~ m"t") * 4 +
+ ($options->{'verbose'} =~ m"a") * 2 +
+ ($options->{'verbose'} =~ m"g") * 1
+ : $options->{'verbose'};
+
+ if (!$verbose_error && ( $options->{'log'} &&
+ !(
+ ($options->{'verbose'} & 8) ||
+ ($options->{'verbose'} & 16) ||
+ ($options->{'verbose'} & 32 )
+ )
+ )
+ )
+ {
+ push(@errors,
+"ERROR: The verbosity level '$options->{'verbose'}' does not output anything
+ to a logfile, and you specified '-log'!\n");
+ } # }
+
+ if (!$verbose_error && ( !$options->{'log'} &&
+ (
+ ($options->{'verbose'} & 8) ||
+ ($options->{'verbose'} & 16) ||
+ ($options->{'verbose'} & 32) ||
+ ($options->{'verbose'} & 64)
+ )
+ )
+ )
+ {
+ push(@errors,
+"ERROR: The verbosity level '$options->{'verbose'}' requires that you also
+ specify a logfile via '-log'\n");
+ } # }
+
+
+ (_print( "\n". join("\n", @errors), -1), return(0)) if (@errors);
+ return(1);
+}
+
+sub _print
+{
+ my ($text, $flag ) = @_;
+
+ my $logflag = int($flag/8) * 8;
+ my $regflag = $flag % 8;
+
+ if ($flag == -1 || ($flag & $options->{'verbose'}))
+ {
+ my $dolog = ((($logflag & $options->{'verbose'}) || $flag == -1)
+ && $options->{'log'});
+
+ my $doreg = (($regflag & $options->{'verbose'}) || $flag == -1);
+
+ if ($doreg) { print( STDERR $text ); }
+ if ($dolog) { print $_fh $text; }
+ }
+}
+
+sub _run
+{
+ my ($command, $flag) = @_;
+
+ my $logflag = ($flag != -1)? int($flag/8) * 8 : 0;
+ my $regflag = $flag % 8;
+
+ if ($flag == -1 || ($flag & $options->{'verbose'}))
+ {
+ my $dolog = ($logflag & $options->{'verbose'} && $options->{'log'});
+ my $doreg = (($regflag & $options->{'verbose'}) || $flag == -1);
+
+ if ($doreg && !$dolog)
+ { system("$command"); }
+
+ elsif ($doreg && $dolog)
+ { my $text = `$command 2>&1`; print $_fh $text; print STDERR $text;}
+ else
+ { my $text = `$command 2>&1`; print $_fh $text; }
+ }
+ else
+ {
+ `$command 2>&1`;
+ }
+ return($?);
+}
+
+sub _usage
+{
+ _print
+ (
+ <<"EOF"
+
+Usage: $0 <file_list>
+
+ Flags with arguments
+ -L < extra library dirs for installation (form of 'dir1:dir2') >
+ -I < extra include dirs for installation (form of 'dir1:dir2') >
+ -C < explicit name of resulting C code >
+ -o < explicit name of resulting executable >
+ -e < to compile 'one liners'. Need executable name (-o) or '-run'>
+ -regex < rename regex, -regex 's/\.p/\.exe/' compiles a.p to a.exe >
+ -verbose < verbose level (1-63, or following letters 'gatfcd' >
+ -argv < arguments for the executables to be run via '-run' or '-e' >
+
+ Boolean flags
+ -gen ( to just generate the c code. Implies '-sav' )
+ -sav ( to save intermediate c code, (and executables with '-run'))
+ -run ( to run the compiled program on the fly, as were interpreted.)
+ -prog ( to indicate that the files on command line are programs )
+ -mod ( to indicate that the files on command line are modules )
+
+EOF
+, -1
+
+ );
+ exit(255);
+}
+
+
+__END__
+
+=head1 NAME
+
+perlcc - frontend for perl compiler
+
+=head1 SYNOPSIS
+
+ %prompt perlcc a.p # compiles into executable 'a'
+
+ %prompt perlcc A.pm # compile into 'A.so'
+
+ %prompt perlcc a.p -o execute # compiles 'a.p' into 'execute'.
+
+ %prompt perlcc a.p -o execute -run # compiles 'a.p' into execute, runs on
+ # the fly
+
+ %prompt perlcc a.p -o execute -run -argv 'arg1 arg2 arg3'
+ # compiles into execute, runs with
+ # arg1 arg2 arg3 as @ARGV
+
+ %prompt perlcc a.p b.p c.p -regex 's/\.p/\.exe'
+ # compiles into 'a.exe','b.exe','c.exe'.
+
+ %prompt perlcc a.p -log compilelog # compiles into 'a', saves compilation
+ # info into compilelog, as well
+ # as mirroring to screen
+
+ %prompt perlcc a.p -log compilelog -verbose cdf
+ # compiles into 'a', saves compilation
+ # info into compilelog, being silent
+ # on screen.
+
+ %prompt perlcc a.p -C a.c -gen # generates C code (into a.c) and
+ # stops without compile.
+
+ %prompt perlcc a.p -L ../lib a.c
+ # Compiles with the perl libraries
+ # inside ../lib included.
+
+=head1 DESCRIPTION
+
+'perlcc' is the frontend into the perl compiler. Typing 'perlcc a.p'
+compiles the code inside a.p into a standalone executable, and
+perlcc A.pm will compile into a shared object, A.so, suitable for inclusion
+into a perl program via "use A".
+
+There are quite a few flags to perlcc which help with such issues as compiling
+programs in bulk, testing compiled programs for compatibility with the
+interpreter, and controlling.
+
+=head1 OPTIONS
+
+=over 4
+
+=item -L < library_directories >
+
+Adds directories in B<library_directories> to the compilation command.
+
+=item -I < include_directories >
+
+Adds directories inside B<include_directories> to the compilation command.
+
+=item -C < c_code_name >
+
+Explicitly gives the name B<c_code_name> to the generated c code which is to
+be compiled. Can only be used if compiling one file on the command line.
+
+=item -o < executable_name >
+
+Explicitly gives the name B<executable_name> to the executable which is to be
+compiled. Can only be used if compiling one file on the command line.
+
+=item -e < perl_line_to_execute>
+
+Compiles 'one liners', in the same way that B<perl -e> runs text strings at
+the command line. Default is to have the 'one liner' be compiled, and run all
+in one go (see B<-run>); giving the B<-o> flag saves the resultant executable,
+rather than throwing it away. Use '-argv' to pass arguments to the executable
+created.
+
+=item -regex <rename_regex>
+
+Gives a rule B<rename_regex> - which is a legal perl regular expression - to
+create executable file names.
+
+=item -verbose <verbose_level>
+
+Show exactly what steps perlcc is taking to compile your code. You can change
+the verbosity level B<verbose_level> much in the same way that the '-D' switch
+changes perl's debugging level, by giving either a number which is the sum of
+bits you want or a list of letters representing what you wish to see. Here are
+the verbosity levels so far :
+
+ Bit 1(g): Code Generation Errors to STDERR
+ Bit 2(a): Compilation Errors to STDERR
+ Bit 4(t): Descriptive text to STDERR
+ Bit 8(f): Code Generation Errors to file (B<-log> flag needed)
+ Bit 16(c): Compilation Errors to file (B<-log> flag needed)
+ Bit 32(d): Descriptive text to file (B<-log> flag needed)
+
+If the B<-log> tag is given, the default verbose level is 63 (ie: mirroring
+all of perlcc's output to both the screen and to a log file). If no B<-log>
+tag is given, then the default verbose level is 7 (ie: outputting all of
+perlcc's output to STDERR).
+
+NOTE: Because of buffering concerns, you CANNOT shadow the output of '-run' to
+both a file, and to the screen! Suggestions are welcome on how to overcome this
+difficulty, but for now it simply does not work properly, and hence will only go
+to the screen.
+
+=item -log <logname>
+
+Opens, for append, a logfile to save some or all of the text for a given
+compile command. No rewrite version is available, so this needs to be done
+manually.
+
+=item -argv <arguments>
+
+In combination with '-run' or '-e', tells perlcc to run the resulting
+executable with the string B<arguments> as @ARGV.
+
+=item -sav
+
+Tells perl to save the intermediate C code. Usually, this C code is the name
+of the perl code, plus '.c'; 'perlcode.p' gets generated in 'perlcode.p.c',
+for example. If used with the '-e' operator, you need to tell perlcc where to
+save resulting executables.
+
+=item -gen
+
+Tells perlcc to only create the intermediate C code, and not compile the
+results. Does an implicit B<-sav>, saving the C code rather than deleting it.
+
+=item -run
+
+Immediately run the perl code that has been generated. NOTE: IF YOU GIVE THE
+B<-run> FLAG TO B<perlcc>, THEN THE REST OF @ARGV WILL BE INTERPRETED AS
+ARGUMENTS TO THE PROGRAM THAT YOU ARE COMPILING.
+
+=item -prog
+
+Indicate that the programs at the command line are programs, and should be
+compiled as such. B<perlcc> will automatically determine files to be
+programs if they have B<.p>, B<.pl>, B<.bat> extensions.
+
+=item -mod
+
+Indicate that the programs at the command line are modules, and should be
+compiled as such. B<perlcc> will automatically determine files to be
+modules if they have the extension B<.pm>.
+
+=back
+
+=head1 ENVIRONMENT
+
+Most of the work of B<perlcc> is done at the command line. However, you can
+change the heuristic which determines what is a module and what is a program.
+As indicated above, B<perlcc> assumes that the extensions:
+
+.p$, .pl$, and .bat$
+
+indicate a perl program, and:
+
+.pm$
+
+indicate a library, for the purposes of creating executables. And furthermore,
+by default, these extensions will be replaced (and dropped ) in the process of
+creating an executable.
+
+To change the extensions which are programs, and which are modules, set the
+environmental variables:
+
+PERL_SCRIPT_EXT
+PERL_MODULE_EXT
+
+These two environmental variables take colon-separated, legal perl regular
+expressions, and are used by perlcc to decide which objects are which.
+For example:
+
+setenv PERL_SCRIPT_EXT '.prl$:.perl$'
+prompt% perlcc sample.perl
+
+will compile the script 'sample.perl' into the executable 'sample', and
+
+setenv PERL_MODULE_EXT '.perlmod$:.perlmodule$'
+
+prompt% perlcc sample.perlmod
+
+will compile the module 'sample.perlmod' into the shared object
+'sample.so'
+
+NOTE: the '.' in the regular expressions for PERL_SCRIPT_EXT and PERL_MODULE_EXT
+is a literal '.', and not a wild-card. To get a true wild-card, you need to
+backslash the '.'; as in:
+
+setenv PERL_SCRIPT_EXT '\.\.\.\.\.'
+
+which would have the effect of compiling ANYTHING (except what is in
+PERL_MODULE_EXT) into an executable with 5 less characters in its name.
+
+=head1 FILES
+
+'perlcc' uses a temporary file when you use the B<-e> option to evaluate
+text and compile it. This temporary file is 'perlc$$.p'. The temporary C code is
+perlc$$.p.c, and the temporary executable is perlc$$.
+
+When you use '-run' and don't save your executable, the temporary executable is
+perlc$$
+
+=head1 BUGS
+
+perlcc currently cannot compile shared objects on Win32. This should be fixed
+by perl5.005.
+
+=cut
+
+!NO!SUBS!
+
+close OUT or die "Can't close $file: $!";
+chmod 0755, $file or die "Can't reset permissions for $file: $!\n";
+exec("$Config{'eunicefix'} $file") if $Config{'eunicefix'} ne ':';
+chdir $origdir;
diff --git a/contrib/perl5/utils/perldoc.PL b/contrib/perl5/utils/perldoc.PL
new file mode 100644
index 0000000..875cd25
--- /dev/null
+++ b/contrib/perl5/utils/perldoc.PL
@@ -0,0 +1,687 @@
+#!/usr/local/bin/perl
+
+use Config;
+use File::Basename qw(&basename &dirname);
+use Cwd;
+
+# List explicitly here the variables you want Configure to
+# generate. Metaconfig only looks for shell variables, so you
+# have to mention them as if they were shell variables, not
+# %Config entries. Thus you write
+# $startperl
+# to ensure Configure will look for $Config{startperl}.
+
+# This forces PL files to create target in same directory as PL file.
+# This is so that make depend always knows where to find PL derivatives.
+$origdir = cwd;
+chdir dirname($0);
+$file = basename($0, '.PL');
+$file .= '.com' if $^O eq 'VMS';
+
+open OUT,">$file" or die "Can't create $file: $!";
+
+print "Extracting $file (with variable substitutions)\n";
+
+# In this section, perl variables will be expanded during extraction.
+# You can use $Config{...} to use Configure variables.
+
+print OUT <<"!GROK!THIS!";
+$Config{startperl}
+ eval 'exec $Config{perlpath} -S \$0 \${1+"\$@"}'
+ if 0;
+
+use strict;
+my \@pagers = ();
+push \@pagers, "$Config{'pager'}" if -x "$Config{'pager'}";
+!GROK!THIS!
+
+# In the following, perl variables are not expanded during extraction.
+
+print OUT <<'!NO!SUBS!';
+
+#
+# Perldoc revision #1 -- look up a piece of documentation in .pod format that
+# is embedded in the perl installation tree.
+#
+# This is not to be confused with Tom Christianson's perlman, which is a
+# man replacement, written in perl. This perldoc is strictly for reading
+# the perl manuals, though it too is written in perl.
+
+if(@ARGV<1) {
+ my $me = $0; # Editing $0 is unportable
+ $me =~ s,.*/,,;
+ die <<EOF;
+Usage: $me [-h] [-r] [-i] [-v] [-t] [-u] [-m] [-l] [-F] [-X] PageName|ModuleName|ProgramName
+ $me -f PerlFunc
+ $me -q FAQKeywords
+
+The -h option prints more help. Also try "perldoc perldoc" to get
+aquainted with the system.
+EOF
+}
+
+use Getopt::Std;
+use Config '%Config';
+
+my @global_found = ();
+my $global_target = "";
+
+my $Is_VMS = $^O eq 'VMS';
+my $Is_MSWin32 = $^O eq 'MSWin32';
+my $Is_Dos = $^O eq 'dos';
+
+sub usage{
+ warn "@_\n" if @_;
+ # Erase evidence of previous errors (if any), so exit status is simple.
+ $! = 0;
+ die <<EOF;
+perldoc [options] PageName|ModuleName|ProgramName...
+perldoc [options] -f BuiltinFunction
+perldoc [options] -q FAQRegex
+
+Options:
+ -h Display this help message
+ -r Recursive search (slow)
+ -i Ignore case
+ -t Display pod using pod2text instead of pod2man and nroff
+ (-t is the default on win32)
+ -u Display unformatted pod text
+ -m Display module's file in its entirety
+ -l Display the module's file name
+ -F Arguments are file names, not modules
+ -v Verbosely describe what's going on
+ -X use index if present (looks for pod.idx at $Config{archlib})
+
+
+PageName|ModuleName...
+ is the name of a piece of documentation that you want to look at. You
+ may either give a descriptive name of the page (as in the case of
+ `perlfunc') the name of a module, either like `Term::Info',
+ `Term/Info', the partial name of a module, like `info', or
+ `makemaker', or the name of a program, like `perldoc'.
+
+BuiltinFunction
+ is the name of a perl function. Will extract documentation from
+ `perlfunc'.
+
+FAQRegex
+ is a regex. Will search perlfaq[1-9] for and extract any
+ questions that match.
+
+Any switches in the PERLDOC environment variable will be used before the
+command line arguments. The optional pod index file contains a list of
+filenames, one per line.
+
+EOF
+}
+
+if( defined $ENV{"PERLDOC"} ) {
+ require Text::ParseWords;
+ unshift(@ARGV, Text::ParseWords::shellwords($ENV{"PERLDOC"}));
+}
+!NO!SUBS!
+
+my $getopts = "mhtluvriFf:Xq:";
+print OUT <<"!GET!OPTS!";
+
+use vars qw( @{[map "\$opt_$_", ($getopts =~ /\w/g)]} );
+
+getopts("$getopts") || usage;
+!GET!OPTS!
+
+print OUT <<'!NO!SUBS!';
+
+usage if $opt_h;
+
+my $podidx;
+if( $opt_X ) {
+ $podidx = "$Config{'archlib'}/pod.idx";
+ $podidx = "" unless -f $podidx && -r _ && -M _ <= 7;
+}
+
+if( (my $opts = do{ local $^W; $opt_t + $opt_u + $opt_m + $opt_l }) > 1) {
+ usage("only one of -t, -u, -m or -l")
+} elsif ($Is_MSWin32 || $Is_Dos) {
+ $opt_t = 1 unless $opts
+}
+
+if ($opt_t) { require Pod::Text; import Pod::Text; }
+
+my @pages;
+if ($opt_f) {
+ @pages = ("perlfunc");
+} elsif ($opt_q) {
+ @pages = ("perlfaq1" .. "perlfaq9");
+} else {
+ @pages = @ARGV;
+}
+
+# Does this look like a module or extension directory?
+if (-f "Makefile.PL") {
+ # Add ., lib and blib/* libs to @INC (if they exist)
+ unshift(@INC, '.');
+ unshift(@INC, 'lib') if -d 'lib';
+ require ExtUtils::testlib;
+}
+
+
+
+sub containspod {
+ my($file, $readit) = @_;
+ return 1 if !$readit && $file =~ /\.pod$/i;
+ local($_);
+ open(TEST,"<$file");
+ while(<TEST>) {
+ if(/^=head/) {
+ close(TEST);
+ return 1;
+ }
+ }
+ close(TEST);
+ return 0;
+}
+
+sub minus_f_nocase {
+ my($dir,$file) = @_;
+ my $path = join('/',$dir,$file);
+ return $path if -f $path and -r _;
+ if (!$opt_i or $Is_VMS or $Is_MSWin32 or $Is_Dos or $^O eq 'os2') {
+ # on a case-forgiving file system or if case is important
+ # that is it all we can do
+ warn "Ignored $file: unreadable\n" if -f _;
+ return '';
+ }
+ local *DIR;
+ local($")="/";
+ my @p = ($dir);
+ my($p,$cip);
+ foreach $p (split(/\//, $file)){
+ my $try = "@p/$p";
+ stat $try;
+ if (-d _){
+ push @p, $p;
+ if ( $p eq $global_target) {
+ my $tmp_path = join ('/', @p);
+ my $path_f = 0;
+ for (@global_found) {
+ $path_f = 1 if $_ eq $tmp_path;
+ }
+ push (@global_found, $tmp_path) unless $path_f;
+ print STDERR "Found as @p but directory\n" if $opt_v;
+ }
+ } elsif (-f _ && -r _) {
+ return $try;
+ } elsif (-f _) {
+ warn "Ignored $try: unreadable\n";
+ } else {
+ my $found=0;
+ my $lcp = lc $p;
+ opendir DIR, "@p";
+ while ($cip=readdir(DIR)) {
+ if (lc $cip eq $lcp){
+ $found++;
+ last;
+ }
+ }
+ closedir DIR;
+ return "" unless $found;
+ push @p, $cip;
+ return "@p" if -f "@p" and -r _;
+ warn "Ignored $file: unreadable\n" if -f _;
+ }
+ }
+ return "";
+}
+
+
+sub check_file {
+ my($dir,$file) = @_;
+ if ($opt_m) {
+ return minus_f_nocase($dir,$file);
+ } else {
+ my $path = minus_f_nocase($dir,$file);
+ return $path if length $path and containspod($path);
+ }
+ return "";
+}
+
+
+sub searchfor {
+ my($recurse,$s,@dirs) = @_;
+ $s =~ s!::!/!g;
+ $s = VMS::Filespec::unixify($s) if $Is_VMS;
+ return $s if -f $s && containspod($s);
+ printf STDERR "Looking for $s in @dirs\n" if $opt_v;
+ my $ret;
+ my $i;
+ my $dir;
+ $global_target = (split('/', $s))[-1];
+ for ($i=0; $i<@dirs; $i++) {
+ $dir = $dirs[$i];
+ ($dir = VMS::Filespec::unixpath($dir)) =~ s!/$!! if $Is_VMS;
+ if ( ( $ret = check_file $dir,"$s.pod")
+ or ( $ret = check_file $dir,"$s.pm")
+ or ( $ret = check_file $dir,$s)
+ or ( $Is_VMS and
+ $ret = check_file $dir,"$s.com")
+ or ( $^O eq 'os2' and
+ $ret = check_file $dir,"$s.cmd")
+ or ( ($Is_MSWin32 or $Is_Dos or $^O eq 'os2') and
+ $ret = check_file $dir,"$s.bat")
+ or ( $ret = check_file "$dir/pod","$s.pod")
+ or ( $ret = check_file "$dir/pod",$s)
+ ) {
+ return $ret;
+ }
+
+ if ($recurse) {
+ opendir(D,$dir);
+ my @newdirs = map "$dir/$_", grep {
+ not /^\.\.?$/ and
+ not /^auto$/ and # save time! don't search auto dirs
+ -d "$dir/$_"
+ } readdir D;
+ closedir(D);
+ next unless @newdirs;
+ @newdirs = map((s/.dir$//,$_)[1],@newdirs) if $Is_VMS;
+ print STDERR "Also looking in @newdirs\n" if $opt_v;
+ push(@dirs,@newdirs);
+ }
+ }
+ return ();
+}
+
+my @found;
+foreach (@pages) {
+ if ($podidx && open(PODIDX, $podidx)) {
+ my $searchfor = $_;
+ local($_);
+ $searchfor =~ s,::,/,g;
+ print STDERR "Searching for '$searchfor' in $podidx\n" if $opt_v;
+ while (<PODIDX>) {
+ chomp;
+ push(@found, $_) if m,/$searchfor(?:\.(?:pod|pm))?$,i;
+ }
+ close(PODIDX);
+ next;
+ }
+ print STDERR "Searching for $_\n" if $opt_v;
+ # We must look both in @INC for library modules and in PATH
+ # for executables, like h2xs or perldoc itself.
+ my @searchdirs = @INC;
+ if ($opt_F) {
+ next unless -r;
+ push @found, $_ if $opt_m or containspod($_);
+ next;
+ }
+ unless ($opt_m) {
+ if ($Is_VMS) {
+ my($i,$trn);
+ for ($i = 0; $trn = $ENV{'DCL$PATH'.$i}; $i++) {
+ push(@searchdirs,$trn);
+ }
+ push(@searchdirs,'perl_root:[lib.pod]') # installed pods
+ } else {
+ push(@searchdirs, grep(-d, split($Config{path_sep},
+ $ENV{'PATH'})));
+ }
+ }
+ my @files = searchfor(0,$_,@searchdirs);
+ if( @files ) {
+ print STDERR "Found as @files\n" if $opt_v;
+ } else {
+ # no match, try recursive search
+
+ @searchdirs = grep(!/^\.$/,@INC);
+
+ @files= searchfor(1,$_,@searchdirs) if $opt_r;
+ if( @files ) {
+ print STDERR "Loosely found as @files\n" if $opt_v;
+ } else {
+ print STDERR "No documentation found for \"$_\".\n";
+ if (@global_found) {
+ print STDERR "However, try\n";
+ for my $dir (@global_found) {
+ opendir(DIR, $dir) or die "$!";
+ while (my $file = readdir(DIR)) {
+ next if ($file =~ /^\./);
+ $file =~ s/\.(pm|pod)$//;
+ print STDERR "\tperldoc $_\::$file\n";
+ }
+ closedir DIR;
+ }
+ }
+ }
+ }
+ push(@found,@files);
+}
+
+if(!@found) {
+ exit ($Is_VMS ? 98962 : 1);
+}
+
+if ($opt_l) {
+ print join("\n", @found), "\n";
+ exit;
+}
+
+my $lines = $ENV{LINES} || 24;
+
+my $no_tty;
+if( ! -t STDOUT ) { $no_tty = 1 }
+
+my $tmp;
+if ($Is_MSWin32) {
+ $tmp = "$ENV{TEMP}\\perldoc1.$$";
+ push @pagers, qw( more< less notepad );
+ unshift @pagers, $ENV{PAGER} if $ENV{PAGER};
+} elsif ($Is_VMS) {
+ $tmp = 'Sys$Scratch:perldoc.tmp1_'.$$;
+ push @pagers, qw( most more less type/page );
+} elsif ($Is_Dos) {
+ $tmp = "$ENV{TEMP}/perldoc1.$$";
+ $tmp =~ tr!\\/!//!s;
+ push @pagers, qw( less.exe more.com< );
+ unshift @pagers, $ENV{PAGER} if $ENV{PAGER};
+} else {
+ if ($^O eq 'os2') {
+ require POSIX;
+ $tmp = POSIX::tmpnam();
+ unshift @pagers, 'less', 'cmd /c more <';
+ } else {
+ $tmp = "/tmp/perldoc1.$$";
+ }
+ push @pagers, qw( more less pg view cat );
+ unshift @pagers, $ENV{PAGER} if $ENV{PAGER};
+}
+unshift @pagers, $ENV{PERLDOC_PAGER} if $ENV{PERLDOC_PAGER};
+
+if ($opt_m) {
+ foreach my $pager (@pagers) {
+ system("$pager @found") or exit;
+ }
+ if ($Is_VMS) { eval 'use vmsish qw(status exit); exit $?' }
+ exit 1;
+}
+
+if ($opt_f) {
+ my $perlfunc = shift @found;
+ open(PFUNC, $perlfunc) or die "Can't open $perlfunc: $!";
+
+ # Skip introduction
+ while (<PFUNC>) {
+ last if /^=head2 Alphabetical Listing of Perl Functions/;
+ }
+
+ # Look for our function
+ my $found = 0;
+ my @pod;
+ while (<PFUNC>) {
+ if (/^=item\s+\Q$opt_f\E\b/o) {
+ $found = 1;
+ } elsif (/^=item/) {
+ last if $found > 1;
+ }
+ next unless $found;
+ push @pod, $_;
+ ++$found if /^\w/; # found descriptive text
+ }
+ if (@pod) {
+ if ($opt_t) {
+ open(FORMATTER, "| pod2text") || die "Can't start filter";
+ print FORMATTER "=over 8\n\n";
+ print FORMATTER @pod;
+ print FORMATTER "=back\n";
+ close(FORMATTER);
+ } elsif (@pod < $lines-2) {
+ print @pod;
+ } else {
+ foreach my $pager (@pagers) {
+ open (PAGER, "| $pager") or next;
+ print PAGER @pod ;
+ close(PAGER) or next;
+ last;
+ }
+ }
+ } else {
+ die "No documentation for perl function `$opt_f' found\n";
+ }
+ exit;
+}
+
+if ($opt_q) {
+ local @ARGV = @found; # I'm lazy, sue me.
+ my $found = 0;
+ my %found_in;
+ my @pod;
+
+ while (<>) {
+ if (/^=head2\s+.*$opt_q/oi) {
+ $found = 1;
+ push @pod, "=head1 Found in $ARGV\n\n" unless $found_in{$ARGV}++;
+ } elsif (/^=head2/) {
+ $found = 0;
+ }
+ next unless $found;
+ push @pod, $_;
+ }
+
+ if (@pod) {
+ if ($opt_t) {
+ open(FORMATTER, "| pod2text") || die "Can't start filter";
+ print FORMATTER "=over 8\n\n";
+ print FORMATTER @pod;
+ print FORMATTER "=back\n";
+ close(FORMATTER);
+ } elsif (@pod < $lines-2) {
+ print @pod;
+ } else {
+ foreach my $pager (@pagers) {
+ open (PAGER, "| $pager") or next;
+ print PAGER @pod ;
+ close(PAGER) or next;
+ last;
+ }
+ }
+ } else {
+ die "No documentation for perl FAQ keyword `$opt_q' found\n";
+ }
+ exit;
+}
+
+foreach (@found) {
+
+ my $err;
+ if($opt_t) {
+ open(TMP,">>$tmp");
+ Pod::Text::pod2text($_,*TMP);
+ close(TMP);
+ } elsif(not $opt_u) {
+ my $cmd = "pod2man --lax $_ | nroff -man";
+ $cmd .= " | col -x" if $^O =~ /hpux/;
+ my $rslt = `$cmd`;
+ unless(($err = $?)) {
+ open(TMP,">>$tmp");
+ print TMP $rslt;
+ close TMP;
+ }
+ }
+
+ if( $opt_u or $err or -z $tmp) {
+ open(OUT,">>$tmp");
+ open(IN,"<$_");
+ my $cut = 1;
+ while (<IN>) {
+ $cut = $1 eq 'cut' if /^=(\w+)/;
+ next if $cut;
+ print OUT;
+ }
+ close(IN);
+ close(OUT);
+ }
+}
+
+if( $no_tty ) {
+ open(TMP,"<$tmp");
+ print while <TMP>;
+ close(TMP);
+} else {
+ foreach my $pager (@pagers) {
+ system("$pager $tmp") or last;
+ }
+}
+
+1 while unlink($tmp); #Possibly pointless VMSism
+
+exit 0;
+
+__END__
+
+=head1 NAME
+
+perldoc - Look up Perl documentation in pod format.
+
+=head1 SYNOPSIS
+
+B<perldoc> [B<-h>] [B<-v>] [B<-t>] [B<-u>] [B<-m>] [B<-l>] [B<-F>] [B<-X>] PageName|ModuleName|ProgramName
+
+B<perldoc> B<-f> BuiltinFunction
+
+B<perldoc> B<-q> FAQ Keyword
+
+=head1 DESCRIPTION
+
+I<perldoc> looks up a piece of documentation in .pod format that is embedded
+in the perl installation tree or in a perl script, and displays it via
+C<pod2man | nroff -man | $PAGER>. (In addition, if running under HP-UX,
+C<col -x> will be used.) This is primarily used for the documentation for
+the perl library modules.
+
+Your system may also have man pages installed for those modules, in
+which case you can probably just use the man(1) command.
+
+=head1 OPTIONS
+
+=over 5
+
+=item B<-h> help
+
+Prints out a brief help message.
+
+=item B<-v> verbose
+
+Describes search for the item in detail.
+
+=item B<-t> text output
+
+Display docs using plain text converter, instead of nroff. This may be faster,
+but it won't look as nice.
+
+=item B<-u> unformatted
+
+Find docs only; skip reformatting by pod2*
+
+=item B<-m> module
+
+Display the entire module: both code and unformatted pod documentation.
+This may be useful if the docs don't explain a function in the detail
+you need, and you'd like to inspect the code directly; perldoc will find
+the file for you and simply hand it off for display.
+
+=item B<-l> file name only
+
+Display the file name of the module found.
+
+=item B<-F> file names
+
+Consider arguments as file names, no search in directories will be performed.
+
+=item B<-f> perlfunc
+
+The B<-f> option followed by the name of a perl built in function will
+extract the documentation of this function from L<perlfunc>.
+
+=item B<-q> perlfaq
+
+The B<-q> option takes a regular expression as an argument. It will search
+the question headings in perlfaq[1-9] and print the entries matching
+the regular expression.
+
+=item B<-X> use an index if present
+
+The B<-X> option looks for a entry whose basename matches the name given on the
+command line in the file C<$Config{archlib}/pod.idx>. The pod.idx file should
+contain fully qualified filenames, one per line.
+
+=item B<PageName|ModuleName|ProgramName>
+
+The item you want to look up. Nested modules (such as C<File::Basename>)
+are specified either as C<File::Basename> or C<File/Basename>. You may also
+give a descriptive name of a page, such as C<perlfunc>. You make also give a
+partial or wrong-case name, such as "basename" for "File::Basename", but
+this will be slower, if there is more then one page with the same partial
+name, you will only get the first one.
+
+=back
+
+=head1 ENVIRONMENT
+
+Any switches in the C<PERLDOC> environment variable will be used before the
+command line arguments. C<perldoc> also searches directories
+specified by the C<PERL5LIB> (or C<PERLLIB> if C<PERL5LIB> is not
+defined) and C<PATH> environment variables.
+(The latter is so that embedded pods for executables, such as
+C<perldoc> itself, are available.) C<perldoc> will use, in order of
+preference, the pager defined in C<PERLDOC_PAGER>, C<MANPAGER>, or
+C<PAGER> before trying to find a pager on its own. (C<MANPAGER> is not
+used if C<perldoc> was told to display plain text or unformatted pod.)
+
+=head1 AUTHOR
+
+Kenneth Albanowski <kjahds@kjahds.com>
+
+Minor updates by Andy Dougherty <doughera@lafcol.lafayette.edu>
+
+=cut
+
+#
+# Version 1.14: Wed Jul 15 01:50:20 EST 1998
+# Robin Barker <rmb1@cise.npl.co.uk>
+# -strict, -w cleanups
+# Version 1.13: Fri Feb 27 16:20:50 EST 1997
+# Gurusamy Sarathy <gsar@umich.edu>
+# -doc tweaks for -F and -X options
+# Version 1.12: Sat Apr 12 22:41:09 EST 1997
+# Gurusamy Sarathy <gsar@umich.edu>
+# -various fixes for win32
+# Version 1.11: Tue Dec 26 09:54:33 EST 1995
+# Kenneth Albanowski <kjahds@kjahds.com>
+# -added Charles Bailey's further VMS patches, and -u switch
+# -added -t switch, with pod2text support
+#
+# Version 1.10: Thu Nov 9 07:23:47 EST 1995
+# Kenneth Albanowski <kjahds@kjahds.com>
+# -added VMS support
+# -added better error recognition (on no found pages, just exit. On
+# missing nroff/pod2man, just display raw pod.)
+# -added recursive/case-insensitive matching (thanks, Andreas). This
+# slows things down a bit, unfortunately. Give a precise name, and
+# it'll run faster.
+#
+# Version 1.01: Tue May 30 14:47:34 EDT 1995
+# Andy Dougherty <doughera@lafcol.lafayette.edu>
+# -added pod documentation.
+# -added PATH searching.
+# -added searching pod/ subdirectory (mainly to pick up perlfunc.pod
+# and friends.
+#
+#
+# TODO:
+#
+# Cache directories read during sloppy match
+!NO!SUBS!
+
+close OUT or die "Can't close $file: $!";
+chmod 0755, $file or die "Can't reset permissions for $file: $!\n";
+exec("$Config{'eunicefix'} $file") if $Config{'eunicefix'} ne ':';
+chdir $origdir;
diff --git a/contrib/perl5/utils/pl2pm.PL b/contrib/perl5/utils/pl2pm.PL
new file mode 100644
index 0000000..48e281d
--- /dev/null
+++ b/contrib/perl5/utils/pl2pm.PL
@@ -0,0 +1,389 @@
+#!/usr/local/bin/perl
+
+use Config;
+use File::Basename qw(&basename &dirname);
+use Cwd;
+
+# List explicitly here the variables you want Configure to
+# generate. Metaconfig only looks for shell variables, so you
+# have to mention them as if they were shell variables, not
+# %Config entries. Thus you write
+# $startperl
+# to ensure Configure will look for $Config{startperl}.
+
+# This forces PL files to create target in same directory as PL file.
+# This is so that make depend always knows where to find PL derivatives.
+$origdir = cwd;
+chdir dirname($0);
+$file = basename($0, '.PL');
+$file .= '.com' if $^O eq 'VMS';
+
+open OUT,">$file" or die "Can't create $file: $!";
+
+print "Extracting $file (with variable substitutions)\n";
+
+# In this section, perl variables will be expanded during extraction.
+# You can use $Config{...} to use Configure variables.
+
+print OUT <<"!GROK!THIS!";
+$Config{startperl}
+ eval 'exec $Config{perlpath} -S \$0 \${1+"\$@"}'
+ if \$running_under_some_shell;
+!GROK!THIS!
+
+# In the following, perl variables are not expanded during extraction.
+
+print OUT <<'!NO!SUBS!';
+
+=head1 NAME
+
+pl2pm - Rough tool to translate Perl4 .pl files to Perl5 .pm modules.
+
+=head1 SYNOPSIS
+
+B<pl2pm> F<files>
+
+=head1 DESCRIPTION
+
+B<pl2pm> is a tool to aid in the conversion of Perl4-style .pl
+library files to Perl5-style library modules. Usually, your old .pl
+file will still work fine and you should only use this tool if you
+plan to update your library to use some of the newer Perl 5 features,
+such as AutoLoading.
+
+=head1 LIMITATIONS
+
+It's just a first step, but it's usually a good first step.
+
+=head1 AUTHOR
+
+Larry Wall <larry@wall.org>
+
+=cut
+
+while (<DATA>) {
+ chop;
+ $keyword{$_} = 1;
+}
+
+undef $/;
+$* = 1;
+while (<>) {
+ $newname = $ARGV;
+ $newname =~ s/\.pl$/.pm/ || next;
+ $newname =~ s#(.*/)?(\w+)#$1\u$2#;
+ if (-f $newname) {
+ warn "Won't overwrite existing $newname\n";
+ next;
+ }
+ $oldpack = $2;
+ $newpack = "\u$2";
+ @export = ();
+ print "$oldpack => $newpack\n" if $verbose;
+
+ s/\bstd(in|out|err)\b/\U$&/g;
+ s/(sub\s+)(\w+)(\s*\{[ \t]*\n)\s*package\s+$oldpack\s*;[ \t]*\n+/${1}main'$2$3/ig;
+ if (/sub\s+main'/) {
+ @export = m/sub\s+main'(\w+)/g;
+ s/(sub\s+)main'(\w+)/$1$2/g;
+ }
+ else {
+ @export = m/sub\s+([A-Za-z]\w*)/g;
+ }
+ @export_ok = grep($keyword{$_}, @export);
+ @export = grep(!$keyword{$_}, @export);
+ @export{@export} = (1) x @export;
+ s/(^\s*);#/$1#/g;
+ s/(#.*)require ['"]$oldpack\.pl['"]/$1use $newpack/;
+ s/(package\s*)($oldpack)\s*;[ \t]*\n+//ig;
+ s/([\$\@%&*])'(\w+)/&xlate($1,"",$2)/eg;
+ s/([\$\@%&*]?)(\w+)'(\w+)/&xlate($1,$2,$3)/eg;
+ if (!/\$\[\s*\)?\s*=\s*[^0\s]/) {
+ s/^\s*(local\s*\()?\s*\$\[\s*\)?\s*=\s*0\s*;[ \t]*\n//g;
+ s/\$\[\s*\+\s*//g;
+ s/\s*\+\s*\$\[//g;
+ s/\$\[/0/g;
+ }
+ s/open\s+(\w+)/open($1)/g;
+
+ if (s/\bdie\b/croak/g) {
+ $carp = "use Carp;\n";
+ s/croak "([^"]*)\\n"/croak "$1"/g;
+ }
+ else {
+ $carp = "";
+ }
+ if (@export_ok) {
+ $export_ok = "\@EXPORT_OK = qw(@export_ok);\n";
+ }
+ else {
+ $export_ok = "";
+ }
+
+ open(PM, ">$newname") || warn "Can't create $newname: $!\n";
+ print PM <<"END";
+package $newpack;
+require 5.000;
+require Exporter;
+$carp
+\@ISA = qw(Exporter);
+\@EXPORT = qw(@export);
+$export_ok
+$_
+END
+}
+
+sub xlate {
+ local($prefix, $pack, $ident) = @_;
+ if ($prefix eq '' && $ident =~ /^(t|s|m|d|ing|ll|ed|ve|re)$/) {
+ "${pack}'$ident";
+ }
+ elsif ($pack eq "" || $pack eq "main") {
+ if ($export{$ident}) {
+ "$prefix$ident";
+ }
+ else {
+ "$prefix${pack}::$ident";
+ }
+ }
+ elsif ($pack eq $oldpack) {
+ "$prefix${newpack}::$ident";
+ }
+ else {
+ "$prefix${pack}::$ident";
+ }
+}
+__END__
+AUTOLOAD
+BEGIN
+CORE
+DESTROY
+END
+abs
+accept
+alarm
+and
+atan2
+bind
+binmode
+bless
+caller
+chdir
+chmod
+chop
+chown
+chr
+chroot
+close
+closedir
+cmp
+connect
+continue
+cos
+crypt
+dbmclose
+dbmopen
+defined
+delete
+die
+do
+dump
+each
+else
+elsif
+endgrent
+endhostent
+endnetent
+endprotoent
+endpwent
+endservent
+eof
+eq
+eval
+exec
+exit
+exp
+fcntl
+fileno
+flock
+for
+foreach
+fork
+format
+formline
+ge
+getc
+getgrent
+getgrgid
+getgrnam
+gethostbyaddr
+gethostbyname
+gethostent
+getlogin
+getnetbyaddr
+getnetbyname
+getnetent
+getpeername
+getpgrp
+getppid
+getpriority
+getprotobyname
+getprotobynumber
+getprotoent
+getpwent
+getpwnam
+getpwuid
+getservbyname
+getservbyport
+getservent
+getsockname
+getsockopt
+glob
+gmtime
+goto
+grep
+gt
+hex
+if
+index
+int
+ioctl
+join
+keys
+kill
+last
+lc
+lcfirst
+le
+length
+link
+listen
+local
+localtime
+log
+lstat
+lt
+m
+mkdir
+msgctl
+msgget
+msgrcv
+msgsnd
+my
+ne
+next
+no
+not
+oct
+open
+opendir
+or
+ord
+pack
+package
+pipe
+pop
+print
+printf
+push
+q
+qq
+quotemeta
+qw
+qx
+rand
+read
+readdir
+readline
+readlink
+readpipe
+recv
+redo
+ref
+rename
+require
+reset
+return
+reverse
+rewinddir
+rindex
+rmdir
+s
+scalar
+seek
+seekdir
+select
+semctl
+semget
+semop
+send
+setgrent
+sethostent
+setnetent
+setpgrp
+setpriority
+setprotoent
+setpwent
+setservent
+setsockopt
+shift
+shmctl
+shmget
+shmread
+shmwrite
+shutdown
+sin
+sleep
+socket
+socketpair
+sort
+splice
+split
+sprintf
+sqrt
+srand
+stat
+study
+sub
+substr
+symlink
+syscall
+sysread
+system
+syswrite
+tell
+telldir
+tie
+time
+times
+tr
+truncate
+uc
+ucfirst
+umask
+undef
+unless
+unlink
+unpack
+unshift
+untie
+until
+use
+utime
+values
+vec
+wait
+waitpid
+wantarray
+warn
+while
+write
+x
+xor
+y
+!NO!SUBS!
+
+close OUT or die "Can't close $file: $!";
+chmod 0755, $file or die "Can't reset permissions for $file: $!\n";
+exec("$Config{'eunicefix'} $file") if $Config{'eunicefix'} ne ':';
+chdir $origdir;
diff --git a/contrib/perl5/utils/splain.PL b/contrib/perl5/utils/splain.PL
new file mode 100644
index 0000000..a638dba
--- /dev/null
+++ b/contrib/perl5/utils/splain.PL
@@ -0,0 +1,49 @@
+#!/usr/local/bin/perl
+
+use Config;
+use File::Basename qw(&basename &dirname);
+use Cwd;
+
+# List explicitly here the variables you want Configure to
+# generate. Metaconfig only looks for shell variables, so you
+# have to mention them as if they were shell variables, not
+# %Config entries:
+# $startperl
+# $perlpath
+# $eunicefix
+
+# This forces PL files to create target in same directory as PL file.
+# This is so that make depend always knows where to find PL derivatives.
+$origdir = cwd;
+chdir dirname($0);
+$file = basename($0, '.PL');
+$file .= '.com' if $^O eq 'VMS';
+
+# Open input file before creating output file.
+$IN = '../lib/diagnostics.pm';
+open IN or die "Can't open $IN: $!\n";
+
+# Create output file.
+open OUT,">$file" or die "Can't create $file: $!";
+
+print "Extracting $file (with variable substitutions)\n";
+
+# In this section, perl variables will be expanded during extraction.
+# You can use $Config{...} to use Configure variables.
+
+print OUT <<"!GROK!THIS!";
+$Config{startperl}
+ eval 'exec $Config{perlpath} -S \$0 \${1+"\$@"}'
+ if \$running_under_some_shell;
+!GROK!THIS!
+
+while (<IN>) {
+ print OUT unless /^package diagnostics/;
+}
+
+close IN;
+
+close OUT or die "Can't close $file: $!";
+chmod 0755, $file or die "Can't reset permissions for $file: $!\n";
+exec("$Config{'eunicefix'} $file") if $Config{'eunicefix'} ne ':';
+chdir $origdir;
OpenPOWER on IntegriCloud