frank@morgan.com (Frank Wortner) (05/28/88)
Here is a version of Larry Wall's patch program. I've made a few
minor changes to get it to run under Minix. The program has served me
well over the past month or two and I'm reasonably confident that it
works.
Have fun!
Frank
frank@morgan.com
...!{uunet, sun}!mstan!frank
----------------------------------cut here----------------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# Configure
# EXTERN.h
# INTERN.h
# Makefile
# Makefile.SH
# READ-ME-FIRST
# README
# common.h
# config.h
# inp.c
# inp.h
# patch.doc
# This archive created: Fri May 27 10:02:15 1988
export PATH; PATH=/bin:$PATH
echo shar: extracting "'Configure'" '(21237 characters)'
if test -f 'Configure'
then
echo shar: will not over-write existing file "'Configure'"
else
cat << \SHAR_EOF > 'Configure'
#! /bin/sh
#
# If these # comments don't work, trim them. Don't worry about any other
# shell scripts, Configure will trim # comments from them for you.
#
# Note: if you are running ksh, be sure to say "sh Configure".
#
# (If you are trying to port this package to a machine without sh, I would
# suggest you cut out the prototypical config.h from the end of Configure
# and edit it to reflect your system. Some packages may include samples
# of config.h for certain machines, so you might look for one of those.)
#
# $Header: Configure,v 2.0 86/09/17 15:32:58 lwall Exp $
#
# $Log: Configure,v $
# Revision 2.0 86/09/17 15:32:58 lwall
# Baseline for netwide release.
#
#
# Yes, you may rip this off to use in other distribution packages.
#
# (Note: this Configure script was generated automatically. Rather than
# working with this copy of Configure, you may wish to get metaconfig.)
define='define'
undef='/*undef'
d_eunice=''
eunicefix=''
loclist=''
expr=''
sed=''
echo=''
cat=''
rm=''
mv=''
cp=''
tail=''
tr=''
mkdir=''
sort=''
uniq=''
grep=''
trylist=''
test=''
inews=''
egrep=''
more=''
pg=''
Mcc=''
vi=''
mailx=''
Log=''
Header=''
bin=''
cc=''
contains=''
cpp=''
d_index=''
d_void=''
iandd=''
libc=''
mansrc=''
manext=''
n=''
c=''
package=''
registers=''
reg1=''
reg2=''
reg3=''
reg4=''
reg5=''
reg6=''
reg7=''
reg8=''
reg9=''
reg10=''
reg11=''
reg12=''
reg13=''
reg14=''
reg15=''
reg16=''
spitshell=''
shsharp=''
sharpbang=''
startsh=''
CONFIG=''
package=patch
echo "Beginning of configuration questions for $package kit."
: Eunice requires " " instead of "", can you believe it
echo " "
: sanity checks
PATH='.:/bin:/usr/bin:/usr/local/bin:/usr/ucb:/usr/local:/usr/lbin:/etc'
export PATH || (echo "OOPS, this isn't sh. Desperation time. I will feed myself to sh."; sh $0; kill $$)
if test ! -t 0; then
echo "Say 'sh Configure', not 'sh <Configure'"
exit 1
fi
: some greps do not return status, grrr.
echo "grimblepritz" >grimble
if grep blurfldyick grimble >/dev/null 2>&1 ; then
contains=contains
else
if grep grimblepritz grimble >/dev/null 2>&1 ; then
contains=grep
else
contains=contains
fi
fi
rm -f grimble
: the following should work in any shell
case "$contains" in
contains*)
echo " "
echo "AGH! Grep doesn't return a status. Attempting remedial action."
cat >contains <<'EOSS'
grep "$1" "$2" >.greptmp && cat .greptmp && test -s .greptmp
EOSS
chmod 755 contains
esac
: first determine how to suppress newline on echo command
echo "Checking echo to see how to suppress newlines..."
(echo "hi there\c" ; echo " ") >.echotmp
if $contains c .echotmp >/dev/null 2>&1 ; then
echo "...using -n."
n='-n'
c=''
else
echo "...using \\\c"
echo "c."
n=''
c='\c'
fi
echo $n "Type carriage return to continue. Your cursor should be here-->$c"
read ans
rm -f .echotmp
: now set up to do reads with possible shell escape
: if this does not work on your machine, 1,$ s/. myread/read ans/
cat <<EOSC >myread
ans='!'
while expr "X\$ans" : "X!" >/dev/null; do
read ans
case "\$ans" in
!)
sh
echo " "
echo $n "\$rp $c"
;;
!*)
set \`expr "X\$ans" : "X!\(.*\)\$"\`
sh -c "\$*"
echo " "
echo $n "\$rp $c"
;;
esac
done
rp='Your answer:'
EOSC
: general instructions
cat <<EOH
This installation shell script will examine your system and ask you questions
to determine how $package and any auxiliary files should be installed. If you
get stuck on a question, you may use a ! shell escape to start a subshell or
execute a command. Many of the questions will have default answers in
square brackets--typing carriage return will give you the default.
On some of the questions which ask for file or directory names you are
allowed to use the ~name construct to specify the login directory belonging
to "name", even if you don't have a shell which knows about that. Questions
where this is allowed will be marked "(~name ok)".
EOH
rp="[Type carriage return to continue]"
echo $n "$rp $c"
read ans
cat <<EOH
Much effort has been expended to ensure that this shell script will run
on any Unix system. If despite that it blows up on you, your best bet is
to edit Configure and run it again. (Trying to install this package
without having run Configure may be well nigh impossible.) Also, let me
(lwall@sdcrdcf.UUCP) know how I blew it.
This installation script affects things in two ways: 1) it may do direct
variable substitutions on some of the files included in this kit, and
2) it builds a config.h file for inclusion in C programs. You may edit
any of these files as the need arises after running this script.
EOH
rp="[Type carriage return to continue]"
echo $n "$rp $c"
read ans
: get old answers, if there is a config file out there
if test -f config.sh; then
echo " "
rp="I see a config.sh file. Did Configure make it on THIS system? [y]"
echo $n "$rp $c"
read ans
case "$ans" in
n*) echo "OK, I'll ignore it.";;
*) echo "Fetching default answers from your old config.sh file..."
. config.sh
;;
esac
fi
: get list of predefined functions in a handy place
echo " "
if test -f /lib/libc.a; then
echo "Your C library is in /lib/libc.a. You're normal."
libc=/lib/libc.a
else
if test -f /usr/lib/libc.a; then
echo "Your C library is in /usr/lib/libc.a, of all places."
libc=/usr/lib/libc.a
else
if test -f "$libc"; then
echo "Your C library is in $libc, like you said before."
else
cat <<'EOM'
I can't seem to find your C library. I've looked for /lib/libc.a and
/usr/lib/libc.a, but neither of those are there. What is the full name
EOM
echo $n "of your C library? $c"
rp='C library full name?'
read ans
libc="$ans"
fi
fi
fi
echo " "
echo $n "Extracting names from $libc for later perusal...$c"
if ar t $libc > libc.list; then
echo "done"
else
echo " "
echo "The archiver doesn't think $libc is a reasonable library."
exit 1
fi
: make some quick guesses about what we are up against
echo " "
echo $n "Hmm... $c"
if $contains SIGTSTP /usr/include/signal.h >/dev/null 2>&1 ; then
echo "Looks kind of like a BSD system, but we'll see..."
echo exit 0 >bsd
echo exit 1 >usg
echo exit 1 >v7
else
if $contains fcntl libc.list >/dev/null 2>&1 ; then
echo "Looks kind of like a USG system, but we'll see..."
echo exit 1 >bsd
echo exit 0 >usg
echo exit 1 >v7
else
echo "Looks kind of like a version 7 system, but we'll see..."
echo exit 1 >bsd
echo exit 1 >usg
echo exit 0 >v7
fi
fi
if $contains vmssystem libc.list >/dev/null 2>&1 ; then
cat <<'EOI'
There is, however, a strange, musty smell in the air that reminds me of
something...hmm...yes...I've got it...there's a VMS nearby, or I'm a Blit.
EOI
echo "exit 0" >eunice
eunicefix=unixtovms
d_eunice="$define"
: it so happens the Eunice I know will not run shell scripts in Unix format
else
echo " "
echo "Congratulations. You aren't running Eunice."
eunicefix=':'
d_eunice="$undef"
echo "exit 1" >eunice
fi
chmod 755 bsd usg v7 eunice
$eunicefix bsd usg v7 eunice
: see if sh knows # comments
echo " "
echo "Checking your sh to see if it knows about # comments..."
if sh -c '#' >/dev/null 2>&1 ; then
echo "Your sh handles # comments correctly."
shsharp=true
spitshell=cat
echo " "
echo "Okay, let's see if #! works on this system..."
echo "#!/bin/echo hi" > try
$eunicefix try
chmod 755 try
try > today
if test -s today; then
echo "It does."
sharpbang='#!'
else
echo "#! /bin/echo hi" > try
$eunicefix try
chmod 755 try
try > today
if test -s today; then
echo "It does."
sharpbang='#! '
else
echo "It doesn't."
sharpbang=': use '
fi
fi
else
echo "Your sh doesn't grok # comments--I will strip them later on."
shsharp=false
echo "exec grep -v '^#'" >spitshell
chmod 755 spitshell
$eunicefix spitshell
spitshell=`pwd`/spitshell
echo "I presume that if # doesn't work, #! won't work either!"
sharpbang=': use '
fi
: figure out how to guarantee sh startup
echo " "
echo "Checking out how to guarantee sh startup..."
startsh=$sharpbang'/bin/sh'
echo "Let's see if '$startsh' works..."
cat >try <<EOSS
$startsh
set abc
test "$?abc" != 1
EOSS
chmod 755 try
$eunicefix try
if try; then
echo "Yup, it does."
else
echo "Nope. You may have to fix up the shell scripts to make sure sh runs them."
fi
rm -f try today
: find out where common programs are
echo " "
echo "Locating common programs..."
pth="/usr/ucb /bin /usr/bin /usr/local /usr/local/bin /usr/lbin /etc /usr/lib"
cat <<EOSC >loc
$startsh
thing=\$1
shift
dflt=\$1
shift
for dir in \$*; do
case "\$thing" in
.)
if test -d \$dir/\$thing; then
echo \$dir
exit 0
fi
;;
*)
if test -f \$dir/\$thing; then
echo \$dir/\$thing
exit 0
fi
;;
esac
done
echo \$dflt
exit 1
EOSC
chmod 755 loc
$eunicefix loc
loclist="
expr
sed
echo
cat
rm
grep
"
trylist="
test
Mcc
"
for file in $loclist; do
xxx=`loc $file $file $pth`
eval $file=$xxx
case "$xxx" in
/*)
echo $file is in $xxx.
;;
*)
echo "I don't know where $file is. I hope it's in everyone's PATH."
;;
esac
done
echo " "
echo "Don't worry if any of the following aren't found..."
ans=offhand
for file in $trylist; do
xxx=`loc $file $file $pth`
eval $file=$xxx
case "$xxx" in
/*)
echo $file is in $xxx.
;;
*)
echo "I don't see $file out there, $ans."
ans=either
;;
esac
done
case "$egrep" in
egrep)
echo "Substituting grep for egrep."
egrep=$grep
;;
esac
case "$test" in
test)
echo "Hopefully test is built into your sh."
;;
/bin/test)
echo " "
echo $n 'Is your "test" built into sh? [n] (OK to guess) '"$c"
rp='test built into sh? [n]'
read ans
case "$ans" in
y*) test=test ;;
esac
;;
*)
test=test
;;
esac
case "$echo" in
echo)
echo "Hopefully echo is built into your sh."
;;
/bin/echo)
echo " "
echo "Checking compatibility between /bin/echo and builtin echo (if any)..."
$echo $n "hi there$c" >foo1
echo $n "hi there$c" >foo2
if cmp foo1 foo2 >/dev/null 2>&1; then
echo "They are compatible. In fact, they may be identical."
else
echo "They are not compatible--the echo builtin will be used."
echo=echo
fi
$rm -f foo1 foo2
;;
*)
echo=echo
;;
esac
: index or strcpy
$echo " "
if $contains index libc.list >/dev/null 2>&1 ; then
$echo "Your system appears to use index() and rindex() rather than strchr()"
$echo $n "and strrchr(). Is this correct? [y] $c"
rp='index() rather than strchr()? [y]'
read ans
case "$ans" in
n*|f*) d_index="$define" ;;
*) d_index="$undef" ;;
esac
else
$echo "Your system appears to use strchr() and strrchr() rather than index()"
$echo $n "and rindex(). Is this correct? [y] $c"
rp='strchr() rather than index()? [y]'
read ans
case "$ans" in
n*|f*) d_index="$undef" ;;
*) d_index="$define" ;;
esac
fi
: check for void type
$echo " "
$echo "Checking to see if your C compiler groks the void type..."
$cat >try.c <<'EOCP'
void main();
EOCP
if cc -c try.c >/dev/null 2>&1 ; then
d_void="$undef"
$echo "Yup, it does."
else
d_void="$define"
$echo "Nope, it doesn't (boo hiss). I will substitute int."
fi
$rm -f try.*
: see how we invoke the C preprocessor
echo " "
echo "Checking to see how your C preprocessor is invoked..."
cat <<'EOT' >testcpp.c
#define ABC abc
#define XYZ xyz
ABC.XYZ
EOT
echo 'Maybe "cc -E" will work...'
cc -E testcpp.c >testcpp.out 2>&1
if $contains 'abc.xyz' testcpp.out >/dev/null 2>&1 ; then
echo "Yup, it does."
cpp='cc -E'
else
echo 'Nope...maybe "cc -P" will work...'
cc -P testcpp.c >testcpp.out 2>&1
if $contains 'abc.xyz' testcpp.out >/dev/null 2>&1 ; then
echo "Yup, that does."
cpp='cc -P'
else
echo 'Nixed again...maybe "/lib/cpp" will work...'
/lib/cpp testcpp.c >testcpp.out 2>&1
if $contains 'abc.xyz' testcpp.out >/dev/null 2>&1 ; then
echo "Hooray, it works! I was beginning to wonder."
cpp='/lib/cpp'
else
echo 'Hmm...maybe you already told me...'
case "$cpp" in
'') ;;
*) $cpp testcpp.c >testcpp.out 2>&1;;
esac
if $contains 'abc.xyz' testcpp.out >/dev/null 2>&1 ; then
echo "Hooray, you did! I was beginning to wonder."
else
echo $n "Nope. I can't find a C preprocessor. Name one: $c"
rp='Name a C preprocessor:'
read ans
cpp="$ans"
$cpp testcpp.c >testcpp.out 2>&1
if $contains 'abc.xyz' testcpp.out >/dev/null 2>&1 ; then
echo "OK, that will do."
else
echo "Sorry, I can't get that to work. Go find one."
exit 1
fi
fi
fi
fi
fi
rm -f testcpp.c testcpp.out
: get C preprocessor symbols handy
echo " "
cat <<'EOT' >Cppsym.c
char *sym[] = {
#ifdef mc68000
"mc68000",
#endif
#ifdef sun
"sun",
#endif
#ifdef gcos
"gcos",
#endif
#ifdef unix
"unix",
#endif
#ifdef ibm
"ibm",
#endif
#ifdef gimpel
"gimpel",
#endif
#ifdef interdata
"interdata",
#endif
#ifdef tss
"tss",
#endif
#ifdef os
"os",
#endif
#ifdef mert
"mert",
#endif
#ifdef pyr
"pyr",
#endif
#ifdef vax
"vax",
#endif
#ifdef pdp11
"pdp11",
#endif
#ifdef i8086
"i8086",
#endif
#ifdef z8000
"z8000",
#endif
#ifdef 3b2
"3b2",
#endif
#ifdef 3b5
"3b5",
#endif
#ifdef 3b20
"3b20",
#endif
#ifdef 3b200
"3b200",
#endif
0};
main(argc,argv)
int argc;
char **argv;
{
int i;
for (argc--,argv++; argc; argc--,argv++) {
for (i=0; sym[i]; i++) {
if (strcmp(argv[0],sym[i]) == 0)
exit(0);
}
}
exit(1);
}
EOT
echo "Your machine appears to have the following attributes:"
$cpp Cppsym.c | sed -n -e 's/^ "\(.*\)",$/\1/p'
cc Cppsym.c -o Cppsym
rm -f Cppsym.c
: see how many register declarations we want to use
case "$registers" in
'')
if Cppsym pdp11 i8086 z8000; then
dflt=3
else
if Cppsym sun mc68000; then
dflt=10
else
: if you have any other numbers for me, send them in
dflt=6
fi
fi
;;
*) dflt=$registers ;;
esac
cat <<EOM
Different C compilers on different machines pay attention to different
numbers of register declarations. About how many register declarations in
EOM
$echo $n "each routine does your C compiler pay attention to? (OK to guess) [$dflt] $c"
rp="# register declarations used? [$dflt]"
read ans
case "$ans" in
'') ans=$dflt;;
esac
registers=$ans
reg1=''
awk "END { for (i=1; i<=16; i++) printf \"reg%d=''\n\", i}" </dev/null >.foo
. .foo
awk "END { for (i=1; i<=$registers; i++) printf \"reg%d=register\n\", i}" \
</dev/null >.foo
. .foo
rm -f .foo
: preserve RCS keywords in files with variable substitution, grrr
Log='$Log'
Header='$Header'
: set up shell script to do ~ expansion
cat >filexp <<EOSS
$startsh
: expand filename
case "\$1" in
~/*|~)
$echo \$1 | $sed "s|~|\${HOME-\$LOGDIR}|"
;;
~*)
if $test -f /bin/csh; then
/bin/csh -f -c "glob \$1"
$echo ""
else
name=\`$expr x\$1 : '..\([^/]*\)'\`
dir=\`$sed </etc/passwd -n -e "/^\${name}:/{s/^[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:\([^:]*\).*"'\$'"/\1/" -e p -e q -e '}'\`
if $test ! -d "\$dir"; then
me=\`basename \$0\`
$echo "\$me: can't locate home directory for: \$name" >&2
exit 1
fi
case "\$1" in
*/*)
$echo \$dir/\`$expr x\$1 : '..[^/]*/\(.*\)'\`
;;
*)
$echo \$dir
;;
esac
fi
;;
*)
$echo \$1
;;
esac
EOSS
chmod 755 filexp
$eunicefix filexp
: determine where public executables go
case "$bin" in
'')
dflt=`loc . /bin /usr/local/bin /usr/lbin /usr/local /usr/bin`
;;
*) dflt="$bin"
;;
esac
bin='blurfl/dyick'
while $test ! -d "$bin" ; do
case "$bin" in
blurfl*) ;;
*) $echo "$bin does not appear to exist." ;;
esac
$echo " "
rp="Where do you want to put the public executables? [$dflt]"
$echo $n "$rp $c"
read ans
bin="$ans"
bin=`filexp $bin`
case "$bin" in
'') bin=$dflt ;;
esac
done
: determine where manual pages go
case "$mansrc" in
'')
dflt=`loc . /usr/man/man1 /usr/man/mann /usr/man/local/man1 /usr/man/u_man/man1 /usr/man/man1`
;;
*) dflt="$mansrc"
;;
esac
mansrc='blurfl/dyick'
while $test ! -d "$mansrc" ; do
case "$mansrc" in
blurfl*) ;;
*) $echo "$mansrc does not appear to exist." ;;
esac
$echo " "
rp="Where do the manual pages (source) go? [$dflt]"
$echo $n "$rp $c"
read ans
mansrc=`filexp "$ans"`
case "$mansrc" in
'') mansrc=$dflt ;;
esac
done
case "$mansrc" in
*l)
manext=l
;;
*n)
manext=n
;;
*)
manext=1
;;
esac
: see if we need a special compiler
$echo " "
if usg; then
case "$cc" in
'')
case "$Mcc" in
/*) dflt='Mcc'
;;
*)
if $contains '\-M' $mansrc/cc.1 >/dev/null 2>&1 ; then
dflt='cc -M'
else
dflt='cc'
fi
;;
esac
;;
*) dflt="$cc";;
esac
$cat <<'EOM'
On some systems the default C compiler will not resolve multiple global
references that happen to have the same name. On some such systems the
"Mcc" command may be used to force these to be resolved. On other systems
a "cc -M" command is required. What command will force resolution on
EOM
$echo $n "this system? [$dflt] $c"
rp="Command to resolve multiple refs? [$dflt]"
read ans
cc="$ans"
case "$cc" in
'') cc="$dflt" ;;
esac
else
$echo "Not a USG system--assuming cc can resolve multiple definitions."
cc=cc
fi
: see if we should throw a -i into the Makefile
$echo " "
if Cppsym pdp11 i8086 z8000; then
if $contains '\-i' $mansrc/cc.1 >/dev/null 2>&1 ; then
rp="Your system appears to have separate I and D space. Is this true? [y]"
$echo $n "$rp $c"
read ans
case "$ans" in
n*|f*) iandd='' ;;
*) iandd='-i' ;;
esac
else
$echo "Your system appears to NOT have separate I and D space."
$echo $n "Is this correct? [y] $c"
rp='No separate I and D. Correct? [y]'
read ans
case "$ans" in
n*|f*) iandd='-i' ;;
*) iandd='' ;;
esac
fi
else
$echo $n "Does your machine have separate I and D space? [n] $c"
read ans
case "$ans" in
y*) iandd='-i' ;;
*) iandd='' ;;
esac
fi
$echo " "
$echo "End of configuration questions."
$echo " "
: create config.sh file
$echo " "
$echo "Creating config.sh..."
$spitshell <<EOT >config.sh
$startsh
# config.sh
# This file was produced by running the Configure script.
d_eunice='$d_eunice'
eunicefix='$eunicefix'
loclist='$loclist'
expr='$expr'
sed='$sed'
echo='$echo'
cat='$cat'
rm='$rm'
mv='$mv'
cp='$cp'
tail='$tail'
tr='$tr'
mkdir='$mkdir'
sort='$sort'
uniq='$uniq'
grep='$grep'
trylist='$trylist'
test='$test'
inews='$inews'
egrep='$egrep'
more='$more'
pg='$pg'
Mcc='$Mcc'
vi='$vi'
mailx='$mailx'
Log='$Log'
Header='$Header'
bin='$bin'
cc='$cc'
contains='$contains'
cpp='$cpp'
d_index='$d_index'
d_void='$d_void'
iandd='$iandd'
libc='$libc'
mansrc='$mansrc'
manext='$manext'
n='$n'
c='$c'
package='$package'
registers='$registers'
reg1='$reg1'
reg2='$reg2'
reg3='$reg3'
reg4='$reg4'
reg5='$reg5'
reg6='$reg6'
reg7='$reg7'
reg8='$reg8'
reg9='$reg9'
reg10='$reg10'
reg11='$reg11'
reg12='$reg12'
reg13='$reg13'
reg14='$reg14'
reg15='$reg15'
reg16='$reg16'
spitshell='$spitshell'
shsharp='$shsharp'
sharpbang='$sharpbang'
startsh='$startsh'
CONFIG=true
EOT
: create config.h file
$echo " "
$echo "Creating config.h..."
$cat <<EOT >config.h
/* config.h
* This file was produced by running the Configure script.
* Feel free to modify any of this as the need arises.
*/
#$d_eunice EUNICE /* no file linking? */
#$d_eunice VMS /* other assorted ickies? */
#$d_index index strchr /* cultural */
#$d_index rindex strrchr /* differences? */
#$d_void void int /* is void to be avoided? */
/* How many register declarations are paid attention to? */
#define Reg1 $reg1 /**/
#define Reg2 $reg2 /**/
#define Reg3 $reg3 /**/
#define Reg4 $reg4 /**/
#define Reg5 $reg5 /**/
#define Reg6 $reg6 /**/
#define Reg7 $reg7 /**/
#define Reg8 $reg8 /**/
#define Reg9 $reg9 /**/
#define Reg10 $reg10 /**/
#define Reg11 $reg11 /**/
#define Reg12 $reg12 /**/
#define Reg13 $reg13 /**/
#define Reg14 $reg14 /**/
#define Reg15 $reg15 /**/
#define Reg16 $reg16 /**/
EOT
CONFIG=true
if $contains '\.SH' MANIFEST >/dev/null 2>&1; then
$echo " "
$echo "Doing variable substitutions on .SH files..."
set `$grep <MANIFEST '\.SH' | awk '{print $1}'`
for file in $*; do
case "$file" in
*/*)
dir=`$expr X$file : 'X\(.*\)/'`
file=`$expr X$file : 'X.*/\(.*\)'`
(cd $dir && . $file)
;;
*)
. $file
;;
esac
done
fi
if $contains '^depend:' Makefile >/dev/null 2>&1; then
$echo " "
$echo 'Now you need to generate make dependencies by running "make depend".'
$echo 'You might prefer to run it in background: "make depend > makedepend.out &"'
$echo $n "Would you like me to run it for you (it takes quite a while)? [n] $c"
rp="Run make depend now? [n]"
read ans
case "$ans" in
y*) make depend;;
esac
fi
$rm -f libc.list kit*isdone bsd usg v7 eunice loc Cppsym
if test -f Makefile; then
$echo " "
$echo "Now you must run a make."
else
$echo "Done."
fi
: end of Configure
SHAR_EOF
if test 21237 -ne "`wc -c < 'Configure'`"
then
echo shar: error transmitting "'Configure'" '(should have been 21237 characters)'
fi
chmod +x 'Configure'
fi # end of overwriting check
echo shar: extracting "'EXTERN.h'" '(241 characters)'
if test -f 'EXTERN.h'
then
echo shar: will not over-write existing file "'EXTERN.h'"
else
cat << \SHAR_EOF > 'EXTERN.h'
/* $Header: EXTERN.h,v 2.0 86/09/17 15:35:37 lwall Exp $
*
* $Log: EXTERN.h,v $
* Revision 2.0 86/09/17 15:35:37 lwall
* Baseline for netwide release.
*
*/
#undef EXT
#define EXT extern
#undef INIT
#define INIT(x)
#undef DOINIT
SHAR_EOF
if test 241 -ne "`wc -c < 'EXTERN.h'`"
then
echo shar: error transmitting "'EXTERN.h'" '(should have been 241 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'INTERN.h'" '(239 characters)'
if test -f 'INTERN.h'
then
echo shar: will not over-write existing file "'INTERN.h'"
else
cat << \SHAR_EOF > 'INTERN.h'
/* $Header: INTERN.h,v 2.0 86/09/17 15:35:58 lwall Exp $
*
* $Log: INTERN.h,v $
* Revision 2.0 86/09/17 15:35:58 lwall
* Baseline for netwide release.
*
*/
#undef EXT
#define EXT
#undef INIT
#define INIT(x) = x
#define DOINIT
SHAR_EOF
if test 239 -ne "`wc -c < 'INTERN.h'`"
then
echo shar: error transmitting "'INTERN.h'" '(should have been 239 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'Makefile'" '(1372 characters)'
if test -f 'Makefile'
then
echo shar: will not over-write existing file "'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
###############################################################################
## ##
## File: Makefile ##
## Altered-by: Frank Wortner ##
## Created: Fri May 27 09:47:49 1988 ##
## Contents: A Makefile for Patch Under Minix ##
## ##
## $Log$ ##
###############################################################################
CC = cc
bin = /usr/bin
mansrc = /usr/doc
manext = l
CFLAGS = -DMINIX
LDFLAGS = -i
public = patch
libs =
private =
defs =
manpages = patch.man
util = Makefile
c = patch.c pch.c inp.c version.c util.c
obj = patch.s pch.s inp.s util.s version.s
all: $(public) $(private) $(util)
touch all
patch: $(obj)
$(CC) $(LDFLAGS) $(obj) $(libs) -o patch
# won't work with csh
install: patch
export PATH || exit 1
- mv $(bin)/patch $(bin)/patch.old
- if test `pwd` != $(bin); then cp $(public) $(bin); fi
cd $(bin); chmod 755 $(public)
- if test `pwd` != $(mansrc); then \
for page in $(manpages); do \
cp $$page $(mansrc)/`basename $$page .man`.$(manext); \
done; \
fi
clean:
rm -f *.s *.orig core
patch.s: config.h common.h patch.c inp.h pch.h util.h version.h
pch.s: config.h common.h pch.c pch.h util.h
inp.s: config.h common.h inp.c inp.h util.h
util.s: config.h common.h util.c util.h
version.s: config.h common.h version.c version.h patchlevel.h util.h
SHAR_EOF
if test 1372 -ne "`wc -c < 'Makefile'`"
then
echo shar: error transmitting "'Makefile'" '(should have been 1372 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'Makefile.SH'" '(1954 characters)'
if test -f 'Makefile.SH'
then
echo shar: will not over-write existing file "'Makefile.SH'"
else
cat << \SHAR_EOF > 'Makefile.SH'
case $CONFIG in
'') . config.sh ;;
esac
echo "Extracting Makefile (with variable substitutions)"
cat >Makefile <<!GROK!THIS!
# $Header: Makefile.SH,v 2.0 86/09/17 15:36:15 lwall Exp $
#
# $Log: Makefile.SH,v $
# Revision 2.0 86/09/17 15:36:15 lwall
# Baseline for netwide release.
#
# Revision 1.2 86/09/08 14:07:42 lwall
# Split up patch.c.
#
# Revision 1.1 86/08/01 20:18:35 lwall
# Initial revision
#
CC = $cc
bin = $bin
mansrc = $mansrc
manext = $manext
CFLAGS = $iandd -O
LDFLAGS = $iandd
!GROK!THIS!
cat >>Makefile <<'!NO!SUBS!'
public = patch
private =
manpages = patch.man
util = Makefile
c = patch.c pch.c inp.c version.c util.c
obj = patch.o pch.o inp.o util.o version.o
lintflags = -phbvxac
addedbyconf = Makefile.old bsd config.h config.sh eunice loc pdp11 usg v7
# grrr
SHELL = /bin/sh
.c.o:
$(CC) -c $(CFLAGS) $*.c
all: $(public) $(private) $(util)
touch all
patch: $(obj)
$(CC) $(LDFLAGS) $(obj) $(libs) -o patch
# won't work with csh
install: patch
export PATH || exit 1
- mv $(bin)/patch $(bin)/patch.old
- if test `pwd` != $(bin); then cp $(public) $(bin); fi
cd $(bin); chmod 755 $(public)
- if test `pwd` != $(mansrc); then \
for page in $(manpages); do \
cp $$page $(mansrc)/`basename $$page .man`.$(manext); \
done; \
fi
clean:
rm -f *.o *.orig core
realclean:
rm -f patch *.o *.orig core $(addedbyconf)
# The following lint has practically everything turned on. Unfortunately,
# you have to wade through a lot of mumbo jumbo that can't be suppressed.
# If the source file has a /*NOSTRICT*/ somewhere, ignore the lint message
# for that spot.
lint:
lint $(lintflags) $(defs) $(c) > patch.fuzz
patch.o: config.h common.h patch.c inp.h pch.h util.h version.h
pch.o: config.h common.h pch.c pch.h util.h
inp.o: config.h common.h inp.c inp.h util.h
util.o: config.h common.h util.c util.h
version.o: config.h common.h version.c version.h patchlevel.h util.h
!NO!SUBS!
$eunicefix Makefile
SHAR_EOF
if test 1954 -ne "`wc -c < 'Makefile.SH'`"
then
echo shar: error transmitting "'Makefile.SH'" '(should have been 1954 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'READ-ME-FIRST'" '(2099 characters)'
if test -f 'READ-ME-FIRST'
then
echo shar: will not over-write existing file "'READ-ME-FIRST'"
else
cat << \SHAR_EOF > 'READ-ME-FIRST'
This is the source to Larry Wall's "patch" program ported to the
Minix operating system. I've used this program for several months,
and it seems to work quite well. It certainly is more reliable and
forgiving than "fix." That program can't reconcile diffs with
altered source; this one can.
There are a number of problems with the "virgin" Un*x source under
Minix. The first is the absence of both "sed" and a full
implementation of "expr" from off-the-shelf Minix
1.2. This means that "Configure" can't run to completion under Minix.
I've pre-run Configure and enclosed the results, so this won't
be a problem. All you have to do is type "make."
Another problem arises from patch's use of long integers as indices
into character arrays. The Minix C compiler "knows" that it has at
most 64K worth of memory to play with, so it prints messages about
conversions from long to pointer losing accuracy. At *lot* of
messages. Don't worry. I've been using the program for a couple of
months and it does work in spite of the nasty compilation warnings.
I've tracked down the problem to one line in common.h:
typedef long LINENUM;
Don't bother trying to change long to int; I've tried that. The
warnings disappear, but the program malfunctions. I'll take
compilation warnings over incorrect operation any day.
Patch occasionally uses "ed" to process diffs that look like editor
scripts. Someone (Brian Beatie, I think) posted an ed a while ago
and the sources should be in the achives. I've assumed that ed lives in
/usr/bin.
A final note to the "small is beautiful" fans: yes, I know that patch is
quite large. It is not used constantly, and it eliminates a lot of
frustration. It's memory well spent.
A final plea: I've tried contacting Larry Wall, but to no avail. I'd
like to see "official" support for Minix patch. For one thing, it
would assure that Minix users would always have the latest version.
Does anyone know his current e-mail address?
Enjoy!
Frank Wortner
Morgan Stanley & Co.
(212) 703-6498
frank@morgan.com
...{sun, uunet}!mstan!frank
SHAR_EOF
if test 2099 -ne "`wc -c < 'READ-ME-FIRST'`"
then
echo shar: error transmitting "'READ-ME-FIRST'" '(should have been 2099 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'README'" '(2963 characters)'
if test -f 'README'
then
echo shar: will not over-write existing file "'README'"
else
cat << \SHAR_EOF > 'README'
Patch Kit, Version 2.0
Copyright (c) 1986, Larry Wall
You may copy the patch kit in whole or in part as long as you don't try to
make money off it, or pretend that you wrote it.
--------------------------------------------------------------------------
Please read all the directions below before you proceed any further, and
then follow them carefully. Failure to do so may void your warranty. :-)
After you have unpacked your kit, you should have all the files listed
in MANIFEST.
Installation
1) Run Configure. This will figure out various things about your system.
Some things Configure will figure out for itself, other things it will
ask you about. It will then proceed to make config.h, config.sh, and
Makefile.
You might possibly have to trim # comments from the front of Configure
if your sh doesn't handle them, but all other # comments will be taken
care of.
If you don't have sh, you'll have to rip the prototype of config.h out
of Configure and generate the defines by hand.
2) Glance through config.h to make sure system dependencies are correct.
Most of them should have been taken care of by running the Configure script.
If you have any additional changes to make to the C definitions, they
can be done in the Makefile, or in config.h. Bear in mind that they may
get undone next time you run Configure.
3) make
This will attempt to make patch in the current directory.
4) make install
This will put patch into a public directory (normally /usr/local/bin).
It will also try to put the man pages in a reasonable place. It will not
nroff the man page, however.
5) Read the manual entry before running patch.
6) IMPORTANT! Help save the world! Communicate any problems and
suggested patches to me, lwall@sdcrdcf.UUCP (Larry Wall), so we can
keep the world in sync. If you have a problem, there's someone else
out there who either has had or will have the same problem.
If possible, send in patches such that the patch program will apply them.
Context diffs are the best, then normal diffs. Don't send ed scripts--
I've probably changed my copy since the version you have.
Watch for patch patches in net.sources.bugs. Patches will generally be
in a form usable by the patch program. If you are just now bringing up
patch and aren't sure how many patches there are, write to me and I'll
send any you don't have. Your current patch level is shown in patchlevel.h.
NEW FEATURES IN THIS RELEASE
(Correct) support for 4.3bsd-style context diffs.
Files can be created from scratch.
You can specify a fuzz-factor for context matching.
You can force patch to ask no questions.
You can specify how much of the leading pathname to strip off filenames.
Uses a Configure script for greater portability.
You are now asked if you want to apply a reversed patch.
No limit (apart from memory) on the size of hunks.
SHAR_EOF
if test 2963 -ne "`wc -c < 'README'`"
then
echo shar: error transmitting "'README'" '(should have been 2963 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'common.h'" '(3604 characters)'
if test -f 'common.h'
then
echo shar: will not over-write existing file "'common.h'"
else
cat << \SHAR_EOF > 'common.h'
/* $Header: common.h,v 2.0 86/09/17 15:36:39 lwall Exp $
*
* $Log: common.h,v $
* Revision 2.0 86/09/17 15:36:39 lwall
* Baseline for netwide release.
*
*/
#define DEBUGGING
#include "config.h"
/* shut lint up about the following when return value ignored */
#define Signal (void)signal
#define Unlink (void)unlink
#define Lseek (void)lseek
#define Fseek (void)fseek
#define Fstat (void)fstat
#define Pclose (void)pclose
#define Close (void)close
#define Fclose (void)fclose
#define Fflush (void)fflush
#define Sprintf (void)sprintf
#define Mktemp (void)mktemp
#define Strcpy (void)strcpy
#define Strcat (void)strcat
#include <stdio.h>
#include <assert.h>
#include <sys/types.h>
#include <stat.h>
#include <ctype.h>
#include <signal.h>
/* constants */
#define TRUE (1)
#define FALSE (0)
#define MAXHUNKSIZE 100000 /* is this enough lines? */
#define INITHUNKMAX 125 /* initial dynamic allocation size */
#define MAXLINELEN 1024
#define BUFFERSIZE 1024
#define ORIGEXT ".orig"
#define SCCSPREFIX "s."
#define GET "get -e %s"
#define RCSSUFFIX ",v"
#define CHECKOUT "co -l %s"
/* handy definitions */
#define Null(t) ((t)0)
#define Nullch Null(char *)
#define Nullfp Null(FILE *)
#define Nulline Null(LINENUM)
#define Ctl(ch) ((ch) & 037)
#define strNE(s1,s2) (strcmp(s1, s2))
#define strEQ(s1,s2) (!strcmp(s1, s2))
#define strnNE(s1,s2,l) (strncmp(s1, s2, l))
#define strnEQ(s1,s2,l) (!strncmp(s1, s2, l))
/* typedefs */
typedef char bool;
typedef int LINENUM; /* must be signed */
typedef unsigned MEM; /* what to feed malloc */
/* globals */
EXT int Argc; /* guess */
EXT char **Argv;
EXT int Argc_last; /* for restarting plan_b */
EXT char **Argv_last;
EXT struct stat filestat; /* file statistics area */
EXT int filemode INIT(0644);
EXT char buf[MAXLINELEN]; /* general purpose buffer */
EXT FILE *ofp INIT(Nullfp); /* output file pointer */
EXT FILE *rejfp INIT(Nullfp); /* reject file pointer */
EXT bool using_plan_a INIT(TRUE); /* try to keep everything in memory */
EXT bool out_of_mem INIT(FALSE); /* ran out of memory in plan a */
#define MAXFILEC 2
EXT int filec INIT(0); /* how many file arguments? */
EXT char *filearg[MAXFILEC];
EXT bool ok_to_create_file INIT(FALSE);
EXT char *bestguess INIT(Nullch); /* guess at correct filename */
EXT char *outname INIT(Nullch);
EXT char rejname[128];
EXT char *origext INIT(Nullch);
EXT char TMPOUTNAME[] INIT("/tmp/patchoXXXXXX");
EXT char TMPINNAME[] INIT("/tmp/patchiXXXXXX"); /* might want /usr/tmp here */
EXT char TMPREJNAME[] INIT("/tmp/patchrXXXXXX");
EXT char TMPPATNAME[] INIT("/tmp/patchpXXXXXX");
EXT bool toutkeep INIT(FALSE);
EXT bool trejkeep INIT(FALSE);
EXT LINENUM last_offset INIT(0);
#ifdef DEBUGGING
EXT int debug INIT(0);
#endif
EXT LINENUM maxfuzz INIT(2);
EXT bool force INIT(FALSE);
EXT bool verbose INIT(TRUE);
EXT bool reverse INIT(FALSE);
EXT bool noreverse INIT(FALSE);
EXT bool skip_rest_of_patch INIT(FALSE);
EXT int strippath INIT(957);
EXT bool canonicalize INIT(FALSE);
#define CONTEXT_DIFF 1
#define NORMAL_DIFF 2
#define ED_DIFF 3
#define NEW_CONTEXT_DIFF 4
EXT int diff_type INIT(0);
EXT bool do_defines INIT(FALSE); /* patch using ifdef, ifndef, etc. */
EXT char if_defined[128]; /* #ifdef xyzzy */
EXT char not_defined[128]; /* #ifndef xyzzy */
EXT char else_defined[] INIT("#else\n");/* #else */
EXT char end_defined[128]; /* #endif xyzzy */
EXT char *revision INIT(Nullch); /* prerequisite revision, if any */
char *malloc();
char *realloc();
char *strcpy();
char *strcat();
char *sprintf(); /* usually */
long atol();
long lseek();
char *mktemp();
SHAR_EOF
if test 3604 -ne "`wc -c < 'common.h'`"
then
echo shar: error transmitting "'common.h'" '(should have been 3604 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'config.h'" '(857 characters)'
if test -f 'config.h'
then
echo shar: will not over-write existing file "'config.h'"
else
cat << \SHAR_EOF > 'config.h'
/* config.h
* This file was produced by running the Configure script.
* Feel free to modify any of this as the need arises.
*/
/*undef EUNICE /* no file linking? */
/*undef VMS /* other assorted ickies? */
/*undef index strchr /* cultural */
/*undef rindex strrchr /* differences? */
/*undef void int /* is void to be avoided? */
/* How many register declarations are paid attention to? */
#define Reg1 register /**/
#define Reg2 register /**/
#define Reg3 register /**/
#define Reg4 register /**/
#define Reg5 register /**/
#define Reg6 register /**/
#define Reg7 register /**/
#define Reg8 register /**/
#define Reg9 register /**/
#define Reg10 register /**/
#define Reg11 register /**/
#define Reg12 register /**/
#define Reg13 register /**/
#define Reg14 register /**/
#define Reg15 register /**/
#define Reg16 register /**/
SHAR_EOF
if test 857 -ne "`wc -c < 'config.h'`"
then
echo shar: error transmitting "'config.h'" '(should have been 857 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'inp.c'" '(7942 characters)'
if test -f 'inp.c'
then
echo shar: will not over-write existing file "'inp.c'"
else
cat << \SHAR_EOF > 'inp.c'
/* $Header: inp.c,v 2.0 86/09/17 15:37:02 lwall Exp $
*
* $Log: inp.c,v $
* Revision 2.0 86/09/17 15:37:02 lwall
* Baseline for netwide release.
*
*/
#include "EXTERN.h"
#include "common.h"
#include "util.h"
#include "pch.h"
#include "INTERN.h"
#include "inp.h"
/* Input-file-with-indexable-lines abstract type */
static long i_size; /* size of the input file */
static char *i_womp; /* plan a buffer for entire file */
static char **i_ptr; /* pointers to lines in i_womp */
static int tifd = -1; /* plan b virtual string array */
static char *tibuf[2]; /* plan b buffers */
static LINENUM tiline[2] = {-1, -1}; /* 1st line in each buffer */
static LINENUM lines_per_buf; /* how many lines per buffer */
static int tireclen; /* length of records in tmp file */
/* New patch--prepare to edit another file. */
void
re_input()
{
if (using_plan_a) {
i_size = 0;
#ifndef lint
if (i_ptr != Null(char**))
free((char *)i_ptr);
#endif
if (i_womp != Nullch)
free(i_womp);
i_womp = Nullch;
i_ptr = Null(char **);
}
else {
using_plan_a = TRUE; /* maybe the next one is smaller */
Close(tifd);
tifd = -1;
free(tibuf[0]);
free(tibuf[1]);
tibuf[0] = tibuf[1] = Nullch;
tiline[0] = tiline[1] = -1;
tireclen = 0;
}
}
/* Constuct the line index, somehow or other. */
void
scan_input(filename)
char *filename;
{
if (!plan_a(filename))
plan_b(filename);
if (verbose) {
say3("Patching file %s using Plan %s...\n", filename,
(using_plan_a ? "A" : "B") );
}
}
/* Try keeping everything in memory. */
bool
plan_a(filename)
char *filename;
{
int ifd;
Reg1 char *s;
Reg2 LINENUM iline;
if (ok_to_create_file && stat(filename, &filestat) < 0) {
if (verbose)
say2("(Creating file %s...)\n",filename);
makedirs(filename, TRUE);
close(creat(filename, 0666));
}
if (stat(filename, &filestat) < 0) {
Sprintf(buf, "RCS/%s%s", filename, RCSSUFFIX);
if (stat(buf, &filestat) >= 0 || stat(buf+4, &filestat) >= 0) {
Sprintf(buf, CHECKOUT, filename);
if (verbose)
say2("Can't find %s--attempting to check it out from RCS.\n",
filename);
if (system(buf) || stat(filename, &filestat))
fatal2("Can't check out %s.\n", filename);
}
else {
Sprintf(buf, "SCCS/%s%s", SCCSPREFIX, filename);
if (stat(buf, &filestat) >= 0 || stat(buf+5, &filestat) >= 0) {
Sprintf(buf, GET, filename);
if (verbose)
say2("Can't find %s--attempting to get it from SCCS.\n",
filename);
if (system(buf) || stat(filename, &filestat))
fatal2("Can't get %s.\n", filename);
}
else
fatal2("Can't find %s.\n", filename);
}
}
filemode = filestat.st_mode;
if ((filemode & S_IFMT) & ~S_IFREG)
fatal2("%s is not a normal file--can't patch.\n", filename);
i_size = filestat.st_size;
if (out_of_mem) {
set_hunkmax(); /* make sure dynamic arrays are allocated */
out_of_mem = FALSE;
return FALSE; /* force plan b because plan a bombed */
}
#ifdef lint
i_womp = Nullch;
#else
i_womp = malloc((MEM)(i_size+2)); /* lint says this may alloc less than */
/* i_size, but that's okay, I think. */
#endif
if (i_womp == Nullch)
return FALSE;
if ((ifd = open(filename, 0)) < 0)
fatal2("Can't open file %s\n", filename);
#ifndef lint
if (read(ifd, i_womp, (int)i_size) != i_size) {
Close(ifd); /* probably means i_size > 15 or 16 bits worth */
free(i_womp); /* at this point it doesn't matter if i_womp was */
return FALSE; /* undersized. */
}
#endif
Close(ifd);
if (i_size && i_womp[i_size-1] != '\n')
i_womp[i_size++] = '\n';
i_womp[i_size] = '\0';
/* count the lines in the buffer so we know how many pointers we need */
iline = 0;
for (s=i_womp; *s; s++) {
if (*s == '\n')
iline++;
}
#ifdef lint
i_ptr = Null(char**);
#else
i_ptr = (char **)malloc((MEM)((iline + 2) * sizeof(char *)));
#endif
if (i_ptr == Null(char **)) { /* shucks, it was a near thing */
free((char *)i_womp);
return FALSE;
}
/* now scan the buffer and build pointer array */
iline = 1;
i_ptr[iline] = i_womp;
for (s=i_womp; *s; s++) {
if (*s == '\n')
i_ptr[++iline] = s+1; /* these are NOT null terminated */
}
input_lines = iline - 1;
/* now check for revision, if any */
if (revision != Nullch) {
if (!rev_in_string(i_womp)) {
if (force) {
if (verbose)
say2("\
Warning: this file doesn't appear to be the %s version--patching anyway.\n",
revision);
}
else {
ask2("\
This file doesn't appear to be the %s version--patch anyway? [n] ",
revision);
if (*buf != 'y')
fatal1("Aborted.\n");
}
}
else if (verbose)
say2("Good. This file appears to be the %s version.\n",
revision);
}
return TRUE; /* plan a will work */
}
/* Keep (virtually) nothing in memory. */
void
plan_b(filename)
char *filename;
{
Reg3 FILE *ifp;
Reg1 int i = 0;
Reg2 int maxlen = 1;
Reg4 bool found_revision = (revision == Nullch);
using_plan_a = FALSE;
if ((ifp = fopen(filename, "r")) == Nullfp)
fatal2("Can't open file %s\n", filename);
if ((tifd = creat(TMPINNAME, 0666)) < 0)
fatal2("Can't open file %s\n", TMPINNAME);
while (fgets(buf, sizeof buf, ifp) != Nullch) {
if (revision != Nullch && !found_revision && rev_in_string(buf))
found_revision = TRUE;
if ((i = strlen(buf)) > maxlen)
maxlen = i; /* find longest line */
}
if (revision != Nullch) {
if (!found_revision) {
if (force) {
if (verbose)
say2("\
Warning: this file doesn't appear to be the %s version--patching anyway.\n",
revision);
}
else {
ask2("\
This file doesn't appear to be the %s version--patch anyway? [n] ",
revision);
if (*buf != 'y')
fatal1("Aborted.\n");
}
}
else if (verbose)
say2("Good. This file appears to be the %s version.\n",
revision);
}
Fseek(ifp, 0L, 0); /* rewind file */
lines_per_buf = BUFFERSIZE / maxlen;
tireclen = maxlen;
tibuf[0] = malloc((MEM)(BUFFERSIZE + 1));
tibuf[1] = malloc((MEM)(BUFFERSIZE + 1));
if (tibuf[1] == Nullch)
fatal1("Can't seem to get enough memory.\n");
for (i=1; ; i++) {
if (! (i % lines_per_buf)) /* new block */
if (write(tifd, tibuf[0], BUFFERSIZE) < BUFFERSIZE)
fatal1("patch: can't write temp file.\n");
if (fgets(tibuf[0] + maxlen * (i%lines_per_buf), maxlen + 1, ifp)
== Nullch) {
input_lines = i - 1;
if (i % lines_per_buf)
if (write(tifd, tibuf[0], BUFFERSIZE) < BUFFERSIZE)
fatal1("patch: can't write temp file.\n");
break;
}
}
Fclose(ifp);
Close(tifd);
if ((tifd = open(TMPINNAME, 0)) < 0) {
fatal2("Can't reopen file %s\n", TMPINNAME);
}
}
/* Fetch a line from the input file, \n terminated, not necessarily \0. */
char *
ifetch(line,whichbuf)
Reg1 LINENUM line;
int whichbuf; /* ignored when file in memory */
{
if (line < 1 || line > input_lines)
return "";
if (using_plan_a)
return i_ptr[line];
else {
LINENUM offline = line % lines_per_buf;
LINENUM baseline = line - offline;
if (tiline[0] == baseline)
whichbuf = 0;
else if (tiline[1] == baseline)
whichbuf = 1;
else {
tiline[whichbuf] = baseline;
#ifndef lint /* complains of long accuracy */
Lseek(tifd, (long)baseline / lines_per_buf * BUFFERSIZE, 0);
#endif
if (read(tifd, tibuf[whichbuf], BUFFERSIZE) < 0)
fatal2("Error reading tmp file %s.\n", TMPINNAME);
}
return tibuf[whichbuf] + (tireclen*offline);
}
}
/* True if the string argument contains the revision number we want. */
bool
rev_in_string(string)
char *string;
{
Reg1 char *s;
Reg2 int patlen;
if (revision == Nullch)
return TRUE;
patlen = strlen(revision);
for (s = string; *s; s++) {
if (isspace(*s) && strnEQ(s+1, revision, patlen) &&
isspace(s[patlen+1] )) {
return TRUE;
}
}
return FALSE;
}
SHAR_EOF
if test 7942 -ne "`wc -c < 'inp.c'`"
then
echo shar: error transmitting "'inp.c'" '(should have been 7942 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'inp.h'" '(473 characters)'
if test -f 'inp.h'
then
echo shar: will not over-write existing file "'inp.h'"
else
cat << \SHAR_EOF > 'inp.h'
/* $Header: inp.h,v 2.0 86/09/17 15:37:25 lwall Exp $
*
* $Log: inp.h,v $
* Revision 2.0 86/09/17 15:37:25 lwall
* Baseline for netwide release.
*
*/
EXT LINENUM input_lines INIT(0); /* how long is input file in lines */
EXT LINENUM last_frozen_line INIT(0); /* how many input lines have been */
/* irretractibly output */
bool rev_in_string();
void scan_input();
bool plan_a(); /* returns false if insufficient memory */
void plan_b();
char *ifetch();
SHAR_EOF
if test 473 -ne "`wc -c < 'inp.h'`"
then
echo shar: error transmitting "'inp.h'" '(should have been 473 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'patch.doc'" '(15181 characters)'
if test -f 'patch.doc'
then
echo shar: will not over-write existing file "'patch.doc'"
else
cat << \SHAR_EOF > 'patch.doc'
PATCH(1) USER COMMANDS PATCH(1)
NAME
patch - a program for applying a diff file to an original
SYNOPSIS
patch [options] orig patchfile [+ [options] orig]
but usually just
patch <patchfile
DESCRIPTION
_P_a_t_c_h will take a patch file containing any of the three
forms of difference listing produced by the _d_i_f_f program and
apply those differences to an original file, producing a
patched version. By default, the patched version is put in
place of the original, with the original file backed up to
the same name with the extension ".orig", or as specified by
the -b switch. You may also specify where you want the out-
put to go with a -o switch. If _p_a_t_c_h_f_i_l_e is omitted, or is
a hyphen, the patch will be read from standard input.
Upon startup, patch will attempt to determine the type of
the diff listing, unless over-ruled by a -c, -e, or -n
switch. Context diffs and normal diffs are applied by the
_p_a_t_c_h program itself, while ed diffs are simply fed to the
_e_d editor via a pipe.
_P_a_t_c_h will try to skip any leading garbage, apply the diff,
and then skip any trailing garbage. Thus you could feed an
article or message containing a diff listing to _p_a_t_c_h, and
it should work. If the entire diff is indented by a con-
sistent amount, this will be taken into account.
With context diffs, and to a lesser extent with normal
diffs, _p_a_t_c_h can detect when the line numbers mentioned in
the patch are incorrect, and will attempt to find the
correct place to apply each hunk of the patch. As a first
guess, it takes the line number mentioned for the hunk, plus
or minus any offset used in applying the previous hunk. If
that is not the correct place, _p_a_t_c_h will scan both forwards
and backwards for a set of lines matching the context given
in the hunk. First _p_a_t_c_h looks for a place where all lines
of the context match. If no such place is found, and it's a
context diff, and the maximum fuzz factor is set to 1 or
more, then another scan takes place ignoring the first and
last line of context. If that fails, and the maximum fuzz
factor is set to 2 or more, the first two and last two lines
of context are ignored, and another scan is made. (The
default maximum fuzz factor is 2.) If _p_a_t_c_h cannot find a
place to install that hunk of the patch, it will put the
hunk out to a reject file, which normally is the name of the
output file plus ".rej". (Note that the rejected hunk will
Last change: LOCAL 1
PATCH(1) USER COMMANDS PATCH(1)
come out in context diff form whether the input patch was a
context diff or a normal diff. If the input was a normal
diff, many of the contexts will simply be null.) The line
numbers on the hunks in the reject file may be different
than in the patch file: they reflect the approximate loca-
tion patch thinks the failed hunks belong in the new file
rather than the old one.
As each hunk is completed, you will be told whether the hunk
succeeded or failed, and which line (in the new file) _p_a_t_c_h
thought the hunk should go on. If this is different from
the line number specified in the diff you will be told the
offset. A single large offset MAY be an indication that a
hunk was installed in the wrong place. You will also be
told if a fuzz factor was used to make the match, in which
case you should also be slightly suspicious.
If no original file is specified on the command line, _p_a_t_c_h
will try to figure out from the leading garbage what the
name of the file to edit is. In the header of a context
diff, the filename is found from lines beginning with "***"
or "---", with the shortest name of an existing file win-
ning. Only context diffs have lines like that, but if there
is an "Index:" line in the leading garbage, _p_a_t_c_h will try
to use the filename from that line. The context diff header
takes precedence over an Index line. If no filename can be
intuited from the leading garbage, you will be asked for the
name of the file to patch.
(If the original file cannot be found, but a suitable SCCS
or RCS file is handy, _p_a_t_c_h will attempt to get or check out
the file.)
Additionally, if the leading garbage contains a "Prereq: "
line, _p_a_t_c_h will take the first word from the prerequisites
line (normally a version number) and check the input file to
see if that word can be found. If not, _p_a_t_c_h will ask for
confirmation before proceeding.
The upshot of all this is that you should be able to say,
while in a news interface, the following:
| patch -d /usr/src/local/blurfl
and patch a file in the blurfl directory directly from the
article containing the patch.
If the patch file contains more than one patch, _p_a_t_c_h will
try to apply each of them as if they came from separate
patch files. This means, among other things, that it is
assumed that the name of the file to patch must be deter-
mined for each diff listing, and that the garbage before
Last change: LOCAL 2
PATCH(1) USER COMMANDS PATCH(1)
each diff listing will be examined for interesting things
such as filenames and revision level, as mentioned previ-
ously. You can give switches (and another original file
name) for the second and subsequent patches by separating
the corresponding argument lists by a '+'. (The argument
list for a second or subsequent patch may not specify a new
patch file, however.)
_P_a_t_c_h recognizes the following switches:
-b causes the next argument to be interpreted as the
backup extension, to be used in place of ".orig".
-c forces _p_a_t_c_h to interpret the patch file as a context
diff.
-d causes _p_a_t_c_h to interpret the next argument as a direc-
tory, and cd to it before doing anything else.
-D causes _p_a_t_c_h to use the "#ifdef...#endif" construct to
mark changes. The argument following will be used as
the differentiating symbol. Note that, unlike the C
compiler, there must be a space between the -D and the
argument.
-e forces _p_a_t_c_h to interpret the patch file as an ed
script.
-f forces _p_a_t_c_h to assume that the user knows exactly what
he or she is doing, and to not ask any questions. It
does not suppress commentary, however. Use -s for
that.
-F<number>
sets the maximum fuzz factor. This switch only applied
to context diffs, and causes _p_a_t_c_h to ignore up to that
many lines in looking for places to install a hunk.
Note that a larger fuzz factor increases the odds of a
faulty patch. The default fuzz factor is 2, and it may
not be set to more than the number of lines of context
in the context diff, ordinarily 3.
-l causes the pattern matching to be done loosely, in case
the tabs and spaces have been munged in your input
file. Any sequence of whitespace in the pattern line
will match any sequence in the input file. Normal
characters must still match exactly. Each line of the
context must still match a line in the input file.
-n forces _p_a_t_c_h to interpret the patch file as a normal
diff.
Last change: LOCAL 3
PATCH(1) USER COMMANDS PATCH(1)
-N causes _p_a_t_c_h to ignore patches that it thinks are
reversed or already applied. See also -R .
-o causes the next argument to be interpreted as the out-
put file name.
-p<number>
sets the pathname strip count, which controls how path-
names found in the patch file are treated, in case the
you keep your files in a different directory than the
person who sent out the patch. The strip count speci-
fies how many backslashes are to be stripped from the
front of the pathname. (Any intervening directory
names also go away.) For example, supposing the
filename in the patch file was
/u/howard/src/blurfl/blurfl.c
setting -p or -p0 gives the entire pathname unmodified,
-p1 gives
u/howard/src/blurfl/blurfl.c
without the leading slash, -p4 gives
blurfl/blurfl.c
and not specifying -p at all just gives you "blurfl.c".
Whatever you end up with is looked for either in the
current directory, or the directory specified by the -d
switch.
-r causes the next argument to be interpreted as the
reject file name.
-R tells _p_a_t_c_h that this patch was created with the old
and new files swapped. (Yes, I'm afraid that does hap-
pen occasionally, human nature being what it is.) _P_a_t_c_h
will attempt to swap each hunk around before applying
it. Rejects will come out in the swapped format. The
-R switch will not work with ed diff scripts because
there is too little information to reconstruct the
reverse operation.
If the first hunk of a patch fails, _p_a_t_c_h will reverse
the hunk to see if it can be applied that way. If it
can, you will be asked if you want to have the -R
switch set. If it can't, the patch will continue to be
applied normally. (Note: this method cannot detect a
reversed patch if it is a normal diff and if the first
command is an append (i.e. it should have been a
delete) since appends always succeed, due to the fact
Last change: LOCAL 4
PATCH(1) USER COMMANDS PATCH(1)
that a null context will match anywhere. Luckily, most
patches add or change lines rather than delete them, so
most reversed normal diffs will begin with a delete,
which will fail, triggering the heuristic.)
-s makes _p_a_t_c_h do its work silently, unless an error
occurs.
-S causes _p_a_t_c_h to ignore this patch from the patch file,
but continue on looking for the next patch in the file.
Thus
patch -S + -S + <patchfile
will ignore the first and second of three patches.
-v causes _p_a_t_c_h to print out it's revision header and
patch level.
-x<number>
sets internal debugging flags, and is of interest only
to _p_a_t_c_h patchers.
ENVIRONMENT
No environment variables are used by _p_a_t_c_h.
FILES
/tmp/patch*
SEE ALSO
diff(1)
NOTES FOR PATCH SENDERS
There are several things you should bear in mind if you are
going to be sending out patches. First, you can save people
a lot of grief by keeping a patchlevel.h file which is
patched to increment the patch level as the first diff in
the patch file you send out. If you put a Prereq: line in
with the patch, it won't let them apply patches out of order
without some warning. Second, make sure you've specified
the filenames right, either in a context diff header, or
with an Index: line. If you are patching something in a
subdirectory, be sure to tell the patch user to specify a -p
switch as needed. Third, you can create a file by sending
out a diff that compares a null file to the file you want to
create. This will only work if the file you want to create
doesn't exist already in the target directory. Fourth, take
care not to send out reversed patches, since it makes people
wonder whether they already applied the patch. Fifth, while
you may be able to get away with putting 582 diff listings
into one file, it is probably wiser to group related patches
into separate files in case something goes haywire.
Last change: LOCAL 5
PATCH(1) USER COMMANDS PATCH(1)
DIAGNOSTICS
Too many to list here, but generally indicative that _p_a_t_c_h
couldn't parse your patch file.
The message "Hmm..." indicates that there is unprocessed
text in the patch file and that _p_a_t_c_h is attempting to
intuit whether there is a patch in that text and, if so,
what kind of patch it is.
CAVEATS
_P_a_t_c_h cannot tell if the line numbers are off in an ed
script, and can only detect bad line numbers in a normal
diff when it finds a "change" or a "delete" command. A con-
text diff using fuzz factor 3 may have the same problem.
Until a suitable interactive interface is added, you should
probably do a context diff in these cases to see if the
changes made sense. Of course, compiling without errors is
a pretty good indication that the patch worked, but not
always.
_P_a_t_c_h usually produces the correct results, even when it has
to do a lot of guessing. However, the results are
guaranteed to be correct only when the patch is applied to
exactly the same version of the file that the patch was gen-
erated from.
BUGS
Could be smarter about partial matches, excessively deviant
offsets and swapped code, but that would take an extra pass.
If code has been duplicated (for instance with #ifdef OLD-
CODE ... #else ... #endif), _p_a_t_c_h is incapable of patching
both versions, and, if it works at all, will likely patch
the wrong one, and tell you that it succeeded to boot.
If you apply a patch you've already applied, _p_a_t_c_h will
think it is a reversed patch, and offer to un-apply the
patch. This could be construed as a feature.
Last change: LOCAL 6
SHAR_EOF
echo shar: 205 control characters may be missing from "'patch.doc'"
if test 15181 -ne "`wc -c < 'patch.doc'`"
then
echo shar: error transmitting "'patch.doc'" '(should have been 15181 characters)'
fi
fi # end of overwriting check
# End of shell archive
exit 0ncoverby@ndsuvax.UUCP (Glen Overby) (05/30/88)
In article <2766@louie.udel.EDU> frank@morgan.com (Frank Wortner) writes: >Here is a version of Larry Wall's patch program. I've made a few >minor changes to get it to run under Minix. The program has served me >well over the past month or two and I'm reasonably confident that it >works. I, too, have been using patch on Minix since last summer (I can't remember whose port of it I'm running), with no problems. I would like to note that the patch I use on our BSD Unxi VAX is at patchlevel 9, whereas Frank's is at patchlevel 4. I don't know what bugs/features have been added/removed in the missing 5 patch patches, but it would be good to have those in a version that might be distributed. -- Glen Overby Bitnet: ncoverby@ndsuvax UUCP: {uunet, ihnp4!umn-cs}!ndsuvax!ncoverby