--- /dev/null
+ #!/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*");
--- /dev/null
+ #!/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;
+ }
+
--- /dev/null
+ 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
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'
--- /dev/null
+ #
+ # 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
+
+