[comp.sources.unix] v24i019: GNU Diff, version 1.15, Part04/08

rsalz@uunet.uu.net (Rich Salz) (02/26/91)

Submitted-by: Paul Eggert <eggert@twinsun.com>
Posting-number: Volume 24, Issue 19
Archive-name: gnudiff1.15/part04

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 4 (of 8)."
# Contents:  ChangeLog io.c
# Wrapped by eggert@ata on Mon Jan  7 11:25:30 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'ChangeLog' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'ChangeLog'\"
else
echo shar: Extracting \"'ChangeLog'\" \(19300 characters\)
sed "s/^X//" >'ChangeLog' <<'END_OF_FILE'
XSun Jan  6 18:42:23 1991  Michael I Bushnell  (mib at geech.ai.mit.edu)
X
X	* Version 1.15 released.
X
X	* version.c: Updated from 1.15 alpha to 1.15
X
X	* context.c (print_context_number_range,
X	print_unidiff_number_range): Don't print N,M when N=M, print
X	just N instead.
X	
X	* README: Updated for version 1.15.
X	Makefile: Updated for version 1.15.
X
X	* diff3.c (main): Don't get confused if one of the arguments
X	is a directory.
X
X	* diff.c (compare_files): Don't get confused if comparing
X	standard input to a directory; print error instead.
X
X	* analyze.c (diff_2_files), context.c (print_context_header,
X	print_context_script), diff.c (main), diff.h (enum
X	output_style): Tread unidiff as an output style in its own
X	right.  This also generates an error when both -u and -c are
X	given.
X
X	* diff.c (main): Better error messages when regexps are bad.
X
X	* diff.c (compare_files): Don't assume stdin is opened.
X
X	* diff3.c (read_diff): Don't assume things about the order of
X	descriptor assignment and closes.
X
X	* util.c (setup_output): Don't assume things about the order
X	of descriptor assignment and closes. 
X
X	* diff.c (compare_files): Set a flag so that closes don't
X	happen more than once.
X
X	* diff.c (main): Don't just flush stdout, do a close.  That
X	way on broken systems we can still get errors. 
X
XMon Dec 24 16:24:17 1990  Richard Stallman  (rms at mole.ai.mit.edu)
X
X	* diff.c (usage): Use = for args of long options.
X
XMon Dec 17 18:19:20 1990  Michael I Bushnell  (mib at geech.ai.mit.edu)
X
X	* context.c (print_context_label): Labels were interchanged badly.
X
X	* context.c (pr_unidiff_hunk): Changes to deal with files
X	ending in incomplete lines.
X	* util.c (print_1_line): Other half of the changes.
X
XMon Dec  3 14:23:55 1990  Richard Stallman  (rms at mole.ai.mit.edu)
X
X	* diff.c (longopts, usage): unidiff => unified.
X
XWed Nov  7 17:13:08 1990  Richard Stallman  (rms at mole.ai.mit.edu)
X
X	* analyze.c (diff_2_files): No warnings about newlines for -D.
X
X	* diff.c (pr_unidiff_hunk): Remove ref to output_patch_flag.
X
XTue Oct 23 23:19:18 1990  Richard Stallman  (rms at mole.ai.mit.edu)
X
X	* diff.c (compare_files): For -D, compare even args are same file.
X	* analyze.c (diff_2_files): Likewise.
X	Also, output even if files have no differences.
X
X	* analyze.c (diff_2_files): Print missing newline messages last.
X	Return 2 if a newline is missing.
X	Print them even if files end with identical text.
X
XMon Oct 22 19:40:09 1990  Richard Stallman  (rms at mole.ai.mit.edu)
X
X	* diff.c (usage): Return 2.
X
XWed Oct 10 20:54:04 1990  Richard Stallman  (rms at mole.ai.mit.edu)
X
X	* diff.c (longopts): Add +new-files.
X
XSun Sep 23 22:49:29 1990  Richard Stallman  (rms at mole.ai.mit.edu)
X
X	* context.c (print_context_script): Handle unidiff_flag.
X	(print_context_header): Likewise.
X	(print_unidiff_number_range, pr_unidiff_hunk): New functions.
X	* diff.c (longopts): Add element for +unidiff.
X	(main): Handle +unidiff and -u.
X	(usage): Mention them.
X
XWed Sep  5 16:33:22 1990  Richard Stallman  (rms at mole.ai.mit.edu)
X
X	* io.c (find_and_hash_each_line): Deal with missing final newline
X	after buffering necessary context lines.
X
XSat Sep  1 16:32:32 1990  Richard Stallman  (rms at mole.ai.mit.edu)
X
X	* io.c (find_identical_ends): ROBUST_OUTPUT_FORMAT test was backward.
X
XThu Aug 23 17:17:20 1990  Richard Stallman  (rms at mole.ai.mit.edu)
X
X	* diff3.c (WIFEXITED): Undef it if WEXITSTATUS is not defined.
X	* context.c (find_function): Don't try to return values.
X
XWed Aug 22 11:54:39 1990  Richard Stallman  (rms at mole.ai.mit.edu)
X
X	* diff.h (O_RDONLY): Define if not defined.
X
XTue Aug 21 13:49:26 1990  Richard Stallman  (rms at mole.ai.mit.edu)
X
X	* Handle -L option.
X	* context.c (print_context_label): New function.
X	(print_context_header): Use that.
X	* diff.c (main): Recognize the option.
X	(usage): Updated.
X	* diff.h (file_label): New variable.
X	* diff3.c (main): Recognize -L instead of -t.
X
X	* diff3.c (main): Support -m without other option.
X
X	* diff3.c (WEXITSTATUS, WIFEXITED): Define whenever not defined.
X
X	* diff3.c (bcopy, index, rindex): Delete definitions; not used.
X	(D_LINENUM, D_LINELEN): Likewise.
X	(struct diff_block): lengths includes newlines.
X	(struct diff3_block): Likewise.
X	(always_text, merge): New variables.
X	(read_diff): Return address of end, not size read.  Calls changed.
X	Pass -a to diff if given to diff3.
X	current_chunk_size now an int.  Detect error in `pipe'.
X	Check for incomplete line of output here.
X	(scan_diff_line): Don't make scan_ptr + 2 before knowing it is valid.
X	No need to check validity of diff output here.
X	Include newline in length of line.
X	(main): Compute rev_mapping here.  Handle -a and -m.
X	Error message if excess -t operands.  Error for incompatible options.
X	Error if `-' given more than once.
X	Fix error storing in tag_strings.
X	(output_diff3): REV_MAPPING is now an arg.  Call changed.
X	Change syntax of "missing newline" message.
X	Expect length of line to include newline.
X	(output_diff3_edscript): Return just 0 or 1.
X	REV_MAPPING is now an arg.  Call changed.
X	(output_diff3_merge): New function.
X	(process_diff): Better error message for bad diff format.
X	(fatal, perror_with_exit): Return status 2.
X
X	* analyze.c (diff_2_files): Report missing newline in either
X	or both files, if not robust output style.
X
X	* util.c (setup_output): Detect error from pipe.
X	No need to close stdin.
X
X	* util.c (print_1_line): Change format of missing-newline msg.
X	Change if statements to switch.
X
X	* io.c (slurp): Don't mention differences in final newline if -B.
X
X	* io.c (binary_file_p): Use ISO char set as criterion, not ASCII.
X
X	* io.c (find_identical_ends): Increase value of BEG0 by 1.
X	Other changes in backwards scan to avoid decrementing pointers
X	before start of array, and set LINES properly.
X
X	* diff.h (ROBUST_OUTPUT_STYLE): New macro.
X	* io.c (find_identical_ends, find_and_hash_each_line): Use that macro.
X
X	* diff.h (dup2): Don't define if XENIX.
X
X	* diff.c (main): Check for write error at end.
X
X	* context.c (find_function): Don't return a value.
X	Use argument FILE rather than global files.
X
X	* analyze.c: Add external function declarations.
X	* analyze.c (build_script): Turn off explicit check for final newline.
X
X	* analyze.c (discard_confusing_lines): Make integers unsigned.
X
XTue Jul 31 21:37:16 1990  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* io.c (find_and_hash_each_line): Correct the criterion 
X	for leaving out the newline from the end of the line.
X
XTue May 29 21:28:16 1990  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* dir.c (diff_dirs): Free things only if nonzero.
X
XMon Apr 16 18:31:05 1990  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* diff.h (NDIR_IN_SYS): New macro controls location of ndir.h.
X
X	* diff3.c (xmalloc, xrealloc): Don't die if size == 0 returns 0.
X
XSun Mar 25 15:58:42 1990  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* analyze.c (discard_confusing_lines):
X	`many' wasn't being used; use it.
X	Cancelling provisionals near start of run must handle already
X	cancelled provisionals.
X	Cancelling subruns of provisionals was cancelling last nonprovisional.
X
XSat Mar 24 14:02:51 1990  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* analyze.c (discard_confusing_lines):
X	Threshold for line occurring many times scales by square root
X	of total lines.
X	Within each run, cancel any long subrun of provisionals.
X	Don't update `provisional' while cancelling provisionals.
X	In big outer loop, handle provisional and nonprovisional separately.
X
XThu Mar 22 16:35:33 1990  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* analyze.c (discard_confusing_lines):
X	The first loops to discard provisionals from ends failed to step.
X	In second such loops, keep discarding all consecutive provisionals.
X	Increase threshold for stopping discarding, and also check for
X	consecutive nondiscardables as separate threshold.
X
XFri Mar 16 00:33:08 1990  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* diff3.c (read_diff): Pass -- as first arg to diff.
X
X	* diff3.c: Include wait.h or define equivalent macros.
X	(read_diff): Don't use stdio printing error in the inferior.
X	Remember the pid and wait for it.  Report failing status.
X	Report failure of vfork.
X
XSun Mar 11 17:10:32 1990  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* diff3.c (main): Accept -t options and pass to output_diff3_edscript.
X	(usage): Mention -t.
X	(read_diff): Use vfork.
X	(vfork): Don't use it on Sparc.
X
X	* diff.h (vfork): Don't use it on Sparc.
X
XTue Mar  6 22:37:20 1990  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* diff3.c (dup2): Don't define on Xenix.
X
X	* Makefile: Comments for Xenix.
X
XThu Mar  1 17:19:23 1990  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* analyze.c (diff_2_files): `message' requires three args.
X
XFri Feb 23 10:56:50 1990  David J. MacKenzie  (djm at albert.ai.mit.edu)
X
X	* diff.h, util.c, diff3.c: Change 'void *' to 'VOID *', with
X	VOID defined as void if __STDC__, char if not.
X
XSun Feb 18 20:31:58 1990  David J. MacKenzie  (djm at albert.ai.mit.edu)
X
X	* Makefile: Add rules for getopt.c, getopt1.c, getopt.h.
X
X	* getopt.c, getopt.h, getopt1.c: New files.
X
X	* main.c (main, usage): Add long options.
X
X	* analyze.c (shift_boundaries): Remove unused var 'j_end'.
X
XThu Feb  8 02:43:16 1990  Jim Kingdon  (kingdon at pogo.ai.mit.edu)
X
X	* GNUmakefile: include ../Makerules before Makefile.
X
XFri Feb  2 23:21:38 1990  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* analyze.c (diif_2_files): If -B or -I, don't return 1
X	if all changes were ignored.
X
XWed Jan 24 20:43:57 1990  Richard Stallman  (rms at albert.ai.mit.edu)
X
X	* diff3.c (fatal): Output to stderr.
X
XThu Jan 11 00:25:56 1990  David J. MacKenzie  (djm at hobbes.ai.mit.edu)
X
X	* diff.c (usage): Mention -v.
X
XWed Jan 10 16:06:38 1990  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* diff3.c (output_diff3_edscript): Return number of overlaps.
X	(main): If have overlaps, exit with status 1.
X
XSun Dec 24 10:29:20 1989  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* io.c (find_equiv_class): Fix typo that came from changing init of B
X	to an assigment.
X
X	* version.c: New file.
X	* diff.c (main): -v prints version number.
X
X	* io.c (binary_file_p): Null char implies binary file.
X
XFri Nov 17 23:44:55 1989  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* util.c (print_1_line): Fix off by 1 error.
X
XThu Nov 16 13:51:10 1989  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* util.c (xcalloc): Function deleted.
X
X	* io.c (slurp): Null-terminate the buffer.
X
X	* io.c (read_files): Delete unused vars.
X
X	* io.c (find_equiv_class): Don't index by N if too low.
X
X	* dir.c (dir_sort): Delete the extra declaration of compare_names.
X
X	* diff.h: Don't declare xcalloc.  Declare some other functions.
X
X	* analyze.c (shift_boundaries):
X	Test for END at end of range before indexing by it.
X	Fix typo `preceeding' in var names.
X
XSat Nov 11 14:04:16 1989  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* diff3.c (using_to_diff3_block): Delete unused vars.
X	(make_3way_diff, process_diff_control, read_diff, output_diff3): Likewise.
X
XMon Nov  6 18:15:50 EST 1989 Jay Fenlason (hack@ai.mit.edu)
X
X	* README Fix typo.
X
XFri Nov  3 15:27:47 1989  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* diff.c (usage): Mention -D. 
X
X	* ifdef.c (print_ifdef_hunk): Write comments on #else and #endif.
X
XSun Oct 29 16:41:07 1989  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* diff.c (compare_files): Don't fflush for identical files.
X
XWed Oct 25 17:57:12 1989  Randy Smith  (randy at apple-gunkies.ai.mit.edu)
X
X	* diff3.c (using_to_diff3_block): When defaulting lines from
X	FILE0, only copy up to just under the *lowest* line mentioned
X	in the next diff.
X
X	* diff3.c (fatal): Add \n to error messages.
X
XWed Oct 25 15:05:49 1989  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* Makefile (tapefiles): Add ChangeLog.
X
XTue Oct  3 00:51:17 1989  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* diff3.c (process_diff, create_diff3_block): Init ->next field.
X
XFri Sep 29 08:16:45 1989  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* util.c (line_cmp): Alter end char of line 2, not line 1.
X
XWed Sep 20 00:12:37 1989  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* Makefile (diff.tar): Expect ln to fail on some files;
X	copy them with cp.
X
XMon Sep 18 02:54:29 1989  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* Handle -D option:
X	* io.c (find_and_hash_each_line): Keep all lines of 1st file.
X	* diff.c (main): Handle -D option.
X	(compare_files): Reject -D if files spec'd are directories.
X	* analyze.c (diff_2_files): Handle OUTPUT_IFDEF case.
X
XFri Sep  1 20:15:50 1989  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* diff.c (option_list): Rename arg VECTOR as OPTIONVEC.
X
XMon Aug 28 17:58:27 1989  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* diff.c (compare_files): Clear entire inf[i].stat.
X
XWed Aug 23 17:48:47 1989  Richard Stallman  (rms at apple-gunkies.ai.mit.edu)
X
X	* io.c (find_identical_ends): Sign was backward
X	determining where to bound the scan for the suffix.
X
XWed Aug 16 12:49:16 1989  Richard Stallman  (rms at hobbes.ai.mit.edu)
X
X	* analyze.c (diff_2_files): If -q, treat all files as binary.
X	* diff.c (main): Detect -q, record in no_details_flag.
X
XSun Jul 30 23:12:00 1989  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* diff.c (usage): New function.
X	(main): Call it.
X
XWed Jul 26 02:02:19 1989  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* diff.c (main): Make -C imply -c.
X
XThu Jul 20 17:57:51 1989  Chris Hanson  (cph at kleph)
X
X	* io.c (find_and_hash_each_line): Bug fix in context handling,
X	introduced by last change.
X
XFri Jul 14 17:39:20 1989  Chris Hanson  (cph at kleph)
X
X	* analyze.c: To make RCS work correctly on files that don't
X	necessarily end in newline, introduce some changes that cause
X	diffs to be sensitive to missing final newline.  Because
X	non-RCS modes don't want to be affected by these changes, they
X	are conditional on `output_style == OUTPUT_RCS'.
X	(diff_2_files) [OUTPUT_RCS]: Suppress the "File X missing
X	newline" message.
X	(build_script) [OUTPUT_RCS]: Cause the last line to compare as
X	different if exactly one of the files is missing its final
X	newline.
X
X	* io.c (find_and_hash_each_line): Bug fix in
X	ignore_space_change mode.  Change line's length to include the
X	newline.  For OUTPUT_RCS, decrement last line's length if
X	there is no final newline.
X	(find_identical_ends) [OUTPUT_RCS]: If one of the files is
X	missing a final newline, make sure it's not included in either
X	the prefix or suffix.
X
X	* util.c (print_1_line): Change line output routine to account
X	for line length including the newline.
X
XTue Jun 27 02:35:28 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)
X
X	* Makefile: Inserted $(archpfx) where appropriate.
X
XWed May 17 20:18:43 1989  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* diff3.c [USG]: Include fcntl.h.
X
X	* diff.h [USG]: New compilation flags HAVE_NDIR, HAVE_DIRECT.
X
XWed Apr 26 15:35:57 1989  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* dir.c (diff_dirs): Two new args, NONEX1 and NONEX2, say to pretend
X	nonex dirs are empty.
X	(dir_sort): New arg NONEX, likewise.
X	* diff.c (compare_files): Pass those args.
X	Sometimes call diff_dirs if subdir exists in just one place.
X
XWed Apr 12 01:10:27 1989  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* io.c (find_identical_ends): Set END0 *after* last char
X	during backward scan for suffix.
X
XSat Apr  8 15:49:49 1989  Randall Smith  (randy at apple-gunkies.ai.mit.edu)
X
X	* diff3.c (using_to_diff3_block): Now find high marks in files 1
X	and 2 through mapping off of the last difference instead of the
X	first.
X
X	* diff3.c: Many trivial changes to spelling inside comments. 
X
XFri Feb 24 12:38:03 1989  Randall Smith  (randy at gluteus.ai.mit.edu)
X
X	* util.c, normal.c, io.c, ed.c, dir.c, diff.h, diff.c, context.c,
X	analyze.c, Makefile: Changed copyright header to conform with new
X	GNU General Public license.
X	* diff3.c: Changed copyright header to conform with new GNU
X	General Public license.
X	* COPYING: Made a hard link to /gp/rms/COPYING.
X
XFri Feb 24 10:01:58 1989  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* io.c (slurp): Leave 2 chars space at end of buffer, not one.
X	(find_identical_ends): Special case if either file is empty;
X	don't try to make a sentinel since could crash.
X
XWed Feb 15 14:24:48 1989  Jay Fenlason  (hack at apple-gunkies.ai.mit.edu)
X
X	* diff3.c (message)  Re-wrote routine to avoid using alloca()
X
XWed Feb 15 06:19:14 1989  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* io.c (find_identical_ends): Delete the variable `bytes'.
X
XSun Feb 12 11:50:36 1989  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* io.c (slurp): ->bufsize is nominal amount we have room for;
X	add room for sentinel when calling xmalloc or xrealloc.
X
X	* io.c (find_identical_ends): Do need overrun check in finding suffix.
X
XFri Feb 10 01:28:15 1989  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* diff.c (main): -C now takes arg to specify context length.
X	Now -p to show C function name--Damned IEEE!
X	Fatal error if context length spec'd twice.
X
X	* ed.c (print_ed_hunk): Now special treatment only for lines containing
X	precisely a dot and nothing else.  Output `..', end the insert,
X	substitute that one line, then resume the insert if nec.
X
X	* io.c (find_and_hash_lines): When backing up over starting context,
X	don't move past buffer-beg.
X
X	* io.c (find_identical_ends): Use sentinels to make the loops faster.
X	If files are identical, skip the 2nd loop and return quickly.
X	(slurp): Leave 1 char extra space after each buffer.
X
X	* analyze.c (diff_2_files): Mention difference in final newlines.
X
XWed Jan 25 22:44:44 1989  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* dir.c (diff_dirs): Use * when calling fcn ptr variable.
X
XSat Dec 17 14:12:06 1988  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* Makefile: New vars INSTALL and LIBS used in some rules;
X	provide default defns plus commented-put defns for sysV.
X
XThu Nov 17 16:42:53 1988  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* dir.c (dir_sort): Open-trouble not fatal; just say # files is -1.
X	(diff_dirs): If dir_sort does that, give up and return 2.
X
X	* diff.c (compare_files): Don't open directories.
X	Don't close them specially either.
X	Cross-propagate inf[i].dir_p sooner.
X
XSun Nov 13 11:19:36 1988  Richard Stallman  (rms at sugar-bombs.ai.mit.edu)
X
X	* diff.h: Declare index, rindex.
X
X	* diff.c (compare_files): If comparing foodir with b/f,
X	use foodir/f, not foodir/b/f.
X
X	* diff.c (compare_files): Don't print "are identical" msg for 2 dirs.
X	Status now 1 if one file is a dir and the other isn't, etc.
X
XThu Nov  3 16:30:24 1988  Randall Smith  (randy at gluteus.ai.mit.edu)
X
X	* Makefile: Added a define for diff3 to define DIFF_PROGRAM.
X
X	* util.c: Added hack to make sure that perror was not called with
X	a null pointer.
X
X	* diff.c: Changed S_IFDIR to S_IFMT in masking type of file bits
X	out. 
X
X	* diff3.c: Included USG compatibility defines.
X
X	* diff.h: Moved sys/file.h into #else USG section (not needed or
X	wanted on System V).
X
X	* ed.c, analyze.c, context.c: Shortened names to 12 characters for
X	the sake of System V (too simple not to do).
X
XLocal Variables:
Xmode: indented-text
Xleft-margin: 8
Xversion-control: never
XEnd:
END_OF_FILE
if test 19300 -ne `wc -c <'ChangeLog'`; then
    echo shar: \"'ChangeLog'\" unpacked with wrong size!
fi
# end of 'ChangeLog'
fi
if test -f 'io.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'io.c'\"
else
echo shar: Extracting \"'io.c'\" \(18072 characters\)
sed "s/^X//" >'io.c' <<'END_OF_FILE'
X/* File I/O for GNU DIFF.
X   Copyright (C) 1988, 1989 Free Software Foundation, Inc.
X
XThis file is part of GNU DIFF.
X
XGNU DIFF is free software; you can redistribute it and/or modify
Xit under the terms of the GNU General Public License as published by
Xthe Free Software Foundation; either version 1, or (at your option)
Xany later version.
X
XGNU DIFF is distributed in the hope that it will be useful,
Xbut WITHOUT ANY WARRANTY; without even the implied warranty of
XMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
XGNU General Public License for more details.
X
XYou should have received a copy of the GNU General Public License
Xalong with GNU DIFF; see the file COPYING.  If not, write to
Xthe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
X
X#include "diff.h"
X
X/* Rotate a value n bits to the left. */
X#define UINT_BIT (sizeof (unsigned) * CHAR_BIT)
X#define ROL(v, n) ((v) << (n) | (v) >> UINT_BIT - (n))
X
X/* Given a hash value and a new character, return a new hash value. */
X#define HASH(h, c) ((c) + ROL (h, 7))
X
X/* Current file under consideration. */
Xstruct file_data *current;
X
X/* Check for binary files and compare them for exact identity.  */
X
X/* Return 1 if BUF contains a non text character.
X   SIZE is the number of characters in BUF.  */
X
Xstatic int
Xbinary_file_p (buf, size)
X     char *buf;
X     int size;
X{
X  static const char textchar[] = {
X    /* ISO 8859 */
X    0, 0, 0, 0, 0, 0, 0, 0,
X    0, 1, 1, 1, 1, 1, 0, 0,
X    0, 0, 0, 0, 0, 0, 0, 0,
X    0, 0, 0, 0, 0, 0, 0, 0,
X    1, 1, 1, 1, 1, 1, 1, 1,
X    1, 1, 1, 1, 1, 1, 1, 1,
X    1, 1, 1, 1, 1, 1, 1, 1,
X    1, 1, 1, 1, 1, 1, 1, 1,
X    1, 1, 1, 1, 1, 1, 1, 1,
X    1, 1, 1, 1, 1, 1, 1, 1,
X    1, 1, 1, 1, 1, 1, 1, 1,
X    1, 1, 1, 1, 1, 1, 1, 1,
X    1, 1, 1, 1, 1, 1, 1, 1,
X    1, 1, 1, 1, 1, 1, 1, 1,
X    1, 1, 1, 1, 1, 1, 1, 1,
X    1, 1, 1, 1, 1, 1, 1, 0,
X    0, 0, 0, 0, 0, 0, 0, 0,
X    0, 0, 0, 0, 0, 0, 0, 0,
X    0, 0, 0, 0, 0, 0, 0, 0,
X    0, 0, 0, 0, 0, 0, 0, 0,
X    1, 1, 1, 1, 1, 1, 1, 1,
X    1, 1, 1, 1, 1, 1, 1, 1,
X    1, 1, 1, 1, 1, 1, 1, 1,
X    1, 1, 1, 1, 1, 1, 1, 1,
X    1, 1, 1, 1, 1, 1, 1, 1,
X    1, 1, 1, 1, 1, 1, 1, 1,
X    1, 1, 1, 1, 1, 1, 1, 1,
X    1, 1, 1, 1, 1, 1, 1, 1,
X    1, 1, 1, 1, 1, 1, 1, 1,
X    1, 1, 1, 1, 1, 1, 1, 1,
X    1, 1, 1, 1, 1, 1, 1, 1,
X    1, 1, 1, 1, 1, 1, 1, 1,
X  };
X  while (--size >= 0)
X    if (!textchar[*buf++ & 0377])
X      return 1;
X  return 0;
X}
X
Xint binary_file_threshold = 512;
X
X/* Slurp the current file completely into core.
X   Return nonzero if it appears to be a binary file.  */
X
Xstatic int
Xslurp ()
X{
X  /* If we have a nonexistent file at this stage, treat it as empty.  */
X  if (current->desc < 0)
X    {
X      current->bufsize = 0;
X      current->buffered_chars = 0;
X      current->buffer = 0;
X    }
X  /* If it's a regular file, we can just get the size out of the stat
X     block and slurp it in all at once. */
X  /* In all cases, we leave room in the buffer for 2 extra chars
X     beyond those that current->bufsize describes:
X     one for a newline (in case the text does not end with one)
X     and one for a sentinel in find_identical_ends.  */
X  else if ((current->stat.st_mode & S_IFMT) == S_IFREG)
X    {
X      current->bufsize = current->stat.st_size;
X      current->buffer = (char *) xmalloc (current->bufsize + 2);
X      current->buffered_chars
X	= read (current->desc, current->buffer, current->bufsize);
X      if (current->buffered_chars < 0)
X	pfatal_with_name (current->name);
X    }
X  else
X    {
X      int cc;
X
X      current->bufsize = 4096;
X      current->buffer = (char *) xmalloc (current->bufsize + 2);
X      current->buffered_chars = 0;
X      
X      /* Not a regular file; read it in a little at a time, growing the
X	 buffer as necessary. */
X      while ((cc = read (current->desc,
X			 current->buffer + current->buffered_chars,
X			 current->bufsize - current->buffered_chars))
X	     > 0)
X	{
X	  current->buffered_chars += cc;
X	  if (current->buffered_chars == current->bufsize)
X	    {
X	      current->bufsize = current->bufsize * 2;
X	      current->buffer = (char *) xrealloc (current->buffer,
X						   current->bufsize + 2);
X	    }
X	}
X      if (cc < 0)
X	pfatal_with_name (current->name);
X    }
X  
X  /* Check first part of file to see if it's a binary file.  */
X  if (! always_text_flag
X      && binary_file_p (current->buffer,
X			min (current->buffered_chars, binary_file_threshold)))
X    return 1;
X
X  /* If not binary, make sure text ends in a newline,
X     but remember that we had to add one unless -B is in effect.  */
X  if (current->buffered_chars > 0
X      && current->buffer[current->buffered_chars - 1] != '\n')
X    {
X      current->missing_newline = !ignore_blank_lines_flag;
X      current->buffer[current->buffered_chars++] = '\n';
X    }
X  else
X    current->missing_newline = 0;
X
X  /* Don't use uninitialized storage. */
X  if (current->buffer != 0)
X    current->buffer[current->buffered_chars] = '\0';
X
X  return 0;
X}
X
X/* Split the file into lines, simultaneously computing the hash codes for
X   each line. */
X
Xvoid
Xfind_and_hash_each_line ()
X{
X  unsigned h;
X  int i;
X  unsigned char *p = (unsigned char *) current->prefix_end, *ip, c;
X
X  /* Attempt to get a good initial guess as to the number of lines. */
X  current->linbufsize = current->buffered_chars / 50 + 5;
X  current->linbuf
X    = (struct line_def *) xmalloc (current->linbufsize * sizeof (struct line_def));
X
X  if (function_regexp || output_style == OUTPUT_IFDEF)
X    {
X      /* If the -C, -D or -F option is used, we need to find the lines
X	 of the matching prefix.  At least we will need to find the last few,
X	 but since we don't know how many, it's easiest to find them all.
X	 If -D is specified, we need all the lines of the first file.  */
X      current->buffered_lines = 0;
X      p = (unsigned char *) current->buffer;
X    }
X  else
X    {
X      /* Skip the identical prefixes, except be prepared to handle context.
X	 In fact, handle 1 more preceding line than the context says,
X	 in case shift_boundaries moves things backwards in this file.  */
X      current->buffered_lines = current->prefix_lines - context - 1;
X      if (current->buffered_lines < 0)
X	current->buffered_lines = 0;
X      for (i = 0; i < context + 1; ++i)
X	/* Unless we are at the beginning, */
X	if ((char *) p != current->buffer)
X	  /* Back up at least 1 char until at the start of a line.  */
X	  while ((char *) --p != current->buffer && p[-1] != '\n')
X	    ;
X    }
X
X  while ((char *) p < current->suffix_begin)
X    {
X      h = 0;
X      ip = p;
X
X      if (current->prefix_end <= (char *) p)
X	{
X	  /* Hash this line until we find a newline. */
X	  if (ignore_case_flag)
X	    {
X	      if (ignore_all_space_flag)
X		while ((c = *p) != '\n')
X		  {
X		    if (! isspace (c))
X		      if (isupper (c))
X			h = HASH (h, tolower (c));
X		      else
X			h = HASH (h, c);
X		    ++p;
X		  }
X	      else if (ignore_space_change_flag)
X
X		while ((c = *p) != '\n')
X		  {
X		    if (c == ' ' || c == '\t')
X		      {
X			while ((c = *p) == ' ' || c == '\t')
X			  ++p;
X			if (c == '\n')
X			  break;
X			h = HASH (h, ' ');
X		      }
X		    /* C is now the first non-space.  */
X		    if (isupper (c))
X		      h = HASH (h, tolower (c));
X		    else
X		      h = HASH (h, c);
X		    ++p;
X		  }
X	      else
X		while ((c = *p) != '\n')
X		  {
X		    if (isupper (c))
X		      h = HASH (h, tolower (c));
X		    else
X		      h = HASH (h, c);
X		    ++p;
X		  }
X	    }
X	  else
X	    {
X	      if (ignore_all_space_flag)
X		while ((c = *p) != '\n')
X		  {
X		    if (! isspace (c))
X		      h = HASH (h, c);
X		    ++p;
X		  }
X	      else if (ignore_space_change_flag)
X		while ((c = *p) != '\n')
X		  {
X		    if (c == ' ' || c == '\t')
X		      {
X			while ((c = *p) == ' ' || c == '\t')
X			  ++p;
X			if (c == '\n')
X			  break;
X			h = HASH (h, ' ');
X		      }
X		    /* C is not the first non-space.  */
X		    h = HASH (h, c);
X		    ++p;
X		  }
X	      else
X		while ((c = *p) != '\n')
X		  {
X		    h = HASH (h, c);
X		    ++p;
X		  }
X	    }
X	}
X      else
X	/* This line is part of the matching prefix,
X	   so we don't need to hash it.  */
X	while (*p != '\n')
X	  ++p;
X      
X      /* Maybe increase the size of the line table. */
X      if (current->buffered_lines >= current->linbufsize)
X	{
X	  while (current->buffered_lines >= current->linbufsize)
X	    current->linbufsize *= 2;
X	  current->linbuf
X	    = (struct line_def *) xrealloc (current->linbuf,
X					    current->linbufsize
X					    * sizeof (struct line_def));
X	}
X      current->linbuf[current->buffered_lines].text = (char *) ip;
X      current->linbuf[current->buffered_lines].length = p - ip + 1;
X      current->linbuf[current->buffered_lines].hash = h;
X      ++current->buffered_lines;
X      ++p;
X    }
X
X  i = 0;
X  while ((i < context || output_style == OUTPUT_IFDEF)
X	 && (char *) p < current->buffer + current->buffered_chars)
X    {
X      ip = p;
X      while (*p++ != '\n')
X	;
X      /* Maybe increase the size of the line table. */
X      if (current->buffered_lines >= current->linbufsize)
X	{
X	  while (current->buffered_lines >= current->linbufsize)
X	    current->linbufsize *= 2;
X	  current->linbuf
X	    = (struct line_def *) xrealloc (current->linbuf,
X					    current->linbufsize
X					    * sizeof (struct line_def));
X	}
X      current->linbuf[current->buffered_lines].text = (char *) ip;
X      current->linbuf[current->buffered_lines].length = p - ip;
X      current->linbuf[current->buffered_lines].hash = 0;
X      ++current->buffered_lines;
X      ++i;
X    }
X
X  if (ROBUST_OUTPUT_STYLE (output_style)
X      && current->missing_newline
X      && current->suffix_begin == current->buffer + current->buffered_chars)
X    --current->linbuf[current->buffered_lines - 1].length;
X}
X
X/* Given a vector of two file_data objects, find the identical
X   prefixes and suffixes of each object. */
X
Xstatic void
Xfind_identical_ends (filevec)
X     struct file_data filevec[];
X{
X  char *p0, *p1, *end0, *beg0;
X  int lines;
X
X  if (filevec[0].buffered_chars == 0 || filevec[1].buffered_chars == 0)
X    {
X      filevec[0].prefix_end = filevec[0].buffer;
X      filevec[1].prefix_end = filevec[1].buffer;
X      filevec[0].prefix_lines = filevec[1].prefix_lines = 0;
X      filevec[0].suffix_begin = filevec[0].buffer + filevec[0].buffered_chars;
X      filevec[1].suffix_begin = filevec[1].buffer + filevec[1].buffered_chars;
X      filevec[0].suffix_lines = filevec[1].suffix_lines = 0;
X      return;
X    }
X
X  /* Find identical prefix.  */
X
X  p0 = filevec[0].buffer;
X  p1 = filevec[1].buffer;
X  lines = 0;
X
X  /* Insert end "sentinels", in this case characters that are guaranteed
X     to make the equality test false, and thus terminate the loop.  */
X
X  if (filevec[0].buffered_chars < filevec[1].buffered_chars)
X    p0[filevec[0].buffered_chars] = ~p1[filevec[0].buffered_chars];
X  else
X    p1[filevec[1].buffered_chars] = ~p0[filevec[1].buffered_chars];
X
X  /* Loop until first mismatch, or to the sentinel characters.  */
X  while (1)
X    {
X      char c = *p0++;
X      if (c != *p1++)
X	break;
X      if (c == '\n')
X	++lines;
X    }
X
X  /* Don't count missing newline as part of prefix in RCS mode. */
X  if (ROBUST_OUTPUT_STYLE (output_style)
X      && ((filevec[0].missing_newline
X	   && p0 - filevec[0].buffer > filevec[0].buffered_chars)
X	  ||
X	  (filevec[1].missing_newline
X	   && p1 - filevec[1].buffer > filevec[1].buffered_chars)))
X    --p0, --p1, --lines;
X
X  /* If the sentinel was passed, and lengths are equal, the
X     files are identical.  */
X  if (p0 - filevec[0].buffer > filevec[0].buffered_chars
X      && filevec[0].buffered_chars == filevec[1].buffered_chars)
X    {
X      filevec[0].prefix_end = p0 - 1;
X      filevec[1].prefix_end = p1 - 1;
X      filevec[0].prefix_lines = filevec[1].prefix_lines = lines;
X      filevec[0].suffix_begin = filevec[0].buffer;
X      filevec[1].suffix_begin = filevec[1].buffer;
X      filevec[0].suffix_lines = filevec[1].suffix_lines = lines;
X      return;
X    }
X
X  /* Point at first nonmatching characters.  */
X  --p0, --p1;
X
X  /* Skip back to last line-beginning in the prefix.  */
X  while (p0 != filevec[0].buffer && p0[-1] != '\n')
X    --p0, --p1;
X
X  /* Record the prefix.  */
X  filevec[0].prefix_end = p0;
X  filevec[1].prefix_end = p1;
X  filevec[0].prefix_lines = filevec[1].prefix_lines = lines;
X  
X  /* Find identical suffix.  */
X
X  /* P0 and P1 point beyond the last chars not yet compared.  */
X  p0 = filevec[0].buffer + filevec[0].buffered_chars;
X  p1 = filevec[1].buffer + filevec[1].buffered_chars;
X  lines = 0;
X
X  if (! ROBUST_OUTPUT_STYLE (output_style)
X      || filevec[0].missing_newline == filevec[1].missing_newline)
X    {
X      end0 = p0;		/* Addr of last char in file 0.  */
X
X      /* Get value of P0 at which we should stop scanning backward:
X	 this is when either P0 or P1 points just past the last char
X	 of the identical prefix.  */
X      if (filevec[0].buffered_chars < filevec[1].buffered_chars)
X	beg0 = filevec[0].prefix_end;
X      else
X	/* Figure out where P0 will be when P1 is at the end of the prefix.
X	   Thus we only need to test P0.  */
X	beg0 = (filevec[0].prefix_end
X		+ filevec[0].buffered_chars - filevec[1].buffered_chars);
X
X      /* Scan back until chars don't match or we reach that point.  */
X      while (p0 != beg0)
X	{
X	  char c = *--p0;
X	  if (c != *--p1)
X	    {
X	      /* Point at the first char of the matching suffix.  */
X	      ++p0, ++p1;
X	      break;
X	    }
X	  if (c == '\n')
X	    ++lines;
X	}
X
X      /* Are we at a line-beginning in both files?  */
X      if (p0 != end0
X	  && !((p0 == filevec[0].buffer || p0[-1] == '\n')
X	       &&
X	       (p1 == filevec[1].buffer || p1[-1] == '\n')))
X	{
X	  /* No.  We counted one line too many.  */
X	  --lines;
X	  /* Advance to next place that is a line-beginning in both files.  */
X	  do
X	    {
X	      ++p0, ++p1;
X	    }
X	  while (p0 != end0 && p0[-1] != '\n');
X	}
X    }
X
X  /* Record the suffix.  */
X  filevec[0].suffix_begin = p0;
X  filevec[1].suffix_begin = p1;
X  filevec[0].suffix_lines = filevec[1].suffix_lines = lines;
X}
X
X/* Lines are put into equivalence classes (of lines that match in line_cmp).
X   Each equivalence class is represented by one of these structures,
X   but only while the classes are being computed.
X   Afterward, each class is represented by a number.  */
Xstruct equivclass
X{
X  struct equivclass *next;	/* Next item in this bucket. */
X  struct line_def line;	/* A line that fits this class. */
X};
X
X/* Hash-table: array of buckets, each being a chain of equivalence classes.  */
Xstatic struct equivclass **buckets;
X  
X/* Size of the bucket array. */
Xstatic int nbuckets;
X
X/* Array in which the equivalence classes are allocated.
X   The bucket-chains go through the elements in this array.
X   The number of an equivalence class is its index in this array.  */
Xstatic struct equivclass *equivs;
X
X/* Index of first free element in the array `equivs'.  */
Xstatic int equivs_index;
X
X/* Size allocated to the array `equivs'.  */
Xstatic int equivs_alloc;
X
X/* Largest primes less than some power of two, for nbuckets.  Values range
X   from useful to preposterous.  If one of these numbers isn't prime
X   after all, don't blame it on me, blame it on primes (6) . . . */
Xstatic int primes[] =
X{
X  509,
X  1021,
X  2039,
X  4093,
X  8191,
X  16381,
X  32749,
X  65521,
X  131071,
X  262139,
X  524287,
X  1048573,
X  2097143,
X  4194301,
X  8388593,
X  16777213,
X  33554393,
X  67108859,			/* Preposterously large . . . */
X  -1
X};
X
X/* Index of current nbuckets in primes. */
Xstatic int primes_index;
X
X/* Find the equiv class associated with line N of the current file.  */
X
Xstatic int
Xfind_equiv_class (n)
X     int n;
X{
X  int bucket;
X  struct equivclass *b, *p = NULL;
X
X  /* Equivalence class 0 is permanently allocated to lines that were
X     not hashed because they were parts of identical prefixes or
X     suffixes. */
X  if (n < current->prefix_lines
X      || current->linbuf[n].text >= current->suffix_begin)
X    return 0;
X
X  /* Check through the appropriate bucket to see if there isn't already
X     an equivalence class for this line. */
X  bucket = current->linbuf[n].hash % nbuckets;
X  b = buckets[bucket];
X  while (b)
X    {
X      if (b->line.hash == current->linbuf[n].hash
X	  && (b->line.length == current->linbuf[n].length
X	      /* Lines of different lengths can match with certain options.  */
X	      || length_varies)
X	  && !line_cmp (&b->line, &current->linbuf[n]))
X	return b - equivs;
X      p = b, b = b->next;
X    }
X
X  /* Create a new equivalence class in this bucket. */
X
X  p = &equivs[equivs_index++];
X  p->next = buckets[bucket];
X  buckets[bucket] = p;
X  p->line = current->linbuf[n];
X
X  return equivs_index - 1;
X}
X
X/* Given a vector of two file_data objects, read the file associated
X   with each one, and build the table of equivalence classes.
X   Return nonzero if either file appears to be a binary file.  */
X
Xint
Xread_files (filevec)
X     struct file_data filevec[];
X{
X  int i, j;
X  int binary = 0;
X  int this_binary;
X
X  current = &filevec[0];
X  binary = this_binary = slurp ();
X
X  current = &filevec[1];
X  this_binary = slurp ();
X  if (binary || this_binary)
X    return 1;
X
X  find_identical_ends (filevec);
X
X  for (i = 0; i < 2; ++i)
X    {
X      current = &filevec[i];
X      find_and_hash_each_line ();
X    }
X
X  /* This is guaranteed to be enough space.  */
X  equivs_alloc = filevec[0].buffered_lines + filevec[1].buffered_lines + 1;
X  equivs = (struct equivclass *) xmalloc (equivs_alloc * sizeof (struct equivclass));
X  /* Equivalence class 0 is permanently safe for lines that were not
X     hashed.  Real equivalence classes start at 1. */
X  equivs_index = 1;
X  
X  primes_index = 0;
X  while (primes[primes_index] < equivs_alloc / 3)
X    primes_index++;
X
X  buckets = (struct equivclass **) xmalloc (primes[primes_index] * sizeof (struct equivclass *));
X  bzero (buckets, primes[primes_index] * sizeof (struct equivclass *));
X  nbuckets = primes[primes_index];
X
X  for (i = 0; i < 2; ++i)
X    {
X      current = &filevec[i];
X      current->equivs
X	= (int *) xmalloc (current->buffered_lines * sizeof (int));
X      for (j = 0; j < current->buffered_lines; ++j)
X	current->equivs[j] = find_equiv_class (j);
X    }
X
X  filevec[0].equiv_max = filevec[1].equiv_max = equivs_index;
X
X  free (equivs);
X  free (buckets);
X
X  return 0;
X}
END_OF_FILE
if test 18072 -ne `wc -c <'io.c'`; then
    echo shar: \"'io.c'\" unpacked with wrong size!
fi
# end of 'io.c'
fi
echo shar: End of archive 4 \(of 8\).
cp /dev/null ark4isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 8 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0

exit 0 # Just in case...
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.