xref: /netbsd/external/gpl2/diffutils/dist/src/ed.c (revision eec8fc77)
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