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