diff options
| author | jtc <jtc@NetBSD.org> | 1994-11-01 20:38:40 +0000 |
|---|---|---|
| committer | jtc <jtc@NetBSD.org> | 1994-11-01 20:38:40 +0000 |
| commit | cd439d82af9522ec662102dfebdc44875eb58bf4 (patch) | |
| tree | 78fe55729c4ac3d1f789a33cc7e4612c390ce28b /gnu/usr.bin/diff/io.c | |
| parent | 0f8e6cf96801bbae057bcf623b51ab7d71b765e4 (diff) | |
Upgraded to diffutils 2.7.
Diffstat (limited to 'gnu/usr.bin/diff/io.c')
| -rw-r--r-- | gnu/usr.bin/diff/io.c | 152 |
1 files changed, 98 insertions, 54 deletions
diff --git a/gnu/usr.bin/diff/io.c b/gnu/usr.bin/diff/io.c index 956f6efb837..66059155109 100644 --- a/gnu/usr.bin/diff/io.c +++ b/gnu/usr.bin/diff/io.c @@ -1,5 +1,5 @@ /* File I/O for GNU DIFF. - Copyright (C) 1988, 1989, 1992, 1993 Free Software Foundation, Inc. + Copyright (C) 1988, 1989, 1992, 1993, 1994 Free Software Foundation, Inc. This file is part of GNU DIFF. @@ -17,10 +17,6 @@ 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. */ -#ifndef lint -static char *rcsid = "$Id: io.c,v 1.5 1993/11/12 02:26:03 jtc Exp $"; -#endif - #include "diff.h" /* Rotate a value n bits to the left. */ @@ -35,7 +31,9 @@ static char *rcsid = "$Id: io.c,v 1.5 1993/11/12 02:26:03 jtc Exp $"; #define GUESS_LINES(n,s,t) (((t) - (s)) / ((n) < 10 ? 32 : (s) / ((n)-1)) + 5) /* Type used for fast prefix comparison in find_identical_ends. */ -typedef int word; +#ifndef word +#define word int +#endif /* Lines are put into equivalence classes (of lines that match in line_cmp). Each equivalence class is represented by one of these structures, @@ -46,13 +44,14 @@ struct equivclass int next; /* Next item in this bucket. */ unsigned hash; /* Hash of lines in this class. */ char const *line; /* A line that fits this class. */ - size_t length; /* The length of that line. */ + size_t length; /* That line's length, not counting its newline. */ }; -/* Hash-table: array of buckets, each being a chain of equivalence classes. */ +/* Hash-table: array of buckets, each being a chain of equivalence classes. + buckets[-1] is reserved for incomplete lines. */ static int *buckets; - -/* Number of buckets in the hash table array. */ + +/* Number of buckets in the hash table array, not counting buckets[-1]. */ static int nbuckets; /* Array in which the equivalence classes are allocated. @@ -75,7 +74,7 @@ static void prepare_text_end PARAMS((struct file_data *)); /* Return 1 if BUF contains a non text character. SIZE is the number of characters in BUF. */ -#define binary_file_p(buf, size) (size != 0 && memchr (buf, '\0', size) != 0) +#define binary_file_p(buf, size) (memchr (buf, '\0', size) != 0) /* Get ready to read the current file. Return nonzero if SKIP_TEST is zero, @@ -101,15 +100,26 @@ sip (current, skip_test) if (! skip_test) { /* Check first part of file to see if it's a binary file. */ - current->buffered_chars = read (current->desc, - current->buffer, - current->bufsize); - if (current->buffered_chars == -1) +#if HAVE_SETMODE + int oldmode = setmode (current->desc, O_BINARY); +#endif + size_t n = read (current->desc, current->buffer, current->bufsize); + if (n == -1) pfatal_with_name (current->name); - return binary_file_p (current->buffer, current->buffered_chars); + current->buffered_chars = n; +#if HAVE_SETMODE + if (oldmode != O_BINARY) + { + if (lseek (current->desc, - (off_t) n, SEEK_CUR) == -1) + pfatal_with_name (current->name); + setmode (current->desc, oldmode); + current->buffered_chars = 0; + } +#endif + return binary_file_p (current->buffer, n); } } - + current->buffered_chars = 0; return 0; } @@ -197,10 +207,7 @@ find_and_hash_each_line (current) int eqs_alloc = equivs_alloc; char const *suffix_begin = current->suffix_begin; char const *bufend = current->buffer + current->buffered_chars; - char const *incomplete_tail - = current->missing_newline && ROBUST_OUTPUT_STYLE (output_style) - ? bufend : (char const *) 0; - int varies = length_varies; + int use_line_cmp = ignore_some_line_changes; while ((char const *) p < suffix_begin) { @@ -216,42 +223,52 @@ find_and_hash_each_line (current) if (ignore_all_space_flag) while ((c = *p++) != '\n') { - if (! isspace (c)) - h = HASH (h, isupper (c) ? tolower (c) : c); + if (! ISSPACE (c)) + h = HASH (h, ISUPPER (c) ? tolower (c) : c); } else if (ignore_space_change_flag) while ((c = *p++) != '\n') { - if (isspace (c)) + if (ISSPACE (c)) { - while (isspace (c = *p++)) - if (c == '\n') - goto hashing_done; + for (;;) + { + c = *p++; + if (!ISSPACE (c)) + break; + if (c == '\n') + goto hashing_done; + } h = HASH (h, ' '); } /* C is now the first non-space. */ - h = HASH (h, isupper (c) ? tolower (c) : c); + h = HASH (h, ISUPPER (c) ? tolower (c) : c); } else while ((c = *p++) != '\n') - h = HASH (h, isupper (c) ? tolower (c) : c); + h = HASH (h, ISUPPER (c) ? tolower (c) : c); } else { if (ignore_all_space_flag) while ((c = *p++) != '\n') { - if (! isspace (c)) + if (! ISSPACE (c)) h = HASH (h, c); } else if (ignore_space_change_flag) while ((c = *p++) != '\n') { - if (isspace (c)) + if (ISSPACE (c)) { - while (isspace (c = *p++)) - if (c == '\n') - goto hashing_done; + for (;;) + { + c = *p++; + if (!ISSPACE (c)) + break; + if (c == '\n') + goto hashing_done; + } h = HASH (h, ' '); } /* C is now the first non-space. */ @@ -264,7 +281,22 @@ find_and_hash_each_line (current) hashing_done:; bucket = &buckets[h % nbuckets]; - length = (char const *) p - ip - ((char const *) p == incomplete_tail); + length = (char const *) p - ip - 1; + + if ((char const *) p == bufend + && current->missing_newline + && ROBUST_OUTPUT_STYLE (output_style)) + { + /* This line is incomplete. If this is significant, + put the line into bucket[-1]. */ + if (! (ignore_space_change_flag | ignore_all_space_flag)) + bucket = &buckets[-1]; + + /* Omit the inserted newline when computing linbuf later. */ + p--; + bufend = suffix_begin = (char const *) p; + } + for (i = *bucket; ; i = eqs[i].next) if (!i) { @@ -280,11 +312,20 @@ find_and_hash_each_line (current) *bucket = i; break; } - else if (eqs[i].hash == h - && (eqs[i].length == length || varies) - && ! line_cmp (eqs[i].line, eqs[i].length, ip, length)) - /* Reuse existing equivalence class. */ - break; + else if (eqs[i].hash == h) + { + char const *eqline = eqs[i].line; + + /* Reuse existing equivalence class if the lines are identical. + This detects the common case of exact identity + faster than complete comparison would. */ + if (eqs[i].length == length && memcmp (eqline, ip, length) == 0) + break; + + /* Reuse existing class if line_cmp reports the lines equal. */ + if (use_line_cmp && line_cmp (eqline, ip) == 0) + break; + } /* Maybe increase the size of the line table. */ if (line == alloc_lines) @@ -307,7 +348,7 @@ find_and_hash_each_line (current) for (i = 0; ; i++) { /* Record the line start for lines in the suffix that we care about. - Record one more line start than lines, + Record one more line start than lines, so that we can compute the length of any buffered line. */ if (line == alloc_lines) { @@ -319,12 +360,9 @@ find_and_hash_each_line (current) - linbuf_base; } linbuf[line] = (char const *) p; - + if ((char const *) p == bufend) - { - linbuf[line] -= (char const *) p == incomplete_tail; - break; - } + break; if (context <= i && no_diff_means_no_output) break; @@ -347,7 +385,7 @@ find_and_hash_each_line (current) /* Prepare the end of the text. Make sure it's initialized. Make sure text ends in a newline, - but remember that we had to add one unless -B is in effect. */ + but remember that we had to add one. */ static void prepare_text_end (current) @@ -362,9 +400,9 @@ prepare_text_end (current) { p[buffered_chars++] = '\n'; current->buffered_chars = buffered_chars; - current->missing_newline = ! ignore_blank_lines_flag; + current->missing_newline = 1; } - + /* Don't use uninitialized storage when planting or using sentinels. */ if (p) bzero (p + buffered_chars, sizeof (word)); @@ -640,7 +678,13 @@ read_files (filevec, pretend_binary) filevec[1].buffered_chars = filevec[0].buffered_chars; } if (appears_binary) - return 1; + { +#if HAVE_SETMODE + setmode (filevec[0].desc, O_BINARY); + setmode (filevec[1].desc, O_BINARY); +#endif + return 1; + } find_identical_ends (filevec); @@ -655,16 +699,16 @@ read_files (filevec, pretend_binary) abort (); nbuckets = primes[i]; - buckets = (int *) xmalloc (nbuckets * sizeof (*buckets)); - bzero (buckets, nbuckets * sizeof (*buckets)); + buckets = (int *) xmalloc ((nbuckets + 1) * sizeof (*buckets)); + bzero (buckets++, (nbuckets + 1) * sizeof (*buckets)); - for (i = 0; i < 2; ++i) + for (i = 0; i < 2; i++) find_and_hash_each_line (&filevec[i]); filevec[0].equiv_max = filevec[1].equiv_max = equivs_index; free (equivs); - free (buckets); + free (buckets - 1); return 0; } |
