The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
case $CONFIG in
'')
	if test -f config.sh; then TOP=.;
	elif test -f ../config.sh; then TOP=..;
	elif test -f ../../config.sh; then TOP=../..;
	elif test -f ../../../config.sh; then TOP=../../..;
	elif test -f ../../../../config.sh; then TOP=../../../..;
	else
		echo "Can't find config.sh."; exit 1
	fi
	. $TOP/config.sh
	;;
esac
case "$0" in
*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
esac
echo "Extracting pat/patlog (with variable substitutions)"
cat >patlog <<!GROK!THIS!
$startperl
	eval "exec perl -S \$0 \$*"
		if \$running_under_some_shell;

# $Id: patlog.SH,v 3.0.1.2 1997/02/28 16:33:03 ram Exp $
#
#  Copyright (c) 1991-1993, Raphael Manfredi
#  
#  You may redistribute only under the terms of the Artistic Licence,
#  as specified in the README file that comes with the distribution.
#  You may reuse parts of this distribution only within the terms of
#  that same Artistic Licence; a copy of which may be found at the root
#  of the source tree for dist 3.0.
#
# $Log: patlog.SH,v $
# Revision 3.0.1.2  1997/02/28  16:33:03  ram
# patch61: typo fix
#
# Revision 3.0.1.1  1994/10/29  16:42:26  ram
# patch36: created
#

\$defeditor='$defeditor';
\$version = '$VERSION';
\$patchlevel = '$PATCHLEVEL';
!GROK!THIS!
cat >>patlog <<'!NO!SUBS!'

$progname = &profile;	# Read ~/.dist_profile
require 'getopts.pl';
&usage unless &Getopts("hnruV");

if ($opt_V) {
	print STDERR "$progname $version PL$patchlevel\n";
	exit 0;
} elsif ($opt_h) {
	&usage;
}

&readpackage;

if (-f 'patchlevel.h') {
	open(PL,"patchlevel.h") || die "$progname: can't open patchlevel.h: $!\n";
	while (<PL>) {
		if (/^#define\s+PATCHLEVEL\s+(\d+)/) {
			$last = $1;
			$patchline = $.;	# Record PATCHLEVEL line
		}
	}
	die "$progname: malformed patchlevel.h file.\n" if $last eq '';
	$bnum = $last + 1;
}
else {
	$patchline = 1;
	$bnum = 1;
	$last = '';
}

chdir 'bugs' if -d 'bugs';

die "$progname: patch #$bnum already exists.\n" if -f "patch$bnum";

@patlist=<*.$bnum>;
die "$progname: no diff files for patch #$bnum.\n" if
	$patlist[0] =~ /^\*/ || $patlist[0] eq '';

# Set up a proper editor, for later perusal
$editor = $ENV{'VISUAL'};
$editor = $ENV{'EDITOR'} unless $editor;
$editor = $defeditor unless $editor;
$editor = 'vi' unless $editor;

# The following used to be done in patmake. Only we do not really need to
# compute the subject lines for the generated patch here, we do it nonetheless
# to avoid code duplication in patmake.

if (-s ".logs$bnum") {
	$logs = '';
	open(LOGS,".logs$bnum");
	while (<LOGS>) {
		unless ($logseen{$_}) {
			$logs .= $_;
			$logseen{$_}++;
			$logsnum++;			# One more log
		}
	}
	close LOGS;
	$* = 1;
	$subj = $logs;
	$logs =~ s/^patch\d+:\s*/\t/g;
	$logs =~ s/\n/\n\n/g;
	$subj =~ s/^patch\d+:\s*/Subject: /g;
	$* = 0;
} else {
	$subj = "Subject: \n";
}

# Try to guess the priority of the patch
if (-s ".mods$bnum") {
	open(MODS, ".mods$bnum");
	while (<MODS>) {
		chop;
		unless ($fileseen{$_}) {
			$fileseen{$_}++;
			$modsnum++;			# One more modified file
		}
	}
	close MODS;
}
$modsnum++ unless $modsnum;		# Avoid divisions by zero
$mean = $logsnum / $modsnum;
if ($mean > 0.7 && $mean < 1.3) {
	$priority = "MEDIUM";
} elsif ($mean <= 0.7) {
	$priority = "HIGH";		# Small changes
} else {
	$priority = "LOW";		# Big changes
}

