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