Integrated changes on mainline into the win32 branch. Had to set
Gurusamy Sarathy [Fri, 10 Oct 1997 20:58:40 +0000 (20:58 +0000)]
P4USER=mbeattie for the resolve step (due to the presence of newly
branched files that had not been submitted?)

p4raw-id: //depot/win32/perl@122

1  2 
Porting/makerel
Porting/patchls
README.threads
win32/config.bc
win32/config.vc
win32/config_H.bc
win32/config_H.vc
win32/makefile.mk

diff --cc Porting/makerel
index 0000000,bc472ee..0476ab5
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,97 +1,90 @@@
+ #!/bin/env perl -w
+ # A first attempt at some automated support for making a perl release.
+ # Very basic but functional - if you're on a unix system.
+ #
+ # No matter how automated this gets, you'll always need to read
+ # and re-read pumpkin.pod checking for things to be done at various
+ # stages of the process.
+ #
+ # Tim Bunce, June 1997
+ use ExtUtils::Manifest qw(fullcheck);
+ $|=1;
+ $relroot = "..";      # XXX make an option
+ die "Must be in root of the perl source tree.\n"
+       unless -f "./MANIFEST" and -f "patchlevel.h";
+ $patchlevel_h = `grep '#define ' patchlevel.h`;
+ print $patchlevel_h;
+ $patchlevel = $1 if $patchlevel_h =~ /PATCHLEVEL\s+(\d+)/;
+ $subversion = $1 if $patchlevel_h =~ /SUBVERSION\s+(\d+)/;
+ die "Unable to parse patchlevel.h" unless $subversion > 0;
+ $vers = sprintf("5.%03d", $patchlevel);
+ $vers.= sprintf( "_%02d", $subversion) if $subversion;
+ $perl = "perl$vers";
+ $reldir = "$relroot/$perl";
+ print "\nMaking a release for $perl in $reldir\n\n";
+ print "Cross-checking the MANIFEST...\n";
+ ($missfile, $missentry) = fullcheck();
+ warn "Can't make a release with MANIFEST files missing.\n" if @$missfile;
+ warn "Can't make a release with files not listed in MANIFEST.\n" if @$missentry;
 -if ("@$missentry" =~ m/\.orig\b/) {
 -    # Handy listing of find command and .orig files from patching work.
 -    # I tend to run 'xargs rm' and copy and paste the file list.
 -    my $cmd = "find . -name '*.orig' -print";
 -    print "$cmd\n";
 -    system($cmd);
 -}
