Home | History | Annotate | Line # | Download | only in diff
ed.c revision 1.1
      1  1.1  christos /* Output routines for ed-script format.
      2  1.1  christos    Copyright (C) 1988, 89, 91, 92, 93, 1998 Free Software Foundation, Inc.
      3  1.1  christos 
      4  1.1  christos This file is part of GNU DIFF.
      5  1.1  christos 
      6  1.1  christos GNU DIFF is free software; you can redistribute it and/or modify
      7  1.1  christos it under the terms of the GNU General Public License as published by
      8  1.1  christos the Free Software Foundation; either version 2, or (at your option)
      9  1.1  christos any later version.
     10  1.1  christos 
     11  1.1  christos GNU DIFF is distributed in the hope that it will be useful,
     12  1.1  christos but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  1.1  christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14  1.1  christos GNU General Public License for more details.
     15  1.1  christos 
     16  1.1  christos */
     17  1.1  christos 
     18  1.1  christos #include "diff.h"
     19  1.1  christos 
     20  1.1  christos static void print_ed_hunk PARAMS((struct change *));
     21  1.1  christos static void print_rcs_hunk PARAMS((struct change *));
     22  1.1  christos static void pr_forward_ed_hunk PARAMS((struct change *));
     23  1.1  christos 
     24  1.1  christos /* Print our script as ed commands.  */
     26  1.1  christos 
     27  1.1  christos void
     28  1.1  christos print_ed_script (script)
     29  1.1  christos     struct change *script;
     30  1.1  christos {
     31  1.1  christos   print_script (script, find_reverse_change, print_ed_hunk);
     32  1.1  christos }
     33  1.1  christos 
     34  1.1  christos /* Print a hunk of an ed diff */
     35  1.1  christos 
     36  1.1  christos static void
     37  1.1  christos print_ed_hunk (hunk)
     38  1.1  christos      struct change *hunk;
     39  1.1  christos {
     40  1.1  christos   int f0, l0, f1, l1;
     41  1.1  christos   int deletes, inserts;
     42  1.1  christos 
     43  1.1  christos #if 0
     44  1.1  christos   hunk = flip_script (hunk);
     45  1.1  christos #endif
     46  1.1  christos #ifdef DEBUG
     47  1.1  christos   debug_script (hunk);
     48  1.1  christos #endif
     49  1.1  christos 
     50  1.1  christos   /* Determine range of line numbers involved in each file.  */
     51  1.1  christos   analyze_hunk (hunk, &f0, &l0, &f1, &l1, &deletes, &inserts);
     52  1.1  christos   if (!deletes && !inserts)
     53  1.1  christos     return;
     54  1.1  christos 
     55  1.1  christos   begin_output ();
     56  1.1  christos 
     57  1.1  christos   /* Print out the line number header for this hunk */
     58  1.1  christos   print_number_range (',', &files[0], f0, l0);
     59  1.1  christos   printf_output ("%c\n", change_letter (inserts, deletes));
     60  1.1  christos 
     61  1.1  christos   /* Print new/changed lines from second file, if needed */
     62  1.1  christos   if (inserts)
     63  1.1  christos     {
     64  1.1  christos       int i;
     65  1.1  christos       int inserting = 1;
     66  1.1  christos       for (i = f1; i <= l1; i++)
     67  1.1  christos 	{
     68  1.1  christos 	  /* Resume the insert, if we stopped.  */
     69  1.1  christos 	  if (! inserting)
     70  1.1  christos 	    printf_output ("%da\n",
     71  1.1  christos 			   i - f1 + translate_line_number (&files[0], f0) - 1);
     72  1.1  christos 	  inserting = 1;
     73  1.1  christos 
     74  1.1  christos 	  /* If the file's line is just a dot, it would confuse `ed'.
     75  1.1  christos 	     So output it with a double dot, and set the flag LEADING_DOT
     76  1.1  christos 	     so that we will output another ed-command later
     77  1.1  christos 	     to change the double dot into a single dot.  */
     78  1.1  christos 
     79  1.1  christos 	  if (files[1].linbuf[i][0] == '.'
     80  1.1  christos 	      && files[1].linbuf[i][1] == '\n')
     81  1.1  christos 	    {
     82  1.1  christos 	      printf_output ("..\n");
     83  1.1  christos 	      printf_output (".\n");
     84  1.1  christos 	      /* Now change that double dot to the desired single dot.  */
     85  1.1  christos 	      printf_output ("%ds/^\\.\\././\n",
     86  1.1  christos 			     i - f1 + translate_line_number (&files[0], f0));
     87  1.1  christos 	      inserting = 0;
     88  1.1  christos 	    }
     89  1.1  christos 	  else
     90  1.1  christos 	    /* Line is not `.', so output it unmodified.  */
     91  1.1  christos 	    print_1_line ("", &files[1].linbuf[i]);
     92  1.1  christos 	}
     93  1.1  christos 
     94  1.1  christos       /* End insert mode, if we are still in it.  */
     95  1.1  christos       if (inserting)
     96  1.1  christos 	printf_output (".\n");
     97  1.1  christos     }
     98  1.1  christos }
     99  1.1  christos 
    100  1.1  christos /* Print change script in the style of ed commands,
    102  1.1  christos    but print the changes in the order they appear in the input files,
    103  1.1  christos    which means that the commands are not truly useful with ed.  */
    104  1.1  christos 
    105  1.1  christos void
    106  1.1  christos pr_forward_ed_script (script)
    107  1.1  christos      struct change *script;
    108  1.1  christos {
    109  1.1  christos   print_script (script, find_change, pr_forward_ed_hunk);
    110  1.1  christos }
    111  1.1  christos 
    112  1.1  christos static void
    113  1.1  christos pr_forward_ed_hunk (hunk)
    114  1.1  christos      struct change *hunk;
    115  1.1  christos {
    116  1.1  christos   int i;
    117  1.1  christos   int f0, l0, f1, l1;
    118  1.1  christos   int deletes, inserts;
    119  1.1  christos 
    120  1.1  christos   /* Determine range of line numbers involved in each file.  */
    121  1.1  christos   analyze_hunk (hunk, &f0, &l0, &f1, &l1, &deletes, &inserts);
    122  1.1  christos   if (!deletes && !inserts)
    123  1.1  christos     return;
    124  1.1  christos 
    125  1.1  christos   begin_output ();
    126  1.1  christos 
    127  1.1  christos   printf_output ("%c", change_letter (inserts, deletes));
    128  1.1  christos   print_number_range (' ', files, f0, l0);
    129  1.1  christos   printf_output ("\n");
    130  1.1  christos 
    131  1.1  christos   /* If deletion only, print just the number range.  */
    132  1.1  christos 
    133  1.1  christos   if (!inserts)
    134  1.1  christos     return;
    135  1.1  christos 
    136  1.1  christos   /* For insertion (with or without deletion), print the number range
    137  1.1  christos      and the lines from file 2.  */
    138  1.1  christos 
    139  1.1  christos   for (i = f1; i <= l1; i++)
    140  1.1  christos     print_1_line ("", &files[1].linbuf[i]);
    141  1.1  christos 
    142  1.1  christos   printf_output (".\n");
    143  1.1  christos }
    144  1.1  christos 
    145  1.1  christos /* Print in a format somewhat like ed commands
    147  1.1  christos    except that each insert command states the number of lines it inserts.
    148  1.1  christos    This format is used for RCS.  */
    149  1.1  christos 
    150  1.1  christos void
    151  1.1  christos print_rcs_script (script)
    152  1.1  christos      struct change *script;
    153  1.1  christos {
    154  1.1  christos   print_script (script, find_change, print_rcs_hunk);
    155  1.1  christos }
    156  1.1  christos 
    157  1.1  christos /* Print a hunk of an RCS diff */
    158  1.1  christos 
    159  1.1  christos static void
    160  1.1  christos print_rcs_hunk (hunk)
    161  1.1  christos      struct change *hunk;
    162  1.1  christos {
    163  1.1  christos   int i;
    164  1.1  christos   int f0, l0, f1, l1;
    165  1.1  christos   int deletes, inserts;
    166  1.1  christos   int tf0, tl0, tf1, tl1;
    167  1.1  christos 
    168  1.1  christos   /* Determine range of line numbers involved in each file.  */
    169  1.1  christos   analyze_hunk (hunk, &f0, &l0, &f1, &l1, &deletes, &inserts);
    170  1.1  christos   if (!deletes && !inserts)
    171  1.1  christos     return;
    172  1.1  christos 
    173  1.1  christos   begin_output ();
    174  1.1  christos 
    175  1.1  christos   translate_range (&files[0], f0, l0, &tf0, &tl0);
    176  1.1  christos 
    177  1.1  christos   if (deletes)
    178  1.1  christos     {
    179  1.1  christos       printf_output ("d");
    180  1.1  christos       /* For deletion, print just the starting line number from file 0
    181  1.1  christos 	 and the number of lines deleted.  */
    182  1.1  christos       printf_output ("%d %d\n",
    183  1.1  christos 		     tf0,
    184  1.1  christos 		     (tl0 >= tf0 ? tl0 - tf0 + 1 : 1));
    185  1.1  christos     }
    186  1.1  christos 
    187  1.1  christos   if (inserts)
    188  1.1  christos     {
    189  1.1  christos       printf_output ("a");
    190  1.1  christos 
    191  1.1  christos       /* Take last-line-number from file 0 and # lines from file 1.  */
    192  1.1  christos       translate_range (&files[1], f1, l1, &tf1, &tl1);
    193  1.1  christos       printf_output ("%d %d\n",
    194  1.1  christos 		     tl0,
    195  1.1  christos 		     (tl1 >= tf1 ? tl1 - tf1 + 1 : 1));
    196  1.1  christos 
    197  1.1  christos       /* Print the inserted lines.  */
    198  1.1  christos       for (i = f1; i <= l1; i++)
    199                	print_1_line ("", &files[1].linbuf[i]);
    200                    }
    201                }
    202