xref: /freebsd/contrib/diff/src/ed.c (revision 18fd37a72c3a7549d2d4f6c6ea00bdcd2bdaca01)
118fd37a7SXin LI /* Output routines for ed-script format.
218fd37a7SXin LI 
318fd37a7SXin LI    Copyright (C) 1988, 1989, 1991, 1992, 1993, 1995, 1998, 2001, 2004
418fd37a7SXin LI    Free Software Foundation, Inc.
518fd37a7SXin LI 
618fd37a7SXin LI    This file is part of GNU DIFF.
718fd37a7SXin LI 
818fd37a7SXin LI    GNU DIFF is free software; you can redistribute it and/or modify
918fd37a7SXin LI    it under the terms of the GNU General Public License as published by
1018fd37a7SXin LI    the Free Software Foundation; either version 2, or (at your option)
1118fd37a7SXin LI    any later version.
1218fd37a7SXin LI 
1318fd37a7SXin LI    GNU DIFF is distributed in the hope that it will be useful,
1418fd37a7SXin LI    but WITHOUT ANY WARRANTY; without even the implied warranty of
1518fd37a7SXin LI    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1618fd37a7SXin LI    GNU General Public License for more details.
1718fd37a7SXin LI 
1818fd37a7SXin LI    You should have received a copy of the GNU General Public License
1918fd37a7SXin LI    along with this program; see the file COPYING.
2018fd37a7SXin LI    If not, write to the Free Software Foundation,
2118fd37a7SXin LI    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
2218fd37a7SXin LI 
2318fd37a7SXin LI #include "diff.h"
2418fd37a7SXin LI 
2518fd37a7SXin LI static void print_ed_hunk (struct change *);
2618fd37a7SXin LI static void print_rcs_hunk (struct change *);
2718fd37a7SXin LI static void pr_forward_ed_hunk (struct change *);
2818fd37a7SXin LI 
2918fd37a7SXin LI /* Print our script as ed commands.  */
3018fd37a7SXin LI 
3118fd37a7SXin LI void
print_ed_script(struct change * script)3218fd37a7SXin LI print_ed_script (struct change *script)
3318fd37a7SXin LI {
3418fd37a7SXin LI   print_script (script, find_reverse_change, print_ed_hunk);
3518fd37a7SXin LI }
3618fd37a7SXin LI 
3718fd37a7SXin LI /* Print a hunk of an ed diff */
3818fd37a7SXin LI 
3918fd37a7SXin LI static void
print_ed_hunk(struct change * hunk)4018fd37a7SXin LI print_ed_hunk (struct change *hunk)
4118fd37a7SXin LI {
4218fd37a7SXin LI   lin f0, l0, f1, l1;
4318fd37a7SXin LI   enum changes changes;
4418fd37a7SXin LI 
4518fd37a7SXin LI #ifdef DEBUG
4618fd37a7SXin LI   debug_script (hunk);
4718fd37a7SXin LI #endif
4818fd37a7SXin LI 
4918fd37a7SXin LI   /* Determine range of line numbers involved in each file.  */
5018fd37a7SXin LI   changes = analyze_hunk (hunk, &f0, &l0, &f1, &l1);
5118fd37a7SXin LI   if (!changes)
5218fd37a7SXin LI     return;
5318fd37a7SXin LI 
5418fd37a7SXin LI   begin_output ();
5518fd37a7SXin LI 
5618fd37a7SXin LI   /* Print out the line number header for this hunk */
5718fd37a7SXin LI   print_number_range (',', &files[0], f0, l0);
5818fd37a7SXin LI   fprintf (outfile, "%c\n", change_letter[changes]);
5918fd37a7SXin LI 
6018fd37a7SXin LI   /* Print new/changed lines from second file, if needed */
6118fd37a7SXin LI   if (changes != OLD)
6218fd37a7SXin LI     {
6318fd37a7SXin LI       lin i;
6418fd37a7SXin LI       for (i = f1; i <= l1; i++)
6518fd37a7SXin LI 	{
6618fd37a7SXin LI 	  if (files[1].linbuf[i][0] == '.' && files[1].linbuf[i][1] == '\n')
6718fd37a7SXin LI 	    {
6818fd37a7SXin LI 	      /* The file's line is just a dot, and it would exit
6918fd37a7SXin LI 		 insert mode.  Precede the dot with another dot, exit
7018fd37a7SXin LI 		 insert mode, remove the extra dot, and then resume
7118fd37a7SXin LI 		 insert mode.  */
7218fd37a7SXin LI 	      fprintf (outfile, "..\n.\ns/.//\na\n");
7318fd37a7SXin LI 	    }
7418fd37a7SXin LI 	  else
7518fd37a7SXin LI 	    print_1_line ("", &files[1].linbuf[i]);
7618fd37a7SXin LI 	}
7718fd37a7SXin LI 
7818fd37a7SXin LI       fprintf (outfile, ".\n");
7918fd37a7SXin LI     }
8018fd37a7SXin LI }
8118fd37a7SXin LI 
8218fd37a7SXin LI /* Print change script in the style of ed commands,
8318fd37a7SXin LI    but print the changes in the order they appear in the input files,
8418fd37a7SXin LI    which means that the commands are not truly useful with ed.  */
8518fd37a7SXin LI 
8618fd37a7SXin LI void
pr_forward_ed_script(struct change * script)8718fd37a7SXin LI pr_forward_ed_script (struct change *script)
8818fd37a7SXin LI {
8918fd37a7SXin LI   print_script (script, find_change, pr_forward_ed_hunk);
9018fd37a7SXin LI }
9118fd37a7SXin LI 
9218fd37a7SXin LI static void
pr_forward_ed_hunk(struct change * hunk)9318fd37a7SXin LI pr_forward_ed_hunk (struct change *hunk)
9418fd37a7SXin LI {
9518fd37a7SXin LI   lin i, f0, l0, f1, l1;
9618fd37a7SXin LI 
9718fd37a7SXin LI   /* Determine range of line numbers involved in each file.  */
9818fd37a7SXin LI   enum changes changes = analyze_hunk (hunk, &f0, &l0, &f1, &l1);
9918fd37a7SXin LI   if (!changes)
10018fd37a7SXin LI     return;
10118fd37a7SXin LI 
10218fd37a7SXin LI   begin_output ();
10318fd37a7SXin LI 
10418fd37a7SXin LI   fprintf (outfile, "%c", change_letter[changes]);
10518fd37a7SXin LI   print_number_range (' ', files, f0, l0);
10618fd37a7SXin LI   fprintf (outfile, "\n");
10718fd37a7SXin LI 
10818fd37a7SXin LI   /* If deletion only, print just the number range.  */
10918fd37a7SXin LI 
11018fd37a7SXin LI   if (changes == OLD)
11118fd37a7SXin LI     return;
11218fd37a7SXin LI 
11318fd37a7SXin LI   /* For insertion (with or without deletion), print the number range
11418fd37a7SXin LI      and the lines from file 2.  */
11518fd37a7SXin LI 
11618fd37a7SXin LI   for (i = f1; i <= l1; i++)
11718fd37a7SXin LI     print_1_line ("", &files[1].linbuf[i]);
11818fd37a7SXin LI 
11918fd37a7SXin LI   fprintf (outfile, ".\n");
12018fd37a7SXin LI }
12118fd37a7SXin LI 
12218fd37a7SXin LI /* Print in a format somewhat like ed commands
12318fd37a7SXin LI    except that each insert command states the number of lines it inserts.
12418fd37a7SXin LI    This format is used for RCS.  */
12518fd37a7SXin LI 
12618fd37a7SXin LI void
print_rcs_script(struct change * script)12718fd37a7SXin LI print_rcs_script (struct change *script)
12818fd37a7SXin LI {
12918fd37a7SXin LI   print_script (script, find_change, print_rcs_hunk);
13018fd37a7SXin LI }
13118fd37a7SXin LI 
13218fd37a7SXin LI /* Print a hunk of an RCS diff */
13318fd37a7SXin LI 
13418fd37a7SXin LI static void
print_rcs_hunk(struct change * hunk)13518fd37a7SXin LI print_rcs_hunk (struct change *hunk)
13618fd37a7SXin LI {
13718fd37a7SXin LI   lin i, f0, l0, f1, l1;
13818fd37a7SXin LI   long int tf0, tl0, tf1, tl1;
13918fd37a7SXin LI 
14018fd37a7SXin LI   /* Determine range of line numbers involved in each file.  */
14118fd37a7SXin LI   enum changes changes = analyze_hunk (hunk, &f0, &l0, &f1, &l1);
14218fd37a7SXin LI   if (!changes)
14318fd37a7SXin LI     return;
14418fd37a7SXin LI 
14518fd37a7SXin LI   begin_output ();
14618fd37a7SXin LI 
14718fd37a7SXin LI   translate_range (&files[0], f0, l0, &tf0, &tl0);
14818fd37a7SXin LI 
14918fd37a7SXin LI   if (changes & OLD)
15018fd37a7SXin LI     {
15118fd37a7SXin LI       fprintf (outfile, "d");
15218fd37a7SXin LI       /* For deletion, print just the starting line number from file 0
15318fd37a7SXin LI 	 and the number of lines deleted.  */
15418fd37a7SXin LI       fprintf (outfile, "%ld %ld\n", tf0, tf0 <= tl0 ? tl0 - tf0 + 1 : 1);
15518fd37a7SXin LI     }
15618fd37a7SXin LI 
15718fd37a7SXin LI   if (changes & NEW)
15818fd37a7SXin LI     {
15918fd37a7SXin LI       fprintf (outfile, "a");
16018fd37a7SXin LI 
16118fd37a7SXin LI       /* Take last-line-number from file 0 and # lines from file 1.  */
16218fd37a7SXin LI       translate_range (&files[1], f1, l1, &tf1, &tl1);
16318fd37a7SXin LI       fprintf (outfile, "%ld %ld\n", tl0, tf1 <= tl1 ? tl1 - tf1 + 1 : 1);
16418fd37a7SXin LI 
16518fd37a7SXin LI       /* Print the inserted lines.  */
16618fd37a7SXin LI       for (i = f1; i <= l1; i++)
16718fd37a7SXin LI 	print_1_line ("", &files[1].linbuf[i]);
16818fd37a7SXin LI     }
16918fd37a7SXin LI }
170