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, ¤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@uunet.uu.net. Use a domain-based address or give alternate paths, or you may lose out.