1 | /* $Header: /cvsup/minix/src/commands/patch/pch.c,v 1.1.1.1 2005/04/21 14:55:11 beng Exp $
|
---|
2 | *
|
---|
3 | * $Log: pch.c,v $
|
---|
4 | * Revision 1.1.1.1 2005/04/21 14:55:11 beng
|
---|
5 | * Initial import of pre-3.0.1
|
---|
6 | *
|
---|
7 | * Revision 1.1.1.1 2005/04/20 13:33:19 beng
|
---|
8 | * Initial import of minix 2.0.4
|
---|
9 | *
|
---|
10 | * Revision 2.0.1.7 88/06/03 15:13:28 lwall
|
---|
11 | * patch10: Can now find patches in shar scripts.
|
---|
12 | * patch10: Hunks that swapped and then swapped back could core dump.
|
---|
13 | *
|
---|
14 | * Revision 2.0.1.6 87/06/04 16:18:13 lwall
|
---|
15 | * pch_swap didn't swap p_bfake and p_efake.
|
---|
16 | *
|
---|
17 | * Revision 2.0.1.5 87/01/30 22:47:42 lwall
|
---|
18 | * Improved responses to mangled patches.
|
---|
19 | *
|
---|
20 | * Revision 2.0.1.4 87/01/05 16:59:53 lwall
|
---|
21 | * New-style context diffs caused double call to free().
|
---|
22 | *
|
---|
23 | * Revision 2.0.1.3 86/11/14 10:08:33 lwall
|
---|
24 | * Fixed problem where a long pattern wouldn't grow the hunk.
|
---|
25 | * Also restored p_input_line when backtracking so error messages are right.
|
---|
26 | *
|
---|
27 | * Revision 2.0.1.2 86/11/03 17:49:52 lwall
|
---|
28 | * New-style delete triggers spurious assertion error.
|
---|
29 | *
|
---|
30 | * Revision 2.0.1.1 86/10/29 15:52:08 lwall
|
---|
31 | * Could falsely report new-style context diff.
|
---|
32 | *
|
---|
33 | * Revision 2.0 86/09/17 15:39:37 lwall
|
---|
34 | * Baseline for netwide release.
|
---|
35 | *
|
---|
36 | */
|
---|
37 |
|
---|
38 | #include "EXTERN.h"
|
---|
39 | #include "common.h"
|
---|
40 | #include "util.h"
|
---|
41 | #include "INTERN.h"
|
---|
42 | #include "pch.h"
|
---|
43 |
|
---|
44 | /* Patch (diff listing) abstract type. */
|
---|
45 |
|
---|
46 | static long p_filesize; /* size of the patch file */
|
---|
47 | static LINENUM p_first; /* 1st line number */
|
---|
48 | static LINENUM p_newfirst; /* 1st line number of replacement */
|
---|
49 | static LINENUM p_ptrn_lines; /* # lines in pattern */
|
---|
50 | static LINENUM p_repl_lines; /* # lines in replacement text */
|
---|
51 | static LINENUM p_end = -1; /* last line in hunk */
|
---|
52 | static LINENUM p_max; /* max allowed value of p_end */
|
---|
53 | static LINENUM p_context = 3; /* # of context lines */
|
---|
54 | static LINENUM p_input_line = 0; /* current line # from patch file */
|
---|
55 | #ifdef SMALL
|
---|
56 | static long *p_line = Null(long *); /* the text of the hunk */
|
---|
57 | #else
|
---|
58 | static char **p_line = Null(char**); /* the text of the hunk */
|
---|
59 | #endif
|
---|
60 | static short *p_len = Null(short*); /* length of each line */
|
---|
61 | static char *p_char = Nullch; /* +, -, and ! */
|
---|
62 | static int hunkmax = INITHUNKMAX; /* size of above arrays to begin with */
|
---|
63 | static int p_indent; /* indent to patch */
|
---|
64 | static LINENUM p_base; /* where to intuit this time */
|
---|
65 | static LINENUM p_bline; /* line # of p_base */
|
---|
66 | static LINENUM p_start; /* where intuit found a patch */
|
---|
67 | static LINENUM p_sline; /* and the line number for it */
|
---|
68 | static LINENUM p_hunk_beg; /* line number of current hunk */
|
---|
69 | static LINENUM p_efake = -1; /* end of faked up lines--don't free */
|
---|
70 | static LINENUM p_bfake = -1; /* beg of faked up lines */
|
---|
71 |
|
---|
72 | /* Prepare to look for the next patch in the patch file. */
|
---|
73 |
|
---|
74 | void
|
---|
75 | re_patch()
|
---|
76 | {
|
---|
77 | p_first = Nulline;
|
---|
78 | p_newfirst = Nulline;
|
---|
79 | p_ptrn_lines = Nulline;
|
---|
80 | p_repl_lines = Nulline;
|
---|
81 | p_end = (LINENUM)-1;
|
---|
82 | p_max = Nulline;
|
---|
83 | p_indent = 0;
|
---|
84 | }
|
---|
85 |
|
---|
86 | /* Open the patch file at the beginning of time. */
|
---|
87 |
|
---|
88 | void
|
---|
89 | open_patch_file(filename)
|
---|
90 | char *filename;
|
---|
91 | {
|
---|
92 | if (filename == Nullch || !*filename || strEQ(filename, "-")) {
|
---|
93 | pfp = fopen(TMPPATNAME, "w");
|
---|
94 | if (pfp == Nullfp)
|
---|
95 | fatal2("patch: can't create %s.\n", TMPPATNAME);
|
---|
96 | while (fgets(buf, sizeof buf, stdin) != Nullch)
|
---|
97 | fputs(buf, pfp);
|
---|
98 | Fclose(pfp);
|
---|
99 | filename = TMPPATNAME;
|
---|
100 | }
|
---|
101 | pfp = fopen(filename, "r");
|
---|
102 | if (pfp == Nullfp)
|
---|
103 | fatal2("patch file %s not found\n", filename);
|
---|
104 | Fstat(fileno(pfp), &filestat);
|
---|
105 | p_filesize = filestat.st_size;
|
---|
106 | next_intuit_at(0L,1L); /* start at the beginning */
|
---|
107 | set_hunkmax();
|
---|
108 | }
|
---|
109 |
|
---|
110 | /* Make sure our dynamically realloced tables are malloced to begin with. */
|
---|
111 |
|
---|
112 | void
|
---|
113 | set_hunkmax()
|
---|
114 | {
|
---|
115 | #ifndef lint
|
---|
116 | #ifdef SMALL
|
---|
117 | if (p_line == Null(long*))
|
---|
118 | #else
|
---|
119 | if (p_line == Null(char**))
|
---|
120 | #endif
|
---|
121 | #ifdef SMALL
|
---|
122 | p_line = (long *) malloc((MEM)hunkmax * sizeof(long));
|
---|
123 | #else
|
---|
124 | p_line = (char**) malloc((MEM)hunkmax * sizeof(char *));
|
---|
125 | #endif
|
---|
126 | if (p_len == Null(short*))
|
---|
127 | p_len = (short*) malloc((MEM)hunkmax * sizeof(short));
|
---|
128 | #endif
|
---|
129 | if (p_char == Nullch)
|
---|
130 | p_char = (char*) malloc((MEM)hunkmax * sizeof(char));
|
---|
131 | }
|
---|
132 |
|
---|
133 | /* Enlarge the arrays containing the current hunk of patch. */
|
---|
134 |
|
---|
135 | void
|
---|
136 | grow_hunkmax()
|
---|
137 | {
|
---|
138 | hunkmax *= 2;
|
---|
139 | /*
|
---|
140 | * Note that on most systems, only the p_line array ever gets fresh memory
|
---|
141 | * since p_len can move into p_line's old space, and p_char can move into
|
---|
142 | * p_len's old space. Not on PDP-11's however. But it doesn't matter.
|
---|
143 | */
|
---|
144 | #ifdef SMALL
|
---|
145 | assert(p_line != Null(long*) && p_len != Null(short*) && p_char != Nullch);
|
---|
146 | #else
|
---|
147 | assert(p_line != Null(char**) && p_len != Null(short*) && p_char != Nullch);
|
---|
148 | #endif
|
---|
149 | #ifndef lint
|
---|
150 | #ifdef SMALL
|
---|
151 | p_line = (long*) realloc((char*)p_line, (MEM)hunkmax * sizeof(long));
|
---|
152 | #else
|
---|
153 | p_line = (char**) realloc((char*)p_line, (MEM)hunkmax * sizeof(char *));
|
---|
154 | #endif
|
---|
155 | p_len = (short*) realloc((char*)p_len, (MEM)hunkmax * sizeof(short));
|
---|
156 | p_char = (char*) realloc((char*)p_char, (MEM)hunkmax * sizeof(char));
|
---|
157 | #endif
|
---|
158 | #ifdef SMALL
|
---|
159 | if (p_line != Null(long*) && p_len != Null(short*) && p_char != Nullch)
|
---|
160 | #else
|
---|
161 | if (p_line != Null(char**) && p_len != Null(short*) && p_char != Nullch)
|
---|
162 | #endif
|
---|
163 | return;
|
---|
164 | if (!using_plan_a)
|
---|
165 | fatal1("patch: out of memory (grow_hunkmax)\n");
|
---|
166 | out_of_mem = TRUE; /* whatever is null will be allocated again */
|
---|
167 | /* from within plan_a(), of all places */
|
---|
168 | }
|
---|
169 |
|
---|
170 | /* True if the remainder of the patch file contains a diff of some sort. */
|
---|
171 |
|
---|
172 | bool
|
---|
173 | there_is_another_patch()
|
---|
174 | {
|
---|
175 | if (p_base != 0L && p_base >= p_filesize) {
|
---|
176 | if (verbose)
|
---|
177 | say1("done\n");
|
---|
178 | return FALSE;
|
---|
179 | }
|
---|
180 | if (verbose)
|
---|
181 | say1("Hmm...");
|
---|
182 | diff_type = intuit_diff_type();
|
---|
183 | if (!diff_type) {
|
---|
184 | if (p_base != 0L) {
|
---|
185 | if (verbose)
|
---|
186 | say1(" Ignoring the trailing garbage.\ndone\n");
|
---|
187 | }
|
---|
188 | else
|
---|
189 | say1(" I can't seem to find a patch in there anywhere.\n");
|
---|
190 | return FALSE;
|
---|
191 | }
|
---|
192 | if (verbose)
|
---|
193 | say3(" %sooks like %s to me...\n",
|
---|
194 | (p_base == 0L ? "L" : "The next patch l"),
|
---|
195 | diff_type == CONTEXT_DIFF ? "a context diff" :
|
---|
196 | diff_type == NEW_CONTEXT_DIFF ? "a new-style context diff" :
|
---|
197 | diff_type == NORMAL_DIFF ? "a normal diff" :
|
---|
198 | "an ed script" );
|
---|
199 | if (p_indent && verbose)
|
---|
200 | say3("(Patch is indented %d space%s.)\n", p_indent, p_indent==1?"":"s");
|
---|
201 | skip_to(p_start,p_sline);
|
---|
202 | while (filearg[0] == Nullch) {
|
---|
203 | if (force) {
|
---|
204 | say1("No file to patch. Skipping...\n");
|
---|
205 | filearg[0] = savestr(bestguess);
|
---|
206 | return TRUE;
|
---|
207 | }
|
---|
208 | ask1("File to patch: ");
|
---|
209 | if (*buf != '\n') {
|
---|
210 | if (bestguess)
|
---|
211 | free(bestguess);
|
---|
212 | bestguess = savestr(buf);
|
---|
213 | filearg[0] = fetchname(buf, 0, FALSE);
|
---|
214 | }
|
---|
215 | if (filearg[0] == Nullch) {
|
---|
216 | ask1("No file found--skip this patch? [n] ");
|
---|
217 | if (*buf != 'y') {
|
---|
218 | continue;
|
---|
219 | }
|
---|
220 | if (verbose)
|
---|
221 | say1("Skipping patch...\n");
|
---|
222 | filearg[0] = fetchname(bestguess, 0, TRUE);
|
---|
223 | skip_rest_of_patch = TRUE;
|
---|
224 | return TRUE;
|
---|
225 | }
|
---|
226 | }
|
---|
227 | return TRUE;
|
---|
228 | }
|
---|
229 |
|
---|
230 | /* Determine what kind of diff is in the remaining part of the patch file. */
|
---|
231 |
|
---|
232 | int
|
---|
233 | intuit_diff_type()
|
---|
234 | {
|
---|
235 | Reg4 long this_line = 0;
|
---|
236 | Reg5 long previous_line;
|
---|
237 | Reg6 long first_command_line = -1;
|
---|
238 | long fcl_line;
|
---|
239 | Reg7 bool last_line_was_command = FALSE;
|
---|
240 | Reg8 bool this_is_a_command = FALSE;
|
---|
241 | Reg9 bool stars_last_line = FALSE;
|
---|
242 | Reg10 bool stars_this_line = FALSE;
|
---|
243 | Reg3 int indent;
|
---|
244 | Reg1 char *s;
|
---|
245 | Reg2 char *t;
|
---|
246 | char *indtmp = Nullch;
|
---|
247 | char *oldtmp = Nullch;
|
---|
248 | char *newtmp = Nullch;
|
---|
249 | char *indname = Nullch;
|
---|
250 | char *oldname = Nullch;
|
---|
251 | char *newname = Nullch;
|
---|
252 | Reg11 int retval;
|
---|
253 | bool no_filearg = (filearg[0] == Nullch);
|
---|
254 |
|
---|
255 | ok_to_create_file = FALSE;
|
---|
256 | Fseek(pfp, p_base, 0);
|
---|
257 | p_input_line = p_bline - 1;
|
---|
258 | for (;;) {
|
---|
259 | previous_line = this_line;
|
---|
260 | last_line_was_command = this_is_a_command;
|
---|
261 | stars_last_line = stars_this_line;
|
---|
262 | this_line = ftell(pfp);
|
---|
263 | indent = 0;
|
---|
264 | p_input_line++;
|
---|
265 | if (fgets(buf, sizeof buf, pfp) == Nullch) {
|
---|
266 | if (first_command_line >= 0L) {
|
---|
267 | /* nothing but deletes!? */
|
---|
268 | p_start = first_command_line;
|
---|
269 | p_sline = fcl_line;
|
---|
270 | retval = ED_DIFF;
|
---|
271 | goto scan_exit;
|
---|
272 | }
|
---|
273 | else {
|
---|
274 | p_start = this_line;
|
---|
275 | p_sline = p_input_line;
|
---|
276 | retval = 0;
|
---|
277 | goto scan_exit;
|
---|
278 | }
|
---|
279 | }
|
---|
280 | for (s = buf; *s == ' ' || *s == '\t' || *s == 'X'; s++) {
|
---|
281 | if (*s == '\t')
|
---|
282 | indent += 8 - (indent % 8);
|
---|
283 | else
|
---|
284 | indent++;
|
---|
285 | }
|
---|
286 | for (t=s; isdigit(*t) || *t == ','; t++) ;
|
---|
287 | this_is_a_command = (isdigit(*s) &&
|
---|
288 | (*t == 'd' || *t == 'c' || *t == 'a') );
|
---|
289 | if (first_command_line < 0L && this_is_a_command) {
|
---|
290 | first_command_line = this_line;
|
---|
291 | fcl_line = p_input_line;
|
---|
292 | p_indent = indent; /* assume this for now */
|
---|
293 | }
|
---|
294 | if (!stars_last_line && strnEQ(s, "*** ", 4))
|
---|
295 | oldtmp = savestr(s+4);
|
---|
296 | else if (strnEQ(s, "--- ", 4))
|
---|
297 | newtmp = savestr(s+4);
|
---|
298 | else if (strnEQ(s, "Index:", 6))
|
---|
299 | indtmp = savestr(s+6);
|
---|
300 | else if (strnEQ(s, "Prereq:", 7)) {
|
---|
301 | for (t=s+7; isspace(*t); t++) ;
|
---|
302 | revision = savestr(t);
|
---|
303 | for (t=revision; *t && !isspace(*t); t++) ;
|
---|
304 | *t = '\0';
|
---|
305 | if (!*revision) {
|
---|
306 | free(revision);
|
---|
307 | revision = Nullch;
|
---|
308 | }
|
---|
309 | }
|
---|
310 | if ((!diff_type || diff_type == ED_DIFF) &&
|
---|
311 | first_command_line >= 0L &&
|
---|
312 | strEQ(s, ".\n") ) {
|
---|
313 | p_indent = indent;
|
---|
314 | p_start = first_command_line;
|
---|
315 | p_sline = fcl_line;
|
---|
316 | retval = ED_DIFF;
|
---|
317 | goto scan_exit;
|
---|
318 | }
|
---|
319 | stars_this_line = strnEQ(s, "********", 8);
|
---|
320 | if ((!diff_type || diff_type == CONTEXT_DIFF) && stars_last_line &&
|
---|
321 | strnEQ(s, "*** ", 4)) {
|
---|
322 | if (!atol(s+4))
|
---|
323 | ok_to_create_file = TRUE;
|
---|
324 | /* if this is a new context diff the character just before */
|
---|
325 | /* the newline is a '*'. */
|
---|
326 | while (*s != '\n')
|
---|
327 | s++;
|
---|
328 | p_indent = indent;
|
---|
329 | p_start = previous_line;
|
---|
330 | p_sline = p_input_line - 1;
|
---|
331 | retval = (*(s-1) == '*' ? NEW_CONTEXT_DIFF : CONTEXT_DIFF);
|
---|
332 | goto scan_exit;
|
---|
333 | }
|
---|
334 | if ((!diff_type || diff_type == NORMAL_DIFF) &&
|
---|
335 | last_line_was_command &&
|
---|
336 | (strnEQ(s, "< ", 2) || strnEQ(s, "> ", 2)) ) {
|
---|
337 | p_start = previous_line;
|
---|
338 | p_sline = p_input_line - 1;
|
---|
339 | p_indent = indent;
|
---|
340 | retval = NORMAL_DIFF;
|
---|
341 | goto scan_exit;
|
---|
342 | }
|
---|
343 | }
|
---|
344 | scan_exit:
|
---|
345 | if (no_filearg) {
|
---|
346 | if (indtmp != Nullch)
|
---|
347 | indname = fetchname(indtmp, strippath, ok_to_create_file);
|
---|
348 | if (oldtmp != Nullch)
|
---|
349 | oldname = fetchname(oldtmp, strippath, ok_to_create_file);
|
---|
350 | if (newtmp != Nullch)
|
---|
351 | newname = fetchname(newtmp, strippath, ok_to_create_file);
|
---|
352 | if (oldname && newname) {
|
---|
353 | if (strlen(oldname) < strlen(newname))
|
---|
354 | filearg[0] = savestr(oldname);
|
---|
355 | else
|
---|
356 | filearg[0] = savestr(newname);
|
---|
357 | }
|
---|
358 | else if (oldname)
|
---|
359 | filearg[0] = savestr(oldname);
|
---|
360 | else if (newname)
|
---|
361 | filearg[0] = savestr(newname);
|
---|
362 | else if (indname)
|
---|
363 | filearg[0] = savestr(indname);
|
---|
364 | }
|
---|
365 | if (bestguess) {
|
---|
366 | free(bestguess);
|
---|
367 | bestguess = Nullch;
|
---|
368 | }
|
---|
369 | if (filearg[0] != Nullch)
|
---|
370 | bestguess = savestr(filearg[0]);
|
---|
371 | else if (indtmp != Nullch)
|
---|
372 | bestguess = fetchname(indtmp, strippath, TRUE);
|
---|
373 | else {
|
---|
374 | if (oldtmp != Nullch)
|
---|
375 | oldname = fetchname(oldtmp, strippath, TRUE);
|
---|
376 | if (newtmp != Nullch)
|
---|
377 | newname = fetchname(newtmp, strippath, TRUE);
|
---|
378 | if (oldname && newname) {
|
---|
379 | if (strlen(oldname) < strlen(newname))
|
---|
380 | bestguess = savestr(oldname);
|
---|
381 | else
|
---|
382 | bestguess = savestr(newname);
|
---|
383 | }
|
---|
384 | else if (oldname)
|
---|
385 | bestguess = savestr(oldname);
|
---|
386 | else if (newname)
|
---|
387 | bestguess = savestr(newname);
|
---|
388 | }
|
---|
389 | if (indtmp != Nullch)
|
---|
390 | free(indtmp);
|
---|
391 | if (oldtmp != Nullch)
|
---|
392 | free(oldtmp);
|
---|
393 | if (newtmp != Nullch)
|
---|
394 | free(newtmp);
|
---|
395 | if (indname != Nullch)
|
---|
396 | free(indname);
|
---|
397 | if (oldname != Nullch)
|
---|
398 | free(oldname);
|
---|
399 | if (newname != Nullch)
|
---|
400 | free(newname);
|
---|
401 | return retval;
|
---|
402 | }
|
---|
403 |
|
---|
404 | /* Remember where this patch ends so we know where to start up again. */
|
---|
405 |
|
---|
406 | void
|
---|
407 | next_intuit_at(file_pos,file_line)
|
---|
408 | long file_pos;
|
---|
409 | long file_line;
|
---|
410 | {
|
---|
411 | p_base = file_pos;
|
---|
412 | p_bline = file_line;
|
---|
413 | }
|
---|
414 |
|
---|
415 | /* Basically a verbose fseek() to the actual diff listing. */
|
---|
416 |
|
---|
417 | void
|
---|
418 | skip_to(file_pos,file_line)
|
---|
419 | long file_pos;
|
---|
420 | long file_line;
|
---|
421 | {
|
---|
422 | char *ret;
|
---|
423 |
|
---|
424 | assert(p_base <= file_pos);
|
---|
425 | if (verbose && p_base < file_pos) {
|
---|
426 | Fseek(pfp, p_base, 0);
|
---|
427 | say1("The text leading up to this was:\n--------------------------\n");
|
---|
428 | while (ftell(pfp) < file_pos) {
|
---|
429 | ret = fgets(buf, sizeof buf, pfp);
|
---|
430 | assert(ret != Nullch);
|
---|
431 | say2("|%s", buf);
|
---|
432 | }
|
---|
433 | say1("--------------------------\n");
|
---|
434 | }
|
---|
435 | else
|
---|
436 | Fseek(pfp, file_pos, 0);
|
---|
437 | p_input_line = file_line - 1;
|
---|
438 | }
|
---|
439 |
|
---|
440 | /* True if there is more of the current diff listing to process. */
|
---|
441 |
|
---|
442 | bool
|
---|
443 | another_hunk()
|
---|
444 | {
|
---|
445 | Reg1 char *s;
|
---|
446 | Reg8 char *ret;
|
---|
447 | Reg2 int context = 0;
|
---|
448 |
|
---|
449 | while (p_end >= 0) {
|
---|
450 | if (p_end == p_efake)
|
---|
451 | p_end = p_bfake; /* don't free twice */
|
---|
452 | #ifndef SMALL
|
---|
453 | else
|
---|
454 | free(p_line[p_end]);
|
---|
455 | #endif
|
---|
456 | p_end--;
|
---|
457 | }
|
---|
458 | assert(p_end == -1);
|
---|
459 | p_efake = -1;
|
---|
460 | #ifdef SMALL
|
---|
461 | if (sfp != Nullfp)
|
---|
462 | Fclose(sfp);
|
---|
463 | sfp = fopen(TMPSTRNAME, "w");
|
---|
464 | if (sfp == Nullfp)
|
---|
465 | fatal2("patch: can't create %s.\n", TMPSTRNAME);
|
---|
466 | #endif
|
---|
467 |
|
---|
468 | p_max = hunkmax; /* gets reduced when --- found */
|
---|
469 | if (diff_type == CONTEXT_DIFF || diff_type == NEW_CONTEXT_DIFF) {
|
---|
470 | long line_beginning = ftell(pfp);
|
---|
471 | /* file pos of the current line */
|
---|
472 | LINENUM repl_beginning = 0; /* index of --- line */
|
---|
473 | Reg4 LINENUM fillcnt = 0; /* #lines of missing ptrn or repl */
|
---|
474 | Reg5 LINENUM fillsrc; /* index of first line to copy */
|
---|
475 | Reg6 LINENUM filldst; /* index of first missing line */
|
---|
476 | bool ptrn_spaces_eaten = FALSE; /* ptrn was slightly misformed */
|
---|
477 | Reg9 bool repl_could_be_missing = TRUE;
|
---|
478 | /* no + or ! lines in this hunk */
|
---|
479 | bool repl_missing = FALSE; /* we are now backtracking */
|
---|
480 | long repl_backtrack_position = 0;
|
---|
481 | /* file pos of first repl line */
|
---|
482 | LINENUM repl_patch_line; /* input line number for same */
|
---|
483 | Reg7 LINENUM ptrn_copiable = 0;
|
---|
484 | /* # of copiable lines in ptrn */
|
---|
485 |
|
---|
486 | ret = pgets(buf, sizeof buf, pfp);
|
---|
487 | p_input_line++;
|
---|
488 | if (ret == Nullch || strnNE(buf, "********", 8)) {
|
---|
489 | next_intuit_at(line_beginning,p_input_line);
|
---|
490 | return FALSE;
|
---|
491 | }
|
---|
492 | p_context = 100;
|
---|
493 | p_hunk_beg = p_input_line + 1;
|
---|
494 | while (p_end < p_max) {
|
---|
495 | line_beginning = ftell(pfp);
|
---|
496 | ret = pgets(buf, sizeof buf, pfp);
|
---|
497 | p_input_line++;
|
---|
498 | if (ret == Nullch) {
|
---|
499 | if (p_max - p_end < 4)
|
---|
500 | Strcpy(buf, " \n"); /* assume blank lines got chopped */
|
---|
501 | else {
|
---|
502 | if (repl_beginning && repl_could_be_missing) {
|
---|
503 | repl_missing = TRUE;
|
---|
504 | goto hunk_done;
|
---|
505 | }
|
---|
506 | fatal1("Unexpected end of file in patch.\n");
|
---|
507 | }
|
---|
508 | }
|
---|
509 | p_end++;
|
---|
510 | assert(p_end < hunkmax);
|
---|
511 | p_char[p_end] = *buf;
|
---|
512 | #ifdef zilog
|
---|
513 | p_line[(short)p_end] = Nullch;
|
---|
514 | #else
|
---|
515 | #ifdef SMALL
|
---|
516 | p_line[p_end] = -1L;
|
---|
517 | p_len[p_end] = 0;
|
---|
518 | #else
|
---|
519 | p_line[p_end] = Nullch;
|
---|
520 | #endif
|
---|
521 | #endif
|
---|
522 | switch (*buf) {
|
---|
523 | case '*':
|
---|
524 | if (strnEQ(buf, "********", 8)) {
|
---|
525 | if (repl_beginning && repl_could_be_missing) {
|
---|
526 | repl_missing = TRUE;
|
---|
527 | goto hunk_done;
|
---|
528 | }
|
---|
529 | else
|
---|
530 | fatal2("Unexpected end of hunk at line %ld.\n",
|
---|
531 | p_input_line);
|
---|
532 | }
|
---|
533 | if (p_end != 0) {
|
---|
534 | if (repl_beginning && repl_could_be_missing) {
|
---|
535 | repl_missing = TRUE;
|
---|
536 | goto hunk_done;
|
---|
537 | }
|
---|
538 | fatal3("Unexpected *** at line %ld: %s", p_input_line, buf);
|
---|
539 | }
|
---|
540 | context = 0;
|
---|
541 | #ifdef SMALL
|
---|
542 | p_line[p_end] = saveStr(buf, p_len+p_end);
|
---|
543 | #else
|
---|
544 | p_line[p_end] = savestr(buf);
|
---|
545 | if (out_of_mem) {
|
---|
546 | p_end--;
|
---|
547 | return FALSE;
|
---|
548 | }
|
---|
549 | #endif
|
---|
550 | for (s=buf; *s && !isdigit(*s); s++) ;
|
---|
551 | if (!*s)
|
---|
552 | goto malformed;
|
---|
553 | if (strnEQ(s,"0,0",3))
|
---|
554 | strcpy(s,s+2);
|
---|
555 | p_first = (LINENUM) atol(s);
|
---|
556 | while (isdigit(*s)) s++;
|
---|
557 | if (*s == ',') {
|
---|
558 | for (; *s && !isdigit(*s); s++) ;
|
---|
559 | if (!*s)
|
---|
560 | goto malformed;
|
---|
561 | p_ptrn_lines = ((LINENUM)atol(s)) - p_first + 1;
|
---|
562 | }
|
---|
563 | else if (p_first)
|
---|
564 | p_ptrn_lines = 1;
|
---|
565 | else {
|
---|
566 | p_ptrn_lines = 0;
|
---|
567 | p_first = 1;
|
---|
568 | }
|
---|
569 | p_max = p_ptrn_lines + 6; /* we need this much at least */
|
---|
570 | while (p_max >= hunkmax)
|
---|
571 | grow_hunkmax();
|
---|
572 | p_max = hunkmax;
|
---|
573 | break;
|
---|
574 | case '-':
|
---|
575 | if (buf[1] == '-') {
|
---|
576 | if (repl_beginning ||
|
---|
577 | (p_end != p_ptrn_lines + 1 + (p_char[p_end-1] == '\n')))
|
---|
578 | {
|
---|
579 | if (p_end == 1) {
|
---|
580 | /* `old' lines were omitted - set up to fill */
|
---|
581 | /* them in from 'new' context lines. */
|
---|
582 | p_end = p_ptrn_lines + 1;
|
---|
583 | fillsrc = p_end + 1;
|
---|
584 | filldst = 1;
|
---|
585 | fillcnt = p_ptrn_lines;
|
---|
586 | }
|
---|
587 | else {
|
---|
588 | if (repl_beginning) {
|
---|
589 | if (repl_could_be_missing){
|
---|
590 | repl_missing = TRUE;
|
---|
591 | goto hunk_done;
|
---|
592 | }
|
---|
593 | fatal3(
|
---|
594 | "Duplicate \"---\" at line %ld--check line numbers at line %ld.\n",
|
---|
595 | p_input_line, p_hunk_beg + repl_beginning);
|
---|
596 | }
|
---|
597 | else {
|
---|
598 | fatal4(
|
---|
599 | "%s \"---\" at line %ld--check line numbers at line %ld.\n",
|
---|
600 | (p_end <= p_ptrn_lines
|
---|
601 | ? "Premature"
|
---|
602 | : "Overdue" ),
|
---|
603 | p_input_line, p_hunk_beg);
|
---|
604 | }
|
---|
605 | }
|
---|
606 | }
|
---|
607 | repl_beginning = p_end;
|
---|
608 | repl_backtrack_position = ftell(pfp);
|
---|
609 | repl_patch_line = p_input_line;
|
---|
610 | #ifdef SMALL
|
---|
611 | p_line[p_end] = saveStr(buf, p_len+p_end);
|
---|
612 | #else
|
---|
613 | p_line[p_end] = savestr(buf);
|
---|
614 | if (out_of_mem) {
|
---|
615 | p_end--;
|
---|
616 | return FALSE;
|
---|
617 | }
|
---|
618 | #endif
|
---|
619 | p_char[p_end] = '=';
|
---|
620 | for (s=buf; *s && !isdigit(*s); s++) ;
|
---|
621 | if (!*s)
|
---|
622 | goto malformed;
|
---|
623 | p_newfirst = (LINENUM) atol(s);
|
---|
624 | while (isdigit(*s)) s++;
|
---|
625 | if (*s == ',') {
|
---|
626 | for (; *s && !isdigit(*s); s++) ;
|
---|
627 | if (!*s)
|
---|
628 | goto malformed;
|
---|
629 | p_repl_lines = ((LINENUM)atol(s)) - p_newfirst + 1;
|
---|
630 | }
|
---|
631 | else if (p_newfirst)
|
---|
632 | p_repl_lines = 1;
|
---|
633 | else {
|
---|
634 | p_repl_lines = 0;
|
---|
635 | p_newfirst = 1;
|
---|
636 | }
|
---|
637 | p_max = p_repl_lines + p_end;
|
---|
638 | if (p_max > MAXHUNKSIZE)
|
---|
639 | fatal4("Hunk too large (%ld lines) at line %ld: %s",
|
---|
640 | p_max, p_input_line, buf);
|
---|
641 | while (p_max >= hunkmax)
|
---|
642 | grow_hunkmax();
|
---|
643 | if (p_repl_lines != ptrn_copiable)
|
---|
644 | repl_could_be_missing = FALSE;
|
---|
645 | break;
|
---|
646 | }
|
---|
647 | goto change_line;
|
---|
648 | case '+': case '!':
|
---|
649 | repl_could_be_missing = FALSE;
|
---|
650 | change_line:
|
---|
651 | if (buf[1] == '\n' && canonicalize)
|
---|
652 | strcpy(buf+1," \n");
|
---|
653 | if (!isspace(buf[1]) && buf[1] != '>' && buf[1] != '<' &&
|
---|
654 | repl_beginning && repl_could_be_missing) {
|
---|
655 | repl_missing = TRUE;
|
---|
656 | goto hunk_done;
|
---|
657 | }
|
---|
658 | if (context > 0) {
|
---|
659 | if (context < p_context)
|
---|
660 | p_context = context;
|
---|
661 | context = -1000;
|
---|
662 | }
|
---|
663 | #ifdef SMALL
|
---|
664 | p_line[p_end] = saveStr(buf+2, p_len+p_end);
|
---|
665 | #else
|
---|
666 | p_line[p_end] = savestr(buf+2);
|
---|
667 | if (out_of_mem) {
|
---|
668 | p_end--;
|
---|
669 | return FALSE;
|
---|
670 | }
|
---|
671 | #endif
|
---|
672 | break;
|
---|
673 | case '\t': case '\n': /* assume the 2 spaces got eaten */
|
---|
674 | if (repl_beginning && repl_could_be_missing &&
|
---|
675 | (!ptrn_spaces_eaten || diff_type == NEW_CONTEXT_DIFF) ) {
|
---|
676 | repl_missing = TRUE;
|
---|
677 | goto hunk_done;
|
---|
678 | }
|
---|
679 | #ifdef SMALL
|
---|
680 | p_line[p_end] = saveStr(buf, p_len+p_end);
|
---|
681 | #else
|
---|
682 | p_line[p_end] = savestr(buf);
|
---|
683 | if (out_of_mem) {
|
---|
684 | p_end--;
|
---|
685 | return FALSE;
|
---|
686 | }
|
---|
687 | #endif
|
---|
688 | if (p_end != p_ptrn_lines + 1) {
|
---|
689 | ptrn_spaces_eaten |= (repl_beginning != 0);
|
---|
690 | context++;
|
---|
691 | if (!repl_beginning)
|
---|
692 | ptrn_copiable++;
|
---|
693 | p_char[p_end] = ' ';
|
---|
694 | }
|
---|
695 | break;
|
---|
696 | case ' ':
|
---|
697 | if (!isspace(buf[1]) &&
|
---|
698 | repl_beginning && repl_could_be_missing) {
|
---|
699 | repl_missing = TRUE;
|
---|
700 | goto hunk_done;
|
---|
701 | }
|
---|
702 | context++;
|
---|
703 | if (!repl_beginning)
|
---|
704 | ptrn_copiable++;
|
---|
705 | #ifdef SMALL
|
---|
706 | p_line[p_end] = saveStr(buf+2, p_len+p_end);
|
---|
707 | #else
|
---|
708 | p_line[p_end] = savestr(buf+2);
|
---|
709 | if (out_of_mem) {
|
---|
710 | p_end--;
|
---|
711 | return FALSE;
|
---|
712 | }
|
---|
713 | #endif
|
---|
714 | break;
|
---|
715 | default:
|
---|
716 | if (repl_beginning && repl_could_be_missing) {
|
---|
717 | repl_missing = TRUE;
|
---|
718 | goto hunk_done;
|
---|
719 | }
|
---|
720 | goto malformed;
|
---|
721 | }
|
---|
722 | /* set up p_len for strncmp() so we don't have to */
|
---|
723 | /* assume null termination */
|
---|
724 | #ifndef SMALL
|
---|
725 | if (p_line[p_end])
|
---|
726 | p_len[p_end] = strlen(p_line[p_end]);
|
---|
727 | else
|
---|
728 | p_len[p_end] = 0;
|
---|
729 | #endif
|
---|
730 | }
|
---|
731 |
|
---|
732 | hunk_done:
|
---|
733 | if (p_end >=0 && !repl_beginning)
|
---|
734 | fatal2("No --- found in patch at line %ld\n", pch_hunk_beg());
|
---|
735 |
|
---|
736 | if (repl_missing) {
|
---|
737 |
|
---|
738 | /* reset state back to just after --- */
|
---|
739 | p_input_line = repl_patch_line;
|
---|
740 | #ifndef SMALL
|
---|
741 | for (p_end--; p_end > repl_beginning; p_end--)
|
---|
742 | free(p_line[p_end]);
|
---|
743 | #endif
|
---|
744 | Fseek(pfp, repl_backtrack_position, 0);
|
---|
745 |
|
---|
746 | /* redundant 'new' context lines were omitted - set */
|
---|
747 | /* up to fill them in from the old file context */
|
---|
748 | fillsrc = 1;
|
---|
749 | filldst = repl_beginning+1;
|
---|
750 | fillcnt = p_repl_lines;
|
---|
751 | p_end = p_max;
|
---|
752 | }
|
---|
753 |
|
---|
754 | if (diff_type == CONTEXT_DIFF &&
|
---|
755 | (fillcnt || (p_first > 1 && ptrn_copiable > 2*p_context)) ) {
|
---|
756 | if (verbose)
|
---|
757 | say4("%s\n%s\n%s\n",
|
---|
758 | "(Fascinating--this is really a new-style context diff but without",
|
---|
759 | "the telltale extra asterisks on the *** line that usually indicate",
|
---|
760 | "the new style...)");
|
---|
761 | diff_type = NEW_CONTEXT_DIFF;
|
---|
762 | }
|
---|
763 |
|
---|
764 | /* if there were omitted context lines, fill them in now */
|
---|
765 | if (fillcnt) {
|
---|
766 | p_bfake = filldst; /* remember where not to free() */
|
---|
767 | p_efake = filldst + fillcnt - 1;
|
---|
768 | while (fillcnt-- > 0) {
|
---|
769 | while (fillsrc <= p_end && p_char[fillsrc] != ' ')
|
---|
770 | fillsrc++;
|
---|
771 | if (fillsrc > p_end)
|
---|
772 | fatal2("Replacement text or line numbers mangled in hunk at line %ld\n",
|
---|
773 | p_hunk_beg);
|
---|
774 | p_line[filldst] = p_line[fillsrc];
|
---|
775 | p_char[filldst] = p_char[fillsrc];
|
---|
776 | p_len[filldst] = p_len[fillsrc];
|
---|
777 | fillsrc++; filldst++;
|
---|
778 | }
|
---|
779 | while (fillsrc <= p_end && fillsrc != repl_beginning &&
|
---|
780 | p_char[fillsrc] != ' ')
|
---|
781 | fillsrc++;
|
---|
782 | #ifdef DEBUGGING
|
---|
783 | if (debug & 64)
|
---|
784 | printf("fillsrc %ld, filldst %ld, rb %ld, e+1 %ld\n",
|
---|
785 | fillsrc,filldst,repl_beginning,p_end+1);
|
---|
786 | #endif
|
---|
787 | assert(fillsrc==p_end+1 || fillsrc==repl_beginning);
|
---|
788 | assert(filldst==p_end+1 || filldst==repl_beginning);
|
---|
789 | }
|
---|
790 | }
|
---|
791 | else { /* normal diff--fake it up */
|
---|
792 | char hunk_type;
|
---|
793 | Reg3 int i;
|
---|
794 | LINENUM min, max;
|
---|
795 | long line_beginning = ftell(pfp);
|
---|
796 |
|
---|
797 | p_context = 0;
|
---|
798 | ret = pgets(buf, sizeof buf, pfp);
|
---|
799 | p_input_line++;
|
---|
800 | if (ret == Nullch || !isdigit(*buf)) {
|
---|
801 | next_intuit_at(line_beginning,p_input_line);
|
---|
802 | return FALSE;
|
---|
803 | }
|
---|
804 | p_first = (LINENUM)atol(buf);
|
---|
805 | for (s=buf; isdigit(*s); s++) ;
|
---|
806 | if (*s == ',') {
|
---|
807 | p_ptrn_lines = (LINENUM)atol(++s) - p_first + 1;
|
---|
808 | while (isdigit(*s)) s++;
|
---|
809 | }
|
---|
810 | else
|
---|
811 | p_ptrn_lines = (*s != 'a');
|
---|
812 | hunk_type = *s;
|
---|
813 | if (hunk_type == 'a')
|
---|
814 | p_first++; /* do append rather than insert */
|
---|
815 | min = (LINENUM)atol(++s);
|
---|
816 | for (; isdigit(*s); s++) ;
|
---|
817 | if (*s == ',')
|
---|
818 | max = (LINENUM)atol(++s);
|
---|
819 | else
|
---|
820 | max = min;
|
---|
821 | if (hunk_type == 'd')
|
---|
822 | min++;
|
---|
823 | p_end = p_ptrn_lines + 1 + max - min + 1;
|
---|
824 | if (p_end > MAXHUNKSIZE)
|
---|
825 | fatal4("Hunk too large (%ld lines) at line %ld: %s",
|
---|
826 | p_end, p_input_line, buf);
|
---|
827 | while (p_end >= hunkmax)
|
---|
828 | grow_hunkmax();
|
---|
829 | p_newfirst = min;
|
---|
830 | p_repl_lines = max - min + 1;
|
---|
831 | Sprintf(buf, "*** %ld,%ld\n", p_first, p_first + p_ptrn_lines - 1);
|
---|
832 | #ifdef SMALL
|
---|
833 | p_line[0] = saveStr(buf, p_len);
|
---|
834 | #else
|
---|
835 | p_line[0] = savestr(buf);
|
---|
836 | if (out_of_mem) {
|
---|
837 | p_end = -1;
|
---|
838 | return FALSE;
|
---|
839 | }
|
---|
840 | #endif
|
---|
841 | p_char[0] = '*';
|
---|
842 | for (i=1; i<=p_ptrn_lines; i++) {
|
---|
843 | ret = pgets(buf, sizeof buf, pfp);
|
---|
844 | p_input_line++;
|
---|
845 | if (ret == Nullch)
|
---|
846 | fatal2("Unexpected end of file in patch at line %ld.\n",
|
---|
847 | p_input_line);
|
---|
848 | if (*buf != '<')
|
---|
849 | fatal2("< expected at line %ld of patch.\n", p_input_line);
|
---|
850 | #ifdef SMALL
|
---|
851 | p_line[i] = saveStr(buf+2, p_len+i);
|
---|
852 | #else
|
---|
853 | p_line[i] = savestr(buf+2);
|
---|
854 | if (out_of_mem) {
|
---|
855 | p_end = i-1;
|
---|
856 | return FALSE;
|
---|
857 | }
|
---|
858 | #endif
|
---|
859 | #ifndef SMALL
|
---|
860 | p_len[i] = strlen(p_line[i]);
|
---|
861 | #endif
|
---|
862 | p_char[i] = '-';
|
---|
863 | }
|
---|
864 | if (hunk_type == 'c') {
|
---|
865 | ret = pgets(buf, sizeof buf, pfp);
|
---|
866 | p_input_line++;
|
---|
867 | if (ret == Nullch)
|
---|
868 | fatal2("Unexpected end of file in patch at line %ld.\n",
|
---|
869 | p_input_line);
|
---|
870 | if (*buf != '-')
|
---|
871 | fatal2("--- expected at line %ld of patch.\n", p_input_line);
|
---|
872 | }
|
---|
873 | Sprintf(buf, "--- %ld,%ld\n", min, max);
|
---|
874 | #ifdef SMALL
|
---|
875 | p_line[i] = saveStr(buf, p_len+i);
|
---|
876 | #else
|
---|
877 | p_line[i] = savestr(buf);
|
---|
878 | if (out_of_mem) {
|
---|
879 | p_end = i-1;
|
---|
880 | return FALSE;
|
---|
881 | }
|
---|
882 | #endif
|
---|
883 | p_char[i] = '=';
|
---|
884 | for (i++; i<=p_end; i++) {
|
---|
885 | ret = pgets(buf, sizeof buf, pfp);
|
---|
886 | p_input_line++;
|
---|
887 | if (ret == Nullch)
|
---|
888 | fatal2("Unexpected end of file in patch at line %ld.\n",
|
---|
889 | p_input_line);
|
---|
890 | if (*buf != '>')
|
---|
891 | fatal2("> expected at line %ld of patch.\n", p_input_line);
|
---|
892 | #ifdef SMALL
|
---|
893 | p_line[i] = saveStr(buf+2, p_len+i);
|
---|
894 | #else
|
---|
895 | p_line[i] = savestr(buf+2);
|
---|
896 | if (out_of_mem) {
|
---|
897 | p_end = i-1;
|
---|
898 | return FALSE;
|
---|
899 | }
|
---|
900 | #endif
|
---|
901 | #ifndef SMALL
|
---|
902 | p_len[i] = strlen(p_line[i]);
|
---|
903 | #endif
|
---|
904 | p_char[i] = '+';
|
---|
905 | }
|
---|
906 | }
|
---|
907 | if (reverse) /* backwards patch? */
|
---|
908 | if (!pch_swap())
|
---|
909 | say1("Not enough memory to swap next hunk!\n");
|
---|
910 | #ifdef SMALL
|
---|
911 | Fclose(sfp);
|
---|
912 | sfp = fopen(TMPSTRNAME, "r");
|
---|
913 | #endif
|
---|
914 | #ifdef DEBUGGING
|
---|
915 | if (debug & 2) {
|
---|
916 | int i;
|
---|
917 | char special;
|
---|
918 |
|
---|
919 | for (i=0; i <= p_end; i++) {
|
---|
920 | if (i == p_ptrn_lines)
|
---|
921 | special = '^';
|
---|
922 | else
|
---|
923 | special = ' ';
|
---|
924 | #ifdef SMALL
|
---|
925 | fprintf(stderr, "%3d %c %c %s", i, p_char[i], special, pfetch(i));
|
---|
926 | #else
|
---|
927 | fprintf(stderr, "%3d %c %c %s", i, p_char[i], special, p_line[i]);
|
---|
928 | #endif
|
---|
929 | Fflush(stderr);
|
---|
930 | }
|
---|
931 | }
|
---|
932 | #endif
|
---|
933 | if (p_end+1 < hunkmax) /* paranoia reigns supreme... */
|
---|
934 | p_char[p_end+1] = '^'; /* add a stopper for apply_hunk */
|
---|
935 | return TRUE;
|
---|
936 |
|
---|
937 | malformed:
|
---|
938 | #ifdef SMALL
|
---|
939 | Fclose(sfp);
|
---|
940 | sfp = Nullfp;
|
---|
941 | #endif
|
---|
942 | fatal3("Malformed patch at line %ld: %s", p_input_line, buf);
|
---|
943 | /* about as informative as "Syntax error" in C */
|
---|
944 | return FALSE; /* for lint */
|
---|
945 | }
|
---|
946 |
|
---|
947 | /* Input a line from the patch file, worrying about indentation. */
|
---|
948 |
|
---|
949 | char *
|
---|
950 | pgets(bf,sz,fp)
|
---|
951 | char *bf;
|
---|
952 | int sz;
|
---|
953 | FILE *fp;
|
---|
954 | {
|
---|
955 | char *ret = fgets(bf, sz, fp);
|
---|
956 | Reg1 char *s;
|
---|
957 | Reg2 int indent = 0;
|
---|
958 |
|
---|
959 | if (p_indent && ret != Nullch) {
|
---|
960 | for (s=buf;
|
---|
961 | indent < p_indent && (*s == ' ' || *s == '\t' || *s == 'X'); s++) {
|
---|
962 | if (*s == '\t')
|
---|
963 | indent += 8 - (indent % 7);
|
---|
964 | else
|
---|
965 | indent++;
|
---|
966 | }
|
---|
967 | if (buf != s)
|
---|
968 | Strcpy(buf, s);
|
---|
969 | }
|
---|
970 | return ret;
|
---|
971 | }
|
---|
972 |
|
---|
973 | /* Reverse the old and new portions of the current hunk. */
|
---|
974 |
|
---|
975 | bool
|
---|
976 | pch_swap()
|
---|
977 | {
|
---|
978 | #ifdef SMALL
|
---|
979 | long *tp_line; /* the text of the hunk */
|
---|
980 | #else
|
---|
981 | char **tp_line; /* the text of the hunk */
|
---|
982 | #endif
|
---|
983 | short *tp_len; /* length of each line */
|
---|
984 | char *tp_char; /* +, -, and ! */
|
---|
985 | Reg1 LINENUM i;
|
---|
986 | Reg2 LINENUM n;
|
---|
987 | bool blankline = FALSE;
|
---|
988 | Reg3 char *s;
|
---|
989 |
|
---|
990 | i = p_first;
|
---|
991 | p_first = p_newfirst;
|
---|
992 | p_newfirst = i;
|
---|
993 |
|
---|
994 | /* make a scratch copy */
|
---|
995 |
|
---|
996 | tp_line = p_line;
|
---|
997 | tp_len = p_len;
|
---|
998 | tp_char = p_char;
|
---|
999 | #ifdef SMALL
|
---|
1000 | p_line = Null(long*); /* force set_hunkmax to allocate again */
|
---|
1001 | #else
|
---|
1002 | p_line = Null(char**); /* force set_hunkmax to allocate again */
|
---|
1003 | #endif
|
---|
1004 | p_len = Null(short*);
|
---|
1005 | p_char = Nullch;
|
---|
1006 | set_hunkmax();
|
---|
1007 | #ifdef SMALL
|
---|
1008 | if (p_line == Null(long*) || p_len == Null(short*) || p_char == Nullch) {
|
---|
1009 | #else
|
---|
1010 | if (p_line == Null(char**) || p_len == Null(short*) || p_char == Nullch) {
|
---|
1011 | #endif
|
---|
1012 | #ifndef lint
|
---|
1013 | #ifdef SMALL
|
---|
1014 | if (p_line == Null(long*))
|
---|
1015 | #else
|
---|
1016 | if (p_line == Null(char**))
|
---|
1017 | #endif
|
---|
1018 | free((char*)p_line);
|
---|
1019 | p_line = tp_line;
|
---|
1020 | if (p_len == Null(short*))
|
---|
1021 | free((char*)p_len);
|
---|
1022 | p_len = tp_len;
|
---|
1023 | #endif
|
---|
1024 | if (p_char == Nullch)
|
---|
1025 | free((char*)p_char);
|
---|
1026 | p_char = tp_char;
|
---|
1027 | return FALSE; /* not enough memory to swap hunk! */
|
---|
1028 | }
|
---|
1029 |
|
---|
1030 | /* now turn the new into the old */
|
---|
1031 |
|
---|
1032 | i = p_ptrn_lines + 1;
|
---|
1033 | if (tp_char[i] == '\n') { /* account for possible blank line */
|
---|
1034 | blankline = TRUE;
|
---|
1035 | i++;
|
---|
1036 | }
|
---|
1037 | if (p_efake >= 0) { /* fix non-freeable ptr range */
|
---|
1038 | if (p_efake <= i)
|
---|
1039 | n = p_end - i + 1;
|
---|
1040 | else
|
---|
1041 | n = -i;
|
---|
1042 | p_efake += n;
|
---|
1043 | p_bfake += n;
|
---|
1044 | }
|
---|
1045 | for (n=0; i <= p_end; i++,n++) {
|
---|
1046 | p_line[n] = tp_line[i];
|
---|
1047 | p_char[n] = tp_char[i];
|
---|
1048 | if (p_char[n] == '+')
|
---|
1049 | p_char[n] = '-';
|
---|
1050 | p_len[n] = tp_len[i];
|
---|
1051 | }
|
---|
1052 | if (blankline) {
|
---|
1053 | i = p_ptrn_lines + 1;
|
---|
1054 | p_line[n] = tp_line[i];
|
---|
1055 | p_char[n] = tp_char[i];
|
---|
1056 | p_len[n] = tp_len[i];
|
---|
1057 | n++;
|
---|
1058 | }
|
---|
1059 | assert(p_char[0] == '=');
|
---|
1060 | p_char[0] = '*';
|
---|
1061 | #ifdef SMALL
|
---|
1062 | strEdit(p_line[0], '*', '-');
|
---|
1063 | #else
|
---|
1064 | for (s=p_line[0]; *s; s++)
|
---|
1065 | if (*s == '-')
|
---|
1066 | *s = '*';
|
---|
1067 | #endif
|
---|
1068 |
|
---|
1069 | /* now turn the old into the new */
|
---|
1070 |
|
---|
1071 | assert(tp_char[0] == '*');
|
---|
1072 | tp_char[0] = '=';
|
---|
1073 | #ifdef SMALL
|
---|
1074 | strEdit(tp_line[0], '-', '*');
|
---|
1075 | #else
|
---|
1076 | for (s=tp_line[0]; *s; s++)
|
---|
1077 | if (*s == '*')
|
---|
1078 | *s = '-';
|
---|
1079 | #endif
|
---|
1080 | for (i=0; n <= p_end; i++,n++) {
|
---|
1081 | p_line[n] = tp_line[i];
|
---|
1082 | p_char[n] = tp_char[i];
|
---|
1083 | if (p_char[n] == '-')
|
---|
1084 | p_char[n] = '+';
|
---|
1085 | p_len[n] = tp_len[i];
|
---|
1086 | }
|
---|
1087 | assert(i == p_ptrn_lines + 1);
|
---|
1088 | i = p_ptrn_lines;
|
---|
1089 | p_ptrn_lines = p_repl_lines;
|
---|
1090 | p_repl_lines = i;
|
---|
1091 | #ifndef lint
|
---|
1092 | #ifdef SMALL
|
---|
1093 | if (tp_line == Null(long*))
|
---|
1094 | #else
|
---|
1095 | if (tp_line == Null(char**))
|
---|
1096 | #endif
|
---|
1097 | free((char*)tp_line);
|
---|
1098 | if (tp_len == Null(short*))
|
---|
1099 | free((char*)tp_len);
|
---|
1100 | #endif
|
---|
1101 | if (tp_char == Nullch)
|
---|
1102 | free((char*)tp_char);
|
---|
1103 | return TRUE;
|
---|
1104 | }
|
---|
1105 |
|
---|
1106 | /* Return the specified line position in the old file of the old context. */
|
---|
1107 |
|
---|
1108 | LINENUM
|
---|
1109 | pch_first()
|
---|
1110 | {
|
---|
1111 | return p_first;
|
---|
1112 | }
|
---|
1113 |
|
---|
1114 | /* Return the number of lines of old context. */
|
---|
1115 |
|
---|
1116 | LINENUM
|
---|
1117 | pch_ptrn_lines()
|
---|
1118 | {
|
---|
1119 | return p_ptrn_lines;
|
---|
1120 | }
|
---|
1121 |
|
---|
1122 | /* Return the probable line position in the new file of the first line. */
|
---|
1123 |
|
---|
1124 | LINENUM
|
---|
1125 | pch_newfirst()
|
---|
1126 | {
|
---|
1127 | return p_newfirst;
|
---|
1128 | }
|
---|
1129 |
|
---|
1130 | /* Return the number of lines in the replacement text including context. */
|
---|
1131 |
|
---|
1132 | LINENUM
|
---|
1133 | pch_repl_lines()
|
---|
1134 | {
|
---|
1135 | return p_repl_lines;
|
---|
1136 | }
|
---|
1137 |
|
---|
1138 | /* Return the number of lines in the whole hunk. */
|
---|
1139 |
|
---|
1140 | LINENUM
|
---|
1141 | pch_end()
|
---|
1142 | {
|
---|
1143 | return p_end;
|
---|
1144 | }
|
---|
1145 |
|
---|
1146 | /* Return the number of context lines before the first changed line. */
|
---|
1147 |
|
---|
1148 | LINENUM
|
---|
1149 | pch_context()
|
---|
1150 | {
|
---|
1151 | return p_context;
|
---|
1152 | }
|
---|
1153 |
|
---|
1154 | /* Return the length of a particular patch line. */
|
---|
1155 |
|
---|
1156 | short
|
---|
1157 | pch_line_len(line)
|
---|
1158 | LINENUM line;
|
---|
1159 | {
|
---|
1160 | return p_len[line];
|
---|
1161 | }
|
---|
1162 |
|
---|
1163 | /* Return the control character (+, -, *, !, etc) for a patch line. */
|
---|
1164 |
|
---|
1165 | char
|
---|
1166 | pch_char(line)
|
---|
1167 | LINENUM line;
|
---|
1168 | {
|
---|
1169 | return p_char[line];
|
---|
1170 | }
|
---|
1171 |
|
---|
1172 | /* Return a pointer to a particular patch line. */
|
---|
1173 |
|
---|
1174 | #ifdef SMALL
|
---|
1175 | long
|
---|
1176 | saveStr(str, plen)
|
---|
1177 | char *str;
|
---|
1178 | short *plen;
|
---|
1179 | {
|
---|
1180 | long pos, ftell();
|
---|
1181 | int len;
|
---|
1182 |
|
---|
1183 | pos = ftell(sfp);
|
---|
1184 | len = strlen(str);
|
---|
1185 | fwrite(str, sizeof(char), len+1, sfp);
|
---|
1186 | *plen = len;
|
---|
1187 | return pos;
|
---|
1188 | }
|
---|
1189 |
|
---|
1190 | char *
|
---|
1191 | pfetch(line)
|
---|
1192 | LINENUM line;
|
---|
1193 | {
|
---|
1194 | static char *s, strbuf[BUFSIZ];
|
---|
1195 | int i, c;
|
---|
1196 |
|
---|
1197 | if (p_line[line] == -1L)
|
---|
1198 | return Nullch;
|
---|
1199 | else {
|
---|
1200 | Fseek(sfp, p_line[line], 0);
|
---|
1201 | for (i = 0, s = strbuf;
|
---|
1202 | i < BUFSIZ && (c = fgetc(sfp)) != EOF && c; i++)
|
---|
1203 | *s++ = c;
|
---|
1204 | if (i == BUFSIZ)
|
---|
1205 | fatal2("too long line (%.40s ..\n", strbuf);
|
---|
1206 | }
|
---|
1207 | *s = '\0';
|
---|
1208 | return strbuf;
|
---|
1209 | }
|
---|
1210 |
|
---|
1211 | void
|
---|
1212 | strEdit(pos, to, from)
|
---|
1213 | long pos;
|
---|
1214 | int to, from;
|
---|
1215 | {
|
---|
1216 | static char *s, strbuf[BUFSIZ];
|
---|
1217 | int i, c;
|
---|
1218 |
|
---|
1219 | if (pos != -1L) {
|
---|
1220 | for (i = 0, s = strbuf;
|
---|
1221 | i < BUFSIZ && (c = fgetc(sfp)) != EOF && c; i++)
|
---|
1222 | *s++ = c;
|
---|
1223 | for (s = strbuf; *s; s++)
|
---|
1224 | if (*s == from)
|
---|
1225 | *s = to;
|
---|
1226 | fwrite(strbuf, sizeof(char), i+1, sfp);
|
---|
1227 | }
|
---|
1228 | }
|
---|
1229 | #else
|
---|
1230 | char *
|
---|
1231 | pfetch(line)
|
---|
1232 | LINENUM line;
|
---|
1233 | {
|
---|
1234 | return p_line[line];
|
---|
1235 | }
|
---|
1236 | #endif
|
---|
1237 |
|
---|
1238 | /* Return where in the patch file this hunk began, for error messages. */
|
---|
1239 |
|
---|
1240 | LINENUM
|
---|
1241 | pch_hunk_beg()
|
---|
1242 | {
|
---|
1243 | return p_hunk_beg;
|
---|
1244 | }
|
---|
1245 |
|
---|
1246 | /* Apply an ed script by feeding ed itself. */
|
---|
1247 |
|
---|
1248 | void
|
---|
1249 | do_ed_script()
|
---|
1250 | {
|
---|
1251 | Reg1 char *t;
|
---|
1252 | Reg2 long beginning_of_this_line;
|
---|
1253 | Reg3 bool this_line_is_command = FALSE;
|
---|
1254 | Reg4 FILE *pipefp;
|
---|
1255 |
|
---|
1256 | if (!skip_rest_of_patch) {
|
---|
1257 | Unlink(TMPOUTNAME);
|
---|
1258 | copy_file(filearg[0], TMPOUTNAME);
|
---|
1259 | if (verbose)
|
---|
1260 | Sprintf(buf, "/bin/ed %s", TMPOUTNAME);
|
---|
1261 | else
|
---|
1262 | Sprintf(buf, "/bin/ed - %s", TMPOUTNAME);
|
---|
1263 | pipefp = popen(buf, "w");
|
---|
1264 | }
|
---|
1265 | for (;;) {
|
---|
1266 | beginning_of_this_line = ftell(pfp);
|
---|
1267 | if (pgets(buf, sizeof buf, pfp) == Nullch) {
|
---|
1268 | next_intuit_at(beginning_of_this_line,p_input_line);
|
---|
1269 | break;
|
---|
1270 | }
|
---|
1271 | p_input_line++;
|
---|
1272 | for (t=buf; isdigit(*t) || *t == ','; t++) ;
|
---|
1273 | this_line_is_command = (isdigit(*buf) &&
|
---|
1274 | (*t == 'd' || *t == 'c' || *t == 'a') );
|
---|
1275 | if (this_line_is_command) {
|
---|
1276 | if (!skip_rest_of_patch)
|
---|
1277 | fputs(buf, pipefp);
|
---|
1278 | if (*t != 'd') {
|
---|
1279 | while (pgets(buf, sizeof buf, pfp) != Nullch) {
|
---|
1280 | p_input_line++;
|
---|
1281 | if (!skip_rest_of_patch)
|
---|
1282 | fputs(buf, pipefp);
|
---|
1283 | if (strEQ(buf, ".\n"))
|
---|
1284 | break;
|
---|
1285 | }
|
---|
1286 | }
|
---|
1287 | }
|
---|
1288 | else {
|
---|
1289 | next_intuit_at(beginning_of_this_line,p_input_line);
|
---|
1290 | break;
|
---|
1291 | }
|
---|
1292 | }
|
---|
1293 | if (skip_rest_of_patch)
|
---|
1294 | return;
|
---|
1295 | fprintf(pipefp, "w\n");
|
---|
1296 | fprintf(pipefp, "q\n");
|
---|
1297 | Fflush(pipefp);
|
---|
1298 | Pclose(pipefp);
|
---|
1299 | ignore_signals();
|
---|
1300 | if (move_file(TMPOUTNAME, outname) < 0) {
|
---|
1301 | toutkeep = TRUE;
|
---|
1302 | chmod(TMPOUTNAME, filemode);
|
---|
1303 | }
|
---|
1304 | else
|
---|
1305 | chmod(outname, filemode);
|
---|
1306 | set_signals(1);
|
---|
1307 | }
|
---|