+ die "Aborted.\n" if @$missentry or @$missfile;
+ print "\n";
+ print "Setting file permissions...\n";
+ system("find . -type f -print | xargs chmod -w");
+ system("chmod +w configure"); # special case (see pumpkin.pod)
+ @exe = qw(
+     Configure
+     configpm
+     configure
+     embed.pl
+     installperl
+     installman
+     keywords.pl
+     myconfig
+     opcode.pl
+     perly.fixer
+     t/TEST
+     t/*/*.t
+     *.SH
+     vms/ext/Stdio/test.pl
+     vms/ext/filespec.t
+     vms/fndvers.com
+     x2p/*.SH
+     Porting/patchls
+     Porting/makerel
+ );
+ system("chmod +x @exe");
+ print "\n";
+ print "Creating $reldir release directory...\n";
+ die "$reldir release directory already exists\n"   if -e "../$perl";
+ die "$reldir.tar.gz release file already exists\n" if -e "../$perl.tar.gz";
+ mkdir($reldir, 0755) or die "mkdir $reldir: $!\n";
+ print "\n";
+ print "Copying files to release directory...\n";
+ # ExtUtils::Manifest maniread does not preserve the order
+ $cmd = "awk '{print \$1}' MANIFEST | cpio -pdm $reldir";
+ system($cmd) == 0 or die "$cmd failed";
+ print "\n";
+ chdir $relroot or die $!;
+ print "Creating and compressing the tar file...\n";
+ $cmd = "tar cf - $perl | gzip --best > $perl.tar.gz";
+ system($cmd) == 0 or die "$cmd failed";
+ print "\n";
+ system("ls -ld $perl*");
diff --cc Porting/patchls
index 0000000,f4de529..b3e968d
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,369 +1,324 @@@
+ #!/bin/perl -w
+ # 
+ #     patchls - patch listing utility
+ #
+ # Input is one or more patchfiles, output is a list of files to be patched.
+ #
+ # Copyright (c) 1997 Tim Bunce. All rights reserved.
+ # This program is free software; you can redistribute it and/or
+ # modify it under the same terms as Perl itself.
+ #
+ # With thanks to Tom Horsley for the seed code.
+ #
+ # $Id: patchls,v 1.3 1997/06/10 21:38:45 timbo Exp $
+ use Getopt::Std;
+ use Text::Wrap qw(wrap $columns);
+ use Text::Tabs qw(expand unexpand);
+ use strict;
+ sub usage {
 -die q{
++die qq{
++
+   patchls [options] patchfile [ ... ]
 -    -i     Invert: for each patched file list which patch files patch it.
 -    -h     no filename headers (like grep), only the listing.
 -    -l     no listing (like grep), only the filename headers.
 -    -c     Categorise the patch and sort by category (perl specific).
 -    -m     print formatted Meta-information (Subject,From,Msg-ID etc).
 -    -p N   strip N levels of directory Prefix (like patch), else automatic.
 -    -v     more verbose (-d for noisy debugging).
 -    -f F   only list patches which patch files matching regexp F
 -           (F has $ appended unless it contains a /).
 -    -I     just gather and display summary Information about the patches.
++    -i     Invert: for each patched file list which patch files patch it
++    -h     no filename headers (like grep), only the listing
++    -l     no listing (like grep), only the filename headers
++    -c     Categorise the patch and sort by category (perl specific)
++    -m     print formatted Meta-information (Subject,From,Msg-ID etc)
++    -p N   strip N levels of directory Prefix (like patch), else automatic
++    -v     more verbose (-d for noisy debugging)
++
+ }
+ }
+ $columns = 70;
+ $::opt_p = undef;     # undef != 0
+ $::opt_d = 0;
+ $::opt_v = 0;
+ $::opt_m = 0;
+ $::opt_i = 0;
+ $::opt_h = 0;
+ $::opt_l = 0;
+ $::opt_c = 0;
 -$::opt_f = '';
 -$::opt_I = 0;
+ usage unless @ARGV;
 -getopts("mihlvcp:f:I") or usage;
++getopts("mihlvcp:") or usage;
+ my %cat_title = (
 -    'BUILD'   => 'BUILD PROCESS',
 -    'CORE'    => 'CORE LANGUAGE',
 -    'DOC'     => 'DOCUMENTATION',
 -    'LIB'     => 'LIBRARY AND EXTENSIONS',
 -    'PORT1'   => 'PORTABILITY - WIN32',
 -    'PORT2'   => 'PORTABILITY - OTHER',
+     'TEST'    => 'TESTS',
++    'DOC'     => 'DOCUMENTATION',
+     'UTIL'    => 'UTILITIES',
 -    'OTHER'   => 'OTHER CHANGES',
++    'PORT'    => 'PORTABILITY',
++    'LIB'     => 'LIBRARY AND EXTENSIONS',
++    'CORE'    => 'CORE LANGUAGE',
++    'BUILD'   => 'BUILD PROCESS',
++    'OTHER'   => 'OTHER',
+ );
+ my %ls;
+ # Style 1:
+ #     *** perl-5.004/embed.h  Sat May 10 03:39:32 1997
+ #     --- perl-5.004.fixed/embed.h    Thu May 29 19:48:46 1997
+ #     ***************
+ #     *** 308,313 ****
+ #     --- 308,314 ----
+ #
+ # Style 2:
+ #     --- perl5.004001/mg.c   Sun Jun 08 12:26:24 1997
+ #     +++ perl5.004-bc/mg.c   Sun Jun 08 11:56:08 1997
+ #     @@ -656,9 +656,27 @@
+ # or (rcs, note the different date format)
+ #     --- 1.18        1997/05/23 19:22:04
+ #     +++ ./pod/perlembed.pod 1997/06/03 21:41:38
+ #
+ # Variation:
+ #     Index: embed.h
+ my($in, $prevline, $prevtype, $ls);
+ foreach my $argv (@ARGV) {
+     $in = $argv;
+     unless (open F, "<$in") {
+       warn "Unable to open $in: $!\n";
+       next;
+     }
+     print "Reading $in...\n" if $::opt_v and @ARGV > 1;
+     $ls = $ls{$in} ||= { is_in => 1, in => $in };
+     my $type;
+     while (<F>) {
+       unless (/^([-+*]{3}) / || /^(Index):/) {
+           # not an interesting patch line but possibly meta-information
+           next unless $::opt_m;
 -          $ls->{From}{$1}=1       if /^From:\s+(.*\S)/i;
 -          $ls->{Title}{$1}=1      if /^Subject:\s+(?:Re: )?(.*\S)/i;
 -          $ls->{'Msg-ID'}{$1}=1   if /^Message-Id:\s+(.*\S)/i;
 -          $ls->{Date}{$1}=1       if /^Date:\s+(.*\S)/i;
++          $ls->{From}{$1}=1       if /^From: (.*\S)/i;
++          $ls->{Title}{$1}=1      if /^Subject: (?:Re: )?(.*\S)/i;
++          $ls->{'Msg-ID'}{$1}=1   if /^Message-Id: (.*\S)/i;
++          $ls->{Date}{$1}=1       if /^Date: (.*\S)/i;
+           next;
+       }
+       $type = $1;
+       next if /^--- [0-9,]+ ----$/ || /^\*\*\* [0-9,]+ \*\*\*\*$/;
+       print "Last: $prevline","This: ${_}Got:  $1\n\n" if $::opt_d;
+       # Some patches have Index lines but not diff headers
+       # Patch copes with this, so must we. It's also handy for
+       # documenting manual changes by simply adding Index: lines
+       # to the file which describes the problem bing fixed.
+       add_file($ls, $1), next if /^Index:\s+(.*)/;
+       if (    ($type eq '---' and $prevtype eq '***') # Style 1
+           or  ($type eq '+++' and $prevtype eq '---') # Style 2
+       ) {
+           if (/^[-+*]{3} (\S+)\s+.*\d\d:\d\d:\d\d/) { # double check
+               add_file($ls, $1);
+           }
+           else {
+               warn "$in $.: parse error (prev $prevtype, type $type)\n$prevline$_";
+           }
+       }
+     }
+     continue {
+       $prevline = $_;
+       $prevtype = $type;
+       $type = '';
+     }
+     # if we don't have a title for -m then use the file name
+     $ls->{Title}{$in}=1 if $::opt_m
+       and !$ls->{Title} and $ls->{out};
+     $ls->{category} = $::opt_c
+       ? categorize_files([keys %{ $ls->{out} }], $::opt_v) : '';
+ }
+ print scalar(@ARGV)." files read.\n" if $::opt_v and @ARGV > 1;
+ my @ls  = sort {
+     $a->{category} cmp $b->{category} || $a->{in} cmp $b->{in}
+ } values %ls;
 -if ($::opt_f) {               # filter out patches based on -f <regexp>
 -    my $out;
 -    $::opt_f .= '$' unless $::opt_f =~ m:/:;
 -    @ls = grep {
 -      my @out = keys %{$_->{out}};
 -      my $match = 0;
 -      for $out (@out) {
 -          ++$match if $out =~ m/$::opt_f/o;
 -      }
 -      $match;
 -    } @ls;
 -}
 -
 -if ($::opt_I) {
 -    my $n_patches = 0;
 -    my($in,$out);
 -    my %all_out;
 -    foreach $in (@ls) {
 -      next unless $in->{is_in};
 -      ++$n_patches;
 -      my @outs = keys %{$in->{out}};
 -      @all_out{@outs} = ($in->{in}) x @outs;
 -    }
 -    my @all_out = sort keys %all_out;
 -    my @missing = grep { ! -f $_ } @all_out;
 -    print "$n_patches patch files patch ".@all_out." files (".@missing." missing)\n";
 -    if ($::opt_v and @missing) {
 -      print "Missing files:\n";
 -      foreach $out (@missing) {
 -          printf "  %-20s\t%s\n", $out, $all_out{$out};
 -      }
 -    }
 -    exit 0+@missing;
 -}
 -
+ unless ($::opt_c and $::opt_m) {
+     foreach $ls (@ls) {
+       next unless ($::opt_i) ? $ls->{is_out} : $ls->{is_in};
+       list_files_by_patch($ls);
+     }
+ }
+ else {
+     my $c = '';
+     foreach $ls (@ls) {
+       next unless ($::opt_i) ? $ls->{is_out} : $ls->{is_in};
 -      print "\n  ------  $cat_title{$ls->{category}}  ------\n"
 -          if $ls->{category} ne $c;
++      print "\n  $cat_title{$ls->{category}}\n" if $ls->{category} ne $c;
+       $c = $ls->{category};
+       unless ($::opt_i) {
+           list_files_by_patch($ls);
+       }
+       else {
+           my $out = $ls->{in};
+           print "\n$out patched by:\n";
+           # find all the patches which patch $out and list them
+           my @p = grep { $_->{out}->{$out} } values %ls;
+           foreach $ls (@p) {
+               list_files_by_patch($ls, '');
+           }
+       }
+     }
+     print "\n";
+ }
+ exit 0;
+ # ---
+ sub add_file {
+     my $ls = shift;
+     my $out = trim_name(shift);
+     $ls->{out}->{$out} = 1;
+     # do the -i inverse as well, even if we're not doing -i
+     my $i = $ls{$out} ||= {
+       is_out   => 1,
+       in       => $out,
+       category => $::opt_c ? categorize_files([ $out ], $::opt_v) : '',
+     };
+     $i->{out}->{$in} = 1;
+ }
+ sub trim_name {               # reduce/tidy file paths from diff lines
+     my $name = shift;
+     $name = "$name ($in)" if $name eq "/dev/null";
 -    $name =~ s:\\:/:g;        # adjust windows paths
 -    $name =~ s://:/:g;        # simplify (and make win \\share into absolute path)
+     if (defined $::opt_p) {
+       # strip on -p levels of directory prefix
+       my $dc = $::opt_p;
+       $name =~ s:^[^/]+/(.+)$:$1: while $dc-- > 0;
+     }
+     else {    # try to strip off leading path to perl directory
+       # if absolute path, strip down to any *perl* directory first
+       $name =~ s:^/.*?perl.*?/::i;
 -      $name =~ s:.*perl[-_]?5?[._]?[-_a-z0-9.+]*/::i;
++      $name =~ s:.*perl[-_]?5\.[-_a-z0-9.]+/::i;
+       $name =~ s:^\./::;
+     }
+     return $name;
+ }
+ sub list_files_by_patch {
+     my($ls, $name) = @_;
+     $name = $ls->{in} unless defined $name;
+     my @meta;
+     if ($::opt_m) {
+       foreach(qw(Title From Msg-ID)) {
+           next unless $ls->{$_};
+           my @list = sort keys %{$ls->{$_}};
+           push @meta, sprintf "%7s:  ", $_;
+           @list = map { "\"$_\"" } @list if $_ eq 'Title';
+           push @meta, my_wrap("","          ", join(", ",@list)."\n");
+       }
+       $name = "\n$name" if @meta and $name;
+     }
+     # don't print the header unless the file contains something interesting
+     return if !@meta and !$ls->{out};
+     print("$ls->{in}\n"),return  if $::opt_l; # -l = no listing
+     # a twisty maze of little options
+     my $cat = ($ls->{category} and !$::opt_m) ? "\t$ls->{category}" : "";
+     print "$name$cat: "       unless ($::opt_h and !$::opt_v) or !"$name$cat";
+     print join('',"\n",@meta) if @meta;
+     my @v = sort PATORDER keys %{ $ls->{out} };
+     my $v = "@v\n";
+     print $::opt_m ? "  Files:  ".my_wrap("","          ",$v) : $v;
+ }
+ sub my_wrap {
 -      my $txt = eval { expand(wrap(@_)) };    # die's on long lines!
 -    return $txt unless $@;
 -      return expand("@_");
++    return expand(wrap(@_));
+ }
+ sub categorize_files {
+     my($files, $verb) = @_;
+     my(%c, $refine);
+     foreach (@$files) {       # assign a score to a file path
+       # the order of some of the tests is important
+       $c{TEST} += 5,next   if m:^t/:;
+       $c{DOC}  += 5,next   if m:^pod/:;
+       $c{UTIL} += 10,next  if m:^(utils|x2p|h2pl)/:;
 -      $c{PORT1}+= 15,next  if m:^win32:;
 -      $c{PORT2} += 15,next
 -          if m:^(cygwin32|os2|plan9|qnx|vms)/:
++      $c{PORT} += 15,next
++          if m:^(cygwin32|os2|plan9|qnx|vms|win32)/:
+           or m:^(hints|Porting|ext/DynaLoader)/:
+           or m:^README\.:;
+       $c{LIB}  += 10,next
+           if m:^(lib|ext)/:;
+       $c{'CORE'} += 15,next
 -          if m:^[^/]+[\._]([chH]|sym|pl)$:;
++          if m:^[^/]+[\._]([chH]|sym)$:;
+       $c{BUILD} += 10,next
+           if m:^[A-Z]+$: or m:^[^/]+\.SH$:
 -          or m:^(install|configure|configpm):i;
++          or m:^(install|configure):i;
+       print "Couldn't categorise $_\n" if $::opt_v;
+       $c{OTHER} += 1;
+     }
+     if (keys %c > 1) {        # sort to find category with highest score
+       refine:
+       ++$refine;
+       my @c = sort { $c{$b} <=> $c{$a} || $a cmp $b } keys %c;
+       my @v = map  { $c{$_} } @c;
+       if (@v > 1 and $refine <= 1 and "@v" =~ /^(\d) \1/
+               and $c[0] =~ m/^(DOC|TESTS|OTHER)/) { # rare
+           print "Tie, promoting $c[1] over $c[0]\n" if $::opt_d;
+           ++$c{$c[1]};
+           goto refine;
+       }
+       print "  ".@$files." patches: ", join(", ", map { "$_: $c{$_}" } @c),".\n"
+           if $verb;
+       return $c[0] || 'OTHER';
+     }
+     else {
+       my($c, $v) = %c;
+       $c ||= 'OTHER'; $v ||= 0;
+       print "  ".@$files." patches: $c: $v\n" if $verb;
+       return $c;
+     }
+ }
+ sub PATORDER {                # PATORDER sort by Chip Salzenberg
+     my ($i, $j);
+     $i = ($a =~ m#^[A-Z]+$#);
+     $j = ($b =~ m#^[A-Z]+$#);
+     return $j - $i if $i != $j;
+     $i = ($a =~ m#configure|hint#i) || ($a =~ m#[S_]H$#);
+     $j = ($b =~ m#configure|hint#i) || ($b =~ m#[S_]H$#);
+     return $j - $i if $i != $j;
+     $i = ($a =~ m#\.pod$#);
+     $j = ($b =~ m#\.pod$#);
+     return $j - $i if $i != $j;
+     $i = ($a =~ m#include/#);
+     $j = ($b =~ m#include/#);
+     return $j - $i if $i != $j;
+     if ((($i = $a) =~ s#/+[^/]*$##)
+       && (($j = $b) =~ s#/+[^/]*$##)) {
+           return $i cmp $j if $i ne $j;
+     }
+     $i = ($a =~ m#\.h$#);
+     $j = ($b =~ m#\.h$#);
+     return $j - $i if $i != $j;
+     return $a cmp $b;
+ }
diff --cc README.threads
index 0000000,4d20243..12abbe5
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,171 +1,181 @@@
+ Building
 -If you want to build with multi-threading support and you are
 -running Linux 2.x (with the LinuxThreads library installed:
 -that's the linuxthreads and linuxthreads-devel RPMs for RedHat)
 -or Digital UNIX 4.x or Solaris 2.x for recentish x (2.5 is OK)
 -then you should be able to use
 -    ./Configure -Dusethreads -Doptimize=-g -ders
 -    make
 -and ignore the rest of this "Building" section. If it doesn't
 -work or you are using another platform which you believe supports
 -POSIX.1c threads then read on.
 -
+ Omit the -e from your ./Configure arguments. For example, use
+     ./Configure -drs
+ When it offers to let you change config.sh, do so. If you already
+ have a config.sh then you can edit it and do
+     ./Configure -S
+ to propagate the required changes.
+ In ccflags, insert -DUSE_THREADS (and probably -DDEBUGGING since
+ that's what I've been building with). Also insert any other
+ arguments in there that your compiler needs to use POSIX threads.
+ Change optimize to -g to give you better debugging information.
+ Include any necessary explicit libraries in libs and change
+ ldflags if you need any linker flags instead or as well.
+ More explicitly, for Linux (when using the standard kernel-threads
+ based LinuxThreads library):
+     Add -DUSE_THREADS -D_REENTRANT -DDEBUGGING to ccflags and cppflags
+     Add -lpthread to libs
+     Change optimize to -g
+ For Digital Unix 4.x:
+     Add -pthread -DUSE_THREADS -DDEBUGGING to ccflags
+     Add -DUSE_THREADS -DDEBUGGING to cppflags
+     Add -pthread to ldflags
+     Change optimize to -g
 -    Add -lpthread -lc_r to lddlflags
++    Maybe add -lpthread -lc_r to lddlflags
+     For some reason, the extra includes for pthreads make Digital UNIX
+     complain fatally about the sbrk() delcaration in perl's malloc.c
+     so use the native malloc as follows:
+     Change usemymalloc to n
+     Zap mallocobj and mallocsrc (foo='')
+     Change d_mymalloc to undef
 -For Solaris, do the same as for Linux above.
 -Now you can do a
 -    make
++Now you can do a
++    make perl
++For Digital UNIX, it will get as far as building miniperl and then
++bomb out buidling DynaLoader when MakeMaker tries to find where
++perl is. This seems to be a problem with backticks/system when
++threading is in. A minimal failing example is
++    perl -e 'eval q($foo = 0); system("echo foo")'
++which doesn't echo anything. The resulting ext/DynaLoader/Makefile
++will have lines
++    PERL = 0
++    FULLPERL = 0
++Change them to be the pathnames of miniperl and perl respectively
++(the ones in your perl build directory). The resume the make with
++    make perl
++This time it should manage to build perl. If not, try some cutting
++and pasting to compile and link things manually. Be careful when
++building extensions that your ordinary perl doesn't end up making
++a Makefile without the correct pthreads compiler options.
+ Building the Thread extension
+ Build it away from the perl tree in the usual way. Set your PATH
+ environment variable to have your perl build directory first and
+ set PERL5LIB to be /your/perl/build/directory/lib (without those,
+ I had problems where the config information from the ordinary perl
+ on the system would end up in the Makefile). Then
+     perl Makefile.PL PERL_SRC=/your/perl/build/directory
+     make
++On Digital UNIX, you'll probably have to fix the "PERL = 0" and
++"FULLPERL = 0" lines in the generated Makefile as for DynaLoader.
+ Then you can try some of the tests with
+     perl -Mblib create.t
+     perl -Mblib join.t
+     perl -Mblib lock.t
+     perl -Mblib unsync.t
+     perl -Mblib unsync2.t
+     perl -Mblib unsync3.t
+     perl -Mblib io.t
 -    perl -Mblib queue.t
+ The io one leaves a thread reading from the keyboard on stdin so
+ as the ping messages appear you can type lines and see them echoed.
+ Try running the main perl test suite too. There are known
+ failures for po/misc test 45 (tries to do local(@_) but @_ is
+ now lexical) and some tests involving backticks/system/fork
 -may or may not work. Under Linux, many tests may appear to fail
++may or may not work. Under Linux, many tests appear to fail
+ when run under the test harness but work fine when invoked
+ manually.
+ Bugs
++* Thread states (DETACHED, JOINED etc.) and perl's idea of what's
++  in scope and out of scope aren't properly integrated. Expect
++  segaults and hangs when thread objects whose threads have ended
++  go out of scope (e.g. at program exit).
++
+ * cond.t hasn't been redone since condition variable changed.
+ * FAKE_THREADS should produce a working perl but the Thread
+ extension won't build with it yet.
+ * There's a known memory leak (curstack isn't freed at the end
+ of each thread because it causes refcount problems that I
+ haven't tracked down yet) and there are very probably others too.
+ * There are still races where bugs show up under contention.
+ * Need to document "lock", Thread.pm, Queue.pm, ...
+ * Plenty of others
+ Debugging
+ Use the -DL command-line option to turn on debugging of the
+ multi-threading code. Under Linux, that also turns on a quick
+ hack I did to grab a bit of extra information from segfaults.
+ If you have a fancier gdb/threads setup than I do then you'll
+ have to delete the lines in perl.c which say
+     #if defined(DEBUGGING) && defined(USE_THREADS) && defined(__linux__)
+         DEBUG_L(signal(SIGSEGV, (void(*)(int))catch_sigsegv););
+     #endif
+ Background
+ Some old globals (e.g. stack_sp, op) and some old per-interpreter
+ variables (e.g. tmps_stack, cxstack) move into struct thread.
+ All fields of struct thread (apart from a few only applicable to
+ FAKE_THREADS) are of the form Tfoo. For example, stack_sp becomes
+ the field Tstack_sp of struct thread. For those fields which moved
+ from original perl, thread.h does
+     #define foo (thr->Tfoo)
+ This means that all functions in perl which need to use one of these
+ fields need an (automatic) variable thr which points at the current
+ thread's struct thread. For pp_foo functions, it is passed around as
+ an argument, for other functions they do
+     dTHR;
+ which declares and initialises thr from thread-specific data
+ via pthread_getspecific. If a function fails to compile with an
+ error about "no such variable thr", it probably just needs a dTHR
+ at the top.
+ Fake threads
+ For FAKE_THREADS, thr is a global variable and perl schedules threads
+ by altering thr in between appropriate ops. The next and prev fields
+ of struct thread keep all fake threads on a doubly linked list and
+ the next_run and prev_run fields keep all runnable threads on a
+ doubly linked list. Mutexes are stubs for FAKE_THREADS. Condition
+ variables are implemented as a list of waiting threads.
+ Mutexes and condition variables
+ The API is via macros MUTEX_{INIT,LOCK,UNLOCK,DESTROY} and
+ COND_{INIT,WAIT,SIGNAL,BROADCAST,DESTROY}. For POSIX threads,
+ perl mutexes and condition variables correspond to POSIX ones.
+ For FAKE_THREADS, mutexes are stubs and condition variables are
+ implmented as lists of waiting threads. For FAKE_THREADS, a thread
+ waits on a condition variable by removing itself from the runnable
+ list, calling SCHEDULE to change thr to the next appropriate
+ runnable thread and returning op (i.e. the new threads next op).
+ This means that fake threads can only block while in PP code.
+ A PP function which contains a COND_WAIT must be prepared to
+ handle such restarts and can use the field "private" of struct
+ thread to record its state. For fake threads, COND_SIGNAL and
+ COND_BROADCAST work by putting back all the threads on the
+ condition variables list into the run queue. Note that a mutex
+ must *not* be held while returning from a PP function.
+ Perl locks are a condpair_t structure (a triple of a mutex, a
+ condtion variable and an owner thread field) attached by 'm'
+ magic to any SV. pp_lock locks such an object by waiting on the
+ condition variable until the owner field is zero and then setting
+ the owner field to its own thread pointer. The lock is recursive
+ so if the owner field already matches the current thread then
+ pp_lock returns straight away. If the owner field has to be filled
+ in then unlock_condpair is queued as an end-of-block destructor and
+ that function zeroes out the owner field, releasing the lock.
+ Malcolm Beattie
+ mbeattie@sable.ox.ac.uk
 -2 October 1997
++9 September 1997
diff --cc win32/config.bc
@@@ -68,20 -68,20 +68,20 @@@ chgrp='
  chmod=''
  chown=''
  clocktype='clock_t'
 -comm=''
 +comm='comm'
  compress=''
  contains='grep'
 -cp='copy'
 +cp='cp'
  cpio=''
- cpp='cpp'
+ cpp='cpp32'
  cpp_stuff='42'
  cpplast=''
  cppminus=''
- cpprun='cl -E'
- cppstdin='cl -E'
+ cpprun=''
+ cppstdin=''
  cryptlib=''
  csh='undef'
 -d_Gconvert='gcvt((x),(n),(b))'
 +d_Gconvert='sprintf((b),"%.*g",(n),(x))'
  d_access='define'
  d_alarm='undef'
  d_archlib='define'
diff --cc win32/config.vc
Simple merge
Simple merge
Simple merge
index 0000000,4696dcb..b91fffc
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,596 +1,586 @@@
+ #
+ # Makefile to build perl on Windowns NT using Microsoft NMAKE.
+ #
+ #
+ # This is set up to build a perl.exe that runs off a shared library
+ # (perl.dll).  Also makes individual DLLs for the XS extensions.
+ #
+ #
+ # Set these to wherever you want "nmake install" to put your
+ # newly built perl.
+ INST_DRV=c:
+ INST_TOP=$(INST_DRV)\perl
+ #
+ # uncomment one if you are using Visual C++ 2.x or Borland
+ # comment out both if you are using Visual C++ 4.x and above
+ #CCTYPE=MSVC20
+ CCTYPE=BORLAND
+ #
+ # uncomment next line if you want debug version of perl (big,slow)
+ #CFG=Debug
+ #
+ # set the install locations of the compiler include/libraries
+ #CCHOME = f:\msdev\vc
+ CCHOME = D:\bc5
+ CCINCDIR = $(CCHOME)\include
+ CCLIBDIR = $(CCHOME)\lib
+ #
+ # set this to point to cmd.exe (only needed if you use some
+ # alternate shell that doesn't grok cmd.exe style commands)
+ SHELL = g:\winnt\system32\cmd.exe
+ #
+ # set this to your email address (perl will guess a value from
+ # from your loginname and your hostname, which may not be right)
+ #EMAIL = 
+ ##################### CHANGE THESE ONLY IF YOU MUST #####################
+ #
+ # Programs to compile, build .lib files and link
+ #
+ .USESHELL :
+ .IF "$(CCTYPE)" == "BORLAND"
+ CC = bcc32
+ LINK32 = tlink32
+ LIB32 = tlib
+ IMPLIB = implib
+ #
+ # Options
+ #
+ RUNTIME  = -D_RTLDLL
+ INCLUDES = -I.\include -I. -I.. -I$(CCINCDIR)
+ #PCHFLAGS = -H -H$(INTDIR)\bcmoduls.pch 
+ DEFINES  = -DWIN32 -DPERLDLL
+ SUBSYS   = console
+ LIBC = cw32mti.lib
+ LIBFILES = import32.lib $(LIBC) odbc32.lib odbccp32.lib
+ WINIOMAYBE =
+ .IF  "$(CFG)" == "Debug"
+ OPTIMIZE = -v $(RUNTIME)
+ LINK_DBG = -v
+ .ELSE
+ OPTIMIZE = -O $(RUNTIME)
+ LINK_DBG = 
+ .ENDIF
+ CFLAGS   = -w -tWM -tWD $(INCLUDES) $(DEFINES) $(PCHFLAGS) $(OPTIMIZE)
+ LINK_FLAGS  = $(LINK_DBG) -L$(CCLIBDIR)
+ OBJOUT_FLAG = -o
+ .ELSE
+ CC=cl.exe
+ LINK32=link.exe
+ LIB32=$(LINK32) -lib
+ #
+ # Options
+ #
+ .IF "$(RUNTIME)" == ""
+ RUNTIME  = -MD
+ .ENDIF
+ INCLUDES = -I.\include -I. -I..
+ #PCHFLAGS = -Fp$(INTDIR)\vcmoduls.pch -YX 
+ DEFINES  = -DWIN32 -D_CONSOLE -DPERLDLL
+ SUBSYS   = console
+ .IF "$(RUNTIME)" == "-MD"
+ LIBC = msvcrt.lib
+ WINIOMAYBE =
+ .ELSE
+ LIBC = libcmt.lib
+ WINIOMAYBE = win32io.obj
+ .ENDIF
+ .IF  "$(CFG)" == "Debug"
+ .IF "$(CCTYPE)" == "MSVC20"
+ OPTIMIZE = -Od $(RUNTIME) -Z7 -D_DEBUG
+ .ELSE
+ OPTIMIZE = -Od $(RUNTIME)d -Z7 -D_DEBUG
+ .ENDIF
+ LINK_DBG = -debug -pdb:none
+ .ELSE
+ .IF "$(CCTYPE)" == "MSVC20"
+ OPTIMIZE = -Od $(RUNTIME) -DNDEBUG
+ .ELSE
+ OPTIMIZE = -Od $(RUNTIME) -DNDEBUG
+ .ENDIF
+ LINK_DBG = -release
+ .ENDIF
+ # we don't add LIBC here, the compiler do it based on -MD/-MT
+ LIBFILES = oldnames.lib kernel32.lib user32.lib gdi32.lib \
+       winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib \
+       oleaut32.lib netapi32.lib uuid.lib wsock32.lib mpr.lib winmm.lib \
+       version.lib odbc32.lib odbccp32.lib
+ CFLAGS   = -nologo -W3 $(INCLUDES) $(DEFINES) $(PCHFLAGS) $(OPTIMIZE)
+ LINK_FLAGS  = -nologo $(LIBFILES) $(LINK_DBG) -machine:I386
+ OBJOUT_FLAG = -Fo
+ .ENDIF
+ #################### do not edit below this line #######################
+ ############# NO USER-SERVICEABLE PARTS BEYOND THIS POINT ##############
+ #
+ # Rules
+ # 
+ .SUFFIXES : 
+ .SUFFIXES : .c .obj .dll .lib .exe
+ .c.obj:
+       $(CC) -c $(CFLAGS) $(OBJOUT_FLAG)$@ $<
+ .IF "$(CCTYPE)" == "BORLAND"
+ .obj.dll:
+       $(LINK32) -Tpd -ap $(LINK_FLAGS) c0d32.obj $<,$@,,$(LIBFILES),$(*B).def
+       $(IMPLIB) $(*B).lib $@
+ .ELSE
+ .obj.dll:
+       $(LINK32) -dll -subsystem:windows -implib:$(*B).lib -def:$(*B).def \
+           -out:$@ $(LINK_FLAGS) $< $(LIBPERL)  
+ .ENDIF
+ #
+ INST_BIN=$(INST_TOP)\bin
+ INST_LIB=$(INST_TOP)\lib
+ INST_POD=$(INST_LIB)\pod
+ INST_HTML=$(INST_POD)\html
+ LIBDIR=..\lib
+ EXTDIR=..\ext
+ PODDIR=..\pod
+ EXTUTILSDIR=$(LIBDIR)\extutils
+ #
+ # various targets
+ PERLIMPLIB=..\perl.lib
+ MINIPERL=..\miniperl.exe
+ PERLDLL=..\perl.dll
+ PERLEXE=..\perl.exe
+ GLOBEXE=..\perlglob.exe
+ CONFIGPM=..\lib\Config.pm
+ MINIMOD=..\lib\ExtUtils\Miniperl.pm
 -PL2BAT=bin\pl2bat.pl
 -GLOBBAT = bin\perlglob.bat
++PL2BAT=bin\PL2BAT.BAT
++GLOBBAT = perlglob.bat
+ .IF "$(CCTYPE)" == "BORLAND"
+ # Borland wildargs is incompatible with MS setargv
+ CFGSH_TMPL = config.bc
+ CFGH_TMPL = config_H.bc
+ # Borland's perl.exe will work on W95, so we don't make this
+ .ELSE
+ MAKE = nmake -nologo
+ CFGSH_TMPL = config.vc
+ CFGH_TMPL = config_H.vc
+ PERL95EXE=..\perl95.exe
+ .ENDIF
+ XCOPY=xcopy /f /r /i /d
+ RCOPY=xcopy /f /r /i /e /d
+ #NULL=
+ #
+ # filenames given to xsubpp must have forward slashes (since it puts
+ # full pathnames in #line strings)
+ XSUBPP=..\$(MINIPERL) -I..\..\lib ..\$(EXTUTILSDIR)\xsubpp -C++ -prototypes
+ CORE_C=       ..\av.c         \
+       ..\deb.c        \
+       ..\doio.c       \
+       ..\doop.c       \
+       ..\dump.c       \
+       ..\globals.c    \
+       ..\gv.c         \
+       ..\hv.c         \
+       ..\mg.c         \
+       ..\op.c         \
+       ..\perl.c       \
+       ..\perlio.c     \
+       ..\perly.c      \
+       ..\pp.c         \
+       ..\pp_ctl.c     \
+       ..\pp_hot.c     \
+       ..\pp_sys.c     \
+       ..\regcomp.c    \
+       ..\regexec.c    \
+       ..\run.c        \
+       ..\scope.c      \
+       ..\sv.c         \
+       ..\taint.c      \
+       ..\toke.c       \
+       ..\universal.c  \
+       ..\util.c
+ CORE_OBJ= ..\av.obj   \
+       ..\deb.obj      \
+       ..\doio.obj     \
+       ..\doop.obj     \
+       ..\dump.obj     \
+       ..\globals.obj  \
+       ..\gv.obj       \
+       ..\hv.obj       \
+       ..\mg.obj       \
+       ..\op.obj       \
+       ..\perl.obj     \
+       ..\perlio.obj   \
+       ..\perly.obj    \
+       ..\pp.obj       \
+       ..\pp_ctl.obj   \
+       ..\pp_hot.obj   \
+       ..\pp_sys.obj   \
+       ..\regcomp.obj  \
+       ..\regexec.obj  \
+       ..\run.obj      \
+       ..\scope.obj    \
+       ..\sv.obj       \
+       ..\taint.obj    \
+       ..\toke.obj     \
+       ..\universal.obj\
+       ..\util.obj
+ WIN32_C = perllib.c \
+       win32.c \
+       win32io.c \
+       win32sck.c
+ WIN32_OBJ = win32.obj \
+       win32io.obj \
+       win32sck.obj
+ DLL_OBJ = perllib.obj $(DYNALOADER).obj
+ CORE_H = ..\av.h      \
+       ..\cop.h        \
+       ..\cv.h         \
+       ..\dosish.h     \
+       ..\embed.h      \
+       ..\form.h       \
+       ..\gv.h         \
+       ..\handy.h      \
+       ..\hv.h         \
+       ..\mg.h         \
+       ..\nostdio.h    \
+       ..\op.h         \
+       ..\opcode.h     \
+       ..\perl.h       \
+       ..\perlio.h     \
+       ..\perlsdio.h   \
+       ..\perlsfio.h   \
+       ..\perly.h      \
+       ..\pp.h         \
+       ..\proto.h      \
+       ..\regexp.h     \
+       ..\scope.h      \
+       ..\sv.h         \
+       ..\unixish.h    \
+       ..\util.h       \
+       ..\XSUB.h       \
+       .\config.h      \
+       ..\EXTERN.h     \
+       .\include\dirent.h      \
+       .\include\netdb.h       \
+       .\include\sys\socket.h  \
+       .\win32.h
+ EXTENSIONS=DynaLoader Socket IO Fcntl Opcode SDBM_File
+ DYNALOADER=$(EXTDIR)\DynaLoader\DynaLoader
+ SOCKET=$(EXTDIR)\Socket\Socket
+ FCNTL=$(EXTDIR)\Fcntl\Fcntl
+ OPCODE=$(EXTDIR)\Opcode\Opcode
+ SDBM_FILE=$(EXTDIR)\SDBM_File\SDBM_File
+ IO=$(EXTDIR)\IO\IO
+ SOCKET_DLL=..\lib\auto\Socket\Socket.dll
+ FCNTL_DLL=..\lib\auto\Fcntl\Fcntl.dll
+ OPCODE_DLL=..\lib\auto\Opcode\Opcode.dll
+ SDBM_FILE_DLL=..\lib\auto\SDBM_File\SDBM_File.dll
+ IO_DLL=..\lib\auto\IO\IO.dll
+ STATICLINKMODULES=DynaLoader
+ DYNALOADMODULES=      \
+       $(SOCKET_DLL)   \
+       $(FCNTL_DLL)    \
+       $(OPCODE_DLL)   \
+       $(SDBM_FILE_DLL)\
+       $(IO_DLL)
+ POD2HTML=$(PODDIR)\pod2html
+ POD2MAN=$(PODDIR)\pod2man
+ POD2LATEX=$(PODDIR)\pod2latex
+ POD2TEXT=$(PODDIR)\pod2text
+ #
+ # Top targets
+ #
+ all: $(PERLEXE) $(PERL95EXE) $(GLOBEXE) $(DYNALOADMODULES) $(MINIMOD) $(GLOBBAT)
+ $(DYNALOADER).obj : $(DYNALOADER).c $(CORE_H) $(EXTDIR)\DynaLoader\dlutils.c
+ #------------------------------------------------------------
+ $(GLOBEXE): perlglob.obj
+ .IF "$(CCTYPE)" == "BORLAND"
+       $(CC) -c -w -v -tWM -I$(CCINCDIR) perlglob.c
+       $(LINK32) -Tpe -ap $(LINK_FLAGS) c0x32.obj perlglob.obj \
+           $(CCLIBDIR)\32BIT\wildargs.obj,$@,,import32.lib cw32mt.lib,
+ .ELSE
+       $(LINK32) $(LINK_FLAGS) -out:$@ -subsystem:$(SUBSYS) perlglob.obj setargv.obj 
+ .ENDIF
 -$(GLOBBAT) : ..\lib\File\DosGlob.pm $(MINIPERL)
 -      $(MINIPERL) $(PL2BAT) - < ..\lib\File\DosGlob.pm > $(GLOBBAT)
++perlglob.bat : ..\lib\File\DosGlob.pm $(MINIPERL)
++      $(MINIPERL) $(PL2BAT) - < ..\lib\File\DosGlob.pm > $(*B).bat
+ perlglob.obj  : perlglob.c
+ ..\miniperlmain.obj : ..\miniperlmain.c $(CORE_H)
+ config.w32 : $(CFGSH_TMPL)
+       copy $(CFGSH_TMPL) config.w32
+ .\config.h : $(CFGSH_TMPL)
+       -del /f config.h
+       copy $(CFGH_TMPL) config.h
+ ..\config.sh : config.w32 $(MINIPERL) config_sh.PL
+       $(MINIPERL) -I..\lib config_sh.PL "INST_DRV=$(INST_DRV)" \
+           "INST_TOP=$(INST_TOP)" "cc=$(CC)" "ccflags=$(RUNTIME) -DWIN32" \
 -          "cf_email=$(EMAIL)" "libs=$(LIBFILES:f)" "incpath=$(CCINCDIR)" \
++          "cf_email=$(EMAIL)" "libs=$(LIBFILES:f)" \
+           "libpth=$(strip $(CCLIBDIR) $(LIBFILES:d))" "libc=$(LIBC)" \
+           config.w32 > ..\config.sh
+ $(CONFIGPM) : $(MINIPERL) ..\config.sh config_h.PL ..\minimod.pl
+       cd .. && miniperl configpm
+       if exist lib\* $(RCOPY) lib\*.* ..\lib\$(NULL)
+       $(XCOPY) ..\*.h ..\lib\CORE\*.*
+       $(XCOPY) *.h ..\lib\CORE\*.*
+       $(RCOPY) include ..\lib\CORE\*.*
+       $(MINIPERL) -I..\lib config_h.PL || $(MAKE) CCTYPE=$(CCTYPE) \
+           RUNTIME=$(RUNTIME) CFG=$(CFG) $(CONFIGPM)
+ $(MINIPERL) : ..\miniperlmain.obj $(CORE_OBJ) $(WIN32_OBJ)
+ .IF "$(CCTYPE)" == "BORLAND"
+       $(LINK32) -Tpe -ap $(LINK_FLAGS) \
+           @$(mktmp c0x32.obj ..\miniperlmain.obj \
+               $(CORE_OBJ:s,\,\\) $(WIN32_OBJ:s,\,\\),$@,,$(LIBFILES),)
+ .ELSE
+       $(LINK32) -subsystem:console -out:$@ \
+           @$(mktmp $(LINK_FLAGS) ..\miniperlmain.obj \
+               $(CORE_OBJ:s,\,\\) $(WIN32_OBJ:s,\,\\))
+ .ENDIF
+ $(WIN32_OBJ) : $(CORE_H)
+ $(CORE_OBJ)  : $(CORE_H)
+ $(DLL_OBJ)   : $(CORE_H) 
+ perldll.def : $(MINIPERL) $(CONFIGPM)
+       $(MINIPERL) -w makedef.pl $(CCTYPE) > perldll.def
+ $(PERLDLL): perldll.def $(CORE_OBJ) $(WIN32_OBJ) $(DLL_OBJ)
+ .IF "$(CCTYPE)" == "BORLAND"
+       $(LINK32) -Tpd -ap $(LINK_FLAGS) \
+           @$(mktmp c0d32.obj $(CORE_OBJ:s,\,\\) \
+               $(WIN32_OBJ:s,\,\\) $(DLL_OBJ:s,\,\\)\n \
+               $@,\n \
+               $(LIBFILES)\n \
+               perldll.def\n)
+       $(IMPLIB) $*.lib $@
+ .ELSE
+       $(LINK32) -dll -def:perldll.def -out:$@ \
+           @$(mktmp $(LINK_FLAGS) $(CORE_OBJ:s,\,\\) \
+               $(WIN32_OBJ:s,\,\\) $(DLL_OBJ:s,\,\\))
+ .ENDIF
+       $(XCOPY) $(PERLIMPLIB) ..\lib\CORE
+ perl.def  : $(MINIPERL) makeperldef.pl
+       $(MINIPERL) -I..\lib makeperldef.pl $(NULL) > perl.def
+ $(MINIMOD) : $(MINIPERL) ..\minimod.pl
+       cd .. && miniperl minimod.pl > lib\ExtUtils\Miniperl.pm
+ perlmain.c : runperl.c 
+       copy runperl.c perlmain.c
+ perlmain.obj : perlmain.c
+       $(CC) $(CFLAGS) -UPERLDLL -c perlmain.c
+ $(PERLEXE): $(PERLDLL) $(CONFIGPM) perlmain.obj  
+ .IF "$(CCTYPE)" == "BORLAND"
+       $(LINK32) -Tpe -ap $(LINK_FLAGS) \
+           @$(mktmp c0x32.obj perlmain.obj $(WINIOMAYBE)\n \
+           $@,\n \
+           $(PERLIMPLIB) $(LIBFILES)\n)
+ .ELSE
+       $(LINK32) -subsystem:console -out:perl.exe $(LINK_FLAGS) \
+           perlmain.obj $(WINIOMAYBE) $(PERLIMPLIB) 
+       copy perl.exe $@
+       del perl.exe
+ .ENDIF
+       copy splittree.pl .. 
+       $(MINIPERL) -I..\lib ..\splittree.pl "../LIB" "../LIB/auto"
+       attrib -r ..\t\*.*
+       copy test ..\t
+ .IF "$(CCTYPE)" != "BORLAND"
+ perl95.c : runperl.c 
+       copy runperl.c perl95.c
+ perl95.obj : perl95.c
+       $(CC) $(CFLAGS) -MT -UPERLDLL -c perl95.c
+ win32iomt.obj : win32io.c
+       $(CC) $(CFLAGS) -MT -c $(OBJOUT_FLAG)win32iomt.obj win32io.c
+ $(PERL95EXE): $(PERLDLL) $(CONFIGPM) perl95.obj win32iomt.obj
+       $(LINK32) -subsystem:console -out:perl95.exe $(LINK_FLAGS) \
+           perl95.obj win32iomt.obj $(PERLIMPLIB) 
+       copy perl95.exe $@
+       del perl95.exe
+ .ENDIF
+ $(DYNALOADER).c: $(MINIPERL) $(EXTDIR)\DynaLoader\dl_win32.xs $(CONFIGPM)
+       if not exist ..\lib\auto mkdir ..\lib\auto
+       $(XCOPY) $(EXTDIR)\$(*B)\$(*B).pm $(LIBDIR)\$(NULL)
+       cd $(EXTDIR)\$(*B) && $(XSUBPP) dl_win32.xs > $(*B).c
+       $(XCOPY) $(EXTDIR)\$(*B)\dlutils.c .
+ $(EXTDIR)\DynaLoader\dl_win32.xs: dl_win32.xs
+       copy dl_win32.xs $(EXTDIR)\DynaLoader\dl_win32.xs
+ $(IO_DLL): $(PERLEXE) $(CONFIGPM) $(IO).xs
+       cd $(EXTDIR)\$(*B) && \
+       ..\..\miniperl -I..\..\lib Makefile.PL INSTALLDIRS=perl
+       cd $(EXTDIR)\$(*B) && $(MAKE)
+ $(SDBM_FILE_DLL) : $(PERLEXE) $(SDBM_FILE).xs
+       cd $(EXTDIR)\$(*B) && \
+       ..\..\miniperl -I..\..\lib Makefile.PL INSTALLDIRS=perl
+       cd $(EXTDIR)\$(*B) && $(MAKE)
+ $(FCNTL_DLL): $(PERLEXE) $(FCNTL).xs
+       cd $(EXTDIR)\$(*B) && \
+       ..\..\miniperl -I..\..\lib Makefile.PL INSTALLDIRS=perl
+       cd $(EXTDIR)\$(*B) && $(MAKE)
+ $(OPCODE_DLL): $(PERLEXE) $(OPCODE).xs
+       cd $(EXTDIR)\$(*B) && \
+       ..\..\miniperl -I..\..\lib Makefile.PL INSTALLDIRS=perl
+       cd $(EXTDIR)\$(*B) && $(MAKE)
+ $(SOCKET_DLL): $(SOCKET).xs $(PERLEXE)
+       cd $(EXTDIR)\$(*B) && \
+       ..\..\miniperl -I..\..\lib Makefile.PL INSTALLDIRS=perl
+       cd $(EXTDIR)\$(*B) && $(MAKE)
+ doc: $(PERLEXE)
 -      cd ..\pod && $(MAKE) -f ..\win32\pod.mak checkpods \
 -              pod2html pod2latex pod2man pod2text
 -      cd ..\pod && $(XCOPY) *.bat ..\win32\bin\*.*
+       copy ..\README.win32 ..\pod\perlwin32.pod
+       $(PERLEXE) ..\installhtml --podroot=.. --htmldir=./html \
+           --podpath=pod:lib:ext:utils --htmlroot="//$(INST_HTML:s,:,|,)" \
+           --libpod=perlfunc:perlguts:perlvar:perlrun:perlop --recurse
+ utils: $(PERLEXE)
+       cd ..\utils && $(MAKE) PERL=$(MINIPERL)
+       cd ..\utils && $(PERLEXE) ..\win32\$(PL2BAT) h2ph splain perlbug \
+               pl2pm c2ph h2xs perldoc pstruct
 -      $(XCOPY) ..\utils\*.bat bin\*.*
 -      $(PERLEXE) $(PL2BAT) bin\network.pl bin\www.pl bin\runperl.pl \
 -                      bin\pl2bat.pl
++      cd ..\utils && $(XCOPY) *.bat ..\win32\bin\*.*
+ distclean: clean
+       -del /f $(MINIPERL) $(PERLEXE) $(PERLDLL) $(GLOBEXE) \
+               $(PERLIMPLIB) ..\miniperl.lib $(MINIMOD)
+       -del /f *.def *.map
+       -del /f $(SOCKET_DLL) $(IO_DLL) $(SDBM_FILE_DLL) $(FCNTL_DLL) \
+               $(OPCODE_DLL)
+       -del /f $(SOCKET).c $(IO).c $(SDBM_FILE).c $(FCNTL).c $(OPCODE).c \
+               $(DYNALOADER).c
+       -del /f $(PODDIR)\*.html
+       -del /f $(PODDIR)\*.bat
 -      -del /f ..\config.sh ..\splittree.pl perlmain.c dlutils.c config.h.new
 -.IF "$(PERL95EXE)" != ""
 -      -del /f perl95.c
 -.ENDIF
 -      -del /f bin\*.bat
+       -cd $(EXTDIR) && del /s *.lib *.def *.map *.bs Makefile *.obj pm_to_blib
+       -rmdir /s /q ..\lib\auto
+       -rmdir /s /q ..\lib\CORE
+ install : all doc utils
+       if not exist $(INST_TOP) mkdir $(INST_TOP)
+       echo I $(INST_TOP) L $(LIBDIR)
+       $(XCOPY) $(PERLEXE) $(INST_BIN)\*.*
+ .IF "$(PERL95EXE)" != ""
+       $(XCOPY) $(PERL95EXE) $(INST_BIN)\*.*
+ .ENDIF
+       $(XCOPY) $(GLOBEXE) $(INST_BIN)\*.*
++      $(XCOPY) $(GLOBBAT) $(INST_BIN)\*.*
+       $(XCOPY) $(PERLDLL) $(INST_BIN)\*.*
 -      $(XCOPY) bin\*.bat $(INST_BIN)\*.*
++      $(XCOPY) bin\*.* $(INST_BIN)\*.*
+       $(RCOPY) ..\lib $(INST_LIB)\*.*
+       $(XCOPY) ..\pod\*.bat $(INST_BIN)\*.*
+       $(XCOPY) ..\pod\*.pod $(INST_POD)\*.*
+       $(RCOPY) html\*.* $(INST_HTML)\*.*
+ inst_lib : $(CONFIGPM)
+       copy splittree.pl .. 
+       $(MINIPERL) -I..\lib ..\splittree.pl "../LIB" "../LIB/auto"
+       $(RCOPY) ..\lib $(INST_LIB)\*.*
+ minitest : $(MINIPERL) $(GLOBEXE) $(CONFIGPM)
+       $(XCOPY) $(MINIPERL) ..\t\perl.exe
+ .IF "$(CCTYPE)" == "BORLAND"
+       $(XCOPY) $(GLOBBAT) ..\t\$(NULL)
+ .ELSE
+       $(XCOPY) $(GLOBEXE) ..\t\$(NULL)
+ .ENDIF
+       attrib -r ..\t\*.*
+       copy test ..\t
+       cd ..\t && \
+       $(MINIPERL) -I..\lib test base/*.t comp/*.t cmd/*.t io/*.t op/*.t pragma/*.t
+ test : all
+       $(XCOPY) $(PERLEXE) ..\t\$(NULL)
+       $(XCOPY) $(PERLDLL) ..\t\$(NULL)
+ .IF "$(CCTYPE)" == "BORLAND"
+       $(XCOPY) $(GLOBBAT) ..\t\$(NULL)
+ .ELSE
+       $(XCOPY) $(GLOBEXE) ..\t\$(NULL)
+ .ENDIF
+       cd ..\t && $(PERLEXE) -I..\lib harness
+ clean : 
+       -@erase miniperlmain.obj
+       -@erase $(MINIPERL)
+       -@erase perlglob.obj
+       -@erase perlmain.obj
+       -@erase config.w32
+       -@erase /f config.h
+       -@erase $(GLOBEXE)
+       -@erase $(PERLEXE)
+       -@erase $(PERLDLL)
+       -@erase $(CORE_OBJ)
+       -@erase $(WIN32_OBJ)
+       -@erase $(DLL_OBJ)
 -      -@erase ..\*.obj ..\*.lib ..\*.exp *.obj *.lib *.exp
 -      -@erase ..\t\*.exe ..\t\*.dll ..\t\*.bat
++      -@erase ..\*.obj *.obj ..\*.lib ..\*.exp
+       -@erase *.ilk
+       -@erase *.pdb