# Save priority for patmake
open(PRIORITY, ">.pri$bnum") || die "$progname: can't create .pri$bnum: $!\n";
print PRIORITY $priority, "\n";
close PRIORITY;

# Save subject lines for patmake
open(SUBJECTS, ">.subj$bnum") || die "$progname: can't create .subj$bnum: $!\n";
print SUBJECTS $subj;
close SUBJECTS;

#
# Generate description file, then edit it so that the user may fixup things.
#

unless (($opt_r && -f ".clog$bnum") || ($opt_u && &uptodate(".clog$bnum"))) {
	open(CHANGES, ">.clog$bnum") ||
		die "$progname: can't create .clog$bnum: $!\n";
	print CHANGES <<EOM;
Edition of the Description section for patch #$bnum.
Please leave those three lines here, they will be removed automatically.
------------------------------------------------------------------------
EOM
	print CHANGES $logs;
	close CHANGES;
}

# If they don't want to maintain a ChangeLog file, that's it. They'll get
# the old behaviour where the description is edited directly from within
# the generated patch.

exit(0) if $changelog =~ /^\s*$/;

system $editor, ".clog$bnum";

#
# Generate RCS log file.
#

if ($changercs) {
	unless (
		($opt_r && -f ".rlog$bnum") || ($opt_u && &uptodate(".rlog$bnum"))
	) {
		&buildlogs;
		open(RCS, ">.rlog$bnum") ||
			die "$progname: can't create .rlog$bnum: $!\n";
		print RCS <<EOM;
Edition of the RCS log section for $changelog (patch #$bnum).
Please leave those three lines here, they will be removed automatically.
------------------------------------------------------------------------
EOM
		foreach $key (sort keys %rcslog) {
			print RCS &format('* ' . $rcslog{$key}), "\n";
		}
		close RCS;
	}
	system $editor, ".rlog$bnum";
}

#
# Final logfile entry generation
#

chop($date=`date`);

unless (
	($opt_r && -f ".xlog$bnum") ||
	($opt_u && &uptodate(".xlog$bnum") && !&newertmp)
) {
	open(LOG, ">.xlog$bnum") || die "$progname: can't create .xlog$bnum: $!\n";
	print LOG <<EOM;
Edition of the $changelog entry for patch #$bnum.
Please leave those three lines here, they will be removed automatically.
------------------------------------------------------------------------
EOM
	print LOG "$date   $maintname <$maintloc>\n\n";
	print LOG ". Description:\n\n";
	&addlog(".clog$bnum");
	if ($changercs) {
		print LOG ". Files changed:\n\n";
		&addlog(".rlog$bnum");
	}
	close LOG;
}
system $editor, ".xlog$bnum";
exit(0) if $opt_n;

#
# Changelog file update, checking in and diff computation.
#

print "$progname: updating $changelog...\n";

chdir('..') || die "$progname: can't go back to ..: $!\n";
if (-f $changelog) {
	rename($changelog, "$changelog.bak") ||
		die "$progname: can't rename $changelog into $changelog.bak: $!\n";
}

open(LOG, ">$changelog") || die "$progname: can't create $changelog: $!\n";
&addlog("bugs/.xlog$bnum");
if (-f "$changelog.bak") {
	open(OLOG, "$changelog.bak") ||
		die "$progname: can't open $changelog.bak: $!\n";
	print LOG while <OLOG>;
	close OLOG;
}
close LOG;

print "$progname: checking in $changelog and computing diff...\n";

# It is safe to run a patcil and a patdiff now, since the Changelog file has
# been updated anyway: any log done while checking that file in will not
# appear in the patch log nor the Changelog.

system 'perl', '-S', 'patcil', '-p', $changelog;
system 'perl', '-S', 'patdiff', $changelog;

exit 0;		# All done.

# Returns true if .clog and .rlog (it it exists) are newer than .xlog.
sub newertmp {
	return 1 unless -f ".xlog$bnum";	# To force regeneration
	return 1 if &newer(".clog$bnum", ".xlog$bnum") ||
		(!$changercs || &newer(".rlog$bnum", ".xlog$bnum"));
	0;
}

# Returns true if $file is newer than the reference file $ref.
sub newer {
	local($file, $ref) = @_;
	(stat($file))[9] >= (stat($ref))[9];
}

# Retursn true if $file is up-to-date with respect to .logs and .mods.
sub uptodate {
	local($file) = @_;
	return 0 unless -f $file;	# Cannot be up-to-date if missing
	&newer($file, ".logs$bnum") && &newer($file, ".mods$bnum");
}

# Add file to the LOG descriptor, skipping the first three lines of that file.
sub addlog {
	local($file) = @_;
	open(FILE, $file) || die "$progname: can't reopen $file: $!\n";
	$_ = <FILE>; $_ = <FILE>; $_ = <FILE>;
	print LOG while <FILE>;
	close FILE;
}

# Build RCS logs, for each file listed in the %fileseen array, into %rcslog.
# Common RCS log messages are grouped under the same entry.
sub buildlogs {
	local($log);
	local(@files);
	local($first);
	local(%invertedlog);
	foreach $file (keys %fileseen) {
		$log = &rcslog($file);
		next if $log eq '';
		$invertedlog{$log} .= "$file ";
	}
	foreach $log (keys %invertedlog) {
		@files = split(' ', $invertedlog{$log});
		$first = (sort @files)[0];
		$rcslog{$first} = join(', ', @files) . ': ' . $log;
	}
}

# Grab log for a given file by parsing its $Log section. Only comments
# relevant to the patch are kept. This relies on the presence of the patchxx:
# leading string in front of each comment.
# If not sufficient (because people don't use patchxx prefixes), then we'll
# need a more sophisticated algorithm parsing revisions lines to see where we
# left of at the last patch.
sub rcslog {
	local($file) = @_;
	open(FILE, "../$file") || warn "$me: can't open $file: $!\n";
	local($_);
	local($comment, $len);
	local($pcomment) = "patch$bnum:";
	local($plen) = length($pcomment);
	local($c);
	local($lastnl) = 1;
	local($kept);			# Relevant part of the RCS comment which is kept
	file: while (<FILE>) {
		if (/^(.*)\$Log[:\$]/) {
			$comment = $1;
			$comment =~ s/\s+$//;	# Newer RCS chop spaces on emtpy lines
			$len = length($comment);
			while (<FILE>) {
				$c = substr($_, 0, $len);
				last file unless $c eq $comment;
				$_ = substr($_, $len, 9_999);
				if ($lastnl) {
					last file unless /^\s*Revision\s+\d/;
					$lastnl = 0;
				} elsif (/^\s*$/) {
					$lastnl = 1;
				} else {
					s/^\s*//;	# Older RCS will have space here
					$c = substr($_, 0, $plen);
					last file unless $c eq $pcomment;
					# Comment for that patch is kept after space cleanup
					$_ = substr($_, $plen, 9_999);
					s/^\s*//;
					s/\s*$//;
					$_ .= '.' unless /\.$/;
					s/^(.)/\U$1/;	# Ensure upper-cased to start sentence
					s/^/  / if $kept;
					$kept .= $_;	# Will be reformatted later on
				}
			}
		}
	}
	close FILE;
	$kept;
}

# Format line to fit in 80 columns (70 + 8 for the added leading tabs).
# Rudimentary parsing to break lines after a , or a space.
sub format {
	local($_) = @_;
	local($tmp);
	local($msg);
	while (length($_) > 70) {
		$tmp = substr($_, 0, 70);
		$tmp =~ s/^(.*)([,\s]).*/$1/;
		$msg .= "\t$tmp" . ($2 eq ',' ? ',' : '') . "\n";
		$_ = substr($_, length($tmp), 9_999);
		$_ =~ s/^\s+//;
	}
	$msg .= "\t$_\n";
	$msg;
}

sub usage {
	print STDERR <<EOM;
Usage: $progname [-hnruV]
  -h : print this message and exit.
  -n : not-really mode: force re-edit, but stop after updating.
  -r : reuse existing change file candidate entries (supersedes -u).
  -u : update mode, recreate files only when out of date.
  -V : print version number and exit.
EOM
	exit 1;
}

!NO!SUBS!
$grep -v '^;#' ../pl/package.pl >>patlog
$grep -v '^;#' ../pl/tilde.pl >>patlog
$grep -v '^;#' ../pl/profile.pl >>patlog
chmod +x patlog
$eunicefix patlog