v24i019: GNU Diff, version 1.15, Part04/08
Rich Salz
rsalz at uunet.uu.net
Tue Feb 26 08:14:20 AEST 1991
Submitted-by: Paul Eggert <eggert at 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 at 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 at 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, ¤t->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 at uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.
More information about the Comp.sources.unix
mailing list