Path: utzoo!attcan!uunet!lll-winken!lll-tis!ames!ll-xn!mit-eddie!bbn!rochester!udel!mmdf From: frank@morgan.com (Frank Wortner) Newsgroups: comp.os.minix Subject: Patch for Minix, Part 1 of 3 Message-ID: <2766@louie.udel.EDU> Date: 27 May 88 17:23:29 GMT Sender: mmdf@udel.EDU Lines: 2366 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 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 <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 < 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 <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 <.foo . .foo awk "END { for (i=1; i<=$registers; i++) printf \"reg%d=register\n\", i}" \ .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 <&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 <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 <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 /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 <>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 #include #include #include #include #include /* 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 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 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 + 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 0