1129471Spjd/* Output routines for ed-script format.
2162142Spjd
3129471Spjd   Copyright (C) 1988, 1989, 1991, 1992, 1993, 1995, 1998, 2001 Free
4129471Spjd   Software Foundation, Inc.
5129471Spjd
6129471Spjd   This file is part of GNU DIFF.
7129471Spjd
8129471Spjd   GNU DIFF is free software; you can redistribute it and/or modify
9129471Spjd   it under the terms of the GNU General Public License as published by
10129471Spjd   the Free Software Foundation; either version 2, or (at your option)
11129471Spjd   any later version.
12129471Spjd
13162834Spjd   GNU DIFF is distributed in the hope that it will be useful,
14129471Spjd   but WITHOUT ANY WARRANTY; without even the implied warranty of
15129471Spjd   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16129471Spjd   GNU General Public License for more details.
17129471Spjd
18129471Spjd   You should have received a copy of the GNU General Public License
19129471Spjd   along with this program; see the file COPYING.
20129471Spjd   If not, write to the Free Software Foundation,
21129471Spjd   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
22129471Spjd
23129471Spjd#include "diff.h"
24129471Spjd
25129471Spjdstatic void print_ed_hunk (struct change *);
26129471Spjdstatic void print_rcs_hunk (struct change *);
27129471Spjdstatic void pr_forward_ed_hunk (struct change *);
28129471Spjd
29129471Spjd/* Print our script as ed commands.  */
30129471Spjd
31129471Spjdvoid
32129471Spjdprint_ed_script (struct change *script)
33162142Spjd{
34129471Spjd  print_script (script, find_reverse_change, print_ed_hunk);
35129471Spjd}
36129471Spjd
37129471Spjd/* Print a hunk of an ed diff */
38129471Spjd
39129471Spjdstatic void
40129471Spjdprint_ed_hunk (struct change *hunk)
41129471Spjd{
42129471Spjd  lin f0, l0, f1, l1;
43129471Spjd  enum changes changes;
44129471Spjd
45129471Spjd#ifdef DEBUG
46129471Spjd  debug_script (hunk);
47249440Sjmg#endif
48249440Sjmg
49249440Sjmg  /* Determine range of line numbers involved in each file.  */
50249440Sjmg  changes = analyze_hunk (hunk, &f0, &l0, &f1, &l1);
51129471Spjd  if (!changes)
52129471Spjd    return;
53129471Spjd
54129471Spjd  begin_output ();
55129471Spjd
56129471Spjd  /* Print out the line number header for this hunk */
57132381Spjd  print_number_range (',', &files[0], f0, l0);
58132381Spjd  fprintf (outfile, "%c\n", change_letter[changes]);
59162142Spjd
60153250Spjd  /* Print new/changed lines from second file, if needed */
61238219Strasz  if (changes != OLD)
62289520Strasz    {
63289520Strasz      lin i;
64162142Spjd      for (i = f1; i <= l1; i++)
65162142Spjd	{
66153250Spjd	  if (files[1].linbuf[i][0] == '.' && files[1].linbuf[i][1] == '\n')
67153250Spjd	    {
68293738Strasz	      /* The file's line is just a dot, and it would exit
69293738Strasz		 insert mode.  Precede the dot with another dot, exit
70293738Strasz		 insert mode, remove the extra dot, and then resume
71293738Strasz		 insert mode.  */
72293738Strasz	      fprintf (outfile, "..\n.\ns/.//\na\n");
73293738Strasz	    }
74153250Spjd	  else
75153250Spjd	    print_1_line ("", &files[1].linbuf[i]);
76260385Sscottl	}
77132381Spjd
78129471Spjd      fprintf (outfile, ".\n");
79129471Spjd    }
80129471Spjd}
81
82/* Print change script in the style of ed commands,
83   but print the changes in the order they appear in the input files,
84   which means that the commands are not truly useful with ed.  */
85
86void
87pr_forward_ed_script (struct change *script)
88{
89  print_script (script, find_change, pr_forward_ed_hunk);
90}
91
92static void
93pr_forward_ed_hunk (struct change *hunk)
94{
95  lin i, f0, l0, f1, l1;
96
97  /* Determine range of line numbers involved in each file.  */
98  enum changes changes = analyze_hunk (hunk, &f0, &l0, &f1, &l1);
99  if (!changes)
100    return;
101
102  begin_output ();
103
104  fprintf (outfile, "%c", change_letter[changes]);
105  print_number_range (' ', files, f0, l0);
106  fprintf (outfile, "\n");
107
108  /* If deletion only, print just the number range.  */
109
110  if (changes == OLD)
111    return;
112
113  /* For insertion (with or without deletion), print the number range
114     and the lines from file 2.  */
115
116  for (i = f1; i <= l1; i++)
117    print_1_line ("", &files[1].linbuf[i]);
118
119  fprintf (outfile, ".\n");
120}
121
122/* Print in a format somewhat like ed commands
123   except that each insert command states the number of lines it inserts.
124   This format is used for RCS.  */
125
126void
127print_rcs_script (struct change *script)
128{
129  print_script (script, find_change, print_rcs_hunk);
130}
131
132/* Print a hunk of an RCS diff */
133
134static void
135print_rcs_hunk (struct change *hunk)
136{
137  lin i, f0, l0, f1, l1;
138  long tf0, tl0, tf1, tl1;
139
140  /* Determine range of line numbers involved in each file.  */
141  enum changes changes = analyze_hunk (hunk, &f0, &l0, &f1, &l1);
142  if (!changes)
143    return;
144
145  begin_output ();
146
147  translate_range (&files[0], f0, l0, &tf0, &tl0);
148
149  if (changes & OLD)
150    {
151      fprintf (outfile, "d");
152      /* For deletion, print just the starting line number from file 0
153	 and the number of lines deleted.  */
154      fprintf (outfile, "%ld %ld\n", tf0, tf0 <= tl0 ? tl0 - tf0 + 1 : 1);
155    }
156
157  if (changes & NEW)
158    {
159      fprintf (outfile, "a");
160
161      /* Take last-line-number from file 0 and # lines from file 1.  */
162      translate_range (&files[1], f1, l1, &tf1, &tl1);
163      fprintf (outfile, "%ld %ld\n", tl0, tf1 <= tl1 ? tl1 - tf1 + 1 : 1);
164
165      /* Print the inserted lines.  */
166      for (i = f1; i <= l1; i++)
167	print_1_line ("", &files[1].linbuf[i]);
168    }
169}
170