1*eec8fc77Schristos /* $NetBSD: ed.c,v 1.1.1.1 2016/01/13 03:15:30 christos Exp $ */
2*eec8fc77Schristos
3*eec8fc77Schristos /* Output routines for ed-script format.
4*eec8fc77Schristos
5*eec8fc77Schristos Copyright (C) 1988, 1989, 1991, 1992, 1993, 1995, 1998, 2001 Free
6*eec8fc77Schristos Software Foundation, Inc.
7*eec8fc77Schristos
8*eec8fc77Schristos This file is part of GNU DIFF.
9*eec8fc77Schristos
10*eec8fc77Schristos GNU DIFF is free software; you can redistribute it and/or modify
11*eec8fc77Schristos it under the terms of the GNU General Public License as published by
12*eec8fc77Schristos the Free Software Foundation; either version 2, or (at your option)
13*eec8fc77Schristos any later version.
14*eec8fc77Schristos
15*eec8fc77Schristos GNU DIFF is distributed in the hope that it will be useful,
16*eec8fc77Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of
17*eec8fc77Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18*eec8fc77Schristos GNU General Public License for more details.
19*eec8fc77Schristos
20*eec8fc77Schristos You should have received a copy of the GNU General Public License
21*eec8fc77Schristos along with this program; see the file COPYING.
22*eec8fc77Schristos If not, write to the Free Software Foundation,
23*eec8fc77Schristos 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
24*eec8fc77Schristos
25*eec8fc77Schristos #include "diff.h"
26*eec8fc77Schristos
27*eec8fc77Schristos static void print_ed_hunk (struct change *);
28*eec8fc77Schristos static void print_rcs_hunk (struct change *);
29*eec8fc77Schristos static void pr_forward_ed_hunk (struct change *);
30*eec8fc77Schristos
31*eec8fc77Schristos /* Print our script as ed commands. */
32*eec8fc77Schristos
33*eec8fc77Schristos void
print_ed_script(struct change * script)34*eec8fc77Schristos print_ed_script (struct change *script)
35*eec8fc77Schristos {
36*eec8fc77Schristos print_script (script, find_reverse_change, print_ed_hunk);
37*eec8fc77Schristos }
38*eec8fc77Schristos
39*eec8fc77Schristos /* Print a hunk of an ed diff */
40*eec8fc77Schristos
41*eec8fc77Schristos static void
print_ed_hunk(struct change * hunk)42*eec8fc77Schristos print_ed_hunk (struct change *hunk)
43*eec8fc77Schristos {
44*eec8fc77Schristos lin f0, l0, f1, l1;
45*eec8fc77Schristos enum changes changes;
46*eec8fc77Schristos
47*eec8fc77Schristos #ifdef DEBUG
48*eec8fc77Schristos debug_script (hunk);
49*eec8fc77Schristos #endif
50*eec8fc77Schristos
51*eec8fc77Schristos /* Determine range of line numbers involved in each file. */
52*eec8fc77Schristos changes = analyze_hunk (hunk, &f0, &l0, &f1, &l1);
53*eec8fc77Schristos if (!changes)
54*eec8fc77Schristos return;
55*eec8fc77Schristos
56*eec8fc77Schristos begin_output ();
57*eec8fc77Schristos
58*eec8fc77Schristos /* Print out the line number header for this hunk */
59*eec8fc77Schristos print_number_range (',', &files[0], f0, l0);
60*eec8fc77Schristos fprintf (outfile, "%c\n", change_letter[changes]);
61*eec8fc77Schristos
62*eec8fc77Schristos /* Print new/changed lines from second file, if needed */
63*eec8fc77Schristos if (changes != OLD)
64*eec8fc77Schristos {
65*eec8fc77Schristos lin i;
66*eec8fc77Schristos for (i = f1; i <= l1; i++)
67*eec8fc77Schristos {
68*eec8fc77Schristos if (files[1].linbuf[i][0] == '.' && files[1].linbuf[i][1] == '\n')
69*eec8fc77Schristos {
70*eec8fc77Schristos /* The file's line is just a dot, and it would exit
71*eec8fc77Schristos insert mode. Precede the dot with another dot, exit
72*eec8fc77Schristos insert mode, remove the extra dot, and then resume
73*eec8fc77Schristos insert mode. */
74*eec8fc77Schristos fprintf (outfile, "..\n.\ns/.//\na\n");
75*eec8fc77Schristos }
76*eec8fc77Schristos else
77*eec8fc77Schristos print_1_line ("", &files[1].linbuf[i]);
78*eec8fc77Schristos }
79*eec8fc77Schristos
80*eec8fc77Schristos fprintf (outfile, ".\n");
81*eec8fc77Schristos }
82*eec8fc77Schristos }
83*eec8fc77Schristos
84*eec8fc77Schristos /* Print change script in the style of ed commands,
85*eec8fc77Schristos but print the changes in the order they appear in the input files,
86*eec8fc77Schristos which means that the commands are not truly useful with ed. */
87*eec8fc77Schristos
88*eec8fc77Schristos void
pr_forward_ed_script(struct change * script)89*eec8fc77Schristos pr_forward_ed_script (struct change *script)
90*eec8fc77Schristos {
91*eec8fc77Schristos print_script (script, find_change, pr_forward_ed_hunk);
92*eec8fc77Schristos }
93*eec8fc77Schristos
94*eec8fc77Schristos static void
pr_forward_ed_hunk(struct change * hunk)95*eec8fc77Schristos pr_forward_ed_hunk (struct change *hunk)
96*eec8fc77Schristos {
97*eec8fc77Schristos lin i, f0, l0, f1, l1;
98*eec8fc77Schristos
99*eec8fc77Schristos /* Determine range of line numbers involved in each file. */
100*eec8fc77Schristos enum changes changes = analyze_hunk (hunk, &f0, &l0, &f1, &l1);
101*eec8fc77Schristos if (!changes)
102*eec8fc77Schristos return;
103*eec8fc77Schristos
104*eec8fc77Schristos begin_output ();
105*eec8fc77Schristos
106*eec8fc77Schristos fprintf (outfile, "%c", change_letter[changes]);
107*eec8fc77Schristos print_number_range (' ', files, f0, l0);
108*eec8fc77Schristos fprintf (outfile, "\n");
109*eec8fc77Schristos
110*eec8fc77Schristos /* If deletion only, print just the number range. */
111*eec8fc77Schristos
112*eec8fc77Schristos if (changes == OLD)
113*eec8fc77Schristos return;
114*eec8fc77Schristos
115*eec8fc77Schristos /* For insertion (with or without deletion), print the number range
116*eec8fc77Schristos and the lines from file 2. */
117*eec8fc77Schristos
118*eec8fc77Schristos for (i = f1; i <= l1; i++)
119*eec8fc77Schristos print_1_line ("", &files[1].linbuf[i]);
120*eec8fc77Schristos
121*eec8fc77Schristos fprintf (outfile, ".\n");
122*eec8fc77Schristos }
123*eec8fc77Schristos
124*eec8fc77Schristos /* Print in a format somewhat like ed commands
125*eec8fc77Schristos except that each insert command states the number of lines it inserts.
126*eec8fc77Schristos This format is used for RCS. */
127*eec8fc77Schristos
128*eec8fc77Schristos void
print_rcs_script(struct change * script)129*eec8fc77Schristos print_rcs_script (struct change *script)
130*eec8fc77Schristos {
131*eec8fc77Schristos print_script (script, find_change, print_rcs_hunk);
132*eec8fc77Schristos }
133*eec8fc77Schristos
134*eec8fc77Schristos /* Print a hunk of an RCS diff */
135*eec8fc77Schristos
136*eec8fc77Schristos static void
print_rcs_hunk(struct change * hunk)137*eec8fc77Schristos print_rcs_hunk (struct change *hunk)
138*eec8fc77Schristos {
139*eec8fc77Schristos lin i, f0, l0, f1, l1;
140*eec8fc77Schristos long tf0, tl0, tf1, tl1;
141*eec8fc77Schristos
142*eec8fc77Schristos /* Determine range of line numbers involved in each file. */
143*eec8fc77Schristos enum changes changes = analyze_hunk (hunk, &f0, &l0, &f1, &l1);
144*eec8fc77Schristos if (!changes)
145*eec8fc77Schristos return;
146*eec8fc77Schristos
147*eec8fc77Schristos begin_output ();
148*eec8fc77Schristos
149*eec8fc77Schristos translate_range (&files[0], f0, l0, &tf0, &tl0);
150*eec8fc77Schristos
151*eec8fc77Schristos if (changes & OLD)
152*eec8fc77Schristos {
153*eec8fc77Schristos fprintf (outfile, "d");
154*eec8fc77Schristos /* For deletion, print just the starting line number from file 0
155*eec8fc77Schristos and the number of lines deleted. */
156*eec8fc77Schristos fprintf (outfile, "%ld %ld\n", tf0, tf0 <= tl0 ? tl0 - tf0 + 1 : 1);
157*eec8fc77Schristos }
158*eec8fc77Schristos
159*eec8fc77Schristos if (changes & NEW)
160*eec8fc77Schristos {
161*eec8fc77Schristos fprintf (outfile, "a");
162*eec8fc77Schristos
163*eec8fc77Schristos /* Take last-line-number from file 0 and # lines from file 1. */
164*eec8fc77Schristos translate_range (&files[1], f1, l1, &tf1, &tl1);
165*eec8fc77Schristos fprintf (outfile, "%ld %ld\n", tl0, tf1 <= tl1 ? tl1 - tf1 + 1 : 1);
166*eec8fc77Schristos
167*eec8fc77Schristos /* Print the inserted lines. */
168*eec8fc77Schristos for (i = f1; i <= l1; i++)
169*eec8fc77Schristos print_1_line ("", &files[1].linbuf[i]);
170*eec8fc77Schristos }
171*eec8fc77Schristos }
172