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