~ubuntu-branches/ubuntu/lucid/patch/lucid

« back to all changes in this revision

Viewing changes to pch.c

  • Committer: Bazaar Package Importer
  • Author(s): Christoph Berg
  • Date: 2009-12-02 10:25:26 UTC
  • mfrom: (5.1.1 sid)
  • Revision ID: james.westby@ubuntu.com-20091202102526-5luk0zsqhghu58l2
Tags: 2.6-2
* Update watch file.
* Section: vcs.
* Suggests: diffutils-doc instead of diff-doc, thanks Christoph Anton
  Mitterer for spotting. Closes: #558974.

Show diffs side-by-side

added added

removed removed

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