1170754Sdelphij/* Output routines for ed-script format.
2170754Sdelphij
3170754Sdelphij   Copyright (C) 1988, 1989, 1991, 1992, 1993, 1995, 1998, 2001, 2004
4170754Sdelphij   Free Software Foundation, Inc.
5170754Sdelphij
6170754Sdelphij   This file is part of GNU DIFF.
7170754Sdelphij
8170754Sdelphij   GNU DIFF is free software; you can redistribute it and/or modify
9170754Sdelphij   it under the terms of the GNU General Public License as published by
10170754Sdelphij   the Free Software Foundation; either version 2, or (at your option)
11170754Sdelphij   any later version.
12170754Sdelphij
13170754Sdelphij   GNU DIFF is distributed in the hope that it will be useful,
14170754Sdelphij   but WITHOUT ANY WARRANTY; without even the implied warranty of
15170754Sdelphij   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16170754Sdelphij   GNU General Public License for more details.
17170754Sdelphij
18170754Sdelphij   You should have received a copy of the GNU General Public License
19170754Sdelphij   along with this program; see the file COPYING.
20170754Sdelphij   If not, write to the Free Software Foundation,
21170754Sdelphij   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
22170754Sdelphij
23170754Sdelphij#include "diff.h"
24170754Sdelphij
25170754Sdelphijstatic void print_ed_hunk (struct change *);
26170754Sdelphijstatic void print_rcs_hunk (struct change *);
27170754Sdelphijstatic void pr_forward_ed_hunk (struct change *);
28170754Sdelphij
29170754Sdelphij/* Print our script as ed commands.  */
30170754Sdelphij
31170754Sdelphijvoid
32170754Sdelphijprint_ed_script (struct change *script)
33170754Sdelphij{
34170754Sdelphij  print_script (script, find_reverse_change, print_ed_hunk);
35170754Sdelphij}
36170754Sdelphij
37170754Sdelphij/* Print a hunk of an ed diff */
38170754Sdelphij
39170754Sdelphijstatic void
40170754Sdelphijprint_ed_hunk (struct change *hunk)
41170754Sdelphij{
42170754Sdelphij  lin f0, l0, f1, l1;
43170754Sdelphij  enum changes changes;
44170754Sdelphij
45170754Sdelphij#ifdef DEBUG
46170754Sdelphij  debug_script (hunk);
47170754Sdelphij#endif
48170754Sdelphij
49170754Sdelphij  /* Determine range of line numbers involved in each file.  */
50170754Sdelphij  changes = analyze_hunk (hunk, &f0, &l0, &f1, &l1);
51170754Sdelphij  if (!changes)
52170754Sdelphij    return;
53170754Sdelphij
54170754Sdelphij  begin_output ();
55170754Sdelphij
56170754Sdelphij  /* Print out the line number header for this hunk */
57170754Sdelphij  print_number_range (',', &files[0], f0, l0);
58170754Sdelphij  fprintf (outfile, "%c\n", change_letter[changes]);
59170754Sdelphij
60170754Sdelphij  /* Print new/changed lines from second file, if needed */
61170754Sdelphij  if (changes != OLD)
62170754Sdelphij    {
63170754Sdelphij      lin i;
64170754Sdelphij      for (i = f1; i <= l1; i++)
65170754Sdelphij	{
66170754Sdelphij	  if (files[1].linbuf[i][0] == '.' && files[1].linbuf[i][1] == '\n')
67170754Sdelphij	    {
68170754Sdelphij	      /* The file's line is just a dot, and it would exit
69170754Sdelphij		 insert mode.  Precede the dot with another dot, exit
70170754Sdelphij		 insert mode, remove the extra dot, and then resume
71170754Sdelphij		 insert mode.  */
72170754Sdelphij	      fprintf (outfile, "..\n.\ns/.//\na\n");
73170754Sdelphij	    }
74170754Sdelphij	  else
75170754Sdelphij	    print_1_line ("", &files[1].linbuf[i]);
76170754Sdelphij	}
77170754Sdelphij
78170754Sdelphij      fprintf (outfile, ".\n");
79170754Sdelphij    }
80170754Sdelphij}
81170754Sdelphij
82170754Sdelphij/* Print change script in the style of ed commands,
83170754Sdelphij   but print the changes in the order they appear in the input files,
84170754Sdelphij   which means that the commands are not truly useful with ed.  */
85170754Sdelphij
86170754Sdelphijvoid
87170754Sdelphijpr_forward_ed_script (struct change *script)
88170754Sdelphij{
89170754Sdelphij  print_script (script, find_change, pr_forward_ed_hunk);
90170754Sdelphij}
91170754Sdelphij
92170754Sdelphijstatic void
93170754Sdelphijpr_forward_ed_hunk (struct change *hunk)
94170754Sdelphij{
95170754Sdelphij  lin i, f0, l0, f1, l1;
96170754Sdelphij
97170754Sdelphij  /* Determine range of line numbers involved in each file.  */
98170754Sdelphij  enum changes changes = analyze_hunk (hunk, &f0, &l0, &f1, &l1);
99170754Sdelphij  if (!changes)
100170754Sdelphij    return;
101170754Sdelphij
102170754Sdelphij  begin_output ();
103170754Sdelphij
104170754Sdelphij  fprintf (outfile, "%c", change_letter[changes]);
105170754Sdelphij  print_number_range (' ', files, f0, l0);
106170754Sdelphij  fprintf (outfile, "\n");
107170754Sdelphij
108170754Sdelphij  /* If deletion only, print just the number range.  */
109170754Sdelphij
110170754Sdelphij  if (changes == OLD)
111170754Sdelphij    return;
112170754Sdelphij
113170754Sdelphij  /* For insertion (with or without deletion), print the number range
114170754Sdelphij     and the lines from file 2.  */
115170754Sdelphij
116170754Sdelphij  for (i = f1; i <= l1; i++)
117170754Sdelphij    print_1_line ("", &files[1].linbuf[i]);
118170754Sdelphij
119170754Sdelphij  fprintf (outfile, ".\n");
120170754Sdelphij}
121170754Sdelphij
122170754Sdelphij/* Print in a format somewhat like ed commands
123170754Sdelphij   except that each insert command states the number of lines it inserts.
124170754Sdelphij   This format is used for RCS.  */
125170754Sdelphij
126170754Sdelphijvoid
127170754Sdelphijprint_rcs_script (struct change *script)
128170754Sdelphij{
129170754Sdelphij  print_script (script, find_change, print_rcs_hunk);
130170754Sdelphij}
131170754Sdelphij
132170754Sdelphij/* Print a hunk of an RCS diff */
133170754Sdelphij
134170754Sdelphijstatic void
135170754Sdelphijprint_rcs_hunk (struct change *hunk)
136170754Sdelphij{
137170754Sdelphij  lin i, f0, l0, f1, l1;
138170754Sdelphij  long int tf0, tl0, tf1, tl1;
139170754Sdelphij
140170754Sdelphij  /* Determine range of line numbers involved in each file.  */
141170754Sdelphij  enum changes changes = analyze_hunk (hunk, &f0, &l0, &f1, &l1);
142170754Sdelphij  if (!changes)
143170754Sdelphij    return;
144170754Sdelphij
145170754Sdelphij  begin_output ();
146170754Sdelphij
147170754Sdelphij  translate_range (&files[0], f0, l0, &tf0, &tl0);
148170754Sdelphij
149170754Sdelphij  if (changes & OLD)
150170754Sdelphij    {
151170754Sdelphij      fprintf (outfile, "d");
152170754Sdelphij      /* For deletion, print just the starting line number from file 0
153170754Sdelphij	 and the number of lines deleted.  */
154170754Sdelphij      fprintf (outfile, "%ld %ld\n", tf0, tf0 <= tl0 ? tl0 - tf0 + 1 : 1);
155170754Sdelphij    }
156170754Sdelphij
157170754Sdelphij  if (changes & NEW)
158170754Sdelphij    {
159170754Sdelphij      fprintf (outfile, "a");
160170754Sdelphij
161170754Sdelphij      /* Take last-line-number from file 0 and # lines from file 1.  */
162170754Sdelphij      translate_range (&files[1], f1, l1, &tf1, &tl1);
163170754Sdelphij      fprintf (outfile, "%ld %ld\n", tl0, tf1 <= tl1 ? tl1 - tf1 + 1 : 1);
164170754Sdelphij
165170754Sdelphij      /* Print the inserted lines.  */
166170754Sdelphij      for (i = f1; i <= l1; i++)
167170754Sdelphij	print_1_line ("", &files[1].linbuf[i]);
168170754Sdelphij    }
169170754Sdelphij}
170