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