1/* reading patches */
2
3/* $Id: pch.c 8008 2004-06-16 21:22:10Z korli $ */
4
5/* Copyright 1986, 1987, 1988 Larry Wall
6   Copyright 1990, 1991-1993, 1997-1998, 1999 Free Software 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 2, or (at your option)
11   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; see the file COPYING.
20   If not, write to the Free Software Foundation,
21   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
22
23#define XTERN extern
24#include <common.h>
25#include <backupfile.h>
26#include <basename.h>
27#include <inp.h>
28#include <quotearg.h>
29#include <util.h>
30#undef XTERN
31#define XTERN
32#include <pch.h>
33
34#define INITHUNKMAX 125			/* initial dynamic allocation size */
35
36/* Patch (diff listing) abstract type. */
37
38static FILE *pfp;			/* patch file pointer */
39static int p_says_nonexistent[2];	/* [0] for old file, [1] for new:
40		0 for existent and nonempty,
41		1 for existent and probably (but not necessarily) empty,
42		2 for nonexistent */
43static int p_rfc934_nesting;		/* RFC 934 nesting level */
44static time_t p_timestamp[2];		/* timestamps in patch headers */
45static off_t p_filesize;		/* size of the patch file */
46static LINENUM p_first;			/* 1st line number */
47static LINENUM p_newfirst;		/* 1st line number of replacement */
48static LINENUM p_ptrn_lines;		/* # lines in pattern */
49static LINENUM p_repl_lines;		/* # lines in replacement text */
50static LINENUM p_end = -1;		/* last line in hunk */
51static LINENUM p_max;			/* max allowed value of p_end */
52static LINENUM p_prefix_context;	/* # of prefix context lines */
53static LINENUM p_suffix_context;	/* # of suffix context lines */
54static LINENUM p_input_line;		/* current line # from patch file */
55static char **p_line;			/* the text of the hunk */
56static size_t *p_len;			/* line length including \n if any */
57static char *p_Char;			/* +, -, and ! */
58static LINENUM hunkmax = INITHUNKMAX;	/* size of above arrays */
59static int p_indent;			/* indent to patch */
60static int p_strip_trailing_cr;		/* nonzero if stripping trailing \r */
61static file_offset p_base;		/* where to intuit this time */
62static LINENUM p_bline;			/* line # of p_base */
63static file_offset p_start;		/* where intuit found a patch */
64static LINENUM p_sline;			/* and the line number for it */
65static LINENUM p_hunk_beg;		/* line number of current hunk */
66static LINENUM p_efake = -1;		/* end of faked up lines--don't free */
67static LINENUM p_bfake = -1;		/* beg of faked up lines */
68
69enum nametype { OLD, NEW, INDEX, NONE };
70
71static char *scan_linenum PARAMS ((char *, LINENUM *));
72static enum diff intuit_diff_type PARAMS ((void));
73static enum nametype best_name PARAMS ((char * const *, int const *));
74static int prefix_components PARAMS ((char *, int));
75static size_t pget_line PARAMS ((int, int, int));
76static size_t get_line PARAMS ((void));
77static bool incomplete_line PARAMS ((void));
78static bool grow_hunkmax PARAMS ((void));
79static void malformed PARAMS ((void)) __attribute__ ((noreturn));
80static void next_intuit_at PARAMS ((file_offset, LINENUM));
81static void skip_to PARAMS ((file_offset, LINENUM));
82
83/* Prepare to look for the next patch in the patch file. */
84
85void
86re_patch (void)
87{
88    p_first = 0;
89    p_newfirst = 0;
90    p_ptrn_lines = 0;
91    p_repl_lines = 0;
92    p_end = -1;
93    p_max = 0;
94    p_indent = 0;
95    p_strip_trailing_cr = 0;
96}
97
98/* Open the patch file at the beginning of time. */
99
100void
101open_patch_file (char const *filename)
102{
103    file_offset file_pos = 0;
104    struct stat st;
105    if (!filename || !*filename || strEQ (filename, "-"))
106      {
107	file_offset stdin_pos;
108#if HAVE_SETMODE
109	if (binary_transput)
110	  {
111	    if (isatty (STDIN_FILENO))
112	      fatal ("cannot read binary data from tty on this platform");
113	    setmode (STDIN_FILENO, O_BINARY);
114	  }
115#endif
116	if (fstat (STDIN_FILENO, &st) != 0)
117	  pfatal ("fstat");
118	if (S_ISREG (st.st_mode) && (stdin_pos = file_tell (stdin)) != -1)
119	  {
120	    pfp = stdin;
121	    file_pos = stdin_pos;
122	  }
123	else
124	  {
125	    size_t charsread;
126	    int exclusive = TMPPATNAME_needs_removal ? 0 : O_EXCL;
127	    TMPPATNAME_needs_removal = 1;
128	    pfp = fdopen (create_file (TMPPATNAME,
129				       O_RDWR | O_BINARY | exclusive,
130				       (mode_t) 0),
131			  "w+b");
132	    if (!pfp)
133	      pfatal ("Can't open stream for file %s", quotearg (TMPPATNAME));
134	    for (st.st_size = 0;
135		 (charsread = fread (buf, 1, bufsize, stdin)) != 0;
136		 st.st_size += charsread)
137	      if (fwrite (buf, 1, charsread, pfp) != charsread)
138		write_fatal ();
139	    if (ferror (stdin) || fclose (stdin) != 0)
140	      read_fatal ();
141	    if (fflush (pfp) != 0
142		|| file_seek (pfp, (file_offset) 0, SEEK_SET) != 0)
143	      write_fatal ();
144	  }
145      }
146    else
147      {
148	pfp = fopen (filename, binary_transput ? "rb" : "r");
149	if (!pfp)
150	  pfatal ("Can't open patch file %s", quotearg (filename));
151	if (fstat (fileno (pfp), &st) != 0)
152	  pfatal ("fstat");
153      }
154    p_filesize = st.st_size;
155    if (p_filesize != (file_offset) p_filesize)
156      fatal ("patch file is too long");
157    next_intuit_at (file_pos, (LINENUM) 1);
158    set_hunkmax();
159}
160
161/* Make sure our dynamically realloced tables are malloced to begin with. */
162
163void
164set_hunkmax (void)
165{
166    if (!p_line)
167	p_line = (char **) malloc (hunkmax * sizeof *p_line);
168    if (!p_len)
169	p_len = (size_t *) malloc (hunkmax * sizeof *p_len);
170    if (!p_Char)
171	p_Char = malloc (hunkmax * sizeof *p_Char);
172}
173
174/* Enlarge the arrays containing the current hunk of patch. */
175
176static bool
177grow_hunkmax (void)
178{
179    hunkmax *= 2;
180    assert (p_line && p_len && p_Char);
181    if ((p_line = (char **) realloc (p_line, hunkmax * sizeof (*p_line)))
182	&& (p_len = (size_t *) realloc (p_len, hunkmax * sizeof (*p_len)))
183	&& (p_Char = realloc (p_Char, hunkmax * sizeof (*p_Char))))
184      return TRUE;
185    if (!using_plan_a)
186      memory_fatal ();
187    /* Don't free previous values of p_line etc.,
188       since some broken implementations free them for us.
189       Whatever is null will be allocated again from within plan_a (),
190       of all places.  */
191    return FALSE;
192}
193
194/* True if the remainder of the patch file contains a diff of some sort. */
195
196bool
197there_is_another_patch (void)
198{
199    if (p_base != 0 && p_base >= p_filesize) {
200	if (verbosity == VERBOSE)
201	    say ("done\n");
202	return FALSE;
203    }
204    if (verbosity == VERBOSE)
205	say ("Hmm...");
206    diff_type = intuit_diff_type();
207    if (diff_type == NO_DIFF) {
208	if (verbosity == VERBOSE)
209	  say (p_base
210	       ? "  Ignoring the trailing garbage.\ndone\n"
211	       : "  I can't seem to find a patch in there anywhere.\n");
212	if (! p_base && p_filesize)
213	  fatal ("Only garbage was found in the patch input.");
214	return FALSE;
215    }
216    if (skip_rest_of_patch)
217      {
218	Fseek (pfp, p_start, SEEK_SET);
219	p_input_line = p_sline - 1;
220	return TRUE;
221      }
222    if (verbosity == VERBOSE)
223	say ("  %sooks like %s to me...\n",
224	    (p_base == 0 ? "L" : "The next patch l"),
225	    diff_type == UNI_DIFF ? "a unified diff" :
226	    diff_type == CONTEXT_DIFF ? "a context diff" :
227	    diff_type == NEW_CONTEXT_DIFF ? "a new-style context diff" :
228	    diff_type == NORMAL_DIFF ? "a normal diff" :
229	    "an ed script" );
230
231    if (verbosity != SILENT)
232      {
233	if (p_indent)
234	  say ("(Patch is indented %d space%s.)\n", p_indent, p_indent==1?"":"s");
235	if (p_strip_trailing_cr)
236	  say ("(Stripping trailing CRs from patch.)\n");
237	if (! inname)
238	  {
239	    char numbuf[LINENUM_LENGTH_BOUND + 1];
240	    say ("can't find file to patch at input line %s\n",
241		 format_linenum (numbuf, p_sline));
242	    say (strippath == -1
243	         ? "Perhaps you should have used the -p or --strip option?\n"
244		 : "Perhaps you used the wrong -p or --strip option?\n");
245	  }
246      }
247
248    skip_to(p_start,p_sline);
249    while (!inname) {
250	if (force || batch) {
251	    say ("No file to patch.  Skipping patch.\n");
252	    skip_rest_of_patch = TRUE;
253	    return TRUE;
254	}
255	ask ("File to patch: ");
256	inname = fetchname (buf, 0, (time_t *) 0);
257	if (inname)
258	  {
259	    if (stat (inname, &instat) == 0)
260	      {
261		inerrno = 0;
262		invc = -1;
263	      }
264	    else
265	      {
266		perror (inname);
267		free (inname);
268		inname = 0;
269	      }
270	  }
271	if (!inname) {
272	    ask ("Skip this patch? [y] ");
273	    if (*buf != 'n') {
274		if (verbosity != SILENT)
275		    say ("Skipping patch.\n");
276		skip_rest_of_patch = TRUE;
277		return TRUE;
278	    }
279	}
280    }
281    return TRUE;
282}
283
284/* Determine what kind of diff is in the remaining part of the patch file. */
285
286static enum diff
287intuit_diff_type (void)
288{
289    register file_offset this_line = 0;
290    register file_offset first_command_line = -1;
291    LINENUM fcl_line = 0; /* Pacify `gcc -W'.  */
292    register bool this_is_a_command = FALSE;
293    register bool stars_this_line = FALSE;
294    enum nametype i;
295    char *name[3];
296    struct stat st[3];
297    int stat_errno[3];
298    int version_controlled[3];
299    register enum diff retval;
300
301    name[OLD] = name[NEW] = name[INDEX] = 0;
302    version_controlled[OLD] = -1;
303    version_controlled[NEW] = -1;
304    version_controlled[INDEX] = -1;
305    p_rfc934_nesting = 0;
306    p_timestamp[OLD] = p_timestamp[NEW] = (time_t) -1;
307    p_says_nonexistent[OLD] = p_says_nonexistent[NEW] = 0;
308    Fseek (pfp, p_base, SEEK_SET);
309    p_input_line = p_bline - 1;
310    for (;;) {
311	register char *s;
312	register char *t;
313	register file_offset previous_line = this_line;
314	register bool last_line_was_command = this_is_a_command;
315	register bool stars_last_line = stars_this_line;
316	register int indent = 0;
317	int strip_trailing_cr;
318	size_t chars_read;
319
320	this_line = file_tell (pfp);
321	chars_read = pget_line (0, 0, 0);
322	if (chars_read == (size_t) -1)
323	  memory_fatal ();
324	if (! chars_read) {
325	    if (first_command_line >= 0) {
326					/* nothing but deletes!? */
327		p_start = first_command_line;
328		p_sline = fcl_line;
329		retval = ED_DIFF;
330		goto scan_exit;
331	    }
332	    else {
333		p_start = this_line;
334		p_sline = p_input_line;
335		return NO_DIFF;
336	    }
337	}
338	strip_trailing_cr = 2 <= chars_read && buf[chars_read - 2] == '\r';
339	for (s = buf; *s == ' ' || *s == '\t' || *s == 'X'; s++) {
340	    if (*s == '\t')
341		indent = (indent + 8) & ~7;
342	    else
343		indent++;
344	}
345	for (t = s;  ISDIGIT (*t) || *t == ',';  t++)
346	  continue;
347	this_is_a_command = (ISDIGIT (*s) &&
348	  (*t == 'd' || *t == 'c' || *t == 'a') );
349	if (first_command_line < 0 && this_is_a_command) {
350	    first_command_line = this_line;
351	    fcl_line = p_input_line;
352	    p_indent = indent;		/* assume this for now */
353	    p_strip_trailing_cr = strip_trailing_cr;
354	}
355	if (!stars_last_line && strnEQ(s, "*** ", 4))
356	    name[OLD] = fetchname (s+4, strippath, &p_timestamp[OLD]);
357	else if (strnEQ(s, "+++ ", 4))
358	    /* Swap with NEW below.  */
359	    name[OLD] = fetchname (s+4, strippath, &p_timestamp[OLD]);
360	else if (strnEQ(s, "Index:", 6))
361	    name[INDEX] = fetchname (s+6, strippath, (time_t *) 0);
362	else if (strnEQ(s, "Prereq:", 7)) {
363	    for (t = s + 7;  ISSPACE ((unsigned char) *t);  t++)
364	      continue;
365	    revision = t;
366	    for (t = revision;  *t && !ISSPACE ((unsigned char) *t);  t++)
367	      continue;
368	    if (t == revision)
369		revision = 0;
370	    else {
371		char oldc = *t;
372		*t = '\0';
373		revision = savestr (revision);
374		*t = oldc;
375	    }
376	} else
377	  {
378	    for (t = s;  t[0] == '-' && t[1] == ' ';  t += 2)
379	      continue;
380	    if (strnEQ(t, "--- ", 4))
381	      {
382		time_t timestamp = (time_t) -1;
383		name[NEW] = fetchname (t+4, strippath, &timestamp);
384		if (timestamp != (time_t) -1)
385		  {
386		    p_timestamp[NEW] = timestamp;
387		    p_rfc934_nesting = (t - s) >> 1;
388		  }
389	      }
390	  }
391	if ((diff_type == NO_DIFF || diff_type == ED_DIFF) &&
392	  first_command_line >= 0 &&
393	  strEQ(s, ".\n") ) {
394	    p_indent = indent;
395	    p_strip_trailing_cr = strip_trailing_cr;
396	    p_start = first_command_line;
397	    p_sline = fcl_line;
398	    retval = ED_DIFF;
399	    goto scan_exit;
400	}
401	if ((diff_type == NO_DIFF || diff_type == UNI_DIFF)
402	    && strnEQ(s, "@@ -", 4)) {
403
404	    /* `name' and `p_timestamp' are backwards; swap them.  */
405	    time_t ti = p_timestamp[OLD];
406	    p_timestamp[OLD] = p_timestamp[NEW];
407	    p_timestamp[NEW] = ti;
408	    t = name[OLD];
409	    name[OLD] = name[NEW];
410	    name[NEW] = t;
411
412	    s += 4;
413	    if (s[0] == '0' && !ISDIGIT (s[1]))
414	      p_says_nonexistent[OLD] = 1 + ! p_timestamp[OLD];
415	    while (*s != ' ' && *s != '\n')
416	      s++;
417	    while (*s == ' ')
418	      s++;
419	    if (s[0] == '+' && s[1] == '0' && !ISDIGIT (s[2]))
420	      p_says_nonexistent[NEW] = 1 + ! p_timestamp[NEW];
421	    p_indent = indent;
422	    p_strip_trailing_cr = strip_trailing_cr;
423	    p_start = this_line;
424	    p_sline = p_input_line;
425	    retval = UNI_DIFF;
426	    if (! ((name[OLD] || ! p_timestamp[OLD])
427		   && (name[NEW] || ! p_timestamp[NEW])))
428	      {
429		char numbuf[LINENUM_LENGTH_BOUND + 1];
430		say ("missing header for unified diff at line %s of patch\n",
431		     format_linenum (numbuf, p_sline));
432	      }
433	    goto scan_exit;
434	}
435	stars_this_line = strnEQ(s, "********", 8);
436	if ((diff_type == NO_DIFF
437	     || diff_type == CONTEXT_DIFF
438	     || diff_type == NEW_CONTEXT_DIFF)
439	    && stars_last_line && strnEQ (s, "*** ", 4)) {
440	    s += 4;
441	    if (s[0] == '0' && !ISDIGIT (s[1]))
442	      p_says_nonexistent[OLD] = 1 + ! p_timestamp[OLD];
443	    /* if this is a new context diff the character just before */
444	    /* the newline is a '*'. */
445	    while (*s != '\n')
446		s++;
447	    p_indent = indent;
448	    p_strip_trailing_cr = strip_trailing_cr;
449	    p_start = previous_line;
450	    p_sline = p_input_line - 1;
451	    retval = (*(s-1) == '*' ? NEW_CONTEXT_DIFF : CONTEXT_DIFF);
452
453	    {
454	      /* Scan the first hunk to see whether the file contents
455		 appear to have been deleted.  */
456	      file_offset saved_p_base = p_base;
457	      LINENUM saved_p_bline = p_bline;
458	      Fseek (pfp, previous_line, SEEK_SET);
459	      p_input_line -= 2;
460	      if (another_hunk (retval, 0)
461		  && ! p_repl_lines && p_newfirst == 1)
462		p_says_nonexistent[NEW] = 1 + ! p_timestamp[NEW];
463	      next_intuit_at (saved_p_base, saved_p_bline);
464	    }
465
466	    if (! ((name[OLD] || ! p_timestamp[OLD])
467		   && (name[NEW] || ! p_timestamp[NEW])))
468	      {
469		char numbuf[LINENUM_LENGTH_BOUND + 1];
470		say ("missing header for context diff at line %s of patch\n",
471		     format_linenum (numbuf, p_sline));
472	      }
473	    goto scan_exit;
474	}
475	if ((diff_type == NO_DIFF || diff_type == NORMAL_DIFF) &&
476	  last_line_was_command &&
477	  (strnEQ(s, "< ", 2) || strnEQ(s, "> ", 2)) ) {
478	    p_start = previous_line;
479	    p_sline = p_input_line - 1;
480	    p_indent = indent;
481	    p_strip_trailing_cr = strip_trailing_cr;
482	    retval = NORMAL_DIFF;
483	    goto scan_exit;
484	}
485    }
486
487  scan_exit:
488
489    /* To intuit `inname', the name of the file to patch,
490       use the algorithm specified by POSIX 1003.2b/D11 section 5.22.7.2
491       (with some modifications if posixly_correct is zero):
492
493       - Take the old and new names from the context header if present,
494	 and take the index name from the `Index:' line if present and
495	 if either the old and new names are both absent
496	 or posixly_correct is nonzero.
497	 Consider the file names to be in the order (old, new, index).
498       - If some named files exist, use the first one if posixly_correct
499	 is nonzero, the best one otherwise.
500       - If patch_get is nonzero, and no named files exist,
501	 but an RCS or SCCS master file exists,
502	 use the first named file with an RCS or SCCS master.
503       - If no named files exist, no RCS or SCCS master was found,
504	 some names are given, posixly_correct is zero,
505	 and the patch appears to create a file, then use the best name
506	 requiring the creation of the fewest directories.
507       - Otherwise, report failure by setting `inname' to 0;
508	 this causes our invoker to ask the user for a file name.  */
509
510    i = NONE;
511
512    if (!inname)
513      {
514	enum nametype i0 = NONE;
515
516	if (! posixly_correct && (name[OLD] || name[NEW]) && name[INDEX])
517	  {
518	    free (name[INDEX]);
519	    name[INDEX] = 0;
520	  }
521
522	for (i = OLD;  i <= INDEX;  i++)
523	  if (name[i])
524	    {
525	      if (i0 != NONE && strcmp (name[i0], name[i]) == 0)
526		{
527		  /* It's the same name as before; reuse stat results.  */
528		  stat_errno[i] = stat_errno[i0];
529		  if (! stat_errno[i])
530		    st[i] = st[i0];
531		}
532	      else if (stat (name[i], &st[i]) != 0)
533		stat_errno[i] = errno;
534	      else
535		{
536		  stat_errno[i] = 0;
537		  if (posixly_correct)
538		    break;
539		}
540	      i0 = i;
541	    }
542
543	if (! posixly_correct)
544	  {
545	    int is_empty;
546
547	    i = best_name (name, stat_errno);
548
549	    if (i == NONE && patch_get)
550	      {
551		enum nametype nope = NONE;
552
553		for (i = OLD;  i <= INDEX;  i++)
554		  if (name[i])
555		    {
556		      char const *cs;
557		      char *getbuf;
558		      char *diffbuf;
559		      int readonly = outfile && strcmp (outfile, name[i]) != 0;
560
561		      if (nope == NONE || strcmp (name[nope], name[i]) != 0)
562			{
563			  cs = (version_controller
564			        (name[i], readonly, (struct stat *) 0,
565				 &getbuf, &diffbuf));
566			  version_controlled[i] = !! cs;
567			  if (cs)
568			    {
569			      if (version_get (name[i], cs, 0, readonly,
570					       getbuf, &st[i]))
571				stat_errno[i] = 0;
572			      else
573				version_controlled[i] = 0;
574
575			      free (getbuf);
576			      if (diffbuf)
577				free (diffbuf);
578
579			      if (! stat_errno[i])
580				break;
581			    }
582			}
583
584		      nope = i;
585		    }
586	      }
587
588	    is_empty = i == NONE || st[i].st_size == 0;
589	    if ((! is_empty) < p_says_nonexistent[reverse ^ is_empty])
590	      {
591		assert (i0 != NONE);
592		if (ok_to_reverse
593		    ("The next patch%s would %s the file %s,\nwhich %s!",
594		     reverse ? ", when reversed," : "",
595		     (i == NONE ? "delete"
596		      : st[i].st_size == 0 ? "empty out"
597		      : "create"),
598		     quotearg (name[i == NONE || st[i].st_size == 0 ? i0 : i]),
599		     (i == NONE ? "does not exist"
600		      : st[i].st_size == 0 ? "is already empty"
601		      : "already exists")))
602		  reverse ^= 1;
603	      }
604
605	    if (i == NONE && p_says_nonexistent[reverse])
606	      {
607		int newdirs[3];
608		int newdirs_min = INT_MAX;
609		int distance_from_minimum[3];
610
611		for (i = OLD;  i <= INDEX;  i++)
612		  if (name[i])
613		    {
614		      newdirs[i] = (prefix_components (name[i], 0)
615				    - prefix_components (name[i], 1));
616		      if (newdirs[i] < newdirs_min)
617			newdirs_min = newdirs[i];
618		    }
619
620		for (i = OLD;  i <= INDEX;  i++)
621		  if (name[i])
622		    distance_from_minimum[i] = newdirs[i] - newdirs_min;
623
624		i = best_name (name, distance_from_minimum);
625	      }
626	  }
627      }
628
629    if (i == NONE)
630      inerrno = -1;
631    else
632      {
633	inname = name[i];
634	name[i] = 0;
635	inerrno = stat_errno[i];
636	invc = version_controlled[i];
637	instat = st[i];
638      }
639
640    for (i = OLD;  i <= INDEX;  i++)
641      if (name[i])
642	free (name[i]);
643
644    return retval;
645}
646
647/* Count the path name components in FILENAME's prefix.
648   If CHECKDIRS is nonzero, count only existing directories.  */
649static int
650prefix_components (char *filename, int checkdirs)
651{
652  int count = 0;
653  struct stat stat_buf;
654  int stat_result;
655  char *f = filename + FILESYSTEM_PREFIX_LEN (filename);
656
657  if (*f)
658    while (*++f)
659      if (ISSLASH (f[0]) && ! ISSLASH (f[-1]))
660	{
661	  if (checkdirs)
662	    {
663	      *f = '\0';
664	      stat_result = stat (filename, &stat_buf);
665	      *f = '/';
666	      if (! (stat_result == 0 && S_ISDIR (stat_buf.st_mode)))
667		break;
668	    }
669
670	  count++;
671	}
672
673  return count;
674}
675
676/* Return the index of the best of NAME[OLD], NAME[NEW], and NAME[INDEX].
677   Ignore null names, and ignore NAME[i] if IGNORE[i] is nonzero.
678   Return NONE if all names are ignored.  */
679static enum nametype
680best_name (char *const *name, int const *ignore)
681{
682  enum nametype i;
683  int components[3];
684  int components_min = INT_MAX;
685  size_t basename_len[3];
686  size_t basename_len_min = SIZE_MAX;
687  size_t len[3];
688  size_t len_min = SIZE_MAX;
689
690  for (i = OLD;  i <= INDEX;  i++)
691    if (name[i] && !ignore[i])
692      {
693	/* Take the names with the fewest prefix components.  */
694	components[i] = prefix_components (name[i], 0);
695	if (components_min < components[i])
696	  continue;
697	components_min = components[i];
698
699	/* Of those, take the names with the shortest basename.  */
700	basename_len[i] = strlen (base_name (name[i]));
701	if (basename_len_min < basename_len[i])
702	  continue;
703	basename_len_min = basename_len[i];
704
705	/* Of those, take the shortest names.  */
706	len[i] = strlen (name[i]);
707	if (len_min < len[i])
708	  continue;
709	len_min = len[i];
710      }
711
712  /* Of those, take the first name.  */
713  for (i = OLD;  i <= INDEX;  i++)
714    if (name[i] && !ignore[i]
715	&& components[i] == components_min
716	&& basename_len[i] == basename_len_min
717	&& len[i] == len_min)
718      break;
719
720  return i;
721}
722
723/* Remember where this patch ends so we know where to start up again. */
724
725static void
726next_intuit_at (file_offset file_pos, LINENUM file_line)
727{
728    p_base = file_pos;
729    p_bline = file_line;
730}
731
732/* Basically a verbose fseek() to the actual diff listing. */
733
734static void
735skip_to (file_offset file_pos, LINENUM file_line)
736{
737    register FILE *i = pfp;
738    register FILE *o = stdout;
739    register int c;
740
741    assert(p_base <= file_pos);
742    if ((verbosity == VERBOSE || !inname) && p_base < file_pos) {
743	Fseek (i, p_base, SEEK_SET);
744	say ("The text leading up to this was:\n--------------------------\n");
745
746	while (file_tell (i) < file_pos)
747	  {
748	    putc ('|', o);
749	    do
750	      {
751		if ((c = getc (i)) == EOF)
752		  read_fatal ();
753		putc (c, o);
754	      }
755	    while (c != '\n');
756	  }
757
758	say ("--------------------------\n");
759    }
760    else
761	Fseek (i, file_pos, SEEK_SET);
762    p_input_line = file_line - 1;
763}
764
765/* Make this a function for better debugging.  */
766static void
767malformed (void)
768{
769    char numbuf[LINENUM_LENGTH_BOUND + 1];
770    fatal ("malformed patch at line %s: %s",
771	   format_linenum (numbuf, p_input_line), buf);
772		/* about as informative as "Syntax error" in C */
773}
774
775/* Parse a line number from a string.
776   Return the address of the first char after the number.  */
777static char *
778scan_linenum (char *s0, LINENUM *linenum)
779{
780  char *s;
781  LINENUM n = 0;
782  int overflow = 0;
783  char numbuf[LINENUM_LENGTH_BOUND + 1];
784
785  for (s = s0;  ISDIGIT (*s);  s++)
786    {
787      LINENUM new_n = 10 * n + (*s - '0');
788      overflow |= new_n / 10 != n;
789      n = new_n;
790    }
791
792  if (s == s0)
793    fatal ("missing line number at line %s: %s",
794	   format_linenum (numbuf, p_input_line), buf);
795
796  if (overflow)
797    fatal ("line number %.*s is too large at line %s: %s",
798	   (int) (s - s0), s0, format_linenum (numbuf, p_input_line), buf);
799
800  *linenum = n;
801  return s;
802}
803
804/* 1 if there is more of the current diff listing to process;
805   0 if not; -1 if ran out of memory. */
806
807int
808another_hunk (enum diff difftype, int rev)
809{
810    register char *s;
811    register LINENUM context = 0;
812    register size_t chars_read;
813    char numbuf0[LINENUM_LENGTH_BOUND + 1];
814    char numbuf1[LINENUM_LENGTH_BOUND + 1];
815    char numbuf2[LINENUM_LENGTH_BOUND + 1];
816    char numbuf3[LINENUM_LENGTH_BOUND + 1];
817
818    while (p_end >= 0) {
819	if (p_end == p_efake)
820	    p_end = p_bfake;		/* don't free twice */
821	else
822	    free(p_line[p_end]);
823	p_end--;
824    }
825    assert(p_end == -1);
826    p_efake = -1;
827
828    p_max = hunkmax;			/* gets reduced when --- found */
829    if (difftype == CONTEXT_DIFF || difftype == NEW_CONTEXT_DIFF) {
830	file_offset line_beginning = file_tell (pfp);
831					/* file pos of the current line */
832	LINENUM repl_beginning = 0;	/* index of --- line */
833	register LINENUM fillcnt = 0;	/* #lines of missing ptrn or repl */
834	register LINENUM fillsrc;	/* index of first line to copy */
835	register LINENUM filldst;	/* index of first missing line */
836	bool ptrn_spaces_eaten = FALSE;	/* ptrn was slightly misformed */
837	bool some_context = FALSE;	/* (perhaps internal) context seen */
838	register bool repl_could_be_missing = TRUE;
839	bool repl_missing = FALSE;	/* we are now backtracking */
840	file_offset repl_backtrack_position = 0;
841					/* file pos of first repl line */
842	LINENUM repl_patch_line;	/* input line number for same */
843	LINENUM repl_context;		/* context for same */
844	LINENUM ptrn_prefix_context = -1; /* lines in pattern prefix context */
845	LINENUM ptrn_suffix_context = -1; /* lines in pattern suffix context */
846	LINENUM repl_prefix_context = -1; /* lines in replac. prefix context */
847	register LINENUM ptrn_copiable = 0;
848					/* # of copiable lines in ptrn */
849
850	/* Pacify `gcc -Wall'.  */
851	fillsrc = filldst = repl_patch_line = repl_context = 0;
852
853	chars_read = get_line ();
854	if (chars_read == (size_t) -1
855	    || chars_read <= 8
856	    || strncmp (buf, "********", 8) != 0) {
857	    next_intuit_at(line_beginning,p_input_line);
858	    return chars_read == (size_t) -1 ? -1 : 0;
859	}
860	p_hunk_beg = p_input_line + 1;
861	while (p_end < p_max) {
862	    chars_read = get_line ();
863	    if (chars_read == (size_t) -1)
864	      return -1;
865	    if (!chars_read) {
866		if (repl_beginning && repl_could_be_missing) {
867		    repl_missing = TRUE;
868		    goto hunk_done;
869		}
870		if (p_max - p_end < 4) {
871		    strcpy (buf, "  \n");  /* assume blank lines got chopped */
872		    chars_read = 3;
873		} else {
874		    fatal ("unexpected end of file in patch");
875		}
876	    }
877	    p_end++;
878	    if (p_end == hunkmax)
879	      fatal ("unterminated hunk starting at line %s; giving up at line %s: %s",
880		     format_linenum (numbuf0, pch_hunk_beg ()),
881		     format_linenum (numbuf1, p_input_line), buf);
882	    assert(p_end < hunkmax);
883	    p_Char[p_end] = *buf;
884	    p_len[p_end] = 0;
885	    p_line[p_end] = 0;
886	    switch (*buf) {
887	    case '*':
888		if (strnEQ(buf, "********", 8)) {
889		    if (repl_beginning && repl_could_be_missing) {
890			repl_missing = TRUE;
891			goto hunk_done;
892		    }
893		    else
894		      fatal ("unexpected end of hunk at line %s",
895			     format_linenum (numbuf0, p_input_line));
896		}
897		if (p_end != 0) {
898		    if (repl_beginning && repl_could_be_missing) {
899			repl_missing = TRUE;
900			goto hunk_done;
901		    }
902		    fatal ("unexpected `***' at line %s: %s",
903			   format_linenum (numbuf0, p_input_line), buf);
904		}
905		context = 0;
906		p_len[p_end] = strlen (buf);
907		if (! (p_line[p_end] = savestr (buf))) {
908		    p_end--;
909		    return -1;
910		}
911		for (s = buf;  *s && !ISDIGIT (*s);  s++)
912		  continue;
913		if (strnEQ(s,"0,0",3))
914		    remove_prefix (s, 2);
915		s = scan_linenum (s, &p_first);
916		if (*s == ',') {
917		    while (*s && !ISDIGIT (*s))
918		      s++;
919		    scan_linenum (s, &p_ptrn_lines);
920		    p_ptrn_lines += 1 - p_first;
921		}
922		else if (p_first)
923		    p_ptrn_lines = 1;
924		else {
925		    p_ptrn_lines = 0;
926		    p_first = 1;
927		}
928		p_max = p_ptrn_lines + 6;	/* we need this much at least */
929		while (p_max >= hunkmax)
930		    if (! grow_hunkmax ())
931			return -1;
932		p_max = hunkmax;
933		break;
934	    case '-':
935		if (buf[1] != '-')
936		  goto change_line;
937		if (ptrn_prefix_context == -1)
938		  ptrn_prefix_context = context;
939		ptrn_suffix_context = context;
940		if (repl_beginning
941		    || (p_end
942			!= p_ptrn_lines + 1 + (p_Char[p_end - 1] == '\n')))
943		  {
944		    if (p_end == 1)
945		      {
946			/* `Old' lines were omitted.  Set up to fill
947			   them in from `new' context lines.  */
948			p_end = p_ptrn_lines + 1;
949			ptrn_prefix_context = ptrn_suffix_context = -1;
950			fillsrc = p_end + 1;
951			filldst = 1;
952			fillcnt = p_ptrn_lines;
953		      }
954		    else if (! repl_beginning)
955		      fatal ("%s `---' at line %s; check line numbers at line %s",
956			     (p_end <= p_ptrn_lines
957			      ? "Premature"
958			      : "Overdue"),
959			     format_linenum (numbuf0, p_input_line),
960			     format_linenum (numbuf1, p_hunk_beg));
961		    else if (! repl_could_be_missing)
962		      fatal ("duplicate `---' at line %s; check line numbers at line %s",
963			     format_linenum (numbuf0, p_input_line),
964			     format_linenum (numbuf1,
965					     p_hunk_beg + repl_beginning));
966		    else
967		      {
968			repl_missing = TRUE;
969			goto hunk_done;
970		      }
971		  }
972		repl_beginning = p_end;
973		repl_backtrack_position = file_tell (pfp);
974		repl_patch_line = p_input_line;
975		repl_context = context;
976		p_len[p_end] = strlen (buf);
977		if (! (p_line[p_end] = savestr (buf)))
978		  {
979		    p_end--;
980		    return -1;
981		  }
982		p_Char[p_end] = '=';
983		for (s = buf;  *s && ! ISDIGIT (*s);  s++)
984		  continue;
985		s = scan_linenum (s, &p_newfirst);
986		if (*s == ',')
987		  {
988		    do
989		      {
990			if (!*++s)
991			  malformed ();
992		      }
993		    while (! ISDIGIT (*s));
994		    scan_linenum (s, &p_repl_lines);
995		    p_repl_lines += 1 - p_newfirst;
996		  }
997		else if (p_newfirst)
998		  p_repl_lines = 1;
999		else
1000		  {
1001		    p_repl_lines = 0;
1002		    p_newfirst = 1;
1003		  }
1004		p_max = p_repl_lines + p_end;
1005		while (p_max >= hunkmax)
1006		  if (! grow_hunkmax ())
1007		    return -1;
1008		if (p_repl_lines != ptrn_copiable
1009		    && (p_prefix_context != 0
1010			|| context != 0
1011			|| p_repl_lines != 1))
1012		  repl_could_be_missing = FALSE;
1013		context = 0;
1014		break;
1015	    case '+':  case '!':
1016		repl_could_be_missing = FALSE;
1017	      change_line:
1018		s = buf + 1;
1019		chars_read--;
1020		if (*s == '\n' && canonicalize) {
1021		    strcpy (s, " \n");
1022		    chars_read = 2;
1023		}
1024		if (*s == ' ' || *s == '\t') {
1025		    s++;
1026		    chars_read--;
1027		} else if (repl_beginning && repl_could_be_missing) {
1028		    repl_missing = TRUE;
1029		    goto hunk_done;
1030		}
1031		if (! repl_beginning)
1032		  {
1033		    if (ptrn_prefix_context == -1)
1034		      ptrn_prefix_context = context;
1035		  }
1036		else
1037		  {
1038		    if (repl_prefix_context == -1)
1039		      repl_prefix_context = context;
1040		  }
1041		chars_read -=
1042		  (1 < chars_read
1043		   && p_end == (repl_beginning ? p_max : p_ptrn_lines)
1044		   && incomplete_line ());
1045		p_len[p_end] = chars_read;
1046		if (! (p_line[p_end] = savebuf (s, chars_read))) {
1047		    p_end--;
1048		    return -1;
1049		}
1050		context = 0;
1051		break;
1052	    case '\t': case '\n':	/* assume spaces got eaten */
1053		s = buf;
1054		if (*buf == '\t') {
1055		    s++;
1056		    chars_read--;
1057		}
1058		if (repl_beginning && repl_could_be_missing &&
1059		    (!ptrn_spaces_eaten || difftype == NEW_CONTEXT_DIFF) ) {
1060		    repl_missing = TRUE;
1061		    goto hunk_done;
1062		}
1063		chars_read -=
1064		  (1 < chars_read
1065		   && p_end == (repl_beginning ? p_max : p_ptrn_lines)
1066		   && incomplete_line ());
1067		p_len[p_end] = chars_read;
1068		if (! (p_line[p_end] = savebuf (buf, chars_read))) {
1069		    p_end--;
1070		    return -1;
1071		}
1072		if (p_end != p_ptrn_lines + 1) {
1073		    ptrn_spaces_eaten |= (repl_beginning != 0);
1074		    some_context = TRUE;
1075		    context++;
1076		    if (!repl_beginning)
1077			ptrn_copiable++;
1078		    p_Char[p_end] = ' ';
1079		}
1080		break;
1081	    case ' ':
1082		s = buf + 1;
1083		chars_read--;
1084		if (*s == '\n' && canonicalize) {
1085		    strcpy (s, "\n");
1086		    chars_read = 2;
1087		}
1088		if (*s == ' ' || *s == '\t') {
1089		    s++;
1090		    chars_read--;
1091		} else if (repl_beginning && repl_could_be_missing) {
1092		    repl_missing = TRUE;
1093		    goto hunk_done;
1094		}
1095		some_context = TRUE;
1096		context++;
1097		if (!repl_beginning)
1098		    ptrn_copiable++;
1099		chars_read -=
1100		  (1 < chars_read
1101		   && p_end == (repl_beginning ? p_max : p_ptrn_lines)
1102		   && incomplete_line ());
1103		p_len[p_end] = chars_read;
1104		if (! (p_line[p_end] = savebuf (buf + 2, chars_read))) {
1105		    p_end--;
1106		    return -1;
1107		}
1108		break;
1109	    default:
1110		if (repl_beginning && repl_could_be_missing) {
1111		    repl_missing = TRUE;
1112		    goto hunk_done;
1113		}
1114		malformed ();
1115	    }
1116	}
1117
1118    hunk_done:
1119	if (p_end >=0 && !repl_beginning)
1120	  fatal ("no `---' found in patch at line %s",
1121		 format_linenum (numbuf0, pch_hunk_beg ()));
1122
1123	if (repl_missing) {
1124
1125	    /* reset state back to just after --- */
1126	    p_input_line = repl_patch_line;
1127	    context = repl_context;
1128	    for (p_end--; p_end > repl_beginning; p_end--)
1129		free(p_line[p_end]);
1130	    Fseek (pfp, repl_backtrack_position, SEEK_SET);
1131
1132	    /* redundant 'new' context lines were omitted - set */
1133	    /* up to fill them in from the old file context */
1134	    fillsrc = 1;
1135	    filldst = repl_beginning+1;
1136	    fillcnt = p_repl_lines;
1137	    p_end = p_max;
1138	}
1139	else if (!some_context && fillcnt == 1) {
1140	    /* the first hunk was a null hunk with no context */
1141	    /* and we were expecting one line -- fix it up. */
1142	    while (filldst < p_end) {
1143		p_line[filldst] = p_line[filldst+1];
1144		p_Char[filldst] = p_Char[filldst+1];
1145		p_len[filldst] = p_len[filldst+1];
1146		filldst++;
1147	    }
1148#if 0
1149	    repl_beginning--;		/* this doesn't need to be fixed */
1150#endif
1151	    p_end--;
1152	    p_first++;			/* do append rather than insert */
1153	    fillcnt = 0;
1154	    p_ptrn_lines = 0;
1155	}
1156
1157	p_prefix_context = ((repl_prefix_context == -1
1158			     || (ptrn_prefix_context != -1
1159				 && ptrn_prefix_context < repl_prefix_context))
1160			    ? ptrn_prefix_context : repl_prefix_context);
1161	p_suffix_context = ((ptrn_suffix_context != -1
1162			     && ptrn_suffix_context < context)
1163			    ? ptrn_suffix_context : context);
1164	assert (p_prefix_context != -1 && p_suffix_context != -1);
1165
1166	if (difftype == CONTEXT_DIFF
1167	    && (fillcnt
1168		|| (p_first > 1
1169		    && p_prefix_context + p_suffix_context < ptrn_copiable))) {
1170	    if (verbosity == VERBOSE)
1171		say ("%s\n%s\n%s\n",
1172"(Fascinating -- this is really a new-style context diff but without",
1173"the telltale extra asterisks on the *** line that usually indicate",
1174"the new style...)");
1175	    diff_type = difftype = NEW_CONTEXT_DIFF;
1176	}
1177
1178	/* if there were omitted context lines, fill them in now */
1179	if (fillcnt) {
1180	    p_bfake = filldst;		/* remember where not to free() */
1181	    p_efake = filldst + fillcnt - 1;
1182	    while (fillcnt-- > 0) {
1183		while (fillsrc <= p_end && fillsrc != repl_beginning
1184		       && p_Char[fillsrc] != ' ')
1185		    fillsrc++;
1186		if (p_end < fillsrc || fillsrc == repl_beginning)
1187		  {
1188		    fatal ("replacement text or line numbers mangled in hunk at line %s",
1189			   format_linenum (numbuf0, p_hunk_beg));
1190		  }
1191		p_line[filldst] = p_line[fillsrc];
1192		p_Char[filldst] = p_Char[fillsrc];
1193		p_len[filldst] = p_len[fillsrc];
1194		fillsrc++; filldst++;
1195	    }
1196	    while (fillsrc <= p_end && fillsrc != repl_beginning)
1197	      {
1198		if (p_Char[fillsrc] == ' ')
1199		  fatal ("replacement text or line numbers mangled in hunk at line %s",
1200			 format_linenum (numbuf0, p_hunk_beg));
1201		fillsrc++;
1202	      }
1203	    if (debug & 64)
1204	      printf ("fillsrc %s, filldst %s, rb %s, e+1 %s\n",
1205		      format_linenum (numbuf0, fillsrc),
1206		      format_linenum (numbuf1, filldst),
1207		      format_linenum (numbuf2, repl_beginning),
1208		      format_linenum (numbuf3, p_end + 1));
1209	    assert(fillsrc==p_end+1 || fillsrc==repl_beginning);
1210	    assert(filldst==p_end+1 || filldst==repl_beginning);
1211	}
1212    }
1213    else if (difftype == UNI_DIFF) {
1214	file_offset line_beginning = file_tell (pfp);
1215					/* file pos of the current line */
1216	register LINENUM fillsrc;	/* index of old lines */
1217	register LINENUM filldst;	/* index of new lines */
1218	char ch = '\0';
1219
1220	chars_read = get_line ();
1221	if (chars_read == (size_t) -1
1222	    || chars_read <= 4
1223	    || strncmp (buf, "@@ -", 4) != 0) {
1224	    next_intuit_at(line_beginning,p_input_line);
1225	    return chars_read == (size_t) -1 ? -1 : 0;
1226	}
1227	s = scan_linenum (buf + 4, &p_first);
1228	if (*s == ',')
1229	    s = scan_linenum (s + 1, &p_ptrn_lines);
1230	else
1231	    p_ptrn_lines = 1;
1232	if (*s == ' ') s++;
1233	if (*s != '+')
1234	    malformed ();
1235	s = scan_linenum (s + 1, &p_newfirst);
1236	if (*s == ',')
1237	    s = scan_linenum (s + 1, &p_repl_lines);
1238	else
1239	    p_repl_lines = 1;
1240	if (*s == ' ') s++;
1241	if (*s != '@')
1242	    malformed ();
1243	if (!p_ptrn_lines)
1244	    p_first++;			/* do append rather than insert */
1245	if (!p_repl_lines)
1246	    p_newfirst++;
1247	p_max = p_ptrn_lines + p_repl_lines + 1;
1248	while (p_max >= hunkmax)
1249	    if (! grow_hunkmax ())
1250		return -1;
1251	fillsrc = 1;
1252	filldst = fillsrc + p_ptrn_lines;
1253	p_end = filldst + p_repl_lines;
1254	sprintf (buf, "*** %s,%s ****\n",
1255		 format_linenum (numbuf0, p_first),
1256		 format_linenum (numbuf1, p_first + p_ptrn_lines - 1));
1257	p_len[0] = strlen (buf);
1258	if (! (p_line[0] = savestr (buf))) {
1259	    p_end = -1;
1260	    return -1;
1261	}
1262	p_Char[0] = '*';
1263	sprintf (buf, "--- %s,%s ----\n",
1264		 format_linenum (numbuf0, p_newfirst),
1265		 format_linenum (numbuf1, p_newfirst + p_repl_lines - 1));
1266	p_len[filldst] = strlen (buf);
1267	if (! (p_line[filldst] = savestr (buf))) {
1268	    p_end = 0;
1269	    return -1;
1270	}
1271	p_Char[filldst++] = '=';
1272	p_prefix_context = -1;
1273	p_hunk_beg = p_input_line + 1;
1274	while (fillsrc <= p_ptrn_lines || filldst <= p_end) {
1275	    chars_read = get_line ();
1276	    if (!chars_read) {
1277		if (p_max - filldst < 3) {
1278		    strcpy (buf, " \n");  /* assume blank lines got chopped */
1279		    chars_read = 2;
1280		} else {
1281		    fatal ("unexpected end of file in patch");
1282		}
1283	    }
1284	    if (chars_read == (size_t) -1)
1285		s = 0;
1286	    else if (*buf == '\t' || *buf == '\n') {
1287		ch = ' ';		/* assume the space got eaten */
1288		s = savebuf (buf, chars_read);
1289	    }
1290	    else {
1291		ch = *buf;
1292		s = savebuf (buf+1, --chars_read);
1293	    }
1294	    if (!s) {
1295		while (--filldst > p_ptrn_lines)
1296		    free(p_line[filldst]);
1297		p_end = fillsrc-1;
1298		return -1;
1299	    }
1300	    switch (ch) {
1301	    case '-':
1302		if (fillsrc > p_ptrn_lines) {
1303		    free(s);
1304		    p_end = filldst-1;
1305		    malformed ();
1306		}
1307		chars_read -= fillsrc == p_ptrn_lines && incomplete_line ();
1308		p_Char[fillsrc] = ch;
1309		p_line[fillsrc] = s;
1310		p_len[fillsrc++] = chars_read;
1311		break;
1312	    case '=':
1313		ch = ' ';
1314		/* FALL THROUGH */
1315	    case ' ':
1316		if (fillsrc > p_ptrn_lines) {
1317		    free(s);
1318		    while (--filldst > p_ptrn_lines)
1319			free(p_line[filldst]);
1320		    p_end = fillsrc-1;
1321		    malformed ();
1322		}
1323		context++;
1324		chars_read -= fillsrc == p_ptrn_lines && incomplete_line ();
1325		p_Char[fillsrc] = ch;
1326		p_line[fillsrc] = s;
1327		p_len[fillsrc++] = chars_read;
1328		s = savebuf (s, chars_read);
1329		if (!s) {
1330		    while (--filldst > p_ptrn_lines)
1331			free(p_line[filldst]);
1332		    p_end = fillsrc-1;
1333		    return -1;
1334		}
1335		/* FALL THROUGH */
1336	    case '+':
1337		if (filldst > p_end) {
1338		    free(s);
1339		    while (--filldst > p_ptrn_lines)
1340			free(p_line[filldst]);
1341		    p_end = fillsrc-1;
1342		    malformed ();
1343		}
1344		chars_read -= filldst == p_end && incomplete_line ();
1345		p_Char[filldst] = ch;
1346		p_line[filldst] = s;
1347		p_len[filldst++] = chars_read;
1348		break;
1349	    default:
1350		p_end = filldst;
1351		malformed ();
1352	    }
1353	    if (ch != ' ') {
1354		if (p_prefix_context == -1)
1355		    p_prefix_context = context;
1356		context = 0;
1357	    }
1358	}/* while */
1359	if (p_prefix_context == -1)
1360	  malformed ();
1361	p_suffix_context = context;
1362    }
1363    else {				/* normal diff--fake it up */
1364	char hunk_type;
1365	register int i;
1366	LINENUM min, max;
1367	file_offset line_beginning = file_tell (pfp);
1368
1369	p_prefix_context = p_suffix_context = 0;
1370	chars_read = get_line ();
1371	if (chars_read == (size_t) -1 || !chars_read || !ISDIGIT (*buf)) {
1372	    next_intuit_at(line_beginning,p_input_line);
1373	    return chars_read == (size_t) -1 ? -1 : 0;
1374	}
1375	s = scan_linenum (buf, &p_first);
1376	if (*s == ',') {
1377	    s = scan_linenum (s + 1, &p_ptrn_lines);
1378	    p_ptrn_lines += 1 - p_first;
1379	}
1380	else
1381	    p_ptrn_lines = (*s != 'a');
1382	hunk_type = *s;
1383	if (hunk_type == 'a')
1384	    p_first++;			/* do append rather than insert */
1385	s = scan_linenum (s + 1, &min);
1386	if (*s == ',')
1387	    scan_linenum (s + 1, &max);
1388	else
1389	    max = min;
1390	if (hunk_type == 'd')
1391	    min++;
1392	p_end = p_ptrn_lines + 1 + max - min + 1;
1393	while (p_end >= hunkmax)
1394	  if (! grow_hunkmax ())
1395	    {
1396	      p_end = -1;
1397	      return -1;
1398	    }
1399	p_newfirst = min;
1400	p_repl_lines = max - min + 1;
1401	sprintf (buf, "*** %s,%s\n",
1402		 format_linenum (numbuf0, p_first),
1403		 format_linenum (numbuf1, p_first + p_ptrn_lines - 1));
1404	p_len[0] = strlen (buf);
1405	if (! (p_line[0] = savestr (buf))) {
1406	    p_end = -1;
1407	    return -1;
1408	}
1409	p_Char[0] = '*';
1410	for (i=1; i<=p_ptrn_lines; i++) {
1411	    chars_read = get_line ();
1412	    if (chars_read == (size_t) -1)
1413	      {
1414		p_end = i - 1;
1415		return -1;
1416	      }
1417	    if (!chars_read)
1418	      fatal ("unexpected end of file in patch at line %s",
1419		     format_linenum (numbuf0, p_input_line));
1420	    if (buf[0] != '<' || (buf[1] != ' ' && buf[1] != '\t'))
1421	      fatal ("`<' expected at line %s of patch",
1422		     format_linenum (numbuf0, p_input_line));
1423	    chars_read -= 2 + (i == p_ptrn_lines && incomplete_line ());
1424	    p_len[i] = chars_read;
1425	    if (! (p_line[i] = savebuf (buf + 2, chars_read))) {
1426		p_end = i-1;
1427		return -1;
1428	    }
1429	    p_Char[i] = '-';
1430	}
1431	if (hunk_type == 'c') {
1432	    chars_read = get_line ();
1433	    if (chars_read == (size_t) -1)
1434	      {
1435		p_end = i - 1;
1436		return -1;
1437	      }
1438	    if (! chars_read)
1439	      fatal ("unexpected end of file in patch at line %s",
1440		     format_linenum (numbuf0, p_input_line));
1441	    if (*buf != '-')
1442	      fatal ("`---' expected at line %s of patch",
1443		     format_linenum (numbuf0, p_input_line));
1444	}
1445	sprintf (buf, "--- %s,%s\n",
1446		 format_linenum (numbuf0, min),
1447		 format_linenum (numbuf1, max));
1448	p_len[i] = strlen (buf);
1449	if (! (p_line[i] = savestr (buf))) {
1450	    p_end = i-1;
1451	    return -1;
1452	}
1453	p_Char[i] = '=';
1454	for (i++; i<=p_end; i++) {
1455	    chars_read = get_line ();
1456	    if (chars_read == (size_t) -1)
1457	      {
1458		p_end = i - 1;
1459		return -1;
1460	      }
1461	    if (!chars_read)
1462	      fatal ("unexpected end of file in patch at line %s",
1463		     format_linenum (numbuf0, p_input_line));
1464	    if (buf[0] != '>' || (buf[1] != ' ' && buf[1] != '\t'))
1465	      fatal ("`>' expected at line %s of patch",
1466		     format_linenum (numbuf0, p_input_line));
1467	    chars_read -= 2 + (i == p_end && incomplete_line ());
1468	    p_len[i] = chars_read;
1469	    if (! (p_line[i] = savebuf (buf + 2, chars_read))) {
1470		p_end = i-1;
1471		return -1;
1472	    }
1473	    p_Char[i] = '+';
1474	}
1475    }
1476    if (rev)				/* backwards patch? */
1477	if (!pch_swap())
1478	    say ("Not enough memory to swap next hunk!\n");
1479    if (debug & 2) {
1480	LINENUM i;
1481	char special;
1482
1483	for (i=0; i <= p_end; i++) {
1484	    if (i == p_ptrn_lines)
1485		special = '^';
1486	    else
1487		special = ' ';
1488	    fprintf (stderr, "%s %c %c ", format_linenum (numbuf0, i),
1489		     p_Char[i], special);
1490	    pch_write_line (i, stderr);
1491	    fflush (stderr);
1492	}
1493    }
1494    if (p_end+1 < hunkmax)	/* paranoia reigns supreme... */
1495	p_Char[p_end+1] = '^';  /* add a stopper for apply_hunk */
1496    return 1;
1497}
1498
1499static size_t
1500get_line (void)
1501{
1502   return pget_line (p_indent, p_rfc934_nesting, p_strip_trailing_cr);
1503}
1504
1505/* Input a line from the patch file, worrying about indentation.
1506   Strip up to INDENT characters' worth of leading indentation.
1507   Then remove up to RFC934_NESTING instances of leading "- ".
1508   If STRIP_TRAILING_CR is nonzero, remove any trailing carriage-return.
1509   Ignore any partial lines at end of input, but warn about them.
1510   Succeed if a line was read; it is terminated by "\n\0" for convenience.
1511   Return the number of characters read, including '\n' but not '\0'.
1512   Return -1 if we ran out of memory.  */
1513
1514static size_t
1515pget_line (int indent, int rfc934_nesting, int strip_trailing_cr)
1516{
1517  register FILE *fp = pfp;
1518  register int c;
1519  register int i = 0;
1520  register char *b;
1521  register size_t s;
1522
1523  for (;;)
1524    {
1525      c = getc (fp);
1526      if (c == EOF)
1527	{
1528	  if (ferror (fp))
1529	    read_fatal ();
1530	  return 0;
1531	}
1532      if (indent <= i)
1533	break;
1534      if (c == ' ' || c == 'X')
1535	i++;
1536      else if (c == '\t')
1537	i = (i + 8) & ~7;
1538      else
1539	break;
1540    }
1541
1542  i = 0;
1543  b = buf;
1544
1545  while (c == '-' && 0 <= --rfc934_nesting)
1546    {
1547      c = getc (fp);
1548      if (c == EOF)
1549	goto patch_ends_in_middle_of_line;
1550      if (c != ' ')
1551	{
1552	  i = 1;
1553	  b[0] = '-';
1554	  break;
1555	}
1556      c = getc (fp);
1557      if (c == EOF)
1558	goto patch_ends_in_middle_of_line;
1559    }
1560
1561  s = bufsize;
1562
1563  for (;;)
1564    {
1565      if (i == s - 1)
1566	{
1567	  s *= 2;
1568	  b = realloc (b, s);
1569	  if (!b)
1570	    {
1571	      if (!using_plan_a)
1572		memory_fatal ();
1573	      return (size_t) -1;
1574	    }
1575	  buf = b;
1576	  bufsize = s;
1577	}
1578      b[i++] = c;
1579      if (c == '\n')
1580	break;
1581      c = getc (fp);
1582      if (c == EOF)
1583	goto patch_ends_in_middle_of_line;
1584    }
1585
1586  if (strip_trailing_cr && 2 <= i && b[i - 2] == '\r')
1587    b[i-- - 2] = '\n';
1588  b[i] = '\0';
1589  p_input_line++;
1590  return i;
1591
1592 patch_ends_in_middle_of_line:
1593  if (ferror (fp))
1594    read_fatal ();
1595  say ("patch unexpectedly ends in middle of line\n");
1596  return 0;
1597}
1598
1599static bool
1600incomplete_line (void)
1601{
1602  register FILE *fp = pfp;
1603  register int c;
1604  register file_offset line_beginning = file_tell (fp);
1605
1606  if (getc (fp) == '\\')
1607    {
1608      while ((c = getc (fp)) != '\n'  &&  c != EOF)
1609	continue;
1610      return TRUE;
1611    }
1612  else
1613    {
1614      /* We don't trust ungetc.  */
1615      Fseek (pfp, line_beginning, SEEK_SET);
1616      return FALSE;
1617    }
1618}
1619
1620/* Reverse the old and new portions of the current hunk. */
1621
1622bool
1623pch_swap (void)
1624{
1625    char **tp_line;		/* the text of the hunk */
1626    size_t *tp_len;		/* length of each line */
1627    char *tp_char;		/* +, -, and ! */
1628    register LINENUM i;
1629    register LINENUM n;
1630    bool blankline = FALSE;
1631    register char *s;
1632
1633    i = p_first;
1634    p_first = p_newfirst;
1635    p_newfirst = i;
1636
1637    /* make a scratch copy */
1638
1639    tp_line = p_line;
1640    tp_len = p_len;
1641    tp_char = p_Char;
1642    p_line = 0;	/* force set_hunkmax to allocate again */
1643    p_len = 0;
1644    p_Char = 0;
1645    set_hunkmax();
1646    if (!p_line || !p_len || !p_Char) {
1647	if (p_line)
1648	  free (p_line);
1649	p_line = tp_line;
1650	if (p_len)
1651	  free (p_len);
1652	p_len = tp_len;
1653	if (p_Char)
1654	  free (p_Char);
1655	p_Char = tp_char;
1656	return FALSE;		/* not enough memory to swap hunk! */
1657    }
1658
1659    /* now turn the new into the old */
1660
1661    i = p_ptrn_lines + 1;
1662    if (tp_char[i] == '\n') {		/* account for possible blank line */
1663	blankline = TRUE;
1664	i++;
1665    }
1666    if (p_efake >= 0) {			/* fix non-freeable ptr range */
1667	if (p_efake <= i)
1668	    n = p_end - i + 1;
1669	else
1670	    n = -i;
1671	p_efake += n;
1672	p_bfake += n;
1673    }
1674    for (n=0; i <= p_end; i++,n++) {
1675	p_line[n] = tp_line[i];
1676	p_Char[n] = tp_char[i];
1677	if (p_Char[n] == '+')
1678	    p_Char[n] = '-';
1679	p_len[n] = tp_len[i];
1680    }
1681    if (blankline) {
1682	i = p_ptrn_lines + 1;
1683	p_line[n] = tp_line[i];
1684	p_Char[n] = tp_char[i];
1685	p_len[n] = tp_len[i];
1686	n++;
1687    }
1688    assert(p_Char[0] == '=');
1689    p_Char[0] = '*';
1690    for (s=p_line[0]; *s; s++)
1691	if (*s == '-')
1692	    *s = '*';
1693
1694    /* now turn the old into the new */
1695
1696    assert(tp_char[0] == '*');
1697    tp_char[0] = '=';
1698    for (s=tp_line[0]; *s; s++)
1699	if (*s == '*')
1700	    *s = '-';
1701    for (i=0; n <= p_end; i++,n++) {
1702	p_line[n] = tp_line[i];
1703	p_Char[n] = tp_char[i];
1704	if (p_Char[n] == '-')
1705	    p_Char[n] = '+';
1706	p_len[n] = tp_len[i];
1707    }
1708    assert(i == p_ptrn_lines + 1);
1709    i = p_ptrn_lines;
1710    p_ptrn_lines = p_repl_lines;
1711    p_repl_lines = i;
1712    if (tp_line)
1713      free (tp_line);
1714    if (tp_len)
1715      free (tp_len);
1716    if (tp_char)
1717      free (tp_char);
1718    return TRUE;
1719}
1720
1721/* Return whether file WHICH (0 = old, 1 = new) appears to nonexistent.
1722   Return 1 for empty, 2 for nonexistent.  */
1723
1724bool
1725pch_says_nonexistent (int which)
1726{
1727  return p_says_nonexistent[which];
1728}
1729
1730/* Return timestamp of patch header for file WHICH (0 = old, 1 = new),
1731   or -1 if there was no timestamp or an error in the timestamp.  */
1732
1733time_t
1734pch_timestamp (int which)
1735{
1736  return p_timestamp[which];
1737}
1738
1739/* Return the specified line position in the old file of the old context. */
1740
1741LINENUM
1742pch_first (void)
1743{
1744    return p_first;
1745}
1746
1747/* Return the number of lines of old context. */
1748
1749LINENUM
1750pch_ptrn_lines (void)
1751{
1752    return p_ptrn_lines;
1753}
1754
1755/* Return the probable line position in the new file of the first line. */
1756
1757LINENUM
1758pch_newfirst (void)
1759{
1760    return p_newfirst;
1761}
1762
1763/* Return the number of lines in the replacement text including context. */
1764
1765LINENUM
1766pch_repl_lines (void)
1767{
1768    return p_repl_lines;
1769}
1770
1771/* Return the number of lines in the whole hunk. */
1772
1773LINENUM
1774pch_end (void)
1775{
1776    return p_end;
1777}
1778
1779/* Return the number of context lines before the first changed line. */
1780
1781LINENUM
1782pch_prefix_context (void)
1783{
1784    return p_prefix_context;
1785}
1786
1787/* Return the number of context lines after the last changed line. */
1788
1789LINENUM
1790pch_suffix_context (void)
1791{
1792    return p_suffix_context;
1793}
1794
1795/* Return the length of a particular patch line. */
1796
1797size_t
1798pch_line_len (LINENUM line)
1799{
1800    return p_len[line];
1801}
1802
1803/* Return the control character (+, -, *, !, etc) for a patch line. */
1804
1805char
1806pch_char (LINENUM line)
1807{
1808    return p_Char[line];
1809}
1810
1811/* Return a pointer to a particular patch line. */
1812
1813char *
1814pfetch (LINENUM line)
1815{
1816    return p_line[line];
1817}
1818
1819/* Output a patch line.  */
1820
1821bool
1822pch_write_line (LINENUM line, FILE *file)
1823{
1824  bool after_newline = p_line[line][p_len[line] - 1] == '\n';
1825  if (! fwrite (p_line[line], sizeof (*p_line[line]), p_len[line], file))
1826    write_fatal ();
1827  return after_newline;
1828}
1829
1830/* Return where in the patch file this hunk began, for error messages. */
1831
1832LINENUM
1833pch_hunk_beg (void)
1834{
1835    return p_hunk_beg;
1836}
1837
1838/* Apply an ed script by feeding ed itself. */
1839
1840void
1841do_ed_script (FILE *ofp)
1842{
1843    static char const ed_program[] = ed_PROGRAM;
1844
1845    register char *t;
1846    register file_offset beginning_of_this_line;
1847    register bool this_line_is_command = FALSE;
1848    register FILE *pipefp = 0;
1849    register size_t chars_read;
1850
1851    if (!skip_rest_of_patch) {
1852	int exclusive = TMPOUTNAME_needs_removal ? 0 : O_EXCL;
1853	assert (! inerrno);
1854	TMPOUTNAME_needs_removal = 1;
1855	copy_file (inname, TMPOUTNAME, exclusive, instat.st_mode);
1856	sprintf (buf, "%s %s%s", ed_program, verbosity == VERBOSE ? "" : "- ",
1857		 TMPOUTNAME);
1858	fflush (stdout);
1859	pipefp = popen(buf, binary_transput ? "wb" : "w");
1860	if (!pipefp)
1861	  pfatal ("Can't open pipe to %s", quotearg (buf));
1862    }
1863    for (;;) {
1864	beginning_of_this_line = file_tell (pfp);
1865	chars_read = get_line ();
1866	if (! chars_read) {
1867	    next_intuit_at(beginning_of_this_line,p_input_line);
1868	    break;
1869	}
1870	for (t = buf;  ISDIGIT (*t) || *t == ',';  t++)
1871	  continue;
1872	this_line_is_command = (ISDIGIT (*buf) &&
1873	  (*t == 'd' || *t == 'c' || *t == 'a' || *t == 'i' || *t == 's') );
1874	if (this_line_is_command) {
1875	    if (pipefp)
1876		if (! fwrite (buf, sizeof *buf, chars_read, pipefp))
1877		    write_fatal ();
1878	    if (*t != 'd' && *t != 's') {
1879		while ((chars_read = get_line ()) != 0) {
1880		    if (pipefp)
1881			if (! fwrite (buf, sizeof *buf, chars_read, pipefp))
1882			    write_fatal ();
1883		    if (chars_read == 2  &&  strEQ (buf, ".\n"))
1884			break;
1885		}
1886	    }
1887	}
1888	else {
1889	    next_intuit_at(beginning_of_this_line,p_input_line);
1890	    break;
1891	}
1892    }
1893    if (!pipefp)
1894      return;
1895    if (fwrite ("w\nq\n", sizeof (char), (size_t) 4, pipefp) == 0
1896	|| fflush (pipefp) != 0)
1897      write_fatal ();
1898    if (pclose (pipefp) != 0)
1899      fatal ("%s FAILED", ed_program);
1900
1901    if (ofp)
1902      {
1903	FILE *ifp = fopen (TMPOUTNAME, binary_transput ? "rb" : "r");
1904	int c;
1905	if (!ifp)
1906	  pfatal ("can't open `%s'", TMPOUTNAME);
1907	while ((c = getc (ifp)) != EOF)
1908	  if (putc (c, ofp) == EOF)
1909	    write_fatal ();
1910	if (ferror (ifp) || fclose (ifp) != 0)
1911	  read_fatal ();
1912      }
1913}
1914