diff options
| author | jtc <jtc@NetBSD.org> | 1993-11-12 02:25:52 +0000 |
|---|---|---|
| committer | jtc <jtc@NetBSD.org> | 1993-11-12 02:25:52 +0000 |
| commit | dbc9689292c21e5d6065de6864b1bb0c69c35b42 (patch) | |
| tree | 26af35b0b580db7903ee2f0e439c2f0a279ffd80 /gnu/usr.bin/diff | |
| parent | d8cd41a62ae45621d4ba897dc716c2f24ad9c9e8 (diff) | |
Upgraded to diffutils 2.6.
Diffstat (limited to 'gnu/usr.bin/diff')
| -rw-r--r-- | gnu/usr.bin/diff/analyze.c | 368 | ||||
| -rw-r--r-- | gnu/usr.bin/diff/diff.c | 43 | ||||
| -rw-r--r-- | gnu/usr.bin/diff/diff3.c | 44 | ||||
| -rw-r--r-- | gnu/usr.bin/diff/io.c | 46 | ||||
| -rw-r--r-- | gnu/usr.bin/diff/regex.c | 34 | ||||
| -rw-r--r-- | gnu/usr.bin/diff/sdiff.c | 46 | ||||
| -rw-r--r-- | gnu/usr.bin/diff/util.c | 6 | ||||
| -rw-r--r-- | gnu/usr.bin/diff/version.c | 4 |
8 files changed, 374 insertions, 217 deletions
diff --git a/gnu/usr.bin/diff/analyze.c b/gnu/usr.bin/diff/analyze.c index de7dad98e10..a8fe05f8049 100644 --- a/gnu/usr.bin/diff/analyze.c +++ b/gnu/usr.bin/diff/analyze.c @@ -18,12 +18,21 @@ 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: analyze.c,v 1.5 1993/09/29 21:37:02 jtc Exp $"; +static char *rcsid = "$Id: analyze.c,v 1.6 1993/11/12 02:25:52 jtc Exp $"; #endif /* The basic algorithm is described in: "An O(ND) Difference Algorithm and its Variations", Eugene Myers, - Algorithmica Vol. 1 No. 2, 1986, p 251. */ + Algorithmica Vol. 1 No. 2, 1986, pp. 251-266; + see especially section 4.2, which describes the variation used below. + Unless the --minimal option is specified, this code uses the TOO_EXPENSIVE + heuristic, by Paul Eggert, to limit the cost to O(N**1.5 log N) + at the price of producing suboptimal output for large inputs with + many differences. + + The basic algorithm was independently discovered as described in: + "Algorithms for Approximate String Matching", E. Ukkonen, + Information and Control Vol. 64, 1985, pp. 100-118. */ #include "diff.h" #include "cmpbuf.h" @@ -32,56 +41,74 @@ extern int no_discards; static int *xvec, *yvec; /* Vectors being compared. */ static int *fdiag; /* Vector, indexed by diagonal, containing - the X coordinate of the point furthest + 1 + the X coordinate of the point furthest along the given diagonal in the forward search of the edit matrix. */ static int *bdiag; /* Vector, indexed by diagonal, containing the X coordinate of the point furthest along the given diagonal in the backward search of the edit matrix. */ +static int too_expensive; /* Edit scripts longer than this are too + expensive to compute. */ + +#define SNAKE_LIMIT 20 /* Snakes bigger than this are considered `big'. */ -static int diag PARAMS((int, int, int, int, int *)); +struct partition +{ + int xmid, ymid; /* Midpoints of this partition. */ + int lo_minimal; /* Nonzero if low half will be analyzed minimally. */ + int hi_minimal; /* Likewise for high half. */ +}; + +static int diag PARAMS((int, int, int, int, int, struct partition *)); static struct change *add_change PARAMS((int, int, int, int, struct change *)); static struct change *build_reverse_script PARAMS((struct file_data const[])); static struct change *build_script PARAMS((struct file_data const[])); static void briefly_report PARAMS((int, struct file_data const[])); -static void compareseq PARAMS((int, int, int, int)); +static void compareseq PARAMS((int, int, int, int, int)); static void discard_confusing_lines PARAMS((struct file_data[])); static void shift_boundaries PARAMS((struct file_data[])); /* Find the midpoint of the shortest edit script for a specified portion of the two files. - We scan from the beginnings of the files, and simultaneously from the ends, + Scan from the beginnings of the files, and simultaneously from the ends, doing a breadth-first search through the space of edit-sequence. When the two searches meet, we have found the midpoint of the shortest edit sequence. - The value returned is the number of the diagonal on which the midpoint lies. - The diagonal number equals the number of inserted lines minus the number + If MINIMAL is nonzero, find the minimal edit script regardless + of expense. Otherwise, if the search is too expensive, use + heuristics to stop the search and report a suboptimal answer. + + Set PART->(XMID,YMID) to the midpoint (XMID,YMID). The diagonal number + XMID - YMID equals the number of inserted lines minus the number of deleted lines (counting only lines before the midpoint). - The edit cost is stored into *COST; this is the total number of - lines inserted or deleted (counting only lines before the midpoint). + Return the approximate edit cost; this is the total number of + lines inserted or deleted (counting only lines before the midpoint), + unless a heuristic is used to terminate the search prematurely. + + Set PART->LEFT_MINIMAL to nonzero iff the minimal edit script for the + left half of the partition is known; similarly for PART->RIGHT_MINIMAL. This function assumes that the first lines of the specified portions of the two files do not match, and likewise that the last lines do not match. The caller must trim matching lines from the beginning and end of the portions it is going to specify. - Note that if we return the "wrong" diagonal value, or if - the value of bdiag at that diagonal is "wrong", + If we return the "wrong" partitions, the worst this can do is cause suboptimal diff output. It cannot cause incorrect diff output. */ static int -diag (xoff, xlim, yoff, ylim, cost) - int xoff, xlim, yoff, ylim; - int *cost; +diag (xoff, xlim, yoff, ylim, minimal, part) + int xoff, xlim, yoff, ylim, minimal; + struct partition *part; { int *const fd = fdiag; /* Give the compiler a chance. */ int *const bd = bdiag; /* Additional help for the compiler. */ - int *const xv = xvec; /* Still more help for the compiler. */ - int *const yv = yvec; /* And more and more . . . */ + int const *const xv = xvec; /* Still more help for the compiler. */ + int const *const yv = yvec; /* And more and more . . . */ int const dmin = xoff - ylim; /* Minimum valid diagonal. */ int const dmax = xlim - yoff; /* Maximum valid diagonal. */ int const fmid = xoff - yoff; /* Center diagonal of top-down search. */ @@ -115,17 +142,19 @@ diag (xoff, xlim, yoff, ylim, cost) y = x - d; while (x < xlim && y < ylim && xv[x] == yv[y]) ++x, ++y; - if (x - oldx > 20) + if (x - oldx > SNAKE_LIMIT) big_snake = 1; fd[d] = x; - if (odd && bmin <= d && d <= bmax && bd[d] <= fd[d]) + if (odd && bmin <= d && d <= bmax && bd[d] <= x) { - *cost = 2 * c - 1; - return d; + part->xmid = x; + part->ymid = y; + part->lo_minimal = part->hi_minimal = 1; + return 2 * c - 1; } } - /* Similar extend the bottom-up search. */ + /* Similarly extend the bottom-up search. */ bmin > dmin ? bd[--bmin - 1] = INT_MAX : ++bmin; bmax < dmax ? bd[++bmax + 1] = INT_MAX : --bmax; for (d = bmax; d >= bmin; d -= 2) @@ -140,16 +169,21 @@ diag (xoff, xlim, yoff, ylim, cost) y = x - d; while (x > xoff && y > yoff && xv[x - 1] == yv[y - 1]) --x, --y; - if (oldx - x > 20) + if (oldx - x > SNAKE_LIMIT) big_snake = 1; bd[d] = x; - if (!odd && fmin <= d && d <= fmax && bd[d] <= fd[d]) + if (!odd && fmin <= d && d <= fmax && x <= fd[d]) { - *cost = 2 * c; - return d; + part->xmid = x; + part->ymid = y; + part->lo_minimal = part->hi_minimal = 1; + return 2 * c; } } + if (minimal) + continue; + /* Heuristic: check occasionally for a diagonal that has made lots of progress compared with the edit distance. If we have any such, find the one that has made the most @@ -161,74 +195,134 @@ diag (xoff, xlim, yoff, ylim, cost) if (c > 200 && big_snake && heuristic) { int best; - int bestpos; best = 0; - bestpos = 0; /* Pacify `gcc -Wall'. */ for (d = fmax; d >= fmin; d -= 2) { int dd = d - fmid; - if ((fd[d] - xoff)*2 - dd > 12 * (c + (dd > 0 ? dd : -dd))) + int x = fd[d]; + int y = x - d; + int v = (x - xoff) * 2 - dd; + if (v > 12 * (c + (dd < 0 ? -dd : dd))) { - if (fd[d] * 2 - dd > best - && fd[d] - xoff > 20 - && fd[d] - d - yoff > 20) + if (v > best + && xoff + SNAKE_LIMIT <= x && x < xlim + && yoff + SNAKE_LIMIT <= y && y < ylim) { - int k; - int x = fd[d]; - /* We have a good enough best diagonal; now insist that it end with a significant snake. */ - for (k = 1; k <= 20; k++) - if (xvec[x - k] != yvec[x - d - k]) - break; - - if (k == 21) - { - best = fd[d] * 2 - dd; - bestpos = d; - } + int k; + + for (k = 1; xv[x - k] == yv[y - k]; k++) + if (k == SNAKE_LIMIT) + { + best = v; + part->xmid = x; + part->ymid = y; + break; + } } } } if (best > 0) { - *cost = 2 * c - 1; - return bestpos; + part->lo_minimal = 1; + part->hi_minimal = 0; + return 2 * c - 1; } best = 0; for (d = bmax; d >= bmin; d -= 2) { int dd = d - bmid; - if ((xlim - bd[d])*2 + dd > 12 * (c + (dd > 0 ? dd : -dd))) + int x = bd[d]; + int y = x - d; + int v = (xlim - x) * 2 + dd; + if (v > 12 * (c + (dd < 0 ? -dd : dd))) { - if ((xlim - bd[d]) * 2 + dd > best - && xlim - bd[d] > 20 - && ylim - (bd[d] - d) > 20) + if (v > best + && xoff < x && x <= xlim - SNAKE_LIMIT + && yoff < y && y <= ylim - SNAKE_LIMIT) { /* We have a good enough best diagonal; now insist that it end with a significant snake. */ int k; - int x = bd[d]; - - for (k = 0; k < 20; k++) - if (xvec[x + k] != yvec[x - d + k]) - break; - if (k == 20) - { - best = (xlim - bd[d]) * 2 + dd; - bestpos = d; - } + + for (k = 0; xv[x + k] == yv[y + k]; k++) + if (k == SNAKE_LIMIT - 1) + { + best = v; + part->xmid = x; + part->ymid = y; + break; + } } } } if (best > 0) { - *cost = 2 * c - 1; - return bestpos; + part->lo_minimal = 0; + part->hi_minimal = 1; + return 2 * c - 1; } } + + /* Heuristic: if we've gone well beyond the call of duty, + give up and report halfway between our best results so far. */ + if (c >= too_expensive) + { + int fxybest, fxbest; + int bxybest, bxbest; + + fxbest = bxbest = 0; /* Pacify `gcc -Wall'. */ + + /* Find forward diagonal that maximizes X + Y. */ + fxybest = -1; + for (d = fmax; d >= fmin; d -= 2) + { + int x = min (fd[d], xlim); + int y = x - d; + if (ylim < y) + x = ylim + d, y = ylim; + if (fxybest < x + y) + { + fxybest = x + y; + fxbest = x; + } + } + + /* Find backward diagonal that minimizes X + Y. */ + bxybest = INT_MAX; + for (d = bmax; d >= bmin; d -= 2) + { + int x = max (xoff, bd[d]); + int y = x - d; + if (y < yoff) + x = yoff + d, y = yoff; + if (x + y < bxybest) + { + bxybest = x + y; + bxbest = x; + } + } + + /* Use the better of the two diagonals. */ + if ((xlim + ylim) - bxybest < fxybest - (xoff + yoff)) + { + part->xmid = fxbest; + part->ymid = fxybest - fxbest; + part->lo_minimal = 1; + part->hi_minimal = 0; + } + else + { + part->xmid = bxbest; + part->ymid = bxybest - bxbest; + part->lo_minimal = 0; + part->hi_minimal = 1; + } + return 2 * c - 1; + } } } @@ -241,17 +335,23 @@ diag (xoff, xlim, yoff, ylim, cost) The subsequence of file 0 is [XOFF, XLIM) and likewise for file 1. Note that XLIM, YLIM are exclusive bounds. - All line numbers are origin-0 and discarded lines are not counted. */ + All line numbers are origin-0 and discarded lines are not counted. + + If MINIMAL is nonzero, find a minimal difference no matter how + expensive it is. */ static void -compareseq (xoff, xlim, yoff, ylim) - int xoff, xlim, yoff, ylim; +compareseq (xoff, xlim, yoff, ylim, minimal) + int xoff, xlim, yoff, ylim, minimal; { + int * const xv = xvec; /* Help the compiler. */ + int * const yv = yvec; + /* Slide down the bottom initial diagonal. */ - while (xoff < xlim && yoff < ylim && xvec[xoff] == yvec[yoff]) + while (xoff < xlim && yoff < ylim && xv[xoff] == yv[yoff]) ++xoff, ++yoff; /* Slide up the top initial diagonal. */ - while (xlim > xoff && ylim > yoff && xvec[xlim - 1] == yvec[ylim - 1]) + while (xlim > xoff && ylim > yoff && xv[xlim - 1] == yv[ylim - 1]) --xlim, --ylim; /* Handle simple cases. */ @@ -263,13 +363,12 @@ compareseq (xoff, xlim, yoff, ylim) files[0].changed_flag[files[0].realindexes[xoff++]] = 1; else { - int c, d, f, b; + int c; + struct partition part; /* Find a point of correspondence in the middle of the files. */ - d = diag (xoff, xlim, yoff, ylim, &c); - f = fdiag[d]; - b = bdiag[d]; + c = diag (xoff, xlim, yoff, ylim, minimal, &part); if (c == 1) { @@ -281,21 +380,17 @@ compareseq (xoff, xlim, yoff, ylim) #if 0 /* The two subsequences differ by a single insert or delete; record it and we are done. */ - if (d < xoff - yoff) - files[1].changed_flag[files[1].realindexes[b - d - 1]] = 1; + if (part.xmid - part.ymid < xoff - yoff) + files[1].changed_flag[files[1].realindexes[part.ymid - 1]] = 1; else - files[0].changed_flag[files[0].realindexes[b]] = 1; + files[0].changed_flag[files[0].realindexes[part.xmid]] = 1; #endif } else { - /* Use that point to split this problem into two subproblems. */ - compareseq (xoff, b, yoff, b - d); - /* This used to use f instead of b, - but that is incorrect! - It is not necessarily the case that diagonal d - has a snake from b to f. */ - compareseq (b, xlim, b - d, ylim); + /* Use the partitions to split this problem into subproblems. */ + compareseq (xoff, part.xmid, yoff, part.ymid, part.lo_minimal); + compareseq (part.xmid, xlim, part.ymid, ylim, part.hi_minimal); } } } @@ -515,16 +610,15 @@ discard_confusing_lines (filevec) free (equiv_count[0]); } -/* Adjust inserts/deletes of blank lines to join changes +/* Adjust inserts/deletes of identical lines to join changes as much as possible. - We do something when a run of changed lines include a blank - line at one end and have an excluded blank line at the other. - We are free to choose which blank line is included. - `compareseq' always chooses the one at the beginning, - but usually it is cleaner to consider the following blank line - to be the "change". The only exception is if the preceding blank line - would join this change to other changes. */ + We do something when a run of changed lines include a + line at one end and have an excluded, identical line at the other. + We are free to choose which identical line is included. + `compareseq' usually chooses the one at the beginning, + but usually it is cleaner to consider the following identical line + to be the "change". */ int inhibit; @@ -540,16 +634,15 @@ shift_boundaries (filevec) for (f = 0; f < 2; f++) { char *changed = filevec[f].changed_flag; - char *other_changed = filevec[1-f].changed_flag; + char const *other_changed = filevec[1-f].changed_flag; + int const *equivs = filevec[f].equivs; int i = 0; int j = 0; int i_end = filevec[f].buffered_lines; - int preceding = -1; - int other_preceding = -1; while (1) { - int start, other_start; + int runlength, start, corresponding; /* Scan forwards to find beginning of another run of changes. Also keep track of the corresponding point in the other file. */ @@ -557,9 +650,7 @@ shift_boundaries (filevec) while (i < i_end && changed[i] == 0) { while (other_changed[j++]) - /* Non-corresponding lines in the other file - will count as the preceding batch of changes. */ - other_preceding = j; + continue; i++; } @@ -567,42 +658,67 @@ shift_boundaries (filevec) break; start = i; - other_start = j; - while (1) + /* Find the end of this run of changes. */ + + while (changed[++i]) + continue; + while (other_changed[j]) + j++; + + do { - /* Now find the end of this run of changes. */ + /* Record the length of this run of changes, so that + we can later determine whether the run has grown. */ + runlength = i - start; - while (changed[++i] != 0) - ; + /* Move the changed region back, so long as the + previous unchanged line matches the last changed one. + This merges with previous changed regions. */ + + while (start && equivs[start - 1] == equivs[i - 1]) + { + changed[--start] = 1; + changed[--i] = 0; + while (changed[start - 1]) + start--; + while (other_changed[--j]) + continue; + } - /* If the first changed line matches the following unchanged one, - and this run does not follow right after a previous run, - and there are no lines deleted from the other file here, - then classify the first changed line as unchanged - and the following line as changed in its place. */ + /* Set CORRESPONDING to the end of the changed run, at the last + point where it corresponds to a changed run in the other file. + CORRESPONDING == I_END means no such point has been found. */ + corresponding = other_changed[j - 1] ? i : i_end; - /* You might ask, how could this run follow right after another? - Only because the previous run was shifted here. */ + /* Move the changed region forward, so long as the + first changed line matches the following unchanged one. + This merges with following changed regions. + Do this second, so that if there are no merges, + the changed region is moved forward as far as possible. */ - if (i != i_end - && files[f].equivs[start] == files[f].equivs[i] - && !other_changed[j] - && !(start == preceding || other_start == other_preceding)) + while (i != i_end && equivs[start] == equivs[i]) { changed[start++] = 0; - changed[i] = 1; - /* Since one line-that-matches is now before this run - instead of after, we must advance in the other file - to keep in synch. */ - ++j; + changed[i++] = 1; + while (changed[i]) + i++; + while (other_changed[++j]) + corresponding = i; } - else - break; } + while (runlength != i - start); + + /* If possible, move the fully-merged run of changes + back to a corresponding run in the other file. */ - preceding = i; - other_preceding = j; + while (corresponding < i) + { + changed[--start] = 1; + changed[--i] = 0; + while (other_changed[--j]) + continue; + } } } } @@ -827,11 +943,19 @@ diff_2_files (filevec, depth) fdiag += filevec[1].nondiscarded_lines + 1; bdiag += filevec[1].nondiscarded_lines + 1; + /* Set TOO_EXPENSIVE to be approximate square root of input size, + bounded below by 256. */ + too_expensive = 1; + for (i = filevec[0].nondiscarded_lines + filevec[1].nondiscarded_lines; + i != 0; i >>= 2) + too_expensive <<= 1; + too_expensive = max (256, too_expensive); + files[0] = filevec[0]; files[1] = filevec[1]; compareseq (0, filevec[0].nondiscarded_lines, - 0, filevec[1].nondiscarded_lines); + 0, filevec[1].nondiscarded_lines, no_discards); free (fdiag - (filevec[1].nondiscarded_lines + 1)); diff --git a/gnu/usr.bin/diff/diff.c b/gnu/usr.bin/diff/diff.c index d5e7f8c09be..6541d99f6e9 100644 --- a/gnu/usr.bin/diff/diff.c +++ b/gnu/usr.bin/diff/diff.c @@ -18,7 +18,7 @@ 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: diff.c,v 1.5 1993/09/29 21:37:04 jtc Exp $"; +static char *rcsid = "$Id: diff.c,v 1.6 1993/11/12 02:25:55 jtc Exp $"; #endif /* GNU DIFF was written by Mike Haertel, David Hayes, @@ -46,7 +46,7 @@ static int specify_format PARAMS((char **, char *)); static void add_exclude PARAMS((char const *)); static void add_regexp PARAMS((struct regexp_list **, char const *)); static void specify_style PARAMS((enum output_style)); -static void usage PARAMS((void)); +static void usage PARAMS((char const *)); /* Nonzero for -r: if comparing two directories, compare their common subdirectories recursively. */ @@ -216,6 +216,7 @@ static struct option const longopts[] = {"unchanged-group-format", 1, 0, 138}, {"changed-group-format", 1, 0, 139}, {"horizon-lines", 1, 0, 140}, + {"help", 0, 0, 141}, {0, 0, 0, 0} }; @@ -454,8 +455,8 @@ main (argc, argv) break; case 'v': - fprintf (stderr, "GNU diff version %s\n", version_string); - break; + printf ("GNU diff version %s\n", version_string); + exit (0); case 'w': /* Ignore horizontal white space when comparing lines. */ @@ -531,14 +532,17 @@ main (argc, argv) fatal ("horizon must be a nonnegative integer"); break; + case 141: + usage (0); + default: - usage (); + usage (""); } prev = c; } if (optind != argc - 2) - usage (); + usage (optind < argc - 2 ? "extra operand" : "missing operand"); { @@ -626,33 +630,37 @@ add_regexp (reglist, pattern) } static void -usage () +usage (reason) + char const *reason; { - fprintf (stderr, "Usage: %s [options] from-file to-file\n", program); - fprintf (stderr, "Options:\n\ + if (reason && *reason) + fprintf (stderr, "%s: %s\n", program, reason); + fflush (stderr); + printf ("Usage: %s [options] from-file to-file\n", program); + printf ("Options:\n\ [-abBcdefhHilnNpPqrstTuvwy] [-C lines] [-D name] [-F regexp]\n\ [-I regexp] [-L from-label [-L to-label]] [-S starting-file] [-U lines]\n\ [-W columns] [-x pattern] [-X pattern-file]\n"); - fprintf (stderr, "\ + printf ("\ [--brief] [--changed-group-format=format] [--context[=lines]] [--ed]\n\ [--exclude=pattern] [--exclude-from=pattern-file] [--expand-tabs]\n\ - [--forward-ed] [--horizon-lines=lines] [--ifdef=name]\n\ + [--forward-ed] [--help] [--horizon-lines=lines] [--ifdef=name]\n\ [--ignore-all-space] [--ignore-blank-lines] [--ignore-case]\n"); - fprintf (stderr, "\ + printf ("\ [--ignore-matching-lines=regexp] [--ignore-space-change]\n\ [--initial-tab] [--label=from-label [--label=to-label]]\n\ [--left-column] [--minimal] [--new-file] [--new-group-format=format]\n\ [--new-line-format=format] [--old-group-format=format]\n"); - fprintf (stderr, "\ + printf ("\ [--old-line-format=format] [--paginate] [--rcs] [--recursive]\n\ [--report-identical-files] [--sdiff-merge-assist] [--show-c-function]\n\ [--show-function-line=regexp] [--side-by-side] [--speed-large-files]\n\ [--starting-file=starting-file] [--suppress-common-lines] [--text]\n"); - fprintf (stderr, "\ + printf ("\ [--unchanged-group-format=format] [--unchanged-line-format=format]\n\ [--unidirectional-new-file] [--unified[=lines]] [--version]\n\ [--width=columns]\n"); - exit (2); + exit (reason ? 2 : 0); } static int @@ -751,6 +759,8 @@ compare_files (dir0, name0, dir1, name1, depth) return 1; } + bzero (inf, sizeof (inf)); + /* Mark any nonexistent file with -1 in the desc field. */ /* Mark unopened files (e.g. directories) with -2. */ @@ -771,9 +781,6 @@ compare_files (dir0, name0, dir1, name1, depth) for (i = 0; i <= 1; i++) { - bzero (&inf[i].stat, sizeof (struct stat)); - inf[i].dir_p = 0; - if (inf[i].desc != -1) { int stat_result; diff --git a/gnu/usr.bin/diff/diff3.c b/gnu/usr.bin/diff/diff3.c index fe27ef2f1cb..5fabe0c3181 100644 --- a/gnu/usr.bin/diff/diff3.c +++ b/gnu/usr.bin/diff/diff3.c @@ -18,7 +18,7 @@ /* Written by Randy Smith */ #ifndef lint -static char *rcsid = "$Id: diff3.c,v 1.4 1993/09/29 21:37:07 jtc Exp $"; +static char *rcsid = "$Id: diff3.c,v 1.5 1993/11/12 02:25:59 jtc Exp $"; #endif #include "system.h" @@ -200,7 +200,7 @@ static void fatal PARAMS((char const *)); static void output_diff3 PARAMS((FILE *, struct diff3_block *, int const[3], int const[3])); static void perror_with_exit PARAMS((char const *)); static void undotlines PARAMS((FILE *, int, int, int)); -static void usage PARAMS((void)); +static void usage PARAMS((int)); static char const diff_program[] = DIFF_PROGRAM; @@ -216,6 +216,7 @@ static struct option const longopts[] = {"overlap-only", 0, 0, 'x'}, {"easy-only", 0, 0, '3'}, {"version", 0, 0, 'v'}, + {"help", 0, 0, 129}, {0, 0, 0, 0} }; @@ -284,8 +285,10 @@ main (argc, argv) tab_align_flag = 1; break; case 'v': - fprintf (stderr, "GNU diff3 version %s\n", version_string); - break; + printf ("GNU diff3 version %s\n", version_string); + exit (0); + case 129: + usage (0); case 'L': /* Handle up to three -L options. */ if (tag_count < 3) @@ -295,8 +298,7 @@ main (argc, argv) } /* Falls through */ default: - usage (); - /* NOTREACHED */ + usage (2); } } @@ -308,7 +310,7 @@ main (argc, argv) || finalwrite & merge /* -i -m would rewrite input file. */ || (tag_count && ! flagging) /* -L requires one of -AEX. */ || argc - optind != 3) - usage (); + usage (2); file = &argv[optind]; @@ -396,17 +398,19 @@ main (argc, argv) * Explain, patiently and kindly, how to use this program. Then exit. */ static void -usage () +usage (status) + int status; { - fprintf (stderr, "\ + fflush (stderr); + printf ("\ Usage: %s [options] my-file older-file your-file\n\ Options:\n\ [-exAEX3aTv] [-i|-m] [-L label1 [-L label2 [-L label3]]]\n\ - [--easy-only] [--ed] [--initial-tab]\n\ + [--easy-only] [--ed] [--help] [--initial-tab]\n\ [--label=label1 [--label=label2 [--label=label3]]] [--merge]\n\ [--overlap-only] [--show-all] [--show-overlap] [--text] [--version]\n\ Only one of [exAEX3] is allowed\n", argv0); - exit (2); + exit (status); } /* @@ -1094,12 +1098,12 @@ read_diff (filea, fileb, output_placement) char const *filea, *fileb; char **output_placement; { + char *diff_result; + size_t bytes, current_chunk_size, total; char const *argv[7]; char horizon_arg[256]; char const **ap; int fds[2]; - char *diff_result; - size_t bytes, current_chunk_size, total; pid_t pid; int wstatus; @@ -1147,7 +1151,15 @@ read_diff (filea, fileb, output_placement) current_chunk_size - total); total += bytes; if (total == current_chunk_size) - diff_result = xrealloc (diff_result, (current_chunk_size *= 2)); + { + if (current_chunk_size < 2 * current_chunk_size) + current_chunk_size = 2 * current_chunk_size; + else if (current_chunk_size < (size_t) -1) + current_chunk_size = (size_t) -1; + else + fatal ("files are too large to fit into memory"); + diff_result = xrealloc (diff_result, (current_chunk_size *= 2)); + } } while (bytes); if (total != 0 && diff_result[total-1] != '\n') @@ -1664,7 +1676,7 @@ xmalloc (size) { VOID *result = (VOID *) malloc (size ? size : 1); if (!result) - fatal ("virtual memory exhausted"); + fatal ("memory exhausted"); return result; } @@ -1675,7 +1687,7 @@ xrealloc (ptr, size) { VOID *result = (VOID *) realloc (ptr, size ? size : 1); if (!result) - fatal ("virtual memory exhausted"); + fatal ("memory exhausted"); return result; } diff --git a/gnu/usr.bin/diff/io.c b/gnu/usr.bin/diff/io.c index b40623dad0a..956f6efb837 100644 --- a/gnu/usr.bin/diff/io.c +++ b/gnu/usr.bin/diff/io.c @@ -18,7 +18,7 @@ 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.4 1993/09/16 17:39:17 jtc Exp $"; +static char *rcsid = "$Id: io.c,v 1.5 1993/11/12 02:26:03 jtc Exp $"; #endif #include "diff.h" @@ -35,7 +35,7 @@ static char *rcsid = "$Id: io.c,v 1.4 1993/09/16 17:39:17 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 long word; +typedef int word; /* Lines are put into equivalence classes (of lines that match in line_cmp). Each equivalence class is represented by one of these structures, @@ -90,38 +90,27 @@ sip (current, skip_test) if (current->desc < 0) { /* Leave room for a sentinel. */ - current->buffer = xmalloc (sizeof (word)); current->bufsize = sizeof (word); - current->buffered_chars = 0; + current->buffer = xmalloc (current->bufsize); } else { - current->bufsize = current->buffered_chars - = STAT_BLOCKSIZE (current->stat); - - if (S_ISREG (current->stat.st_mode)) - /* Get the size out of the stat block. - Allocate enough room for appended newline and sentinel. - Allocate at least one block, to prevent overrunning the buffer - when comparing growing binary files. */ - current->bufsize = max (current->bufsize, - current->stat.st_size + sizeof (word) + 1); - + current->bufsize = STAT_BLOCKSIZE (current->stat); current->buffer = xmalloc (current->bufsize); - if (skip_test) - current->buffered_chars = 0; - else + + 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->buffered_chars); + current->bufsize); if (current->buffered_chars == -1) pfatal_with_name (current->name); return binary_file_p (current->buffer, current->buffered_chars); } } + current->buffered_chars = 0; return 0; } @@ -139,12 +128,21 @@ slurp (current) else if (S_ISREG (current->stat.st_mode)) { /* It's a regular file; slurp in the rest all at once. */ - cc = current->stat.st_size - current->buffered_chars; - if (cc) + + /* Get the size out of the stat block. + Allocate enough room for appended newline and sentinel. */ + cc = current->stat.st_size + 1 + sizeof (word); + if (current->bufsize < cc) + { + current->bufsize = cc; + current->buffer = xrealloc (current->buffer, cc); + } + + if (current->buffered_chars < current->stat.st_size) { cc = read (current->desc, current->buffer + current->buffered_chars, - cc); + current->stat.st_size - current->buffered_chars); if (cc == -1) pfatal_with_name (current->name); current->buffered_chars += cc; @@ -170,7 +168,7 @@ slurp (current) current->buffered_chars += cc; } /* Allocate just enough room for appended newline and sentinel. */ - current->bufsize = current->buffered_chars + sizeof (word) + 1; + current->bufsize = current->buffered_chars + 1 + sizeof (word); current->buffer = xrealloc (current->buffer, current->bufsize); } } @@ -598,6 +596,7 @@ static int const primes[] = 8191, 16381, 32749, +#if 32767 < INT_MAX 65521, 131071, 262139, @@ -614,6 +613,7 @@ static int const primes[] = 536870909, 1073741789, 2147483647, +#endif 0 }; diff --git a/gnu/usr.bin/diff/regex.c b/gnu/usr.bin/diff/regex.c index dcb51475f82..2c1afe8184f 100644 --- a/gnu/usr.bin/diff/regex.c +++ b/gnu/usr.bin/diff/regex.c @@ -25,11 +25,22 @@ #endif #ifndef lint -static char *rcsid = "$Id: regex.c,v 1.4 1993/09/16 17:39:21 jtc Exp $"; +static char *rcsid = "$Id: regex.c,v 1.5 1993/11/12 02:26:10 jtc Exp $"; #endif #define _GNU_SOURCE +#ifdef HAVE_CONFIG_H +#if defined (CONFIG_BROKETS) +/* We use <config.h> instead of "config.h" so that a compilation + using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h + (which it would do because it found this file in $srcdir). */ +#include <config.h> +#else +#include "config.h" +#endif +#endif + /* We need this for `regex.h', and perhaps for the Emacs include files. */ #include <sys/types.h> @@ -923,7 +934,7 @@ static const char *re_error_msg[] = change it ourselves. */ int re_max_failures = 2000; -typedef const unsigned char *fail_stack_elt_t; +typedef unsigned char *fail_stack_elt_t; typedef struct { @@ -2726,7 +2737,7 @@ re_compile_fastmap (bufp) register char *fastmap = bufp->fastmap; unsigned char *pattern = bufp->buffer; unsigned long size = bufp->used; - const unsigned char *p = pattern; + unsigned char *p = pattern; register unsigned char *pend = pattern + size; /* Assume that each path through the pattern can be null until @@ -3181,8 +3192,10 @@ static boolean alt_match_null_string_p (), /* This converts PTR, a pointer into one of the search strings `string1' and `string2' into an offset from the beginning of that string. */ -#define POINTER_TO_OFFSET(ptr) \ - (FIRST_STRING_P (ptr) ? (ptr) - string1 : (ptr) - string2 + size1) +#define POINTER_TO_OFFSET(ptr) \ + (FIRST_STRING_P (ptr) \ + ? ((regoff_t) ((ptr) - string1)) \ + : ((regoff_t) ((ptr) - string2 + size1))) /* Macros for dealing with the split strings in re_match_2. */ @@ -3621,8 +3634,9 @@ re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) if (regs->num_regs > 0) { regs->start[0] = pos; - regs->end[0] = (MATCHING_IN_FIRST_STRING ? d - string1 - : d - string2 + size1); + regs->end[0] = (MATCHING_IN_FIRST_STRING + ? ((regoff_t) (d - string1)) + : ((regoff_t) (d - string2 + size1))); } /* Go through the first `min (num_regs, regs->num_regs)' @@ -3633,8 +3647,10 @@ re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) regs->start[mcnt] = regs->end[mcnt] = -1; else { - regs->start[mcnt] = POINTER_TO_OFFSET (regstart[mcnt]); - regs->end[mcnt] = POINTER_TO_OFFSET (regend[mcnt]); + regs->start[mcnt] + = (regoff_t) POINTER_TO_OFFSET (regstart[mcnt]); + regs->end[mcnt] + = (regoff_t) POINTER_TO_OFFSET (regend[mcnt]); } } diff --git a/gnu/usr.bin/diff/sdiff.c b/gnu/usr.bin/diff/sdiff.c index 70188a0d99b..fbb9b92eac5 100644 --- a/gnu/usr.bin/diff/sdiff.c +++ b/gnu/usr.bin/diff/sdiff.c @@ -18,7 +18,7 @@ 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: sdiff.c,v 1.4 1993/09/29 21:37:12 jtc Exp $"; +static char *rcsid = "$Id: sdiff.c,v 1.5 1993/11/12 02:26:21 jtc Exp $"; #endif /* GNU SDIFF was written by Thomas Lord. */ @@ -81,7 +81,7 @@ static void lf_skip PARAMS((struct line_filter *, int)); static void perror_fatal PARAMS((char const *)); static void trapsigs PARAMS((void)); static void untrapsig PARAMS((int)); -static void usage PARAMS((void)); +static void usage PARAMS((int)); /* this lossage until the gnu libc conquers the universe */ #define PVT_tmpdir "/tmp" @@ -113,22 +113,24 @@ static struct option const longopts[] = {"expand-tabs", 0, 0, 't'}, {"width", 1, 0, 'w'}, {"version", 0, 0, 'v'}, + {"help", 0, 0, 129}, {0, 0, 0, 0} }; /* prints usage message and quits */ static void -usage () +usage (status) + int status; { - fprintf (stderr, "Usage: %s [options] from-file to-file\n", prog); - fprintf (stderr, "Options:\n\ - [-abBdHilstv] [-I regexp] [-o outfile] [-w columns]\n\ - [--text] [--minimal] [--speed-large-files] [--expand-tabs]\n\ - [--ignore-case] [--ignore-matching-lines=regexp]\n\ - [--ignore-space-change] [--ignore-blank-lines] [--ignore-all-space]\n\ - [--suppress-common-lines] [--left-column] [--output=outfile]\n\ - [--version] [--width=columns]\n"); - exit (2); + printf ("Usage: %s [options] from-file to-file\n", prog); + printf ("Options:\n\ + [-abBdHilstv] [-I regexp] [-o outfile] [-w columns]\n\ + [--expand-tabs] [--help] [--ignore-all-space] [--ignore-blank-lines]\n\ + [--ignore-case] [--ignore-matching-lines=regexp]\n\ + [--ignore-space-change] [--left-column] [--minimal]\n\ + [--output=outfile] [--speed-large-files] [--suppress-common-lines]\n\ + [--text] [--version] [--width=columns]\n"); + exit (status); } static void @@ -177,7 +179,7 @@ xmalloc (size) { VOID *r = (VOID *) malloc (size); if (!r) - fatal ("virtual memory exhausted"); + fatal ("memory exhausted"); return r; } @@ -432,7 +434,6 @@ main (argc, argv) char *argv[]; { int opt; - int version_requested = 0; char *editor = getenv ("EDITOR"); char *differ = getenv ("DIFF"); @@ -496,10 +497,8 @@ main (argc, argv) break; case 'v': - version_requested = 1; - fprintf (stderr, "GNU sdiff version %s\n", version_string); - ck_fflush (stderr); - break; + printf ("GNU sdiff version %s\n", version_string); + exit (0); case 'w': diffarg ("-W"); @@ -510,17 +509,16 @@ main (argc, argv) diffarg ("-w"); break; + case 129: + usage (0); + default: - usage (); + usage (2); } } - /* check: did user just want version message? if so exit. */ - if (version_requested && argc - optind == 0) - exit (0); - if (argc - optind != 2) - usage (); + usage (2); if (! out_file) /* easy case: diff does everything for us */ diff --git a/gnu/usr.bin/diff/util.c b/gnu/usr.bin/diff/util.c index b2fa48d693a..fb4c3c9a596 100644 --- a/gnu/usr.bin/diff/util.c +++ b/gnu/usr.bin/diff/util.c @@ -18,7 +18,7 @@ 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: util.c,v 1.4 1993/09/16 17:39:31 jtc Exp $"; +static char *rcsid = "$Id: util.c,v 1.5 1993/11/12 02:26:25 jtc Exp $"; #endif #include "diff.h" @@ -676,7 +676,7 @@ xmalloc (size) value = (VOID *) malloc (size); if (!value) - fatal ("virtual memory exhausted"); + fatal ("memory exhausted"); return value; } @@ -695,7 +695,7 @@ xrealloc (old, size) value = (VOID *) realloc (old, size); if (!value) - fatal ("virtual memory exhausted"); + fatal ("memory exhausted"); return value; } diff --git a/gnu/usr.bin/diff/version.c b/gnu/usr.bin/diff/version.c index b10e240d4f7..38247a404cc 100644 --- a/gnu/usr.bin/diff/version.c +++ b/gnu/usr.bin/diff/version.c @@ -1,7 +1,7 @@ /* Version number of GNU diff. - * $Id: version.c,v 1.6 1993/09/29 21:37:15 jtc Exp $ + * $Id: version.c,v 1.7 1993/11/12 02:26:27 jtc Exp $ */ #include "config.h" -char const version_string[] = "2.5"; +char const version_string[] = "2.6"; |
