386BSD 0.1 development
authorWilliam F. Jolitz <wjolitz@soda.berkeley.edu>
Sat, 4 Apr 1992 22:40:51 +0000 (14:40 -0800)
committerWilliam F. Jolitz <wjolitz@soda.berkeley.edu>
Sat, 4 Apr 1992 22:40:51 +0000 (14:40 -0800)
Work on file usr/src/usr.bin/diff/ChangeLog
Work on file usr/src/usr.bin/diff/io.c

Co-Authored-By: Lynne Greer Jolitz <ljolitz@cardio.ucsf.edu>
Synthesized-from: 386BSD-0.1

usr/src/usr.bin/diff/ChangeLog [new file with mode: 0644]
usr/src/usr.bin/diff/io.c [new file with mode: 0644]

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