386BSD 0.1 development
[unix-history] / usr / src / usr.bin / diff / ed.c
CommitLineData
3c369cdd
WJ
1/* Output routines for ed-script format.
2 Copyright (C) 1988, 1989 Free Software Foundation, Inc.
3
4This file is part of GNU DIFF.
5
6GNU DIFF is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 1, or (at your option)
9any later version.
10
11GNU DIFF is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU DIFF; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20#include "diff.h"
21
22static void print_rcs_hunk ();
23static void print_ed_hunk ();
24static void pr_forward_ed_hunk ();
25void translate_range ();
26struct change *find_change ();
27struct change *find_reverse_change ();
28\f
29/* Print our script as ed commands. */
30
31void
32print_ed_script (script)
33 struct change *script;
34{
35 print_script (script, find_reverse_change, print_ed_hunk);
36}
37
38/* Print a hunk of an ed diff */
39
40static void
41print_ed_hunk (hunk)
42 struct change *hunk;
43{
44 int f0, l0, f1, l1;
45 int deletes, inserts;
46
47#if 0
48 hunk = flip_script (hunk);
49#endif
50#ifdef DEBUG
51 debug_script (hunk);
52#endif
53
54 /* Determine range of line numbers involved in each file. */
55 analyze_hunk (hunk, &f0, &l0, &f1, &l1, &deletes, &inserts);
56 if (!deletes && !inserts)
57 return;
58
59 /* Print out the line number header for this hunk */
60 print_number_range (',', &files[0], f0, l0);
61 fprintf (outfile, "%c\n", change_letter (inserts, deletes));
62
63 /* Print new/changed lines from second file, if needed */
64 if (inserts)
65 {
66 int i;
67 int inserting = 1;
68 for (i = f1; i <= l1; i++)
69 {
70 /* Resume the insert, if we stopped. */
71 if (! inserting)
72 fprintf (outfile, "%da\n",
73 i - f1 + translate_line_number (&files[0], f0) - 1);
74 inserting = 1;
75
76 /* If the file's line is just a dot, it would confuse `ed'.
77 So output it with a double dot, and set the flag LEADING_DOT
78 so that we will output another ed-command later
79 to change the double dot into a single dot. */
80
81 if (files[1].linbuf[i].text[0] == '.'
82 && files[1].linbuf[i].text[1] == '\n')
83 {
84 fprintf (outfile, "..\n");
85 fprintf (outfile, ".\n");
86 /* Now change that double dot to the desired single dot. */
87 fprintf (outfile, "%ds/^\\.\\././\n",
88 i - f1 + translate_line_number (&files[0], f0));
89 inserting = 0;
90 }
91 else
92 /* Line is not `.', so output it unmodified. */
93 print_1_line ("", &files[1].linbuf[i]);
94 }
95
96 /* End insert mode, if we are still in it. */
97 if (inserting)
98 fprintf (outfile, ".\n");
99 }
100}
101\f
102/* Print change script in the style of ed commands,
103 but print the changes in the order they appear in the input files,
104 which means that the commands are not truly useful with ed. */
105
106void
107pr_forward_ed_script (script)
108 struct change *script;
109{
110 print_script (script, find_change, pr_forward_ed_hunk);
111}
112
113static void
114pr_forward_ed_hunk (hunk)
115 struct change *hunk;
116{
117 int i;
118 int f0, l0, f1, l1;
119 int deletes, inserts;
120
121 /* Determine range of line numbers involved in each file. */
122 analyze_hunk (hunk, &f0, &l0, &f1, &l1, &deletes, &inserts);
123 if (!deletes && !inserts)
124 return;
125
126 fprintf (outfile, "%c", change_letter (inserts, deletes));
127 print_number_range (' ', files, f0, l0);
128 fprintf (outfile, "\n");
129
130 /* If deletion only, print just the number range. */
131
132 if (!inserts)
133 return;
134
135 /* For insertion (with or without deletion), print the number range
136 and the lines from file 2. */
137
138 for (i = f1; i <= l1; i++)
139 print_1_line ("", &files[1].linbuf[i]);
140
141 fprintf (outfile, ".\n");
142}
143\f
144/* Print in a format somewhat like ed commands
145 except that each insert command states the number of lines it inserts.
146 This format is used for RCS. */
147
148void
149print_rcs_script (script)
150 struct change *script;
151{
152 print_script (script, find_change, print_rcs_hunk);
153}
154
155/* Print a hunk of an RCS diff */
156
157static void
158print_rcs_hunk (hunk)
159 struct change *hunk;
160{
161 int i;
162 int f0, l0, f1, l1;
163 int deletes, inserts;
164 int tf0, tl0, tf1, tl1;
165
166 /* Determine range of line numbers involved in each file. */
167 analyze_hunk (hunk, &f0, &l0, &f1, &l1, &deletes, &inserts);
168 if (!deletes && !inserts)
169 return;
170
171 translate_range (&files[0], f0, l0, &tf0, &tl0);
172
173 if (deletes)
174 {
175 fprintf (outfile, "d");
176 /* For deletion, print just the starting line number from file 0
177 and the number of lines deleted. */
178 fprintf (outfile, "%d %d\n",
179 tf0,
180 (tl0 >= tf0 ? tl0 - tf0 + 1 : 1));
181 }
182
183 if (inserts)
184 {
185 fprintf (outfile, "a");
186
187 /* Take last-line-number from file 0 and # lines from file 1. */
188 translate_range (&files[1], f1, l1, &tf1, &tl1);
189 fprintf (outfile, "%d %d\n",
190 tl0,
191 (tl1 >= tf1 ? tl1 - tf1 + 1 : 1));
192
193 /* Print the inserted lines. */
194 for (i = f1; i <= l1; i++)
195 print_1_line ("", &files[1].linbuf[i]);
196 }
197}