Martin Natano wrote: > When diff encounters a line that consists of a single dot, it emits two > dots instead, stops the current command and emits a substitute command > to replace the double dot with a single one. Then it restarts the > (original) command if necessary and inserts further lines. This is done > because a single dot on a line does have special meaning in ed. (It > stops text insertion.) > > However, there are multiple issues with the current implementation, > resulting in mangled output: > > - The line number for the substitute command should be the number of the > most recently inserted line. diff instead uses the number of the first > inserted line of the current hunk. The first character of that line is > removed when applying the diff, while the superfluous dot is not. > > - The line number of the restarted command is not adjusted for the > number of lines already inserted, resulting in the reordering of lines.. > > - When there is a bare dot in the replacement text of a change command, > too many lines are deleted, because a second change command is emitted. > An append command should be emitted instead, because the target lines > have already been removed by the first change command. > > The following patch fixes all those issues.
Hmm, something still does not seem right. For example, try diff -e on the contents below (some other tests attached): A B C vs. W X . Y Z > Index: diffreg.c > =================================================================== > RCS file: /cvs/src/usr.bin/diff/diffreg.c,v > retrieving revision 1.90 > diff -u -p -r1.90 diffreg.c > --- diffreg.c 26 Oct 2015 12:52:27 -0000 1.90 > +++ diffreg.c 13 Feb 2016 16:35:08 -0000 > @@ -1075,8 +1075,12 @@ proceed: > * back and restart where we left off. > */ > diff_output(".\n"); > - diff_output("%ds/.//\n", a); > + diff_output("%ds/.//\n", a + i - 1); This I understand. We really need to substitute the line that contains the .. About the changes below, is something like this the idea behind it? The first change command has already removed lines [a,b] and replaced them with lines [c, c + i]. So for the rest of the lines in [c + i + 1, d], we need to make sure that they are appended after the line that follows the inserted '.' Can't we set b = a + i - 1 and a = b + 1 to make sure that the rest of the 'to' file is appended after the proper line? > a += i; > + if (a > b) > + b += i; > + else > + b = a - 1; > c += i; > goto restart; > }
W X . Y Z
A
W X . Y Z
A B C
W X . Y Z
A B C
W X . Y Z .