132785Speter/* Output routines for ed-script format. 244852Speter Copyright (C) 1988, 89, 91, 92, 93, 1998 Free Software Foundation, Inc. 332785Speter 432785SpeterThis file is part of GNU DIFF. 532785Speter 632785SpeterGNU DIFF is free software; you can redistribute it and/or modify 732785Speterit under the terms of the GNU General Public License as published by 832785Speterthe Free Software Foundation; either version 2, or (at your option) 932785Speterany later version. 1032785Speter 1132785SpeterGNU DIFF is distributed in the hope that it will be useful, 1232785Speterbut WITHOUT ANY WARRANTY; without even the implied warranty of 1332785SpeterMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1432785SpeterGNU General Public License for more details. 1532785Speter 1654427Speter*/ 1732785Speter 1832785Speter#include "diff.h" 1932785Speter 2032785Speterstatic void print_ed_hunk PARAMS((struct change *)); 2132785Speterstatic void print_rcs_hunk PARAMS((struct change *)); 2232785Speterstatic void pr_forward_ed_hunk PARAMS((struct change *)); 2332785Speter 2432785Speter/* Print our script as ed commands. */ 2532785Speter 2632785Spetervoid 2732785Speterprint_ed_script (script) 2832785Speter struct change *script; 2932785Speter{ 3032785Speter print_script (script, find_reverse_change, print_ed_hunk); 3132785Speter} 3232785Speter 3332785Speter/* Print a hunk of an ed diff */ 3432785Speter 3532785Speterstatic void 3632785Speterprint_ed_hunk (hunk) 3732785Speter struct change *hunk; 3832785Speter{ 3932785Speter int f0, l0, f1, l1; 4032785Speter int deletes, inserts; 4132785Speter 4232785Speter#if 0 4332785Speter hunk = flip_script (hunk); 4432785Speter#endif 4532785Speter#ifdef DEBUG 4632785Speter debug_script (hunk); 4732785Speter#endif 4832785Speter 4932785Speter /* Determine range of line numbers involved in each file. */ 5032785Speter analyze_hunk (hunk, &f0, &l0, &f1, &l1, &deletes, &inserts); 5132785Speter if (!deletes && !inserts) 5232785Speter return; 5332785Speter 5432785Speter begin_output (); 5532785Speter 5632785Speter /* Print out the line number header for this hunk */ 5732785Speter print_number_range (',', &files[0], f0, l0); 5844852Speter printf_output ("%c\n", change_letter (inserts, deletes)); 5932785Speter 6032785Speter /* Print new/changed lines from second file, if needed */ 6132785Speter if (inserts) 6232785Speter { 6332785Speter int i; 6432785Speter int inserting = 1; 6532785Speter for (i = f1; i <= l1; i++) 6632785Speter { 6732785Speter /* Resume the insert, if we stopped. */ 6832785Speter if (! inserting) 6944852Speter printf_output ("%da\n", 7044852Speter i - f1 + translate_line_number (&files[0], f0) - 1); 7132785Speter inserting = 1; 7232785Speter 7332785Speter /* If the file's line is just a dot, it would confuse `ed'. 7432785Speter So output it with a double dot, and set the flag LEADING_DOT 7532785Speter so that we will output another ed-command later 7632785Speter to change the double dot into a single dot. */ 7732785Speter 7832785Speter if (files[1].linbuf[i][0] == '.' 7932785Speter && files[1].linbuf[i][1] == '\n') 8032785Speter { 8144852Speter printf_output ("..\n"); 8244852Speter printf_output (".\n"); 8332785Speter /* Now change that double dot to the desired single dot. */ 8444852Speter printf_output ("%ds/^\\.\\././\n", 8544852Speter i - f1 + translate_line_number (&files[0], f0)); 8632785Speter inserting = 0; 8732785Speter } 8832785Speter else 8932785Speter /* Line is not `.', so output it unmodified. */ 9032785Speter print_1_line ("", &files[1].linbuf[i]); 9132785Speter } 9232785Speter 9332785Speter /* End insert mode, if we are still in it. */ 9432785Speter if (inserting) 9544852Speter printf_output (".\n"); 9632785Speter } 9732785Speter} 9832785Speter 9932785Speter/* Print change script in the style of ed commands, 10032785Speter but print the changes in the order they appear in the input files, 10132785Speter which means that the commands are not truly useful with ed. */ 10232785Speter 10332785Spetervoid 10432785Speterpr_forward_ed_script (script) 10532785Speter struct change *script; 10632785Speter{ 10732785Speter print_script (script, find_change, pr_forward_ed_hunk); 10832785Speter} 10932785Speter 11032785Speterstatic void 11132785Speterpr_forward_ed_hunk (hunk) 11232785Speter struct change *hunk; 11332785Speter{ 11432785Speter int i; 11532785Speter int f0, l0, f1, l1; 11632785Speter int deletes, inserts; 11732785Speter 11832785Speter /* Determine range of line numbers involved in each file. */ 11932785Speter analyze_hunk (hunk, &f0, &l0, &f1, &l1, &deletes, &inserts); 12032785Speter if (!deletes && !inserts) 12132785Speter return; 12232785Speter 12332785Speter begin_output (); 12432785Speter 12544852Speter printf_output ("%c", change_letter (inserts, deletes)); 12632785Speter print_number_range (' ', files, f0, l0); 12744852Speter printf_output ("\n"); 12832785Speter 12932785Speter /* If deletion only, print just the number range. */ 13032785Speter 13132785Speter if (!inserts) 13232785Speter return; 13332785Speter 13432785Speter /* For insertion (with or without deletion), print the number range 13532785Speter and the lines from file 2. */ 13632785Speter 13732785Speter for (i = f1; i <= l1; i++) 13832785Speter print_1_line ("", &files[1].linbuf[i]); 13932785Speter 14044852Speter printf_output (".\n"); 14132785Speter} 14232785Speter 14332785Speter/* Print in a format somewhat like ed commands 14432785Speter except that each insert command states the number of lines it inserts. 14532785Speter This format is used for RCS. */ 14632785Speter 14732785Spetervoid 14832785Speterprint_rcs_script (script) 14932785Speter struct change *script; 15032785Speter{ 15132785Speter print_script (script, find_change, print_rcs_hunk); 15232785Speter} 15332785Speter 15432785Speter/* Print a hunk of an RCS diff */ 15532785Speter 15632785Speterstatic void 15732785Speterprint_rcs_hunk (hunk) 15832785Speter struct change *hunk; 15932785Speter{ 16032785Speter int i; 16132785Speter int f0, l0, f1, l1; 16232785Speter int deletes, inserts; 16332785Speter int tf0, tl0, tf1, tl1; 16432785Speter 16532785Speter /* Determine range of line numbers involved in each file. */ 16632785Speter analyze_hunk (hunk, &f0, &l0, &f1, &l1, &deletes, &inserts); 16732785Speter if (!deletes && !inserts) 16832785Speter return; 16932785Speter 17032785Speter begin_output (); 17132785Speter 17232785Speter translate_range (&files[0], f0, l0, &tf0, &tl0); 17332785Speter 17432785Speter if (deletes) 17532785Speter { 17644852Speter printf_output ("d"); 17732785Speter /* For deletion, print just the starting line number from file 0 17832785Speter and the number of lines deleted. */ 17944852Speter printf_output ("%d %d\n", 18044852Speter tf0, 18144852Speter (tl0 >= tf0 ? tl0 - tf0 + 1 : 1)); 18232785Speter } 18332785Speter 18432785Speter if (inserts) 18532785Speter { 18644852Speter printf_output ("a"); 18732785Speter 18832785Speter /* Take last-line-number from file 0 and # lines from file 1. */ 18932785Speter translate_range (&files[1], f1, l1, &tf1, &tl1); 19044852Speter printf_output ("%d %d\n", 19144852Speter tl0, 19244852Speter (tl1 >= tf1 ? tl1 - tf1 + 1 : 1)); 19332785Speter 19432785Speter /* Print the inserted lines. */ 19532785Speter for (i = f1; i <= l1; i++) 19632785Speter print_1_line ("", &files[1].linbuf[i]); 19732785Speter } 19832785Speter} 199