1 /* reading patches */
2 
3 /* Copyright (C) 1986, 1987, 1988 Larry Wall
4 
5    Copyright (C) 1990-1993, 1997-2003, 2006, 2009-2012 Free Software
6    Foundation, Inc.
7 
8    This program is free software: you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation, either version 3 of the License, or
11    (at your option) any later version.
12 
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17 
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20 
21 #define XTERN extern
22 #include <common.h>
23 #include <dirname.h>
24 #include <inp.h>
25 #include <quotearg.h>
26 #include <util.h>
27 #include <xalloc.h>
28 #include <xmemdup0.h>
29 #undef XTERN
30 #define XTERN
31 #include <pch.h>
32 #if HAVE_SETMODE_DOS
33 # include <io.h>
34 #endif
35 #include <safe.h>
36 #include <sys/wait.h>
37 
38 #define INITHUNKMAX 125			/* initial dynamic allocation size */
39 
40 /* Patch (diff listing) abstract type. */
41 
42 static FILE *pfp;			/* patch file pointer */
43 static int p_says_nonexistent[2];	/* [0] for old file, [1] for new:
44 		0 for existent and nonempty,
45 		1 for existent and probably (but not necessarily) empty,
46 		2 for nonexistent */
47 static int p_rfc934_nesting;		/* RFC 934 nesting level */
48 static char *p_name[3];			/* filenames in patch headers */
49 static char const *invalid_names[2];
50 bool p_copy[2];				/* Does this patch create a copy? */
51 bool p_rename[2];			/* Does this patch rename a file? */
52 static char *p_timestr[2];		/* timestamps as strings */
53 static char *p_sha1[2];			/* SHA1 checksums */
54 static mode_t p_mode[2];		/* file modes */
55 static off_t p_filesize;		/* size of the patch file */
56 static lin p_first;			/* 1st line number */
57 static lin p_newfirst;			/* 1st line number of replacement */
58 static lin p_ptrn_lines;		/* # lines in pattern */
59 static lin p_repl_lines;		/* # lines in replacement text */
60 static lin p_end = -1;			/* last line in hunk */
61 static lin p_max;			/* max allowed value of p_end */
62 static lin p_prefix_context;		/* # of prefix context lines */
63 static lin p_suffix_context;		/* # of suffix context lines */
64 static lin p_input_line;		/* current line # from patch file */
65 static char **p_line;			/* the text of the hunk */
66 static size_t *p_len;			/* line length including \n if any */
67 static char *p_Char;			/* +, -, and ! */
68 static lin hunkmax = INITHUNKMAX;	/* size of above arrays */
69 static size_t p_indent;			/* indent to patch */
70 static bool p_strip_trailing_cr;	/* true if stripping trailing \r */
71 static bool p_pass_comments_through;	/* true if not ignoring # lines */
72 static file_offset p_base;		/* where to intuit this time */
73 static lin p_bline;			/* line # of p_base */
74 static file_offset p_start;		/* where intuit found a patch */
75 static lin p_sline;			/* and the line number for it */
76 static lin p_hunk_beg;			/* line number of current hunk */
77 static lin p_efake = -1;		/* end of faked up lines--don't free */
78 static lin p_bfake = -1;		/* beg of faked up lines */
79 static char *p_c_function;		/* the C function a hunk is in */
80 static bool p_git_diff;			/* true if this is a git style diff */
81 
82 static char *scan_linenum (char *, lin *);
83 static enum diff intuit_diff_type (bool, mode_t *);
84 static enum nametype best_name (char * const *, int const *);
85 static int prefix_components (char *, bool);
86 static size_t pget_line (size_t, int, bool, bool);
87 static size_t get_line (void);
88 static bool incomplete_line (void);
89 static bool grow_hunkmax (void);
90 static void malformed (void) __attribute__ ((noreturn));
91 static void next_intuit_at (file_offset, lin);
92 static void skip_to (file_offset, lin);
93 static char get_ed_command_letter (char const *);
94 
95 /* Prepare to look for the next patch in the patch file. */
96 
97 void
re_patch(void)98 re_patch (void)
99 {
100     p_first = 0;
101     p_newfirst = 0;
102     p_ptrn_lines = 0;
103     p_repl_lines = 0;
104     p_end = -1;
105     p_max = 0;
106     p_indent = 0;
107     p_strip_trailing_cr = false;
108 }
109 
110 /* Open the patch file at the beginning of time. */
111 
112 void
open_patch_file(char const * filename)113 open_patch_file (char const *filename)
114 {
115     file_offset file_pos = 0;
116     file_offset pos;
117     struct stat st;
118 
119     if (!filename || !*filename || strEQ (filename, "-"))
120       pfp = stdin;
121     else
122       {
123 	pfp = fopen (filename, binary_transput ? "rb" : "r");
124 	if (!pfp)
125 	  pfatal ("Can't open patch file %s", quotearg (filename));
126       }
127 #if HAVE_SETMODE_DOS
128     if (binary_transput)
129       {
130 	if (isatty (fileno (pfp)))
131 	  fatal ("cannot read binary data from tty on this platform");
132 	setmode (fileno (pfp), O_BINARY);
133       }
134 #endif
135     if (fstat (fileno (pfp), &st) != 0)
136       pfatal ("fstat");
137     if (S_ISREG (st.st_mode) && (pos = file_tell (pfp)) != -1)
138       file_pos = pos;
139     else
140       {
141 	size_t charsread;
142 	int fd;
143 	FILE *read_pfp = pfp;
144 	fd = make_tempfile (&TMPPATNAME, 'p', NULL, O_RDWR | O_BINARY, 0);
145 	if (fd == -1)
146 	  pfatal ("Can't create temporary file %s", TMPPATNAME);
147 	TMPPATNAME_needs_removal = true;
148 	pfp = fdopen (fd, "w+b");
149 	if (! pfp)
150 	  pfatal ("Can't open stream for file %s", quotearg (TMPPATNAME));
151 	for (st.st_size = 0;
152 	     (charsread = fread (buf, 1, bufsize, read_pfp)) != 0;
153 	     st.st_size += charsread)
154 	  if (fwrite (buf, 1, charsread, pfp) != charsread)
155 	    write_fatal ();
156 	if (ferror (read_pfp) || fclose (read_pfp) != 0)
157 	  read_fatal ();
158 	if (fflush (pfp) != 0
159 	    || file_seek (pfp, (file_offset) 0, SEEK_SET) != 0)
160 	  write_fatal ();
161       }
162     p_filesize = st.st_size;
163     if (p_filesize != (file_offset) p_filesize)
164       fatal ("patch file is too long");
165     next_intuit_at (file_pos, 1);
166 }
167 
168 /* Make sure our dynamically realloced tables are malloced to begin with. */
169 
170 static void
set_hunkmax(void)171 set_hunkmax (void)
172 {
173     if (!p_line)
174 	p_line = xmalloc (hunkmax * sizeof *p_line);
175     if (!p_len)
176 	p_len = xmalloc (hunkmax * sizeof *p_len);
177     if (!p_Char)
178 	p_Char = xmalloc (hunkmax * sizeof *p_Char);
179 }
180 
181 /* Enlarge the arrays containing the current hunk of patch. */
182 
183 static bool
grow_hunkmax(void)184 grow_hunkmax (void)
185 {
186     hunkmax *= 2;
187     assert (p_line && p_len && p_Char);
188     if ((p_line = realloc (p_line, hunkmax * sizeof (*p_line)))
189 	&& (p_len = realloc (p_len, hunkmax * sizeof (*p_len)))
190 	&& (p_Char = realloc (p_Char, hunkmax * sizeof (*p_Char))))
191       return true;
192     if (!using_plan_a)
193       xalloc_die ();
194     /* Don't free previous values of p_line etc.,
195        since some broken implementations free them for us.
196        Whatever is null will be allocated again from within plan_a (),
197        of all places.  */
198     return false;
199 }
200 
201 static bool
maybe_reverse(char const * name,bool nonexistent,bool is_empty)202 maybe_reverse (char const *name, bool nonexistent, bool is_empty)
203 {
204   bool looks_reversed = (! is_empty) < p_says_nonexistent[reverse ^ is_empty];
205 
206   /* Allow to create and delete empty files when we know that they are empty:
207      in the "diff --git" format, we know that from the index header.  */
208   if (is_empty
209       && p_says_nonexistent[reverse ^ nonexistent] == 1
210       && p_says_nonexistent[! reverse ^ nonexistent] == 2)
211     return false;
212 
213   if (looks_reversed)
214     reverse ^=
215       ok_to_reverse ("The next patch%s would %s the file %s,\nwhich %s!",
216 		     reverse ? ", when reversed," : "",
217 		     (nonexistent ? "delete"
218 		      : is_empty ? "empty out"
219 		      : "create"),
220 		     quotearg (name),
221 		     (nonexistent ? "does not exist"
222 		      : is_empty ? "is already empty"
223 		      : "already exists"));
224   return looks_reversed;
225 }
226 
227 /* True if the remainder of the patch file contains a diff of some sort. */
228 
229 bool
there_is_another_patch(bool need_header,mode_t * file_type)230 there_is_another_patch (bool need_header, mode_t *file_type)
231 {
232     if (p_base != 0 && p_base >= p_filesize) {
233 	if (verbosity == VERBOSE)
234 	    say ("done\n");
235 	return false;
236     }
237     if (verbosity == VERBOSE)
238 	say ("Hmm...");
239     diff_type = intuit_diff_type (need_header, file_type);
240     if (diff_type == NO_DIFF) {
241 	if (verbosity == VERBOSE)
242 	  say (p_base
243 	       ? "  Ignoring the trailing garbage.\ndone\n"
244 	       : "  I can't seem to find a patch in there anywhere.\n");
245 	if (! p_base && p_filesize)
246 	  fatal ("Only garbage was found in the patch input.");
247 	return false;
248     }
249     if (skip_rest_of_patch)
250       {
251 	Fseek (pfp, p_start, SEEK_SET);
252 	p_input_line = p_sline - 1;
253 	return true;
254       }
255     if (verbosity == VERBOSE)
256 	say ("  %sooks like %s to me...\n",
257 	    (p_base == 0 ? "L" : "The next patch l"),
258 	    diff_type == UNI_DIFF ? "a unified diff" :
259 	    diff_type == CONTEXT_DIFF ? "a context diff" :
260 	    diff_type == NEW_CONTEXT_DIFF ? "a new-style context diff" :
261 	    diff_type == NORMAL_DIFF ? "a normal diff" :
262 	    diff_type == GIT_BINARY_DIFF ? "a git binary diff" :
263 	    "an ed script" );
264 
265     if (no_strip_trailing_cr)
266       p_strip_trailing_cr = false;
267 
268     if (verbosity != SILENT)
269       {
270 	if (p_indent)
271 	  say ("(Patch is indented %lu space%s.)\n",
272 	       (unsigned long int) p_indent, p_indent==1?"":"s");
273 	if (p_strip_trailing_cr)
274 	  say ("(Stripping trailing CRs from patch; use --binary to disable.)\n");
275 	if (! inname)
276 	  {
277 	    char numbuf[LINENUM_LENGTH_BOUND + 1];
278 	    say ("can't find file to patch at input line %s\n",
279 		 format_linenum (numbuf, p_sline));
280 	    if (diff_type != ED_DIFF && diff_type != NORMAL_DIFF)
281 	      say (strippath == -1
282 		   ? "Perhaps you should have used the -p or --strip option?\n"
283 		   : "Perhaps you used the wrong -p or --strip option?\n");
284 	  }
285       }
286 
287     skip_to(p_start,p_sline);
288     while (!inname) {
289 	char *t;
290 	if (force | batch) {
291 	    say ("No file to patch.  Skipping patch.\n");
292 	    skip_rest_of_patch = true;
293 	    return true;
294 	}
295 	ask ("File to patch: ");
296 	t = buf + strlen (buf);
297 	if (t > buf + 1 && *(t - 1) == '\n')
298 	  {
299 	    inname = xmemdup0 (buf, t - buf - 1);
300 	    inerrno = stat_file (inname, &instat);
301 	    if (inerrno)
302 	      {
303 		perror (inname);
304 		fflush (stderr);
305 		free (inname);
306 		inname = 0;
307 	      }
308 	    else
309 	      invc = -1;
310 	  }
311 	if (!inname) {
312 	    ask ("Skip this patch? [y] ");
313 	    if (*buf != 'n') {
314 		if (verbosity != SILENT)
315 		    say ("Skipping patch.\n");
316 		skip_rest_of_patch = true;
317 		return true;
318 	    }
319 	}
320     }
321     return true;
322 }
323 
324 static mode_t _GL_ATTRIBUTE_PURE
fetchmode(char const * str)325 fetchmode (char const *str)
326 {
327    const char *s;
328    mode_t mode;
329 
330    while (ISSPACE ((unsigned char) *str))
331      str++;
332 
333    for (s = str, mode = 0; s < str + 6; s++)
334      {
335        if (*s >= '0' && *s <= '7')
336 	mode = (mode << 3) + (*s - '0');
337        else
338 	{
339 	 mode = 0;
340 	 break;
341 	}
342      }
343    if (*s == '\r')
344      s++;
345    if (*s != '\n')
346      mode = 0;
347 
348     /* NOTE: The "diff --git" format always sets the file mode permission
349        bits of symlinks to 0.  (On Linux, symlinks actually always have
350        0777 permissions, so this is not even consistent.)  */
351 
352    return mode;
353 }
354 
355 static void
get_sha1(char ** sha1,char const * start,char const * end)356 get_sha1(char **sha1, char const *start, char const *end)
357 {
358   unsigned int len = end - start;
359   *sha1 = xmalloc (len + 1);
360   memcpy (*sha1, start, len);
361   (*sha1)[len] = 0;
362 }
363 
364 static int _GL_ATTRIBUTE_PURE
sha1_says_nonexistent(char const * sha1)365 sha1_says_nonexistent(char const *sha1)
366 {
367   char const *empty_sha1 = "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391";
368   char const *s;
369 
370   /* Nonexisting files have an all-zero checksum.  */
371   for (s = sha1; *s; s++)
372     if (*s != '0')
373       break;
374   if (! *s)
375     return 2;
376 
377   /* Empty files have empty_sha1 as their checksum.  */
378   for (s = sha1; *s; s++, empty_sha1++)
379     if (*s != *empty_sha1)
380       break;
381   return ! *s;
382 }
383 
384 static char const * _GL_ATTRIBUTE_PURE
skip_hex_digits(char const * str)385 skip_hex_digits (char const *str)
386 {
387   char const *s;
388 
389   for (s = str; (*s >= '0' && *s <= '9') || (*s >= 'a' && *s <= 'f'); s++)
390     /* do nothing */ ;
391   return s == str ? NULL : s;
392 }
393 
394 static bool
name_is_valid(char const * name)395 name_is_valid (char const *name)
396 {
397   int i;
398   bool is_valid = true;
399 
400   for (i = 0; i < ARRAY_SIZE (invalid_names); i++)
401     {
402       if (! invalid_names[i])
403 	break;
404       if (! strcmp (invalid_names[i], name))
405 	return false;
406     }
407 
408   is_valid = filename_is_safe (name);
409 
410   /* Allow any filename if we are in the filesystem root.  */
411   if (! is_valid && cwd_is_root (name))
412     is_valid = true;
413 
414   if (! is_valid)
415     {
416       say ("Ignoring potentially dangerous file name %s\n", quotearg (name));
417       if (i < ARRAY_SIZE (invalid_names))
418 	invalid_names[i] = name;
419     }
420   return is_valid;
421 }
422 
423 /* Determine what kind of diff is in the remaining part of the patch file. */
424 
425 static enum diff
intuit_diff_type(bool need_header,mode_t * p_file_type)426 intuit_diff_type (bool need_header, mode_t *p_file_type)
427 {
428     file_offset this_line = 0;
429     file_offset first_command_line = -1;
430     char first_ed_command_letter = 0;
431     lin fcl_line = 0; /* Pacify 'gcc -W'.  */
432     bool this_is_a_command = false;
433     bool stars_this_line = false;
434     bool extended_headers = false;
435     enum nametype i;
436     struct stat st[3];
437     int stat_errno[3];
438     int version_controlled[3];
439     enum diff retval;
440     mode_t file_type;
441     size_t indent = 0;
442 
443     for (i = OLD;  i <= INDEX;  i++)
444       if (p_name[i]) {
445 	  free (p_name[i]);
446 	  p_name[i] = 0;
447         }
448     for (i = 0; i < ARRAY_SIZE (invalid_names); i++)
449 	invalid_names[i] = NULL;
450     for (i = OLD; i <= NEW; i++)
451       if (p_timestr[i])
452 	{
453 	  free(p_timestr[i]);
454 	  p_timestr[i] = 0;
455 	}
456     for (i = OLD; i <= NEW; i++)
457       if (p_sha1[i])
458 	{
459 	  free (p_sha1[i]);
460 	  p_sha1[i] = 0;
461 	}
462     p_git_diff = false;
463     for (i = OLD; i <= NEW; i++)
464       {
465 	p_mode[i] = 0;
466 	p_copy[i] = false;
467 	p_rename[i] = false;
468       }
469 
470     /* Ed and normal format patches don't have filename headers.  */
471     if (diff_type == ED_DIFF || diff_type == NORMAL_DIFF)
472       need_header = false;
473 
474     version_controlled[OLD] = -1;
475     version_controlled[NEW] = -1;
476     version_controlled[INDEX] = -1;
477     p_rfc934_nesting = 0;
478     p_timestamp[OLD].tv_sec = p_timestamp[NEW].tv_sec = -1;
479     p_says_nonexistent[OLD] = p_says_nonexistent[NEW] = 0;
480     Fseek (pfp, p_base, SEEK_SET);
481     p_input_line = p_bline - 1;
482     for (;;) {
483 	char *s;
484 	char *t;
485 	file_offset previous_line = this_line;
486 	bool last_line_was_command = this_is_a_command;
487 	bool stars_last_line = stars_this_line;
488 	size_t indent_last_line = indent;
489 	char ed_command_letter;
490 	bool strip_trailing_cr;
491 	size_t chars_read;
492 
493 	indent = 0;
494 	this_line = file_tell (pfp);
495 	chars_read = pget_line (0, 0, false, false);
496 	if (chars_read == (size_t) -1)
497 	  xalloc_die ();
498 	if (! chars_read) {
499 	    if (first_ed_command_letter) {
500 					/* nothing but deletes!? */
501 		p_start = first_command_line;
502 		p_sline = fcl_line;
503 		retval = ED_DIFF;
504 		goto scan_exit;
505 	    }
506 	    else {
507 		p_start = this_line;
508 		p_sline = p_input_line;
509 		if (extended_headers)
510 		  {
511 		    /* Patch contains no hunks; any diff type will do. */
512 		    retval = UNI_DIFF;
513 		    goto scan_exit;
514 		  }
515 		return NO_DIFF;
516 	    }
517 	}
518 	strip_trailing_cr = 2 <= chars_read && buf[chars_read - 2] == '\r';
519 	for (s = buf; *s == ' ' || *s == '\t' || *s == 'X'; s++) {
520 	    if (*s == '\t')
521 		indent = (indent + 8) & ~7;
522 	    else
523 		indent++;
524 	}
525 	if (ISDIGIT (*s))
526 	  {
527 	    for (t = s + 1; ISDIGIT (*t) || *t == ',';  t++)
528 	      /* do nothing */ ;
529 	    if (*t == 'd' || *t == 'c' || *t == 'a')
530 	      {
531 		for (t++;  ISDIGIT (*t) || *t == ',';  t++)
532 		  /* do nothing */ ;
533 		for (; *t == ' ' || *t == '\t'; t++)
534 		  /* do nothing */ ;
535 		if (*t == '\r')
536 		  t++;
537 		this_is_a_command = (*t == '\n');
538 	      }
539 	  }
540 	if (! need_header
541 	    && first_command_line < 0
542 	    && ((ed_command_letter = get_ed_command_letter (s))
543 		|| this_is_a_command)) {
544 	    first_command_line = this_line;
545 	    first_ed_command_letter = ed_command_letter;
546 	    fcl_line = p_input_line;
547 	    p_indent = indent;		/* assume this for now */
548 	    p_strip_trailing_cr = strip_trailing_cr;
549 	}
550 	if (!stars_last_line && strnEQ(s, "*** ", 4))
551 	  {
552 	    fetchname (s+4, strippath, &p_name[OLD], &p_timestr[OLD],
553 		       &p_timestamp[OLD]);
554 	    need_header = false;
555 	  }
556 	else if (strnEQ(s, "+++ ", 4))
557 	  {
558 	    /* Swap with NEW below.  */
559 	    fetchname (s+4, strippath, &p_name[OLD], &p_timestr[OLD],
560 		       &p_timestamp[OLD]);
561 	    need_header = false;
562 	    p_strip_trailing_cr = strip_trailing_cr;
563 	  }
564 	else if (strnEQ(s, "Index:", 6))
565 	  {
566 	    fetchname (s+6, strippath, &p_name[INDEX], (char **) 0, NULL);
567 	    need_header = false;
568 	    p_strip_trailing_cr = strip_trailing_cr;
569 	  }
570 	else if (strnEQ(s, "Prereq:", 7))
571 	  {
572 	    for (t = s + 7;  ISSPACE ((unsigned char) *t);  t++)
573 	      /* do nothing */ ;
574 	    revision = t;
575 	    for (t = revision;  *t;  t++)
576 	      if (ISSPACE ((unsigned char) *t))
577 		{
578 		  char const *u;
579 		  for (u = t + 1;  ISSPACE ((unsigned char) *u);  u++)
580 		    /* do nothing */ ;
581 		  if (*u)
582 		    {
583 		      char numbuf[LINENUM_LENGTH_BOUND + 1];
584 		      say ("Prereq: with multiple words at line %s of patch\n",
585 			   format_linenum (numbuf, this_line));
586 		    }
587 		  break;
588 		}
589 	    if (t == revision)
590 		revision = 0;
591 	    else {
592 		char oldc = *t;
593 		*t = '\0';
594 		revision = xstrdup (revision);
595 		*t = oldc;
596 	    }
597 	  }
598 	else if (strnEQ (s, "diff --git ", 11))
599 	  {
600 	    char const *u;
601 
602 	    if (extended_headers)
603 	      {
604 		p_start = this_line;
605 		p_sline = p_input_line;
606 		/* Patch contains no hunks; any diff type will do. */
607 		retval = UNI_DIFF;
608 		goto scan_exit;
609 	      }
610 
611 	    for (i = OLD; i <= NEW; i++)
612 	      {
613 		free (p_name[i]);
614 		p_name[i] = 0;
615 	      }
616 	    if (! ((p_name[OLD] = parse_name (s + 11, strippath, &u))
617 		   && ISSPACE ((unsigned char) *u)
618 		   && (p_name[NEW] = parse_name (u, strippath, &u))
619 		   && (u = skip_spaces (u), ! *u)))
620 	      for (i = OLD; i <= NEW; i++)
621 		{
622 		  free (p_name[i]);
623 		  p_name[i] = 0;
624 		}
625 	    p_git_diff = true;
626 	    need_header = false;
627 	  }
628 	else if (p_git_diff && strnEQ (s, "index ", 6))
629 	  {
630 	    char const *u, *v;
631 	    if ((u = skip_hex_digits (s + 6))
632 		&& u[0] == '.' && u[1] == '.'
633 		&& (v = skip_hex_digits (u + 2))
634 		&& (! *v || ISSPACE ((unsigned char) *v)))
635 	      {
636 		get_sha1(&p_sha1[OLD], s + 6, u);
637 		get_sha1(&p_sha1[NEW], u + 2, v);
638 		p_says_nonexistent[OLD] = sha1_says_nonexistent (p_sha1[OLD]);
639 		p_says_nonexistent[NEW] = sha1_says_nonexistent (p_sha1[NEW]);
640 		if (*(v = skip_spaces (v)))
641 		  p_mode[OLD] = p_mode[NEW] = fetchmode (v);
642 		extended_headers = true;
643 	      }
644 	  }
645 	else if (p_git_diff && strnEQ (s, "old mode ", 9))
646 	  {
647 	    p_mode[OLD] = fetchmode (s + 9);
648 	    extended_headers = true;
649 	  }
650 	else if (p_git_diff && strnEQ (s, "new mode ", 9))
651 	  {
652 	    p_mode[NEW] = fetchmode (s + 9);
653 	    extended_headers = true;
654 	  }
655 	else if (p_git_diff && strnEQ (s, "deleted file mode ", 18))
656 	  {
657 	    p_mode[OLD] = fetchmode (s + 18);
658 	    p_says_nonexistent[NEW] = 2;
659 	    extended_headers = true;
660 	  }
661 	else if (p_git_diff && strnEQ (s, "new file mode ", 14))
662 	  {
663 	    p_mode[NEW] = fetchmode (s + 14);
664 	    p_says_nonexistent[OLD] = 2;
665 	    extended_headers = true;
666 	  }
667 	else if (p_git_diff && strnEQ (s, "rename from ", 12))
668 	  {
669 	    /* Git leaves out the prefix in the file name in this header,
670 	       so we can only ignore the file name.  */
671 	    p_rename[OLD] = true;
672 	    extended_headers = true;
673 	  }
674 	else if (p_git_diff && strnEQ (s, "rename to ", 10))
675 	  {
676 	    /* Git leaves out the prefix in the file name in this header,
677 	       so we can only ignore the file name.  */
678 	    p_rename[NEW] = true;
679 	    extended_headers = true;
680 	  }
681 	else if (p_git_diff && strnEQ (s, "copy from ", 10))
682 	  {
683 	    /* Git leaves out the prefix in the file name in this header,
684 	       so we can only ignore the file name.  */
685 	    p_copy[OLD] = true;
686 	    extended_headers = true;
687 	  }
688 	else if (p_git_diff && strnEQ (s, "copy to ", 8))
689 	  {
690 	    /* Git leaves out the prefix in the file name in this header,
691 	       so we can only ignore the file name.  */
692 	    p_copy[NEW] = true;
693 	    extended_headers = true;
694 	  }
695 	else if (p_git_diff && strnEQ (s, "GIT binary patch", 16))
696 	  {
697 	    p_start = this_line;
698 	    p_sline = p_input_line;
699 	    retval = GIT_BINARY_DIFF;
700 	    goto scan_exit;
701 	  }
702 	else
703 	  {
704 	    for (t = s;  t[0] == '-' && t[1] == ' ';  t += 2)
705 	      /* do nothing */ ;
706 	    if (strnEQ(t, "--- ", 4))
707 	      {
708 		struct timespec timestamp;
709 		timestamp.tv_sec = -1;
710 		fetchname (t+4, strippath, &p_name[NEW], &p_timestr[NEW],
711 			   &timestamp);
712 		need_header = false;
713 		if (timestamp.tv_sec != -1)
714 		  {
715 		    p_timestamp[NEW] = timestamp;
716 		    p_rfc934_nesting = (t - s) >> 1;
717 		  }
718 		p_strip_trailing_cr = strip_trailing_cr;
719 	      }
720 	  }
721 	if (need_header)
722 	  continue;
723 	if ((diff_type == NO_DIFF || diff_type == ED_DIFF) &&
724 	  first_command_line >= 0 &&
725 	  strEQ(s, ".\n") ) {
726 	    p_start = first_command_line;
727 	    p_sline = fcl_line;
728 	    retval = ED_DIFF;
729 	    goto scan_exit;
730 	}
731 	if ((diff_type == NO_DIFF || diff_type == UNI_DIFF)
732 	    && strnEQ(s, "@@ -", 4)) {
733 
734 	    /* 'p_name', 'p_timestr', and 'p_timestamp' are backwards;
735 	       swap them.  */
736 	    struct timespec ti = p_timestamp[OLD];
737 	    p_timestamp[OLD] = p_timestamp[NEW];
738 	    p_timestamp[NEW] = ti;
739 	    t = p_name[OLD];
740 	    p_name[OLD] = p_name[NEW];
741 	    p_name[NEW] = t;
742 	    t = p_timestr[OLD];
743 	    p_timestr[OLD] = p_timestr[NEW];
744 	    p_timestr[NEW] = t;
745 
746 	    s += 4;
747 	    if (s[0] == '0' && !ISDIGIT (s[1]))
748 	      p_says_nonexistent[OLD] = 1 + ! p_timestamp[OLD].tv_sec;
749 	    while (*s != ' ' && *s != '\n')
750 	      s++;
751 	    while (*s == ' ')
752 	      s++;
753 	    if (s[0] == '+' && s[1] == '0' && !ISDIGIT (s[2]))
754 	      p_says_nonexistent[NEW] = 1 + ! p_timestamp[NEW].tv_sec;
755 	    p_indent = indent;
756 	    p_start = this_line;
757 	    p_sline = p_input_line;
758 	    retval = UNI_DIFF;
759 	    if (! ((p_name[OLD] || ! p_timestamp[OLD].tv_sec)
760 		   && (p_name[NEW] || ! p_timestamp[NEW].tv_sec))
761 		&& ! p_name[INDEX] && need_header)
762 	      {
763 		char numbuf[LINENUM_LENGTH_BOUND + 1];
764 		say ("missing header for unified diff at line %s of patch\n",
765 		     format_linenum (numbuf, p_sline));
766 	      }
767 	    goto scan_exit;
768 	}
769 	stars_this_line = strnEQ(s, "********", 8);
770 	if ((diff_type == NO_DIFF
771 	     || diff_type == CONTEXT_DIFF
772 	     || diff_type == NEW_CONTEXT_DIFF)
773 	    && stars_last_line && indent_last_line == indent
774 	    && strnEQ (s, "*** ", 4)) {
775 	    s += 4;
776 	    if (s[0] == '0' && !ISDIGIT (s[1]))
777 	      p_says_nonexistent[OLD] = 1 + ! p_timestamp[OLD].tv_sec;
778 	    /* if this is a new context diff the character just before */
779 	    /* the newline is a '*'. */
780 	    while (*s != '\n')
781 		s++;
782 	    p_indent = indent;
783 	    p_strip_trailing_cr = strip_trailing_cr;
784 	    p_start = previous_line;
785 	    p_sline = p_input_line - 1;
786 	    retval = (*(s-1) == '*' ? NEW_CONTEXT_DIFF : CONTEXT_DIFF);
787 
788 	    {
789 	      /* Scan the first hunk to see whether the file contents
790 		 appear to have been deleted.  */
791 	      file_offset saved_p_base = p_base;
792 	      lin saved_p_bline = p_bline;
793 	      Fseek (pfp, previous_line, SEEK_SET);
794 	      p_input_line -= 2;
795 	      if (another_hunk (retval, false)
796 		  && ! p_repl_lines && p_newfirst == 1)
797 		p_says_nonexistent[NEW] = 1 + ! p_timestamp[NEW].tv_sec;
798 	      next_intuit_at (saved_p_base, saved_p_bline);
799 	    }
800 
801 	    if (! ((p_name[OLD] || ! p_timestamp[OLD].tv_sec)
802 		   && (p_name[NEW] || ! p_timestamp[NEW].tv_sec))
803 		&& ! p_name[INDEX] && need_header)
804 	      {
805 		char numbuf[LINENUM_LENGTH_BOUND + 1];
806 		say ("missing header for context diff at line %s of patch\n",
807 		     format_linenum (numbuf, p_sline));
808 	      }
809 	    goto scan_exit;
810 	}
811 	if ((diff_type == NO_DIFF || diff_type == NORMAL_DIFF) &&
812 	  last_line_was_command &&
813 	  (strnEQ(s, "< ", 2) || strnEQ(s, "> ", 2)) ) {
814 	    p_start = previous_line;
815 	    p_sline = p_input_line - 1;
816 	    p_indent = indent;
817 	    retval = NORMAL_DIFF;
818 	    goto scan_exit;
819 	}
820     }
821 
822   scan_exit:
823 
824     /* The old, new, or old and new file types may be defined.  When both
825        file types are defined, make sure they are the same, or else assume
826        we do not know the file type.  */
827     file_type = p_mode[OLD] & S_IFMT;
828     if (file_type)
829       {
830 	mode_t new_file_type = p_mode[NEW] & S_IFMT;
831 	if (new_file_type && file_type != new_file_type)
832 	  file_type = 0;
833       }
834     else
835       {
836 	file_type = p_mode[NEW] & S_IFMT;
837 	if (! file_type)
838 	  file_type = S_IFREG;
839       }
840     *p_file_type = file_type;
841 
842     /* To intuit 'inname', the name of the file to patch,
843        use the algorithm specified by POSIX 1003.1-2001 XCU lines 25680-26599
844        (with some modifications if posixly_correct is zero):
845 
846        - Take the old and new names from the context header if present,
847 	 and take the index name from the 'Index:' line if present and
848 	 if either the old and new names are both absent
849 	 or posixly_correct is nonzero.
850 	 Consider the file names to be in the order (old, new, index).
851        - If some named files exist, use the first one if posixly_correct
852 	 is nonzero, the best one otherwise.
853        - If patch_get is nonzero, and no named files exist,
854 	 but an RCS or SCCS master file exists,
855 	 use the first named file with an RCS or SCCS master.
856        - If no named files exist, no RCS or SCCS master was found,
857 	 some names are given, posixly_correct is zero,
858 	 and the patch appears to create a file, then use the best name
859 	 requiring the creation of the fewest directories.
860        - Otherwise, report failure by setting 'inname' to 0;
861 	 this causes our invoker to ask the user for a file name.  */
862 
863     i = NONE;
864 
865     if (!inname)
866       {
867 	enum nametype i0 = NONE;
868 
869 	if (! posixly_correct && (p_name[OLD] || p_name[NEW]) && p_name[INDEX])
870 	  {
871 	    free (p_name[INDEX]);
872 	    p_name[INDEX] = 0;
873 	  }
874 
875 	for (i = OLD;  i <= INDEX;  i++)
876 	  if (p_name[i])
877 	    {
878 	      if (i0 != NONE && strcmp (p_name[i0], p_name[i]) == 0)
879 		{
880 		  /* It's the same name as before; reuse stat results.  */
881 		  stat_errno[i] = stat_errno[i0];
882 		  if (! stat_errno[i])
883 		    st[i] = st[i0];
884 		}
885 	      else
886 		{
887 		  stat_errno[i] = stat_file (p_name[i], &st[i]);
888 		  if (! stat_errno[i])
889 		    {
890 		      if (lookup_file_id (&st[i]) == DELETE_LATER)
891 			stat_errno[i] = ENOENT;
892 		      else if (posixly_correct && name_is_valid (p_name[i]))
893 			break;
894 		    }
895 		}
896 	      i0 = i;
897 	    }
898 
899 	if (! posixly_correct)
900 	  {
901 	    /* The best of all existing files. */
902 	    i = best_name (p_name, stat_errno);
903 
904 	    if (i == NONE && patch_get)
905 	      {
906 		enum nametype nope = NONE;
907 
908 		for (i = OLD;  i <= INDEX;  i++)
909 		  if (p_name[i])
910 		    {
911 		      char const *cs;
912 		      char *getbuf;
913 		      char *diffbuf;
914 		      bool readonly = (outfile
915 				       && strcmp (outfile, p_name[i]) != 0);
916 
917 		      if (nope == NONE || strcmp (p_name[nope], p_name[i]) != 0)
918 			{
919 			  cs = (version_controller
920 			        (p_name[i], readonly, (struct stat *) 0,
921 				 &getbuf, &diffbuf));
922 			  version_controlled[i] = !! cs;
923 			  if (cs)
924 			    {
925 			      if (version_get (p_name[i], cs, false, readonly,
926 					       getbuf, &st[i]))
927 				stat_errno[i] = 0;
928 			      else
929 				version_controlled[i] = 0;
930 
931 			      free (getbuf);
932 			      free (diffbuf);
933 
934 			      if (! stat_errno[i])
935 				break;
936 			    }
937 			}
938 
939 		      nope = i;
940 		    }
941 	      }
942 
943 	    if (i0 != NONE
944 		&& (i == NONE || (st[i].st_mode & S_IFMT) == file_type)
945 		&& maybe_reverse (p_name[i == NONE ? i0 : i], i == NONE,
946 				  i == NONE || st[i].st_size == 0)
947 		&& i == NONE)
948 	      i = i0;
949 
950 	    if (i == NONE && p_says_nonexistent[reverse])
951 	      {
952 		int newdirs[3];
953 		int newdirs_min = INT_MAX;
954 		int distance_from_minimum[3];
955 
956 		for (i = OLD;  i <= INDEX;  i++)
957 		  if (p_name[i])
958 		    {
959 		      newdirs[i] = (prefix_components (p_name[i], false)
960 				    - prefix_components (p_name[i], true));
961 		      if (newdirs[i] < newdirs_min)
962 			newdirs_min = newdirs[i];
963 		    }
964 
965 		for (i = OLD;  i <= INDEX;  i++)
966 		  if (p_name[i])
967 		    distance_from_minimum[i] = newdirs[i] - newdirs_min;
968 
969 		/* The best of the filenames which create the fewest directories. */
970 		i = best_name (p_name, distance_from_minimum);
971 	      }
972 	  }
973       }
974 
975     if ((pch_rename () || pch_copy ())
976 	&& ! inname
977 	&& ! ((i == OLD || i == NEW) &&
978 	      p_name[reverse] && p_name[! reverse] &&
979 	      name_is_valid (p_name[reverse]) &&
980 	      name_is_valid (p_name[! reverse])))
981       {
982 	say ("Cannot %s file without two valid file names\n", pch_rename () ? "rename" : "copy");
983 	skip_rest_of_patch = true;
984       }
985 
986     if (i == NONE)
987       {
988 	if (inname)
989 	  {
990 	    inerrno = stat_file (inname, &instat);
991 	    if (inerrno || (instat.st_mode & S_IFMT) == file_type)
992 	      maybe_reverse (inname, inerrno, inerrno || instat.st_size == 0);
993 	  }
994 	else
995           inerrno = -1;
996       }
997     else
998       {
999 	inname = xstrdup (p_name[i]);
1000 	inerrno = stat_errno[i];
1001 	invc = version_controlled[i];
1002 	instat = st[i];
1003       }
1004 
1005     return retval;
1006 }
1007 
1008 /* Count the path name components in FILENAME's prefix.
1009    If CHECKDIRS is true, count only existing directories.  */
1010 static int
prefix_components(char * filename,bool checkdirs)1011 prefix_components (char *filename, bool checkdirs)
1012 {
1013   int count = 0;
1014   struct stat stat_buf;
1015   int stat_result;
1016   char *f = filename + FILE_SYSTEM_PREFIX_LEN (filename);
1017 
1018   if (*f)
1019     while (*++f)
1020       if (ISSLASH (f[0]) && ! ISSLASH (f[-1]))
1021 	{
1022 	  if (checkdirs)
1023 	    {
1024 	      *f = '\0';
1025 	      stat_result = safe_stat (filename, &stat_buf);
1026 	      *f = '/';
1027 	      if (! (stat_result == 0 && S_ISDIR (stat_buf.st_mode)))
1028 		break;
1029 	    }
1030 
1031 	  count++;
1032 	}
1033 
1034   return count;
1035 }
1036 
1037 /* Return the index of the best of NAME[OLD], NAME[NEW], and NAME[INDEX].
1038    Ignore null names, and ignore NAME[i] if IGNORE[i] is nonzero.
1039    Return NONE if all names are ignored.  */
1040 static enum nametype
best_name(char * const * name,int const * ignore)1041 best_name (char *const *name, int const *ignore)
1042 {
1043   enum nametype i;
1044   int components[3];
1045   int components_min = INT_MAX;
1046   size_t basename_len[3];
1047   size_t basename_len_min = SIZE_MAX;
1048   size_t len[3];
1049   size_t len_min = SIZE_MAX;
1050 
1051   for (i = OLD;  i <= INDEX;  i++)
1052     if (name[i] && !ignore[i])
1053       {
1054 	/* Take the names with the fewest prefix components.  */
1055 	components[i] = prefix_components (name[i], false);
1056 	if (components_min < components[i])
1057 	  continue;
1058 	components_min = components[i];
1059 
1060 	/* Of those, take the names with the shortest basename.  */
1061 	basename_len[i] = base_len (name[i]);
1062 	if (basename_len_min < basename_len[i])
1063 	  continue;
1064 	basename_len_min = basename_len[i];
1065 
1066 	/* Of those, take the shortest names.  */
1067 	len[i] = strlen (name[i]);
1068 	if (len_min < len[i])
1069 	  continue;
1070 	len_min = len[i];
1071       }
1072 
1073   /* Of those, take the first name.  */
1074   for (i = OLD;  i <= INDEX;  i++)
1075     if (name[i] && !ignore[i]
1076 	&& name_is_valid (name[i])
1077 	&& components[i] == components_min
1078 	&& basename_len[i] == basename_len_min
1079 	&& len[i] == len_min)
1080       break;
1081 
1082   return i;
1083 }
1084 
1085 /* Remember where this patch ends so we know where to start up again. */
1086 
1087 static void
next_intuit_at(file_offset file_pos,lin file_line)1088 next_intuit_at (file_offset file_pos, lin file_line)
1089 {
1090     p_base = file_pos;
1091     p_bline = file_line;
1092 }
1093 
1094 /* Basically a verbose fseek() to the actual diff listing. */
1095 
1096 static void
skip_to(file_offset file_pos,lin file_line)1097 skip_to (file_offset file_pos, lin file_line)
1098 {
1099     FILE *i = pfp;
1100     FILE *o = stdout;
1101     int c;
1102 
1103     assert(p_base <= file_pos);
1104     if ((verbosity == VERBOSE || !inname) && p_base < file_pos) {
1105 	Fseek (i, p_base, SEEK_SET);
1106 	say ("The text leading up to this was:\n--------------------------\n");
1107 
1108 	while (file_tell (i) < file_pos)
1109 	  {
1110 	    putc ('|', o);
1111 	    do
1112 	      {
1113 		if ((c = getc (i)) == EOF)
1114 		  read_fatal ();
1115 		putc (c, o);
1116 	      }
1117 	    while (c != '\n');
1118 	  }
1119 
1120 	say ("--------------------------\n");
1121     }
1122     else
1123 	Fseek (i, file_pos, SEEK_SET);
1124     p_input_line = file_line - 1;
1125 }
1126 
1127 /* Make this a function for better debugging.  */
1128 static void
malformed(void)1129 malformed (void)
1130 {
1131     char numbuf[LINENUM_LENGTH_BOUND + 1];
1132     fatal ("malformed patch at line %s: %s",
1133 	   format_linenum (numbuf, p_input_line), buf);
1134 		/* about as informative as "Syntax error" in C */
1135 }
1136 
1137 /* Parse a line number from a string.
1138    Return the address of the first char after the number.  */
1139 static char *
scan_linenum(char * s0,lin * linenum)1140 scan_linenum (char *s0, lin *linenum)
1141 {
1142   char *s;
1143   lin n = 0;
1144   bool overflow = false;
1145   char numbuf[LINENUM_LENGTH_BOUND + 1];
1146 
1147   for (s = s0;  ISDIGIT (*s);  s++)
1148     {
1149       lin new_n = 10 * n + (*s - '0');
1150       overflow |= new_n / 10 != n;
1151       n = new_n;
1152     }
1153 
1154   if (s == s0)
1155     fatal ("missing line number at line %s: %s",
1156 	   format_linenum (numbuf, p_input_line), buf);
1157 
1158   if (overflow)
1159     fatal ("line number %.*s is too large at line %s: %s",
1160 	   (int) (s - s0), s0, format_linenum (numbuf, p_input_line), buf);
1161 
1162   *linenum = n;
1163   return s;
1164 }
1165 
1166 /* 1 if there is more of the current diff listing to process;
1167    0 if not; -1 if ran out of memory. */
1168 
1169 int
another_hunk(enum diff difftype,bool rev)1170 another_hunk (enum diff difftype, bool rev)
1171 {
1172     char *s;
1173     lin context = 0;
1174     size_t chars_read;
1175     char numbuf0[LINENUM_LENGTH_BOUND + 1];
1176     char numbuf1[LINENUM_LENGTH_BOUND + 1];
1177     char numbuf2[LINENUM_LENGTH_BOUND + 1];
1178     char numbuf3[LINENUM_LENGTH_BOUND + 1];
1179 
1180     set_hunkmax();
1181 
1182     while (p_end >= 0) {
1183 	if (p_end == p_efake)
1184 	    p_end = p_bfake;		/* don't free twice */
1185 	else
1186 	    free(p_line[p_end]);
1187 	p_end--;
1188     }
1189     assert(p_end == -1);
1190     p_efake = -1;
1191 
1192     if (p_c_function)
1193       {
1194 	free (p_c_function);
1195 	p_c_function = NULL;
1196       }
1197 
1198     p_max = hunkmax;			/* gets reduced when --- found */
1199     if (difftype == CONTEXT_DIFF || difftype == NEW_CONTEXT_DIFF) {
1200 	file_offset line_beginning = file_tell (pfp);
1201 					/* file pos of the current line */
1202 	lin repl_beginning = 0;		/* index of --- line */
1203 	lin fillcnt = 0;	/* #lines of missing ptrn or repl */
1204 	lin fillsrc;		/* index of first line to copy */
1205 	lin filldst;		/* index of first missing line */
1206 	bool ptrn_spaces_eaten = false;	/* ptrn was slightly misformed */
1207 	bool some_context = false;	/* (perhaps internal) context seen */
1208 	bool repl_could_be_missing = true;
1209 	bool ptrn_missing = false;	/* The pattern was missing.  */
1210 	bool repl_missing = false;	/* Likewise for replacement.  */
1211 	file_offset repl_backtrack_position = 0;
1212 					/* file pos of first repl line */
1213 	lin repl_patch_line;		/* input line number for same */
1214 	lin repl_context;		/* context for same */
1215 	lin ptrn_prefix_context = -1;	/* lines in pattern prefix context */
1216 	lin ptrn_suffix_context = -1;	/* lines in pattern suffix context */
1217 	lin repl_prefix_context = -1;	/* lines in replac. prefix context */
1218 	lin ptrn_copiable = 0;		/* # of copiable lines in ptrn */
1219 	lin repl_copiable = 0;		/* Likewise for replacement.  */
1220 
1221 	/* Pacify 'gcc -Wall'.  */
1222 	fillsrc = filldst = repl_patch_line = repl_context = 0;
1223 
1224 	chars_read = get_line ();
1225 	if (chars_read == (size_t) -1
1226 	    || chars_read <= 8
1227 	    || strncmp (buf, "********", 8) != 0) {
1228 	    next_intuit_at(line_beginning,p_input_line);
1229 	    return chars_read == (size_t) -1 ? -1 : 0;
1230 	}
1231 	s = buf;
1232 	while (*s == '*')
1233 	    s++;
1234 	if (*s == ' ')
1235 	  {
1236 	    p_c_function = s;
1237 	    while (*s != '\n')
1238 		s++;
1239 	    *s = '\0';
1240 	    p_c_function = savestr (p_c_function);
1241 	    if (! p_c_function)
1242 	      return -1;
1243 	  }
1244 	p_hunk_beg = p_input_line + 1;
1245 	while (p_end < p_max) {
1246 	    chars_read = get_line ();
1247 	    if (chars_read == (size_t) -1)
1248 	      return -1;
1249 	    if (!chars_read) {
1250 		if (repl_beginning && repl_could_be_missing) {
1251 		    repl_missing = true;
1252 		    goto hunk_done;
1253 		}
1254 		if (p_max - p_end < 4) {
1255 		    strcpy (buf, "  \n");  /* assume blank lines got chopped */
1256 		    chars_read = 3;
1257 		} else {
1258 		    fatal ("unexpected end of file in patch");
1259 		}
1260 	    }
1261 	    p_end++;
1262 	    if (p_end == hunkmax)
1263 	      fatal ("unterminated hunk starting at line %s; giving up at line %s: %s",
1264 		     format_linenum (numbuf0, pch_hunk_beg ()),
1265 		     format_linenum (numbuf1, p_input_line), buf);
1266 	    assert(p_end < hunkmax);
1267 	    p_Char[p_end] = *buf;
1268 	    p_len[p_end] = 0;
1269 	    p_line[p_end] = 0;
1270 	    switch (*buf) {
1271 	    case '*':
1272 		if (strnEQ(buf, "********", 8)) {
1273 		    if (repl_beginning && repl_could_be_missing) {
1274 			repl_missing = true;
1275 			goto hunk_done;
1276 		    }
1277 		    else
1278 		      fatal ("unexpected end of hunk at line %s",
1279 			     format_linenum (numbuf0, p_input_line));
1280 		}
1281 		if (p_end != 0) {
1282 		    if (repl_beginning && repl_could_be_missing) {
1283 			repl_missing = true;
1284 			goto hunk_done;
1285 		    }
1286 		    fatal ("unexpected '***' at line %s: %s",
1287 			   format_linenum (numbuf0, p_input_line), buf);
1288 		}
1289 		context = 0;
1290 		p_len[p_end] = strlen (buf);
1291 		if (! (p_line[p_end] = savestr (buf))) {
1292 		    p_end--;
1293 		    return -1;
1294 		}
1295 		for (s = buf;  *s && !ISDIGIT (*s);  s++)
1296 		  /* do nothing */ ;
1297 		if (strnEQ(s,"0,0",3))
1298 		    remove_prefix (s, 2);
1299 		s = scan_linenum (s, &p_first);
1300 		if (*s == ',') {
1301 		    while (*s && !ISDIGIT (*s))
1302 		      s++;
1303 		    scan_linenum (s, &p_ptrn_lines);
1304 		    p_ptrn_lines += 1 - p_first;
1305 		    if (p_ptrn_lines < 0)
1306 		      malformed ();
1307 		}
1308 		else if (p_first)
1309 		    p_ptrn_lines = 1;
1310 		else {
1311 		    p_ptrn_lines = 0;
1312 		    p_first = 1;
1313 		}
1314 		if (p_first >= LINENUM_MAX - p_ptrn_lines ||
1315 		    p_ptrn_lines >= LINENUM_MAX - 6)
1316 		  malformed ();
1317 		p_max = p_ptrn_lines + 6;	/* we need this much at least */
1318 		while (p_max + 1 >= hunkmax)
1319 		    if (! grow_hunkmax ())
1320 			return -1;
1321 		p_max = hunkmax;
1322 		break;
1323 	    case '-':
1324 		if (buf[1] != '-')
1325 		  goto change_line;
1326 		if (ptrn_prefix_context == -1)
1327 		  ptrn_prefix_context = context;
1328 		ptrn_suffix_context = context;
1329 		if (repl_beginning
1330 		    || p_end <= 0
1331 		    || (p_end
1332 			!= p_ptrn_lines + 1 + (p_Char[p_end - 1] == '\n')))
1333 		  {
1334 		    if (p_end == 1)
1335 		      {
1336 			/* 'Old' lines were omitted.  Set up to fill
1337 			   them in from 'new' context lines.  */
1338 			ptrn_missing = true;
1339 			p_end = p_ptrn_lines + 1;
1340 			ptrn_prefix_context = ptrn_suffix_context = -1;
1341 			fillsrc = p_end + 1;
1342 			filldst = 1;
1343 			fillcnt = p_ptrn_lines;
1344 		      }
1345 		    else if (! repl_beginning)
1346 		      fatal ("%s '---' at line %s; check line numbers at line %s",
1347 			     (p_end <= p_ptrn_lines
1348 			      ? "Premature"
1349 			      : "Overdue"),
1350 			     format_linenum (numbuf0, p_input_line),
1351 			     format_linenum (numbuf1, p_hunk_beg));
1352 		    else if (! repl_could_be_missing)
1353 		      fatal ("duplicate '---' at line %s; check line numbers at line %s",
1354 			     format_linenum (numbuf0, p_input_line),
1355 			     format_linenum (numbuf1,
1356 					     p_hunk_beg + repl_beginning));
1357 		    else
1358 		      {
1359 			repl_missing = true;
1360 			goto hunk_done;
1361 		      }
1362 		  }
1363 		repl_beginning = p_end;
1364 		repl_backtrack_position = file_tell (pfp);
1365 		repl_patch_line = p_input_line;
1366 		repl_context = context;
1367 		p_len[p_end] = strlen (buf);
1368 		if (! (p_line[p_end] = savestr (buf)))
1369 		  {
1370 		    p_end--;
1371 		    return -1;
1372 		  }
1373 		p_Char[p_end] = '=';
1374 		for (s = buf;  *s && ! ISDIGIT (*s);  s++)
1375 		  /* do nothing */ ;
1376 		s = scan_linenum (s, &p_newfirst);
1377 		if (*s == ',')
1378 		  {
1379 		    do
1380 		      {
1381 			if (!*++s)
1382 			  malformed ();
1383 		      }
1384 		    while (! ISDIGIT (*s));
1385 		    scan_linenum (s, &p_repl_lines);
1386 		    p_repl_lines += 1 - p_newfirst;
1387 		    if (p_repl_lines < 0)
1388 		      malformed ();
1389 		  }
1390 		else if (p_newfirst)
1391 		  p_repl_lines = 1;
1392 		else
1393 		  {
1394 		    p_repl_lines = 0;
1395 		    p_newfirst = 1;
1396 		  }
1397 		if (p_newfirst >= LINENUM_MAX - p_repl_lines ||
1398 		    p_repl_lines >= LINENUM_MAX - p_end)
1399 		  malformed ();
1400 		p_max = p_repl_lines + p_end;
1401 		while (p_max + 1 >= hunkmax)
1402 		  if (! grow_hunkmax ())
1403 		    return -1;
1404 		if (p_repl_lines != ptrn_copiable
1405 		    && (p_prefix_context != 0
1406 			|| context != 0
1407 			|| p_repl_lines != 1))
1408 		  repl_could_be_missing = false;
1409 		context = 0;
1410 		break;
1411 	    case '+':  case '!':
1412 		repl_could_be_missing = false;
1413 	      change_line:
1414 		s = buf + 1;
1415 		chars_read--;
1416 		if (*s == '\n' && canonicalize_ws) {
1417 		    strcpy (s, " \n");
1418 		    chars_read = 2;
1419 		}
1420 		if (*s == ' ' || *s == '\t') {
1421 		    s++;
1422 		    chars_read--;
1423 		} else if (repl_beginning && repl_could_be_missing) {
1424 		    repl_missing = true;
1425 		    goto hunk_done;
1426 		}
1427 		if (! repl_beginning)
1428 		  {
1429 		    if (ptrn_prefix_context == -1)
1430 		      ptrn_prefix_context = context;
1431 		  }
1432 		else
1433 		  {
1434 		    if (repl_prefix_context == -1)
1435 		      repl_prefix_context = context;
1436 		  }
1437 		chars_read -=
1438 		  (1 < chars_read
1439 		   && p_end == (repl_beginning ? p_max : p_ptrn_lines)
1440 		   && incomplete_line ());
1441 		p_len[p_end] = chars_read;
1442 		p_line[p_end] = savebuf (s, chars_read);
1443 		if (chars_read && ! p_line[p_end]) {
1444 		    p_end--;
1445 		    return -1;
1446 	        }
1447 		context = 0;
1448 		break;
1449 	    case '\t': case '\n':	/* assume spaces got eaten */
1450 		s = buf;
1451 		if (*buf == '\t') {
1452 		    s++;
1453 		    chars_read--;
1454 		}
1455 		if (repl_beginning && repl_could_be_missing &&
1456 		    (!ptrn_spaces_eaten || difftype == NEW_CONTEXT_DIFF) ) {
1457 		    repl_missing = true;
1458 		    goto hunk_done;
1459 		}
1460 		chars_read -=
1461 		  (1 < chars_read
1462 		   && p_end == (repl_beginning ? p_max : p_ptrn_lines)
1463 		   && incomplete_line ());
1464 		p_len[p_end] = chars_read;
1465 		p_line[p_end] = savebuf (buf, chars_read);
1466 		if (chars_read && ! p_line[p_end]) {
1467 		    p_end--;
1468 		    return -1;
1469 		}
1470 		if (p_end != p_ptrn_lines + 1) {
1471 		    ptrn_spaces_eaten |= (repl_beginning != 0);
1472 		    some_context = true;
1473 		    context++;
1474 		    if (repl_beginning)
1475 			repl_copiable++;
1476 		    else
1477 			ptrn_copiable++;
1478 		    p_Char[p_end] = ' ';
1479 		}
1480 		break;
1481 	    case ' ':
1482 		s = buf + 1;
1483 		chars_read--;
1484 		if (*s == '\n' && canonicalize_ws) {
1485 		    strcpy (s, "\n");
1486 		    chars_read = 2;
1487 		}
1488 		if (*s == ' ' || *s == '\t') {
1489 		    s++;
1490 		    chars_read--;
1491 		} else if (repl_beginning && repl_could_be_missing) {
1492 		    repl_missing = true;
1493 		    goto hunk_done;
1494 		}
1495 		some_context = true;
1496 		context++;
1497 		if (repl_beginning)
1498 		    repl_copiable++;
1499 		else
1500 		    ptrn_copiable++;
1501 		chars_read -=
1502 		  (1 < chars_read
1503 		   && p_end == (repl_beginning ? p_max : p_ptrn_lines)
1504 		   && incomplete_line ());
1505 		p_len[p_end] = chars_read;
1506 		p_line[p_end] = savebuf (s, chars_read);
1507 		if (chars_read && ! p_line[p_end]) {
1508 		    p_end--;
1509 		    return -1;
1510 		}
1511 		break;
1512 	    default:
1513 		if (repl_beginning && repl_could_be_missing) {
1514 		    repl_missing = true;
1515 		    goto hunk_done;
1516 		}
1517 		malformed ();
1518 	    }
1519 	}
1520 
1521     hunk_done:
1522 	if (p_end >=0 && !repl_beginning)
1523 	  fatal ("no '---' found in patch at line %s",
1524 		 format_linenum (numbuf0, pch_hunk_beg ()));
1525 
1526 	if (repl_missing) {
1527 
1528 	    /* reset state back to just after --- */
1529 	    p_input_line = repl_patch_line;
1530 	    context = repl_context;
1531 	    for (p_end--; p_end > repl_beginning; p_end--)
1532 		free(p_line[p_end]);
1533 	    Fseek (pfp, repl_backtrack_position, SEEK_SET);
1534 
1535 	    /* redundant 'new' context lines were omitted - set */
1536 	    /* up to fill them in from the old file context */
1537 	    fillsrc = 1;
1538 	    filldst = repl_beginning+1;
1539 	    fillcnt = p_repl_lines;
1540 	    p_end = p_max;
1541 	}
1542 	else if (! ptrn_missing && ptrn_copiable != repl_copiable)
1543 	  fatal ("context mangled in hunk at line %s",
1544 		 format_linenum (numbuf0, p_hunk_beg));
1545 	else if (!some_context && fillcnt == 1) {
1546 	    /* the first hunk was a null hunk with no context */
1547 	    /* and we were expecting one line -- fix it up. */
1548 	    while (filldst < p_end) {
1549 		p_line[filldst] = p_line[filldst+1];
1550 		p_Char[filldst] = p_Char[filldst+1];
1551 		p_len[filldst] = p_len[filldst+1];
1552 		filldst++;
1553 	    }
1554 #if 0
1555 	    repl_beginning--;		/* this doesn't need to be fixed */
1556 #endif
1557 	    p_end--;
1558 	    p_first++;			/* do append rather than insert */
1559 	    fillcnt = 0;
1560 	    p_ptrn_lines = 0;
1561 	}
1562 
1563 	p_prefix_context = ((repl_prefix_context == -1
1564 			     || (ptrn_prefix_context != -1
1565 				 && ptrn_prefix_context < repl_prefix_context))
1566 			    ? ptrn_prefix_context : repl_prefix_context);
1567 	p_suffix_context = ((ptrn_suffix_context != -1
1568 			     && ptrn_suffix_context < context)
1569 			    ? ptrn_suffix_context : context);
1570 	if (p_prefix_context == -1 || p_suffix_context == -1)
1571 	    fatal ("replacement text or line numbers mangled in hunk at line %s",
1572 		   format_linenum (numbuf0, p_hunk_beg));
1573 
1574 	if (difftype == CONTEXT_DIFF
1575 	    && (fillcnt
1576 		|| (p_first > 1
1577 		    && p_prefix_context + p_suffix_context < ptrn_copiable))) {
1578 	    if (verbosity == VERBOSE)
1579 		say ("%s\n%s\n%s\n",
1580 "(Fascinating -- this is really a new-style context diff but without",
1581 "the telltale extra asterisks on the *** line that usually indicate",
1582 "the new style...)");
1583 	    diff_type = difftype = NEW_CONTEXT_DIFF;
1584 	}
1585 
1586 	/* if there were omitted context lines, fill them in now */
1587 	if (fillcnt) {
1588 	    p_bfake = filldst;		/* remember where not to free() */
1589 	    p_efake = filldst + fillcnt - 1;
1590 	    while (fillcnt-- > 0) {
1591 		while (fillsrc <= p_end && fillsrc != repl_beginning
1592 		       && p_Char[fillsrc] != ' ')
1593 		    fillsrc++;
1594 		if (p_end < fillsrc || fillsrc == repl_beginning)
1595 		  {
1596 		    fatal ("replacement text or line numbers mangled in hunk at line %s",
1597 			   format_linenum (numbuf0, p_hunk_beg));
1598 		  }
1599 		p_line[filldst] = p_line[fillsrc];
1600 		p_Char[filldst] = p_Char[fillsrc];
1601 		p_len[filldst] = p_len[fillsrc];
1602 		fillsrc++; filldst++;
1603 	    }
1604 	    while (fillsrc <= p_end && fillsrc != repl_beginning)
1605 	      {
1606 		if (p_Char[fillsrc] == ' ')
1607 		  fatal ("replacement text or line numbers mangled in hunk at line %s",
1608 			 format_linenum (numbuf0, p_hunk_beg));
1609 		fillsrc++;
1610 	      }
1611 	    if (debug & 64)
1612 	      printf ("fillsrc %s, filldst %s, rb %s, e+1 %s\n",
1613 		      format_linenum (numbuf0, fillsrc),
1614 		      format_linenum (numbuf1, filldst),
1615 		      format_linenum (numbuf2, repl_beginning),
1616 		      format_linenum (numbuf3, p_end + 1));
1617 	    assert(fillsrc==p_end+1 || fillsrc==repl_beginning);
1618 	    assert(filldst==p_end+1 || filldst==repl_beginning);
1619 	}
1620     }
1621     else if (difftype == UNI_DIFF) {
1622 	file_offset line_beginning = file_tell (pfp);  /* file pos of the current line */
1623 	lin fillsrc;  /* index of old lines */
1624 	lin filldst;  /* index of new lines */
1625 	char ch = '\0';
1626 
1627 	chars_read = get_line ();
1628 	if (chars_read == (size_t) -1
1629 	    || chars_read <= 4
1630 	    || strncmp (buf, "@@ -", 4) != 0) {
1631 	    next_intuit_at(line_beginning,p_input_line);
1632 	    return chars_read == (size_t) -1 ? -1 : 0;
1633 	}
1634 	s = scan_linenum (buf + 4, &p_first);
1635 	if (*s == ',')
1636 	    s = scan_linenum (s + 1, &p_ptrn_lines);
1637 	else
1638 	    p_ptrn_lines = 1;
1639 	if (p_first >= LINENUM_MAX - p_ptrn_lines)
1640 	  malformed ();
1641 	if (*s == ' ') s++;
1642 	if (*s != '+')
1643 	    malformed ();
1644 	s = scan_linenum (s + 1, &p_newfirst);
1645 	if (*s == ',')
1646 	    s = scan_linenum (s + 1, &p_repl_lines);
1647 	else
1648 	    p_repl_lines = 1;
1649 	if (p_newfirst >= LINENUM_MAX - p_repl_lines)
1650 	  malformed ();
1651 	if (*s == ' ') s++;
1652 	if (*s++ != '@')
1653 	    malformed ();
1654 	if (*s++ == '@' && *s == ' ')
1655 	  {
1656 	    p_c_function = s;
1657 	    while (*s != '\n')
1658 		s++;
1659 	    *s = '\0';
1660 	    p_c_function = savestr (p_c_function);
1661 	    if (! p_c_function)
1662 	      return -1;
1663 	  }
1664 	if (!p_ptrn_lines)
1665 	    p_first++;			/* do append rather than insert */
1666 	if (!p_repl_lines)
1667 	    p_newfirst++;
1668 	if (p_ptrn_lines >= LINENUM_MAX - (p_repl_lines + 1))
1669 	  malformed ();
1670 	p_max = p_ptrn_lines + p_repl_lines + 1;
1671 	while (p_max + 1 >= hunkmax)
1672 	    if (! grow_hunkmax ())
1673 		return -1;
1674 	fillsrc = 1;
1675 	filldst = fillsrc + p_ptrn_lines;
1676 	p_end = filldst + p_repl_lines;
1677 	sprintf (buf, "*** %s,%s ****\n",
1678 		 format_linenum (numbuf0, p_first),
1679 		 format_linenum (numbuf1, p_first + p_ptrn_lines - 1));
1680 	p_len[0] = strlen (buf);
1681 	if (! (p_line[0] = savestr (buf))) {
1682 	    p_end = -1;
1683 	    return -1;
1684 	}
1685 	p_Char[0] = '*';
1686 	sprintf (buf, "--- %s,%s ----\n",
1687 		 format_linenum (numbuf0, p_newfirst),
1688 		 format_linenum (numbuf1, p_newfirst + p_repl_lines - 1));
1689 	p_len[filldst] = strlen (buf);
1690 	if (! (p_line[filldst] = savestr (buf))) {
1691 	    p_end = 0;
1692 	    return -1;
1693 	}
1694 	p_Char[filldst++] = '=';
1695 	p_prefix_context = -1;
1696 	p_hunk_beg = p_input_line + 1;
1697 	while (fillsrc <= p_ptrn_lines || filldst <= p_end) {
1698 	    chars_read = get_line ();
1699 	    if (!chars_read) {
1700 		if (p_max - filldst < 3) {
1701 		    strcpy (buf, " \n");  /* assume blank lines got chopped */
1702 		    chars_read = 2;
1703 		} else {
1704 		    fatal ("unexpected end of file in patch");
1705 		}
1706 	    }
1707 	    if (chars_read == (size_t) -1)
1708 		s = 0;
1709 	    else if (*buf == '\t' || *buf == '\n') {
1710 		ch = ' ';		/* assume the space got eaten */
1711 		s = savebuf (buf, chars_read);
1712 	    }
1713 	    else {
1714 		ch = *buf;
1715 		s = savebuf (buf+1, --chars_read);
1716 	    }
1717 	    if (chars_read && ! s)
1718 	      {
1719 		while (--filldst > p_ptrn_lines)
1720 		    free(p_line[filldst]);
1721 		p_end = fillsrc-1;
1722 		return -1;
1723 	      }
1724 	    switch (ch) {
1725 	    case '-':
1726 		if (fillsrc > p_ptrn_lines) {
1727 		    free(s);
1728 		    p_end = filldst-1;
1729 		    malformed ();
1730 		}
1731 		chars_read -= fillsrc == p_ptrn_lines && incomplete_line ();
1732 		p_Char[fillsrc] = ch;
1733 		p_line[fillsrc] = s;
1734 		p_len[fillsrc++] = chars_read;
1735 		break;
1736 	    case '=':
1737 		ch = ' ';
1738 		/* FALL THROUGH */
1739 	    case ' ':
1740 		if (fillsrc > p_ptrn_lines) {
1741 		    free(s);
1742 		    while (--filldst > p_ptrn_lines)
1743 			free(p_line[filldst]);
1744 		    p_end = fillsrc-1;
1745 		    malformed ();
1746 		}
1747 		context++;
1748 		chars_read -= fillsrc == p_ptrn_lines && incomplete_line ();
1749 		p_Char[fillsrc] = ch;
1750 		p_line[fillsrc] = s;
1751 		p_len[fillsrc++] = chars_read;
1752 		s = savebuf (s, chars_read);
1753 		if (chars_read && ! s) {
1754 		    while (--filldst > p_ptrn_lines)
1755 			free(p_line[filldst]);
1756 		    p_end = fillsrc-1;
1757 		    return -1;
1758 		}
1759 		/* FALL THROUGH */
1760 	    case '+':
1761 		if (filldst > p_end) {
1762 		    free(s);
1763 		    while (--filldst > p_ptrn_lines)
1764 			free(p_line[filldst]);
1765 		    p_end = fillsrc-1;
1766 		    malformed ();
1767 		}
1768 		chars_read -= filldst == p_end && incomplete_line ();
1769 		p_Char[filldst] = ch;
1770 		p_line[filldst] = s;
1771 		p_len[filldst++] = chars_read;
1772 		break;
1773 	    default:
1774 		p_end = filldst;
1775 		malformed ();
1776 	    }
1777 	    if (ch != ' ') {
1778 		if (p_prefix_context == -1)
1779 		    p_prefix_context = context;
1780 		context = 0;
1781 	    }
1782 	}/* while */
1783 	if (p_prefix_context == -1)
1784 	  malformed ();
1785 	p_suffix_context = context;
1786     }
1787     else {				/* normal diff--fake it up */
1788 	char hunk_type;
1789 	int i;
1790 	lin min, max;
1791 	file_offset line_beginning = file_tell (pfp);
1792 
1793 	p_prefix_context = p_suffix_context = 0;
1794 	chars_read = get_line ();
1795 	if (chars_read == (size_t) -1 || !chars_read || !ISDIGIT (*buf)) {
1796 	    next_intuit_at(line_beginning,p_input_line);
1797 	    return chars_read == (size_t) -1 ? -1 : 0;
1798 	}
1799 	s = scan_linenum (buf, &p_first);
1800 	if (*s == ',') {
1801 	    s = scan_linenum (s + 1, &p_ptrn_lines);
1802 	    p_ptrn_lines += 1 - p_first;
1803 	}
1804 	else
1805 	    p_ptrn_lines = (*s != 'a');
1806 	if (p_first >= LINENUM_MAX - p_ptrn_lines)
1807 	  malformed ();
1808 	hunk_type = *s;
1809 	if (hunk_type == 'a')
1810 	    p_first++;			/* do append rather than insert */
1811 	s = scan_linenum (s + 1, &min);
1812 	if (*s == ',')
1813 	    scan_linenum (s + 1, &max);
1814 	else
1815 	    max = min;
1816 	if (min > max || max - min == LINENUM_MAX)
1817 	  malformed ();
1818 	if (hunk_type == 'd')
1819 	    min++;
1820 	p_newfirst = min;
1821 	p_repl_lines = max - min + 1;
1822 	if (p_newfirst >= LINENUM_MAX - p_repl_lines)
1823 	  malformed ();
1824 	if (p_ptrn_lines >= LINENUM_MAX - (p_repl_lines + 1))
1825 	  malformed ();
1826 	p_end = p_ptrn_lines + p_repl_lines + 1;
1827 	while (p_end + 1 >= hunkmax)
1828 	  if (! grow_hunkmax ())
1829 	    {
1830 	      p_end = -1;
1831 	      return -1;
1832 	    }
1833 	sprintf (buf, "*** %s,%s\n",
1834 		 format_linenum (numbuf0, p_first),
1835 		 format_linenum (numbuf1, p_first + p_ptrn_lines - 1));
1836 	p_len[0] = strlen (buf);
1837 	if (! (p_line[0] = savestr (buf))) {
1838 	    p_end = -1;
1839 	    return -1;
1840 	}
1841 	p_Char[0] = '*';
1842 	for (i=1; i<=p_ptrn_lines; i++) {
1843 	    chars_read = get_line ();
1844 	    if (chars_read == (size_t) -1)
1845 	      {
1846 		p_end = i - 1;
1847 		return -1;
1848 	      }
1849 	    if (!chars_read)
1850 	      fatal ("unexpected end of file in patch at line %s",
1851 		     format_linenum (numbuf0, p_input_line));
1852 	    if (buf[0] != '<' || (buf[1] != ' ' && buf[1] != '\t'))
1853 	      fatal ("'<' followed by space or tab expected at line %s of patch",
1854 		     format_linenum (numbuf0, p_input_line));
1855 	    chars_read -= 2 + (i == p_ptrn_lines && incomplete_line ());
1856 	    p_len[i] = chars_read;
1857 	    p_line[i] = savebuf (buf + 2, chars_read);
1858 	    if (chars_read && ! p_line[i]) {
1859 		p_end = i-1;
1860 		return -1;
1861 	    }
1862 	    p_Char[i] = '-';
1863 	}
1864 	if (hunk_type == 'c') {
1865 	    chars_read = get_line ();
1866 	    if (chars_read == (size_t) -1)
1867 	      {
1868 		p_end = i - 1;
1869 		return -1;
1870 	      }
1871 	    if (! chars_read)
1872 	      fatal ("unexpected end of file in patch at line %s",
1873 		     format_linenum (numbuf0, p_input_line));
1874 	    if (*buf != '-')
1875 	      fatal ("'---' expected at line %s of patch",
1876 		     format_linenum (numbuf0, p_input_line));
1877 	}
1878 	sprintf (buf, "--- %s,%s\n",
1879 		 format_linenum (numbuf0, min),
1880 		 format_linenum (numbuf1, max));
1881 	p_len[i] = strlen (buf);
1882 	if (! (p_line[i] = savestr (buf))) {
1883 	    p_end = i-1;
1884 	    return -1;
1885 	}
1886 	p_Char[i] = '=';
1887 	for (i++; i<=p_end; i++) {
1888 	    chars_read = get_line ();
1889 	    if (chars_read == (size_t) -1)
1890 	      {
1891 		p_end = i - 1;
1892 		return -1;
1893 	      }
1894 	    if (!chars_read)
1895 	      fatal ("unexpected end of file in patch at line %s",
1896 		     format_linenum (numbuf0, p_input_line));
1897 	    if (buf[0] != '>' || (buf[1] != ' ' && buf[1] != '\t'))
1898 	      fatal ("'>' followed by space or tab expected at line %s of patch",
1899 		     format_linenum (numbuf0, p_input_line));
1900 	    chars_read -= 2 + (i == p_end && incomplete_line ());
1901 	    p_len[i] = chars_read;
1902 	    p_line[i] = savebuf (buf + 2, chars_read);
1903 	    if (chars_read && ! p_line[i]) {
1904 		p_end = i-1;
1905 		return -1;
1906 	    }
1907 	    p_Char[i] = '+';
1908 	}
1909     }
1910     if (rev)				/* backwards patch? */
1911 	if (!pch_swap())
1912 	    say ("Not enough memory to swap next hunk!\n");
1913     assert (p_end + 1 < hunkmax);
1914     p_Char[p_end + 1] = '^';  /* add a stopper for apply_hunk */
1915     if (debug & 2) {
1916 	lin i;
1917 
1918 	for (i = 0; i <= p_end + 1; i++) {
1919 	    fprintf (stderr, "%s %c",
1920 		     format_linenum (numbuf0, i),
1921 		     p_Char[i]);
1922 	    if (p_Char[i] == '*')
1923 	      fprintf (stderr, " %s,%s\n",
1924 		       format_linenum (numbuf0, p_first),
1925 		       format_linenum (numbuf1, p_ptrn_lines));
1926 	    else if (p_Char[i] == '=')
1927 	      fprintf (stderr, " %s,%s\n",
1928 		       format_linenum (numbuf0, p_newfirst),
1929 		       format_linenum (numbuf1, p_repl_lines));
1930 	    else if (p_Char[i] != '^')
1931 	      {
1932 		fputs(" |", stderr);
1933 		pch_write_line (i, stderr);
1934 	      }
1935 	    else
1936 	      fputc('\n', stderr);
1937 	}
1938 	fflush (stderr);
1939     }
1940     return 1;
1941 }
1942 
1943 static size_t
get_line(void)1944 get_line (void)
1945 {
1946    return pget_line (p_indent, p_rfc934_nesting, p_strip_trailing_cr,
1947 		     p_pass_comments_through);
1948 }
1949 
1950 /* Input a line from the patch file, worrying about indentation.
1951    Strip up to INDENT characters' worth of leading indentation.
1952    Then remove up to RFC934_NESTING instances of leading "- ".
1953    If STRIP_TRAILING_CR is true, remove any trailing carriage-return.
1954    Unless PASS_COMMENTS_THROUGH is true, ignore any resulting lines
1955    that begin with '#'; they're comments.
1956    Ignore any partial lines at end of input, but warn about them.
1957    Succeed if a line was read; it is terminated by "\n\0" for convenience.
1958    Return the number of characters read, including '\n' but not '\0'.
1959    Return -1 if we ran out of memory.  */
1960 
1961 static size_t
pget_line(size_t indent,int rfc934_nesting,bool strip_trailing_cr,bool pass_comments_through)1962 pget_line (size_t indent, int rfc934_nesting, bool strip_trailing_cr,
1963 	   bool pass_comments_through)
1964 {
1965   FILE *fp = pfp;
1966   int c;
1967   size_t i;
1968   char *b;
1969   size_t s;
1970 
1971   do
1972     {
1973       i = 0;
1974       for (;;)
1975 	{
1976 	  c = getc (fp);
1977 	  if (c == EOF)
1978 	    {
1979 	      if (ferror (fp))
1980 		read_fatal ();
1981 	      return 0;
1982 	    }
1983 	  if (indent <= i)
1984 	    break;
1985 	  if (c == ' ' || c == 'X')
1986 	    i++;
1987 	  else if (c == '\t')
1988 	    i = (i + 8) & ~7;
1989 	  else
1990 	    break;
1991 	}
1992 
1993       i = 0;
1994       b = buf;
1995 
1996       while (c == '-' && 0 <= --rfc934_nesting)
1997 	{
1998 	  c = getc (fp);
1999 	  if (c == EOF)
2000 	    goto patch_ends_in_middle_of_line;
2001 	  if (c != ' ')
2002 	    {
2003 	      i = 1;
2004 	      b[0] = '-';
2005 	      break;
2006 	    }
2007 	  c = getc (fp);
2008 	  if (c == EOF)
2009 	    goto patch_ends_in_middle_of_line;
2010 	}
2011 
2012       s = bufsize;
2013 
2014       for (;;)
2015 	{
2016 	  if (i == s - 1)
2017 	    {
2018 	      s *= 2;
2019 	      b = realloc (b, s);
2020 	      if (!b)
2021 		{
2022 		  if (!using_plan_a)
2023 		    xalloc_die ();
2024 		  return (size_t) -1;
2025 		}
2026 	      buf = b;
2027 	      bufsize = s;
2028 	    }
2029 	  b[i++] = c;
2030 	  if (c == '\n')
2031 	    break;
2032 	  c = getc (fp);
2033 	  if (c == EOF)
2034 	    goto patch_ends_in_middle_of_line;
2035 	}
2036 
2037       p_input_line++;
2038     }
2039   while (*b == '#' && !pass_comments_through);
2040 
2041   if (strip_trailing_cr && 2 <= i && b[i - 2] == '\r')
2042     b[i-- - 2] = '\n';
2043   b[i] = '\0';
2044   return i;
2045 
2046  patch_ends_in_middle_of_line:
2047   if (ferror (fp))
2048     read_fatal ();
2049   say ("patch unexpectedly ends in middle of line\n");
2050   return 0;
2051 }
2052 
2053 static bool
incomplete_line(void)2054 incomplete_line (void)
2055 {
2056   FILE *fp = pfp;
2057   int c;
2058   file_offset line_beginning = file_tell (fp);
2059 
2060   if (getc (fp) == '\\')
2061     {
2062       while ((c = getc (fp)) != '\n'  &&  c != EOF)
2063 	/* do nothing */ ;
2064       return true;
2065     }
2066   else
2067     {
2068       /* We don't trust ungetc.  */
2069       Fseek (pfp, line_beginning, SEEK_SET);
2070       return false;
2071     }
2072 }
2073 
2074 /* Reverse the old and new portions of the current hunk. */
2075 
2076 bool
pch_swap(void)2077 pch_swap (void)
2078 {
2079     char **tp_line;		/* the text of the hunk */
2080     size_t *tp_len;		/* length of each line */
2081     char *tp_char;		/* +, -, and ! */
2082     lin i;
2083     lin n;
2084     bool blankline = false;
2085     char *s;
2086 
2087     i = p_first;
2088     p_first = p_newfirst;
2089     p_newfirst = i;
2090 
2091     /* make a scratch copy */
2092 
2093     tp_line = p_line;
2094     tp_len = p_len;
2095     tp_char = p_Char;
2096     p_line = 0;	/* force set_hunkmax to allocate again */
2097     p_len = 0;
2098     p_Char = 0;
2099     set_hunkmax();
2100     if (!p_line || !p_len || !p_Char) {
2101 	free (p_line);
2102 	p_line = tp_line;
2103 	free (p_len);
2104 	p_len = tp_len;
2105 	free (p_Char);
2106 	p_Char = tp_char;
2107 	return false;		/* not enough memory to swap hunk! */
2108     }
2109 
2110     /* now turn the new into the old */
2111 
2112     i = p_ptrn_lines + 1;
2113     if (tp_char[i] == '\n') {		/* account for possible blank line */
2114 	blankline = true;
2115 	i++;
2116     }
2117     if (p_efake >= 0) {			/* fix non-freeable ptr range */
2118 	if (p_efake <= i)
2119 	    n = p_end - i + 1;
2120 	else
2121 	    n = -i;
2122 	p_efake += n;
2123 	p_bfake += n;
2124     }
2125     for (n=0; i <= p_end; i++,n++) {
2126 	p_line[n] = tp_line[i];
2127 	p_Char[n] = tp_char[i];
2128 	if (p_Char[n] == '+')
2129 	    p_Char[n] = '-';
2130 	p_len[n] = tp_len[i];
2131     }
2132     if (blankline) {
2133 	i = p_ptrn_lines + 1;
2134 	p_line[n] = tp_line[i];
2135 	p_Char[n] = tp_char[i];
2136 	p_len[n] = tp_len[i];
2137 	n++;
2138     }
2139     assert(p_Char[0] == '=');
2140     p_Char[0] = '*';
2141     for (s=p_line[0]; *s; s++)
2142 	if (*s == '-')
2143 	    *s = '*';
2144 
2145     /* now turn the old into the new */
2146 
2147     assert(tp_char[0] == '*');
2148     tp_char[0] = '=';
2149     for (s=tp_line[0]; *s; s++)
2150 	if (*s == '*')
2151 	    *s = '-';
2152     for (i=0; n <= p_end; i++,n++) {
2153 	p_line[n] = tp_line[i];
2154 	p_Char[n] = tp_char[i];
2155 	if (p_Char[n] == '-')
2156 	    p_Char[n] = '+';
2157 	p_len[n] = tp_len[i];
2158     }
2159     assert(i == p_ptrn_lines + 1);
2160     i = p_ptrn_lines;
2161     p_ptrn_lines = p_repl_lines;
2162     p_repl_lines = i;
2163     p_Char[p_end + 1] = '^';
2164     free (tp_line);
2165     free (tp_len);
2166     free (tp_char);
2167     return true;
2168 }
2169 
2170 /* Return whether file WHICH (false = old, true = new) appears to nonexistent.
2171    Return 1 for empty, 2 for nonexistent.  */
2172 
2173 int
pch_says_nonexistent(bool which)2174 pch_says_nonexistent (bool which)
2175 {
2176   return p_says_nonexistent[which];
2177 }
2178 
2179 const char *
pch_name(enum nametype type)2180 pch_name (enum nametype type)
2181 {
2182   return type == NONE ? NULL : p_name[type];
2183 }
2184 
pch_copy(void)2185 bool pch_copy (void)
2186 {
2187   return p_copy[OLD] && p_copy[NEW];
2188 }
2189 
pch_rename(void)2190 bool pch_rename (void)
2191 {
2192   return p_rename[OLD] && p_rename[NEW];
2193 }
2194 
2195 /* Return the specified line position in the old file of the old context. */
2196 
2197 lin
pch_first(void)2198 pch_first (void)
2199 {
2200     return p_first;
2201 }
2202 
2203 /* Return the number of lines of old context. */
2204 
2205 lin
pch_ptrn_lines(void)2206 pch_ptrn_lines (void)
2207 {
2208     return p_ptrn_lines;
2209 }
2210 
2211 /* Return the probable line position in the new file of the first line. */
2212 
2213 lin
pch_newfirst(void)2214 pch_newfirst (void)
2215 {
2216     return p_newfirst;
2217 }
2218 
2219 /* Return the number of lines in the replacement text including context. */
2220 
2221 lin
pch_repl_lines(void)2222 pch_repl_lines (void)
2223 {
2224     return p_repl_lines;
2225 }
2226 
2227 /* Return the number of lines in the whole hunk. */
2228 
2229 lin
pch_end(void)2230 pch_end (void)
2231 {
2232     return p_end;
2233 }
2234 
2235 /* Return the number of context lines before the first changed line. */
2236 
2237 lin
pch_prefix_context(void)2238 pch_prefix_context (void)
2239 {
2240     return p_prefix_context;
2241 }
2242 
2243 /* Return the number of context lines after the last changed line. */
2244 
2245 lin
pch_suffix_context(void)2246 pch_suffix_context (void)
2247 {
2248     return p_suffix_context;
2249 }
2250 
2251 /* Return the length of a particular patch line. */
2252 
2253 size_t
pch_line_len(lin line)2254 pch_line_len (lin line)
2255 {
2256     return p_len[line];
2257 }
2258 
2259 /* Return the control character (+, -, *, !, etc) for a patch line.  A '\n'
2260    indicates an empty line in a hunk.  (The empty line is not part of the
2261    old or new context.  For some reson, the context format allows that.)  */
2262 
2263 char
pch_char(lin line)2264 pch_char (lin line)
2265 {
2266     return p_Char[line];
2267 }
2268 
2269 /* Return a pointer to a particular patch line. */
2270 
2271 char *
pfetch(lin line)2272 pfetch (lin line)
2273 {
2274     return p_line[line];
2275 }
2276 
2277 /* Output a patch line.  */
2278 
2279 bool
pch_write_line(lin line,FILE * file)2280 pch_write_line (lin line, FILE *file)
2281 {
2282   bool after_newline = (p_len[line] > 0) && (p_line[line][p_len[line] - 1] == '\n');
2283   if (! fwrite (p_line[line], sizeof (*p_line[line]), p_len[line], file))
2284     write_fatal ();
2285   return after_newline;
2286 }
2287 
2288 /* Return where in the patch file this hunk began, for error messages. */
2289 
2290 lin
pch_hunk_beg(void)2291 pch_hunk_beg (void)
2292 {
2293     return p_hunk_beg;
2294 }
2295 
2296 char const *
pch_c_function(void)2297 pch_c_function (void)
2298 {
2299     return p_c_function;
2300 }
2301 
2302 /* Return true if in a git-style patch. */
2303 
2304 bool
pch_git_diff(void)2305 pch_git_diff (void)
2306 {
2307   return p_git_diff;
2308 }
2309 
2310 char const *
pch_timestr(bool which)2311 pch_timestr (bool which)
2312 {
2313   return p_timestr[which];
2314 }
2315 
2316 char const *
pch_sha1(bool which)2317 pch_sha1 (bool which)
2318 {
2319   return p_sha1[which];
2320 }
2321 
2322 mode_t
pch_mode(bool which)2323 pch_mode (bool which)
2324 {
2325   return p_mode[which];
2326 }
2327 
2328 /* Is the newline-terminated line a valid 'ed' command for patch
2329    input?  If so, return the command character; if not, return 0.
2330    This accepts just a subset of the valid commands, but it's
2331    good enough in practice.  */
2332 
2333 static char _GL_ATTRIBUTE_PURE
get_ed_command_letter(char const * line)2334 get_ed_command_letter (char const *line)
2335 {
2336   char const *p = line;
2337   char letter;
2338   bool pair = false;
2339 
2340   if (ISDIGIT (*p))
2341     {
2342       while (ISDIGIT (*++p))
2343 	/* do nothing */ ;
2344       if (*p == ',')
2345 	{
2346 	  if (! ISDIGIT (*++p))
2347 	    return 0;
2348 	  while (ISDIGIT (*++p))
2349 	    /* do nothing */ ;
2350 	  pair = true;
2351 	}
2352     }
2353 
2354   letter = *p++;
2355 
2356   switch (letter)
2357     {
2358     case 'a':
2359     case 'i':
2360       if (pair)
2361 	return 0;
2362       break;
2363 
2364     case 'c':
2365     case 'd':
2366       break;
2367 
2368     case 's':
2369       if (strncmp (p, "/.//", 4) != 0)
2370 	return 0;
2371       p += 4;
2372       break;
2373 
2374     default:
2375       return 0;
2376     }
2377 
2378   while (*p == ' ' || *p == '\t')
2379     p++;
2380   if (*p == '\n')
2381     return letter;
2382   return 0;
2383 }
2384 
2385 /* Apply an ed script by feeding ed itself. */
2386 
2387 void
do_ed_script(char const * inname,char const * outname,bool * outname_needs_removal,FILE * ofp)2388 do_ed_script (char const *inname, char const *outname,
2389 	      bool *outname_needs_removal, FILE *ofp)
2390 {
2391     static char const editor_program[] = EDITOR_PROGRAM;
2392 
2393     file_offset beginning_of_this_line;
2394     size_t chars_read;
2395     FILE *tmpfp = 0;
2396     int tmpfd;
2397     pid_t pid;
2398 
2399     if (! dry_run && ! skip_rest_of_patch)
2400       {
2401 	/* Write ed script to a temporary file.  This causes ed to abort on
2402 	   invalid commands such as when line numbers or ranges exceed the
2403 	   number of available lines.  When ed reads from a pipe, it rejects
2404 	   invalid commands and treats the next line as a new command, which
2405 	   can lead to arbitrary command execution.  */
2406 
2407 	tmpfd = make_tempfile (&TMPEDNAME, 'e', NULL, O_RDWR | O_BINARY, 0);
2408 	if (tmpfd == -1)
2409 	  pfatal ("Can't create temporary file %s", quotearg (TMPEDNAME));
2410 	TMPEDNAME_needs_removal = true;
2411 	tmpfp = fdopen (tmpfd, "w+b");
2412 	if (! tmpfp)
2413 	  pfatal ("Can't open stream for file %s", quotearg (TMPEDNAME));
2414       }
2415 
2416     for (;;) {
2417 	char ed_command_letter;
2418 	beginning_of_this_line = file_tell (pfp);
2419 	chars_read = get_line ();
2420 	if (! chars_read) {
2421 	    next_intuit_at(beginning_of_this_line,p_input_line);
2422 	    break;
2423 	}
2424 	ed_command_letter = get_ed_command_letter (buf);
2425 	if (ed_command_letter) {
2426 	    if (tmpfp)
2427 		if (! fwrite (buf, sizeof *buf, chars_read, tmpfp))
2428 		    write_fatal ();
2429 	    if (ed_command_letter != 'd' && ed_command_letter != 's') {
2430 	        p_pass_comments_through = true;
2431 		while ((chars_read = get_line ()) != 0) {
2432 		    if (tmpfp)
2433 			if (! fwrite (buf, sizeof *buf, chars_read, tmpfp))
2434 			    write_fatal ();
2435 		    if (chars_read == 2  &&  strEQ (buf, ".\n"))
2436 			break;
2437 		}
2438 		p_pass_comments_through = false;
2439 	    }
2440 	}
2441 	else {
2442 	    next_intuit_at(beginning_of_this_line,p_input_line);
2443 	    break;
2444 	}
2445     }
2446     if (!tmpfp)
2447       return;
2448     if (fwrite ("w\nq\n", sizeof (char), (size_t) 4, tmpfp) == 0
2449 	|| fflush (tmpfp) != 0)
2450       write_fatal ();
2451 
2452     if (lseek (tmpfd, 0, SEEK_SET) == -1)
2453       pfatal ("Can't rewind to the beginning of file %s", quotearg (TMPEDNAME));
2454 
2455     if (! dry_run && ! skip_rest_of_patch) {
2456 	int exclusive = *outname_needs_removal ? 0 : O_EXCL;
2457 	*outname_needs_removal = true;
2458 	if (inerrno != ENOENT)
2459 	  {
2460 	    *outname_needs_removal = true;
2461 	    copy_file (inname, outname, 0, exclusive, instat.st_mode, true);
2462 	  }
2463 	fflush (stdout);
2464 
2465 	pid = fork();
2466 	if (pid == -1)
2467 	  pfatal ("Can't fork");
2468 	else if (pid == 0)
2469 	  {
2470 	    dup2 (tmpfd, 0);
2471 	    assert (outname[0] != '!' && outname[0] != '-');
2472 	    execlp (editor_program, editor_program, "-", outname, (char  *) NULL);
2473 	    _exit (2);
2474 	  }
2475 	else
2476 	  {
2477 	    int wstatus;
2478 	    if (waitpid (pid, &wstatus, 0) == -1
2479 	        || ! WIFEXITED (wstatus)
2480 		|| WEXITSTATUS (wstatus) != 0)
2481 	      fatal ("%s FAILED", editor_program);
2482 	  }
2483     }
2484 
2485     fclose (tmpfp);
2486 
2487     if (ofp)
2488       {
2489 	FILE *ifp = fopen (outname, binary_transput ? "rb" : "r");
2490 	int c;
2491 	if (!ifp)
2492 	  pfatal ("can't open '%s'", outname);
2493 	while ((c = getc (ifp)) != EOF)
2494 	  if (putc (c, ofp) == EOF)
2495 	    write_fatal ();
2496 	if (ferror (ifp) || fclose (ifp) != 0)
2497 	  read_fatal ();
2498       }
2499 }
2500 
2501 void
pch_normalize(enum diff format)2502 pch_normalize (enum diff format)
2503 {
2504   lin old = 1;
2505   lin new = p_ptrn_lines + 1;
2506 
2507   while (p_Char[new] == '=' || p_Char[new] == '\n')
2508     new++;
2509 
2510   if (format == UNI_DIFF)
2511     {
2512       /* Convert '!' markers into '-' and '+' as defined by the Unified
2513          Format.  */
2514 
2515       for (; old <= p_ptrn_lines; old++)
2516 	if (p_Char[old] == '!')
2517 	  p_Char[old] = '-';
2518       for (; new <= p_end; new++)
2519 	if (p_Char[new] == '!')
2520 	  p_Char[new] = '+';
2521     }
2522   else
2523     {
2524       /* Convert '-' and '+' markers which are part of a group into '!' as
2525 	 defined by the Context Format.  */
2526 
2527       while (old <= p_ptrn_lines)
2528 	{
2529 	  if (p_Char[old] == '-')
2530 	    {
2531 	      if (new <= p_end && p_Char[new] == '+')
2532 		{
2533 		  do
2534 		    {
2535 		      p_Char[old] = '!';
2536 		      old++;
2537 		    }
2538 		  while (old <= p_ptrn_lines && p_Char[old] == '-');
2539 		  do
2540 		    {
2541 		      p_Char[new] = '!';
2542 		      new++;
2543 		    }
2544 		  while (new <= p_end && p_Char[new] == '+');
2545 		}
2546 	      else
2547 		{
2548 		  do
2549 		    old++;
2550 		  while (old <= p_ptrn_lines && p_Char[old] == '-');
2551 		}
2552 	    }
2553 	  else if (new <= p_end && p_Char[new] == '+')
2554 	    {
2555 	      do
2556 		new++;
2557 	      while (new <= p_end && p_Char[new] == '+');
2558 	    }
2559 	  else
2560 	    {
2561 	      old++;
2562 	      new++;
2563 	    }
2564 	}
2565     }
2566 }
2567