| GCC Code Coverage Report | |||||||||||||||||||||
        
  | 
    |||||||||||||||||||||
| Line | Branch | Exec | Source | 
1  | 
    /* $OpenBSD: pch.c,v 1.58 2017/05/30 06:55:40 florian Exp $ */  | 
    ||
2  | 
    |||
3  | 
    /*  | 
    ||
4  | 
    * patch - a program to apply diffs to original files  | 
    ||
5  | 
    *  | 
    ||
6  | 
    * Copyright 1986, Larry Wall  | 
    ||
7  | 
    *  | 
    ||
8  | 
    * Redistribution and use in source and binary forms, with or without  | 
    ||
9  | 
    * modification, are permitted provided that the following condition is met:  | 
    ||
10  | 
    * 1. Redistributions of source code must retain the above copyright notice,  | 
    ||
11  | 
    * this condition and the following disclaimer.  | 
    ||
12  | 
    *  | 
    ||
13  | 
    * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY  | 
    ||
14  | 
    * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED  | 
    ||
15  | 
    * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE  | 
    ||
16  | 
    * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR  | 
    ||
17  | 
    * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL  | 
    ||
18  | 
    * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR  | 
    ||
19  | 
    * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER  | 
    ||
20  | 
    * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT  | 
    ||
21  | 
    * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY  | 
    ||
22  | 
    * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF  | 
    ||
23  | 
    * SUCH DAMAGE.  | 
    ||
24  | 
    *  | 
    ||
25  | 
    * -C option added in 1998, original code by Marc Espie, based on FreeBSD  | 
    ||
26  | 
    * behaviour  | 
    ||
27  | 
    */  | 
    ||
28  | 
    |||
29  | 
    #include <sys/types.h>  | 
    ||
30  | 
    #include <sys/stat.h>  | 
    ||
31  | 
    |||
32  | 
    #include <ctype.h>  | 
    ||
33  | 
    #include <libgen.h>  | 
    ||
34  | 
    #include <limits.h>  | 
    ||
35  | 
    #include <stdint.h>  | 
    ||
36  | 
    #include <stdio.h>  | 
    ||
37  | 
    #include <stdlib.h>  | 
    ||
38  | 
    #include <string.h>  | 
    ||
39  | 
    #include <unistd.h>  | 
    ||
40  | 
    |||
41  | 
    #include "common.h"  | 
    ||
42  | 
    #include "util.h"  | 
    ||
43  | 
    #include "pch.h"  | 
    ||
44  | 
    #include "pathnames.h"  | 
    ||
45  | 
    |||
46  | 
    /* Patch (diff listing) abstract type. */  | 
    ||
47  | 
    |||
48  | 
    FILE *pfp = NULL; /* patch file pointer */  | 
    ||
49  | 
    LINENUM p_input_line = 0; /* current line # from patch file */  | 
    ||
50  | 
    |||
51  | 
    static off_t p_filesize; /* size of the patch file */  | 
    ||
52  | 
    static LINENUM p_first; /* 1st line number */  | 
    ||
53  | 
    static LINENUM p_newfirst; /* 1st line number of replacement */  | 
    ||
54  | 
    static LINENUM p_ptrn_lines; /* # lines in pattern */  | 
    ||
55  | 
    static LINENUM p_repl_lines; /* # lines in replacement text */  | 
    ||
56  | 
    static LINENUM p_end = -1; /* last line in hunk */  | 
    ||
57  | 
    static LINENUM p_max; /* max allowed value of p_end */  | 
    ||
58  | 
    static LINENUM p_context = 3; /* # of context lines */  | 
    ||
59  | 
    static char **p_line = NULL;/* the text of the hunk */  | 
    ||
60  | 
    static short *p_len = NULL; /* length of each line */  | 
    ||
61  | 
    static char *p_char = NULL; /* +, -, and ! */  | 
    ||
62  | 
    static int hunkmax = INITHUNKMAX; /* size of above arrays to begin with */  | 
    ||
63  | 
    static int p_indent; /* indent to patch */  | 
    ||
64  | 
    static off_t p_base; /* where to intuit this time */  | 
    ||
65  | 
    static LINENUM p_bline; /* line # of p_base */  | 
    ||
66  | 
    static off_t 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  | 
    static char *bestguess = NULL; /* guess at correct filename */  | 
    ||
72  | 
    |||
73  | 
    static void grow_hunkmax(void);  | 
    ||
74  | 
    static int intuit_diff_type(void);  | 
    ||
75  | 
    static void skip_to(off_t, LINENUM);  | 
    ||
76  | 
    static char *best_name(const struct file_name *, bool);  | 
    ||
77  | 
    static char *posix_name(const struct file_name *, bool);  | 
    ||
78  | 
    static size_t num_components(const char *);  | 
    ||
79  | 
    |||
80  | 
    /*  | 
    ||
81  | 
    * Prepare to look for the next patch in the patch file.  | 
    ||
82  | 
    */  | 
    ||
83  | 
    void  | 
    ||
84  | 
    re_patch(void)  | 
    ||
85  | 
    { | 
    ||
86  | 
    936  | 
    p_first = 0;  | 
    |
87  | 
    468  | 
    p_newfirst = 0;  | 
    |
88  | 
    468  | 
    p_ptrn_lines = 0;  | 
    |
89  | 
    468  | 
    p_repl_lines = 0;  | 
    |
90  | 
    468  | 
    p_end = (LINENUM) - 1;  | 
    |
91  | 
    468  | 
    p_max = 0;  | 
    |
92  | 
    468  | 
    p_indent = 0;  | 
    |
93  | 
    468  | 
    }  | 
    |
94  | 
    |||
95  | 
    /*  | 
    ||
96  | 
    * Open the patch file at the beginning of time.  | 
    ||
97  | 
    */  | 
    ||
98  | 
    void  | 
    ||
99  | 
    open_patch_file(const char *filename)  | 
    ||
100  | 
    { | 
    ||
101  | 
    1080  | 
    struct stat filestat;  | 
    |
102  | 
    |||
103  | 
    ✓✗✓✗ ✗✓  | 
    1620  | 
    	if (filename == NULL || *filename == '\0' || strEQ(filename, "-")) { | 
    
104  | 
    pfp = fopen(TMPPATNAME, "w");  | 
    ||
105  | 
    if (pfp == NULL)  | 
    ||
106  | 
    			pfatal("can't create %s", TMPPATNAME); | 
    ||
107  | 
    while (fgets(buf, sizeof buf, stdin) != NULL)  | 
    ||
108  | 
    fputs(buf, pfp);  | 
    ||
109  | 
    fclose(pfp);  | 
    ||
110  | 
    filename = TMPPATNAME;  | 
    ||
111  | 
    }  | 
    ||
112  | 
    540  | 
    pfp = fopen(filename, "r");  | 
    |
113  | 
    ✗✓ | 540  | 
    if (pfp == NULL)  | 
    
114  | 
    		pfatal("patch file %s not found", filename); | 
    ||
115  | 
    ✓✗✗✓ | 
    1620  | 
    if (fstat(fileno(pfp), &filestat))  | 
    
116  | 
    		pfatal("can't stat %s", filename); | 
    ||
117  | 
    540  | 
    p_filesize = filestat.st_size;  | 
    |
118  | 
    540  | 
    next_intuit_at(0, 1L); /* start at the beginning */  | 
    |
119  | 
    540  | 
    set_hunkmax();  | 
    |
120  | 
    540  | 
    }  | 
    |
121  | 
    |||
122  | 
    /*  | 
    ||
123  | 
    * Make sure our dynamically realloced tables are malloced to begin with.  | 
    ||
124  | 
    */  | 
    ||
125  | 
    void  | 
    ||
126  | 
    set_hunkmax(void)  | 
    ||
127  | 
    { | 
    ||
128  | 
    ✓✗ | 1080  | 
    if (p_line == NULL)  | 
    
129  | 
    540  | 
    p_line = calloc((size_t) hunkmax, sizeof(char *));  | 
    |
130  | 
    ✓✗ | 540  | 
    if (p_len == NULL)  | 
    
131  | 
    540  | 
    p_len = calloc((size_t) hunkmax, sizeof(short));  | 
    |
132  | 
    ✓✗ | 540  | 
    if (p_char == NULL)  | 
    
133  | 
    540  | 
    p_char = calloc((size_t) hunkmax, sizeof(char));  | 
    |
134  | 
    540  | 
    }  | 
    |
135  | 
    |||
136  | 
    /*  | 
    ||
137  | 
    * Enlarge the arrays containing the current hunk of patch.  | 
    ||
138  | 
    */  | 
    ||
139  | 
    static void  | 
    ||
140  | 
    grow_hunkmax(void)  | 
    ||
141  | 
    { | 
    ||
142  | 
    int new_hunkmax;  | 
    ||
143  | 
    char **new_p_line;  | 
    ||
144  | 
    short *new_p_len;  | 
    ||
145  | 
    char *new_p_char;  | 
    ||
146  | 
    |||
147  | 
    342  | 
    new_hunkmax = hunkmax * 2;  | 
    |
148  | 
    |||
149  | 
    ✗✓ | 171  | 
    if (p_line == NULL || p_len == NULL || p_char == NULL)  | 
    
150  | 
    		fatal("Internal memory allocation error\n"); | 
    ||
151  | 
    |||
152  | 
    171  | 
    new_p_line = reallocarray(p_line, new_hunkmax, sizeof(char *));  | 
    |
153  | 
    ✗✓ | 171  | 
    if (new_p_line == NULL)  | 
    
154  | 
    free(p_line);  | 
    ||
155  | 
    |||
156  | 
    171  | 
    new_p_len = reallocarray(p_len, new_hunkmax, sizeof(short));  | 
    |
157  | 
    ✗✓ | 171  | 
    if (new_p_len == NULL)  | 
    
158  | 
    free(p_len);  | 
    ||
159  | 
    |||
160  | 
    171  | 
    new_p_char = recallocarray(p_char, hunkmax, new_hunkmax, sizeof(char));  | 
    |
161  | 
    ✗✓ | 171  | 
    if (new_p_char == NULL)  | 
    
162  | 
    free(p_char);  | 
    ||
163  | 
    |||
164  | 
    171  | 
    p_char = new_p_char;  | 
    |
165  | 
    171  | 
    p_len = new_p_len;  | 
    |
166  | 
    171  | 
    p_line = new_p_line;  | 
    |
167  | 
    |||
168  | 
    ✓✗ | 171  | 
    	if (p_line != NULL && p_len != NULL && p_char != NULL) { | 
    
169  | 
    171  | 
    hunkmax = new_hunkmax;  | 
    |
170  | 
    171  | 
    return;  | 
    |
171  | 
    }  | 
    ||
172  | 
    |||
173  | 
    if (!using_plan_a)  | 
    ||
174  | 
    		fatal("out of memory\n"); | 
    ||
175  | 
    out_of_mem = true; /* whatever is null will be allocated again */  | 
    ||
176  | 
    /* from within plan_a(), of all places */  | 
    ||
177  | 
    171  | 
    }  | 
    |
178  | 
    |||
179  | 
    /* True if the remainder of the patch file contains a diff of some sort. */  | 
    ||
180  | 
    |||
181  | 
    bool  | 
    ||
182  | 
    there_is_another_patch(void)  | 
    ||
183  | 
    { | 
    ||
184  | 
    2016  | 
    bool exists = false;  | 
    |
185  | 
    |||
186  | 
    ✓✓✓✗ | 
    1476  | 
    	if (p_base != 0 && p_base >= p_filesize) { | 
    
187  | 
    ✗✓ | 468  | 
    if (verbose)  | 
    
188  | 
    			say("done\n"); | 
    ||
189  | 
    468  | 
    return false;  | 
    |
190  | 
    }  | 
    ||
191  | 
    ✗✓ | 540  | 
    if (verbose)  | 
    
192  | 
    		say("Hmm..."); | 
    ||
193  | 
    540  | 
    diff_type = intuit_diff_type();  | 
    |
194  | 
    ✓✓ | 540  | 
    	if (!diff_type) { | 
    
195  | 
    ✗✓ | 72  | 
    		if (p_base != 0) { | 
    
196  | 
    if (verbose)  | 
    ||
197  | 
    				say("  Ignoring the trailing garbage.\ndone\n"); | 
    ||
198  | 
    } else  | 
    ||
199  | 
    72  | 
    			say("  I can't seem to find a patch in there anywhere.\n"); | 
    |
200  | 
    72  | 
    return false;  | 
    |
201  | 
    }  | 
    ||
202  | 
    ✗✓ | 468  | 
    if (verbose)  | 
    
203  | 
    		say("  %sooks like %s to me...\n", | 
    ||
204  | 
    (p_base == 0 ? "L" : "The next patch l"),  | 
    ||
205  | 
    diff_type == UNI_DIFF ? "a unified diff" :  | 
    ||
206  | 
    diff_type == CONTEXT_DIFF ? "a context diff" :  | 
    ||
207  | 
    diff_type == NEW_CONTEXT_DIFF ? "a new-style context diff" :  | 
    ||
208  | 
    diff_type == NORMAL_DIFF ? "a normal diff" :  | 
    ||
209  | 
    "an ed script");  | 
    ||
210  | 
    ✗✓✗✗ | 
    468  | 
    if (p_indent && verbose)  | 
    
211  | 
    		say("(Patch is indented %d space%s.)\n", p_indent, | 
    ||
212  | 
    p_indent == 1 ? "" : "s");  | 
    ||
213  | 
    468  | 
    skip_to(p_start, p_sline);  | 
    |
214  | 
    ✗✓ | 936  | 
    	while (filearg[0] == NULL) { | 
    
215  | 
    		if (force || batch) { | 
    ||
216  | 
    			say("No file to patch.  Skipping...\n"); | 
    ||
217  | 
    filearg[0] = xstrdup(bestguess);  | 
    ||
218  | 
    skip_rest_of_patch = true;  | 
    ||
219  | 
    return true;  | 
    ||
220  | 
    }  | 
    ||
221  | 
    		ask("File to patch: "); | 
    ||
222  | 
    		if (*buf != '\n') { | 
    ||
223  | 
    free(bestguess);  | 
    ||
224  | 
    bestguess = xstrdup(buf);  | 
    ||
225  | 
    filearg[0] = fetchname(buf, &exists, 0);  | 
    ||
226  | 
    }  | 
    ||
227  | 
    		if (!exists) { | 
    ||
228  | 
    int def_skip = *bestguess == '\0';  | 
    ||
229  | 
    			ask("No file found--skip this patch? [%c] ", | 
    ||
230  | 
    def_skip ? 'y' : 'n');  | 
    ||
231  | 
    if (*buf == 'n' || (!def_skip && *buf != 'y'))  | 
    ||
232  | 
    continue;  | 
    ||
233  | 
    if (verbose)  | 
    ||
234  | 
    				say("Skipping patch...\n"); | 
    ||
235  | 
    free(filearg[0]);  | 
    ||
236  | 
    filearg[0] = fetchname(bestguess, &exists, 0);  | 
    ||
237  | 
    skip_rest_of_patch = true;  | 
    ||
238  | 
    return true;  | 
    ||
239  | 
    }  | 
    ||
240  | 
    }  | 
    ||
241  | 
    468  | 
    return true;  | 
    |
242  | 
    1008  | 
    }  | 
    |
243  | 
    |||
244  | 
    /* Determine what kind of diff is in the remaining part of the patch file. */  | 
    ||
245  | 
    |||
246  | 
    static int  | 
    ||
247  | 
    intuit_diff_type(void)  | 
    ||
248  | 
    { | 
    ||
249  | 
    off_t this_line = 0, previous_line;  | 
    ||
250  | 
    off_t first_command_line = -1;  | 
    ||
251  | 
    LINENUM fcl_line = -1;  | 
    ||
252  | 
    bool last_line_was_command = false, this_is_a_command = false;  | 
    ||
253  | 
    bool stars_last_line = false, stars_this_line = false;  | 
    ||
254  | 
    1080  | 
    char *s, *t;  | 
    |
255  | 
    int indent, retval;  | 
    ||
256  | 
    540  | 
    struct file_name names[MAX_FILE];  | 
    |
257  | 
    int piece_of_git = 0;  | 
    ||
258  | 
    |||
259  | 
    540  | 
    memset(names, 0, sizeof(names));  | 
    |
260  | 
    540  | 
    ok_to_create_file = false;  | 
    |
261  | 
    540  | 
    fseeko(pfp, p_base, SEEK_SET);  | 
    |
262  | 
    540  | 
    p_input_line = p_bline - 1;  | 
    |
263  | 
    540  | 
    	for (;;) { | 
    |
264  | 
    previous_line = this_line;  | 
    ||
265  | 
    8019  | 
    last_line_was_command = this_is_a_command;  | 
    |
266  | 
    8019  | 
    stars_last_line = stars_this_line;  | 
    |
267  | 
    8019  | 
    this_line = ftello(pfp);  | 
    |
268  | 
    indent = 0;  | 
    ||
269  | 
    8019  | 
    p_input_line++;  | 
    |
270  | 
    ✓✓ | 8019  | 
    		if (fgets(buf, sizeof buf, pfp) == NULL) { | 
    
271  | 
    ✓✓ | 108  | 
    			if (first_command_line >= 0) { | 
    
272  | 
    /* nothing but deletes!? */  | 
    ||
273  | 
    36  | 
    p_start = first_command_line;  | 
    |
274  | 
    36  | 
    p_sline = fcl_line;  | 
    |
275  | 
    retval = ED_DIFF;  | 
    ||
276  | 
    36  | 
    goto scan_exit;  | 
    |
277  | 
    			} else { | 
    ||
278  | 
    72  | 
    p_start = this_line;  | 
    |
279  | 
    72  | 
    p_sline = p_input_line;  | 
    |
280  | 
    retval = 0;  | 
    ||
281  | 
    72  | 
    goto scan_exit;  | 
    |
282  | 
    }  | 
    ||
283  | 
    }  | 
    ||
284  | 
    ✓✓✓✓ ✓✓  | 
    70326  | 
    		for (s = buf; *s == ' ' || *s == '\t' || *s == 'X'; s++) { | 
    
285  | 
    ✓✓ | 8190  | 
    if (*s == '\t')  | 
    
286  | 
    6201  | 
    indent += 8 - (indent % 8);  | 
    |
287  | 
    else  | 
    ||
288  | 
    1989  | 
    indent++;  | 
    |
289  | 
    }  | 
    ||
290  | 
    ✓✓✓✓ | 
    24651  | 
    for (t = s; isdigit((unsigned char)*t) || *t == ','; t++)  | 
    
291  | 
    ;  | 
    ||
292  | 
    ✓✓ | 15822  | 
    this_is_a_command = (isdigit((unsigned char)*s) &&  | 
    
293  | 
    ✓✓✓✓ | 
    558  | 
    (*t == 'd' || *t == 'c' || *t == 'a'));  | 
    
294  | 
    ✓✓✓✓ | 
    8964  | 
    		if (first_command_line < 0 && this_is_a_command) { | 
    
295  | 
    first_command_line = this_line;  | 
    ||
296  | 
    234  | 
    fcl_line = p_input_line;  | 
    |
297  | 
    234  | 
    p_indent = indent; /* assume this for now */  | 
    |
298  | 
    234  | 
    }  | 
    |
299  | 
    ✓✓✓✓ | 
    15705  | 
    if (!stars_last_line && strnEQ(s, "*** ", 4))  | 
    
300  | 
    234  | 
    names[OLD_FILE].path = fetchname(s + 4,  | 
    |
301  | 
    117  | 
    &names[OLD_FILE].exists, strippath);  | 
    |
302  | 
    ✓✓ | 7794  | 
    		else if (strnEQ(s, "--- ", 4)) { | 
    
303  | 
    size_t off = 4;  | 
    ||
304  | 
    234  | 
    if (piece_of_git && strippath == 957)  | 
    |
305  | 
    off = 6;  | 
    ||
306  | 
    468  | 
    names[NEW_FILE].path = fetchname(s + off,  | 
    |
307  | 
    234  | 
    &names[NEW_FILE].exists, strippath);  | 
    |
308  | 
    ✓✓ | 7794  | 
    		} else if (strnEQ(s, "+++ ", 4)) { | 
    
309  | 
    /* pretend it is the old name */  | 
    ||
310  | 
    size_t off = 4;  | 
    ||
311  | 
    117  | 
    if (piece_of_git && strippath == 957)  | 
    |
312  | 
    off = 6;  | 
    ||
313  | 
    234  | 
    names[OLD_FILE].path = fetchname(s + off,  | 
    |
314  | 
    117  | 
    &names[OLD_FILE].exists, strippath);  | 
    |
315  | 
    ✗✓ | 7560  | 
    } else if (strnEQ(s, "Index:", 6))  | 
    
316  | 
    names[INDEX_FILE].path = fetchname(s + 6,  | 
    ||
317  | 
    &names[INDEX_FILE].exists, strippath);  | 
    ||
318  | 
    ✗✓ | 7443  | 
    		else if (strnEQ(s, "Prereq:", 7)) { | 
    
319  | 
    for (t = s + 7; isspace((unsigned char)*t); t++)  | 
    ||
320  | 
    ;  | 
    ||
321  | 
    revision = xstrdup(t);  | 
    ||
322  | 
    for (t = revision;  | 
    ||
323  | 
    *t && !isspace((unsigned char)*t); t++)  | 
    ||
324  | 
    ;  | 
    ||
325  | 
    *t = '\0';  | 
    ||
326  | 
    			if (*revision == '\0') { | 
    ||
327  | 
    free(revision);  | 
    ||
328  | 
    revision = NULL;  | 
    ||
329  | 
    }  | 
    ||
330  | 
    ✗✓ | 7443  | 
    } else if (strnEQ(s, "diff --git a/", 13))  | 
    
331  | 
    piece_of_git = 1;  | 
    ||
332  | 
    ✓✓✓✓ | 
    22914  | 
    if ((!diff_type || diff_type == ED_DIFF) &&  | 
    
333  | 
    7911  | 
    first_command_line >= 0 &&  | 
    |
334  | 
    7092  | 
    		    strEQ(s, ".\n")) { | 
    |
335  | 
    81  | 
    p_indent = indent;  | 
    |
336  | 
    81  | 
    p_start = first_command_line;  | 
    |
337  | 
    81  | 
    p_sline = fcl_line;  | 
    |
338  | 
    retval = ED_DIFF;  | 
    ||
339  | 
    81  | 
    goto scan_exit;  | 
    |
340  | 
    }  | 
    ||
341  | 
    ✓✗✓✓ | 
    15660  | 
    		if ((!diff_type || diff_type == UNI_DIFF) && strnEQ(s, "@@ -", 4)) { | 
    
342  | 
    ✓✓ | 117  | 
    if (strnEQ(s + 4, "0,0", 3))  | 
    
343  | 
    9  | 
    ok_to_create_file = true;  | 
    |
344  | 
    117  | 
    p_indent = indent;  | 
    |
345  | 
    117  | 
    p_start = this_line;  | 
    |
346  | 
    117  | 
    p_sline = p_input_line;  | 
    |
347  | 
    retval = UNI_DIFF;  | 
    ||
348  | 
    117  | 
    goto scan_exit;  | 
    |
349  | 
    }  | 
    ||
350  | 
    7713  | 
    stars_this_line = strnEQ(s, "********", 8);  | 
    |
351  | 
    ✓✗✓✓ ✓✗  | 
    15543  | 
    if ((!diff_type || diff_type == CONTEXT_DIFF) && stars_last_line &&  | 
    
352  | 
    117  | 
    		    strnEQ(s, "*** ", 4)) { | 
    |
353  | 
    ✓✓ | 117  | 
    if (strtolinenum(s + 4, &s) == 0)  | 
    
354  | 
    9  | 
    ok_to_create_file = true;  | 
    |
355  | 
    /*  | 
    ||
356  | 
    * If this is a new context diff the character just  | 
    ||
357  | 
    * at the end of the line is a '*'.  | 
    ||
358  | 
    */  | 
    ||
359  | 
    ✓✗✓✓ | 
    2718  | 
    while (*s && *s != '\n')  | 
    
360  | 
    828  | 
    s++;  | 
    |
361  | 
    117  | 
    p_indent = indent;  | 
    |
362  | 
    117  | 
    p_start = previous_line;  | 
    |
363  | 
    117  | 
    p_sline = p_input_line - 1;  | 
    |
364  | 
    117  | 
    retval = (*(s - 1) == '*' ? NEW_CONTEXT_DIFF : CONTEXT_DIFF);  | 
    |
365  | 
    117  | 
    goto scan_exit;  | 
    |
366  | 
    }  | 
    ||
367  | 
    ✗✓✓✓ | 
    7722  | 
    if ((!diff_type || diff_type == NORMAL_DIFF) &&  | 
    
368  | 
    ✓✓ | 7596  | 
    last_line_was_command &&  | 
    
369  | 
    ✓✓ | 351  | 
    		    (strnEQ(s, "< ", 2) || strnEQ(s, "> ", 2))) { | 
    
370  | 
    117  | 
    p_start = previous_line;  | 
    |
371  | 
    117  | 
    p_sline = p_input_line - 1;  | 
    |
372  | 
    117  | 
    p_indent = indent;  | 
    |
373  | 
    retval = NORMAL_DIFF;  | 
    ||
374  | 
    117  | 
    goto scan_exit;  | 
    |
375  | 
    }  | 
    ||
376  | 
    }  | 
    ||
377  | 
    scan_exit:  | 
    ||
378  | 
    ✓✓ | 540  | 
    	if (retval == UNI_DIFF) { | 
    
379  | 
    /* unswap old and new */  | 
    ||
380  | 
    117  | 
    struct file_name tmp = names[OLD_FILE];  | 
    |
381  | 
    117  | 
    names[OLD_FILE] = names[NEW_FILE];  | 
    |
382  | 
    117  | 
    names[NEW_FILE] = tmp;  | 
    |
383  | 
    117  | 
    }  | 
    |
384  | 
    ✗✓ | 540  | 
    	if (filearg[0] == NULL) { | 
    
385  | 
    if (posix)  | 
    ||
386  | 
    filearg[0] = posix_name(names, ok_to_create_file);  | 
    ||
387  | 
    		else { | 
    ||
388  | 
    /* Ignore the Index: name for context diffs, like GNU */  | 
    ||
389  | 
    if (names[OLD_FILE].path != NULL ||  | 
    ||
390  | 
    			    names[NEW_FILE].path != NULL) { | 
    ||
391  | 
    free(names[INDEX_FILE].path);  | 
    ||
392  | 
    names[INDEX_FILE].path = NULL;  | 
    ||
393  | 
    }  | 
    ||
394  | 
    filearg[0] = best_name(names, ok_to_create_file);  | 
    ||
395  | 
    }  | 
    ||
396  | 
    }  | 
    ||
397  | 
    |||
398  | 
    540  | 
    free(bestguess);  | 
    |
399  | 
    540  | 
    bestguess = NULL;  | 
    |
400  | 
    ✓✗ | 540  | 
    if (filearg[0] != NULL)  | 
    
401  | 
    540  | 
    bestguess = xstrdup(filearg[0]);  | 
    |
402  | 
    	else if (!ok_to_create_file) { | 
    ||
403  | 
    /*  | 
    ||
404  | 
    * We don't want to create a new file but we need a  | 
    ||
405  | 
    * filename to set bestguess. Avoid setting filearg[0]  | 
    ||
406  | 
    * so the file is not created automatically.  | 
    ||
407  | 
    */  | 
    ||
408  | 
    if (posix)  | 
    ||
409  | 
    bestguess = posix_name(names, true);  | 
    ||
410  | 
    else  | 
    ||
411  | 
    bestguess = best_name(names, true);  | 
    ||
412  | 
    }  | 
    ||
413  | 
    1080  | 
    free(names[OLD_FILE].path);  | 
    |
414  | 
    540  | 
    free(names[NEW_FILE].path);  | 
    |
415  | 
    540  | 
    free(names[INDEX_FILE].path);  | 
    |
416  | 
    540  | 
    return retval;  | 
    |
417  | 
    540  | 
    }  | 
    |
418  | 
    |||
419  | 
    /*  | 
    ||
420  | 
    * Remember where this patch ends so we know where to start up again.  | 
    ||
421  | 
    */  | 
    ||
422  | 
    void  | 
    ||
423  | 
    next_intuit_at(off_t file_pos, LINENUM file_line)  | 
    ||
424  | 
    { | 
    ||
425  | 
    2016  | 
    p_base = file_pos;  | 
    |
426  | 
    1008  | 
    p_bline = file_line;  | 
    |
427  | 
    1008  | 
    }  | 
    |
428  | 
    |||
429  | 
    /*  | 
    ||
430  | 
    * Basically a verbose fseeko() to the actual diff listing.  | 
    ||
431  | 
    */  | 
    ||
432  | 
    static void  | 
    ||
433  | 
    skip_to(off_t file_pos, LINENUM file_line)  | 
    ||
434  | 
    { | 
    ||
435  | 
    char *ret;  | 
    ||
436  | 
    |||
437  | 
    ✗✓ | 936  | 
    if (p_base > file_pos)  | 
    
438  | 
    		fatal("Internal error: seek %lld>%lld\n", | 
    ||
439  | 
    (long long)p_base, (long long)file_pos);  | 
    ||
440  | 
    ✗✓✗✗ | 
    468  | 
    	if (verbose && p_base < file_pos) { | 
    
441  | 
    fseeko(pfp, p_base, SEEK_SET);  | 
    ||
442  | 
    		say("The text leading up to this was:\n--------------------------\n"); | 
    ||
443  | 
    		while (ftello(pfp) < file_pos) { | 
    ||
444  | 
    ret = fgets(buf, sizeof buf, pfp);  | 
    ||
445  | 
    if (ret == NULL)  | 
    ||
446  | 
    				fatal("Unexpected end of file\n"); | 
    ||
447  | 
    			say("|%s", buf); | 
    ||
448  | 
    }  | 
    ||
449  | 
    		say("--------------------------\n"); | 
    ||
450  | 
    } else  | 
    ||
451  | 
    468  | 
    fseeko(pfp, file_pos, SEEK_SET);  | 
    |
452  | 
    468  | 
    p_input_line = file_line - 1;  | 
    |
453  | 
    468  | 
    }  | 
    |
454  | 
    |||
455  | 
    /* Make this a function for better debugging. */  | 
    ||
456  | 
    static void  | 
    ||
457  | 
    malformed(void)  | 
    ||
458  | 
    { | 
    ||
459  | 
    	fatal("malformed patch at line %ld: %s", p_input_line, buf); | 
    ||
460  | 
    /* about as informative as "Syntax error" in C */  | 
    ||
461  | 
    }  | 
    ||
462  | 
    |||
463  | 
    /*  | 
    ||
464  | 
    * True if the line has been discarded (i.e. it is a line saying  | 
    ||
465  | 
    * "\ No newline at end of file".)  | 
    ||
466  | 
    */  | 
    ||
467  | 
    static bool  | 
    ||
468  | 
    remove_special_line(void)  | 
    ||
469  | 
    { | 
    ||
470  | 
    int c;  | 
    ||
471  | 
    |||
472  | 
    37458  | 
    c = fgetc(pfp);  | 
    |
473  | 
    ✓✓ | 18729  | 
    	if (c == '\\') { | 
    
474  | 
    		do { | 
    ||
475  | 
    4374  | 
    c = fgetc(pfp);  | 
    |
476  | 
    ✓✓ | 4374  | 
    } while (c != EOF && c != '\n');  | 
    
477  | 
    |||
478  | 
    162  | 
    return true;  | 
    |
479  | 
    }  | 
    ||
480  | 
    ✓✓ | 18567  | 
    if (c != EOF)  | 
    
481  | 
    18234  | 
    fseeko(pfp, -1, SEEK_CUR);  | 
    |
482  | 
    |||
483  | 
    18567  | 
    return false;  | 
    |
484  | 
    18729  | 
    }  | 
    |
485  | 
    |||
486  | 
    /*  | 
    ||
487  | 
    * True if there is more of the current diff listing to process.  | 
    ||
488  | 
    */  | 
    ||
489  | 
    bool  | 
    ||
490  | 
    another_hunk(void)  | 
    ||
491  | 
    { | 
    ||
492  | 
    off_t line_beginning; /* file pos of the current line */  | 
    ||
493  | 
    LINENUM repl_beginning; /* index of --- line */  | 
    ||
494  | 
    LINENUM fillcnt; /* #lines of missing ptrn or repl */  | 
    ||
495  | 
    LINENUM fillsrc; /* index of first line to copy */  | 
    ||
496  | 
    LINENUM filldst; /* index of first missing line */  | 
    ||
497  | 
    bool ptrn_spaces_eaten; /* ptrn was slightly misformed */  | 
    ||
498  | 
    bool repl_could_be_missing; /* no + or ! lines in this hunk */  | 
    ||
499  | 
    bool repl_missing; /* we are now backtracking */  | 
    ||
500  | 
    off_t repl_backtrack_position; /* file pos of first repl line */  | 
    ||
501  | 
    LINENUM repl_patch_line; /* input line number for same */  | 
    ||
502  | 
    LINENUM ptrn_copiable; /* # of copiable lines in ptrn */  | 
    ||
503  | 
    14850  | 
    char *s, *ret;  | 
    |
504  | 
    int context = 0;  | 
    ||
505  | 
    |||
506  | 
    ✓✓ | 339930  | 
    	while (p_end >= 0) { | 
    
507  | 
    ✓✓ | 162540  | 
    if (p_end == p_efake)  | 
    
508  | 
    288  | 
    p_end = p_bfake; /* don't free twice */  | 
    |
509  | 
    else  | 
    ||
510  | 
    162252  | 
    free(p_line[p_end]);  | 
    |
511  | 
    162540  | 
    p_end--;  | 
    |
512  | 
    }  | 
    ||
513  | 
    7425  | 
    p_efake = -1;  | 
    |
514  | 
    |||
515  | 
    7425  | 
    p_max = hunkmax; /* gets reduced when --- found */  | 
    |
516  | 
    ✓✓ | 7425  | 
    	if (diff_type == CONTEXT_DIFF || diff_type == NEW_CONTEXT_DIFF) { | 
    
517  | 
    1161  | 
    line_beginning = ftello(pfp);  | 
    |
518  | 
    repl_beginning = 0;  | 
    ||
519  | 
    fillcnt = 0;  | 
    ||
520  | 
    fillsrc = 0;  | 
    ||
521  | 
    ptrn_spaces_eaten = false;  | 
    ||
522  | 
    repl_could_be_missing = true;  | 
    ||
523  | 
    repl_missing = false;  | 
    ||
524  | 
    repl_backtrack_position = 0;  | 
    ||
525  | 
    repl_patch_line = 0;  | 
    ||
526  | 
    ptrn_copiable = 0;  | 
    ||
527  | 
    |||
528  | 
    1161  | 
    ret = pgets(buf, sizeof buf, pfp);  | 
    |
529  | 
    1161  | 
    p_input_line++;  | 
    |
530  | 
    ✓✓✗✓ | 
    2205  | 
    		if (ret == NULL || strnNE(buf, "********", 8)) { | 
    
531  | 
    117  | 
    next_intuit_at(line_beginning, p_input_line);  | 
    |
532  | 
    117  | 
    return false;  | 
    |
533  | 
    }  | 
    ||
534  | 
    1044  | 
    p_context = 100;  | 
    |
535  | 
    1044  | 
    p_hunk_beg = p_input_line + 1;  | 
    |
536  | 
    ✓✓ | 119916  | 
    		while (p_end < p_max) { | 
    
537  | 
    58923  | 
    line_beginning = ftello(pfp);  | 
    |
538  | 
    58923  | 
    ret = pgets(buf, sizeof buf, pfp);  | 
    |
539  | 
    58923  | 
    p_input_line++;  | 
    |
540  | 
    ✓✓ | 58923  | 
    			if (ret == NULL) { | 
    
541  | 
    ✓✗ | 18  | 
    				if (p_max - p_end < 4) { | 
    
542  | 
    /* assume blank lines got chopped */  | 
    ||
543  | 
    18  | 
    strlcpy(buf, " \n", sizeof buf);  | 
    |
544  | 
    18  | 
    				} else { | 
    |
545  | 
    					if (repl_beginning && repl_could_be_missing) { | 
    ||
546  | 
    repl_missing = true;  | 
    ||
547  | 
    goto hunk_done;  | 
    ||
548  | 
    }  | 
    ||
549  | 
    					fatal("unexpected end of file in patch\n"); | 
    ||
550  | 
    }  | 
    ||
551  | 
    }  | 
    ||
552  | 
    58923  | 
    p_end++;  | 
    |
553  | 
    ✗✓ | 58923  | 
    if (p_end >= hunkmax)  | 
    
554  | 
    				fatal("Internal error: hunk larger than hunk " | 
    ||
555  | 
    "buffer size");  | 
    ||
556  | 
    58923  | 
    p_char[p_end] = *buf;  | 
    |
557  | 
    58923  | 
    p_line[p_end] = NULL;  | 
    |
558  | 
    ✓✓✗✓ ✗✗✓✗  | 
    58923  | 
    			switch (*buf) { | 
    
559  | 
    case '*':  | 
    ||
560  | 
    ✓✓ | 1053  | 
    				if (strnEQ(buf, "********", 8)) { | 
    
561  | 
    ✓✗✓✗ | 
    18  | 
    					if (repl_beginning && repl_could_be_missing) { | 
    
562  | 
    repl_missing = true;  | 
    ||
563  | 
    9  | 
    goto hunk_done;  | 
    |
564  | 
    } else  | 
    ||
565  | 
    						fatal("unexpected end of hunk " | 
    ||
566  | 
    "at line %ld\n",  | 
    ||
567  | 
    p_input_line);  | 
    ||
568  | 
    }  | 
    ||
569  | 
    ✗✓ | 1044  | 
    				if (p_end != 0) { | 
    
570  | 
    					if (repl_beginning && repl_could_be_missing) { | 
    ||
571  | 
    repl_missing = true;  | 
    ||
572  | 
    goto hunk_done;  | 
    ||
573  | 
    }  | 
    ||
574  | 
    					fatal("unexpected *** at line %ld: %s", | 
    ||
575  | 
    p_input_line, buf);  | 
    ||
576  | 
    }  | 
    ||
577  | 
    context = 0;  | 
    ||
578  | 
    1044  | 
    p_line[p_end] = savestr(buf);  | 
    |
579  | 
    ✗✓ | 1044  | 
    				if (out_of_mem) { | 
    
580  | 
    p_end--;  | 
    ||
581  | 
    return false;  | 
    ||
582  | 
    }  | 
    ||
583  | 
    ✓✓ | 10440  | 
    for (s = buf;  | 
    
584  | 
    ✓✗ | 14616  | 
    *s && !isdigit((unsigned char)*s); s++)  | 
    
585  | 
    ;  | 
    ||
586  | 
    ✗✓ | 1044  | 
    if (!*s)  | 
    
587  | 
    malformed();  | 
    ||
588  | 
    ✗✓ | 1044  | 
    if (strnEQ(s, "0,0", 3))  | 
    
589  | 
    memmove(s, s + 2, strlen(s + 2) + 1);  | 
    ||
590  | 
    1044  | 
    p_first = strtolinenum(s, &s);  | 
    |
591  | 
    ✓✓ | 1044  | 
    				if (*s == ',') { | 
    
592  | 
    ✓✗✓✓ | 
    5130  | 
    for (; *s && !isdigit((unsigned char)*s); s++)  | 
    
593  | 
    ;  | 
    ||
594  | 
    ✗✓ | 1026  | 
    if (!*s)  | 
    
595  | 
    malformed();  | 
    ||
596  | 
    1026  | 
    p_ptrn_lines = strtolinenum(s, &s) - p_first + 1;  | 
    |
597  | 
    ✗✓ | 1026  | 
    if (p_ptrn_lines < 0)  | 
    
598  | 
    malformed();  | 
    ||
599  | 
    ✓✓ | 18  | 
    } else if (p_first)  | 
    
600  | 
    p_ptrn_lines = 1;  | 
    ||
601  | 
    				else { | 
    ||
602  | 
    9  | 
    p_ptrn_lines = 0;  | 
    |
603  | 
    p_first = 1;  | 
    ||
604  | 
    }  | 
    ||
605  | 
    ✗✓ | 2088  | 
    if (p_first >= LINENUM_MAX - p_ptrn_lines ||  | 
    
606  | 
    1044  | 
    p_ptrn_lines >= LINENUM_MAX - 6)  | 
    |
607  | 
    malformed();  | 
    ||
608  | 
    |||
609  | 
    /* we need this much at least */  | 
    ||
610  | 
    1044  | 
    p_max = p_ptrn_lines + 6;  | 
    |
611  | 
    ✓✓ | 2160  | 
    while (p_max >= hunkmax)  | 
    
612  | 
    36  | 
    grow_hunkmax();  | 
    |
613  | 
    1044  | 
    p_max = hunkmax;  | 
    |
614  | 
    1044  | 
    break;  | 
    |
615  | 
    case '-':  | 
    ||
616  | 
    ✓✓ | 2061  | 
    				if (buf[1] == '-') { | 
    
617  | 
    ✓✗✓✓ | 
    2088  | 
    if (repl_beginning ||  | 
    
618  | 
    2088  | 
    (p_end != p_ptrn_lines + 1 +  | 
    |
619  | 
    1044  | 
    					    (p_char[p_end - 1] == '\n'))) { | 
    |
620  | 
    ✓✗ | 279  | 
    						if (p_end == 1) { | 
    
621  | 
    /*  | 
    ||
622  | 
    * `old' lines were omitted;  | 
    ||
623  | 
    * set up to fill them in  | 
    ||
624  | 
    * from 'new' context lines.  | 
    ||
625  | 
    */  | 
    ||
626  | 
    279  | 
    p_end = p_ptrn_lines + 1;  | 
    |
627  | 
    279  | 
    fillsrc = p_end + 1;  | 
    |
628  | 
    filldst = 1;  | 
    ||
629  | 
    279  | 
    fillcnt = p_ptrn_lines;  | 
    |
630  | 
    279  | 
    						} else { | 
    |
631  | 
    							if (repl_beginning) { | 
    ||
632  | 
    								if (repl_could_be_missing) { | 
    ||
633  | 
    repl_missing = true;  | 
    ||
634  | 
    goto hunk_done;  | 
    ||
635  | 
    }  | 
    ||
636  | 
    								fatal("duplicate \"---\" at line %ld--check line numbers at line %ld\n", | 
    ||
637  | 
    p_input_line, p_hunk_beg + repl_beginning);  | 
    ||
638  | 
    							} else { | 
    ||
639  | 
    								fatal("%s \"---\" at line %ld--check line numbers at line %ld\n", | 
    ||
640  | 
    (p_end <= p_ptrn_lines  | 
    ||
641  | 
    ? "Premature"  | 
    ||
642  | 
    : "Overdue"),  | 
    ||
643  | 
    p_input_line, p_hunk_beg);  | 
    ||
644  | 
    }  | 
    ||
645  | 
    }  | 
    ||
646  | 
    }  | 
    ||
647  | 
    1044  | 
    repl_beginning = p_end;  | 
    |
648  | 
    1044  | 
    repl_backtrack_position = ftello(pfp);  | 
    |
649  | 
    1044  | 
    repl_patch_line = p_input_line;  | 
    |
650  | 
    1044  | 
    p_line[p_end] = savestr(buf);  | 
    |
651  | 
    ✗✓ | 1044  | 
    					if (out_of_mem) { | 
    
652  | 
    p_end--;  | 
    ||
653  | 
    return false;  | 
    ||
654  | 
    }  | 
    ||
655  | 
    1044  | 
    p_char[p_end] = '=';  | 
    |
656  | 
    ✓✓ | 10440  | 
    for (s = buf;  | 
    
657  | 
    ✓✗ | 14616  | 
    *s && !isdigit((unsigned char)*s); s++)  | 
    
658  | 
    ;  | 
    ||
659  | 
    ✗✓ | 1044  | 
    if (!*s)  | 
    
660  | 
    malformed();  | 
    ||
661  | 
    1044  | 
    p_newfirst = strtolinenum(s, &s);  | 
    |
662  | 
    ✓✓ | 1044  | 
    					if (*s == ',') { | 
    
663  | 
    ✓✗✓✓ | 
    5130  | 
    for (; *s && !isdigit((unsigned char)*s); s++)  | 
    
664  | 
    ;  | 
    ||
665  | 
    ✗✓ | 1026  | 
    if (!*s)  | 
    
666  | 
    malformed();  | 
    ||
667  | 
    3078  | 
    p_repl_lines = strtolinenum(s, &s) -  | 
    |
668  | 
    2052  | 
    p_newfirst + 1;  | 
    |
669  | 
    ✗✓ | 1026  | 
    if (p_repl_lines < 0)  | 
    
670  | 
    malformed();  | 
    ||
671  | 
    ✓✓ | 18  | 
    } else if (p_newfirst)  | 
    
672  | 
    p_repl_lines = 1;  | 
    ||
673  | 
    					else { | 
    ||
674  | 
    9  | 
    p_repl_lines = 0;  | 
    |
675  | 
    p_newfirst = 1;  | 
    ||
676  | 
    }  | 
    ||
677  | 
    ✓✗✗✓ | 
    2088  | 
    if (p_newfirst >= LINENUM_MAX - p_repl_lines ||  | 
    
678  | 
    1044  | 
    p_repl_lines >= LINENUM_MAX - p_end)  | 
    |
679  | 
    malformed();  | 
    ||
680  | 
    1044  | 
    p_max = p_repl_lines + p_end;  | 
    |
681  | 
    ✗✓ | 1044  | 
    if (p_max > MAXHUNKSIZE)  | 
    
682  | 
    						fatal("hunk too large (%ld lines) at line %ld: %s", | 
    ||
683  | 
    p_max, p_input_line, buf);  | 
    ||
684  | 
    ✓✓ | 1116  | 
    while (p_max >= hunkmax)  | 
    
685  | 
    36  | 
    grow_hunkmax();  | 
    |
686  | 
    ✓✓ | 1044  | 
    if (p_repl_lines != ptrn_copiable &&  | 
    
687  | 
    ✓✓ | 1017  | 
    (p_context != 0 || p_repl_lines != 1))  | 
    
688  | 
    1008  | 
    repl_could_be_missing = false;  | 
    |
689  | 
    break;  | 
    ||
690  | 
    }  | 
    ||
691  | 
    goto change_line;  | 
    ||
692  | 
    case '+':  | 
    ||
693  | 
    case '!':  | 
    ||
694  | 
    31707  | 
    repl_could_be_missing = false;  | 
    |
695  | 
    change_line:  | 
    ||
696  | 
    ✗✓✗✗ | 
    32724  | 
    if (buf[1] == '\n' && canonicalize)  | 
    
697  | 
    strlcpy(buf + 1, " \n", sizeof buf - 1);  | 
    ||
698  | 
    ✗✓✗✗ | 
    32724  | 
    if (!isspace((unsigned char)buf[1]) &&  | 
    
699  | 
    buf[1] != '>' && buf[1] != '<' &&  | 
    ||
700  | 
    				    repl_beginning && repl_could_be_missing) { | 
    ||
701  | 
    repl_missing = true;  | 
    ||
702  | 
    goto hunk_done;  | 
    ||
703  | 
    }  | 
    ||
704  | 
    ✓✓ | 32724  | 
    				if (context >= 0) { | 
    
705  | 
    ✓✗ | 1044  | 
    if (context < p_context)  | 
    
706  | 
    1044  | 
    p_context = context;  | 
    |
707  | 
    context = -1000;  | 
    ||
708  | 
    1044  | 
    }  | 
    |
709  | 
    32724  | 
    p_line[p_end] = savestr(buf + 2);  | 
    |
710  | 
    ✗✓ | 32724  | 
    				if (out_of_mem) { | 
    
711  | 
    p_end--;  | 
    ||
712  | 
    return false;  | 
    ||
713  | 
    }  | 
    ||
714  | 
    ✓✓ | 32724  | 
    				if (p_end == p_ptrn_lines) { | 
    
715  | 
    ✓✓ | 54  | 
    					if (remove_special_line()) { | 
    
716  | 
    int len;  | 
    ||
717  | 
    |||
718  | 
    36  | 
    len = strlen(p_line[p_end]) - 1;  | 
    |
719  | 
    36  | 
    (p_line[p_end])[len] = 0;  | 
    |
720  | 
    36  | 
    }  | 
    |
721  | 
    }  | 
    ||
722  | 
    break;  | 
    ||
723  | 
    case '\t':  | 
    ||
724  | 
    case '\n': /* assume the 2 spaces got eaten */  | 
    ||
725  | 
    if (repl_beginning && repl_could_be_missing &&  | 
    ||
726  | 
    (!ptrn_spaces_eaten ||  | 
    ||
727  | 
    				    diff_type == NEW_CONTEXT_DIFF)) { | 
    ||
728  | 
    repl_missing = true;  | 
    ||
729  | 
    goto hunk_done;  | 
    ||
730  | 
    }  | 
    ||
731  | 
    p_line[p_end] = savestr(buf);  | 
    ||
732  | 
    				if (out_of_mem) { | 
    ||
733  | 
    p_end--;  | 
    ||
734  | 
    return false;  | 
    ||
735  | 
    }  | 
    ||
736  | 
    				if (p_end != p_ptrn_lines + 1) { | 
    ||
737  | 
    ptrn_spaces_eaten |= (repl_beginning != 0);  | 
    ||
738  | 
    context++;  | 
    ||
739  | 
    if (!repl_beginning)  | 
    ||
740  | 
    ptrn_copiable++;  | 
    ||
741  | 
    p_char[p_end] = ' ';  | 
    ||
742  | 
    }  | 
    ||
743  | 
    break;  | 
    ||
744  | 
    case ' ':  | 
    ||
745  | 
    ✗✓✗✗ | 
    48204  | 
    if (!isspace((unsigned char)buf[1]) &&  | 
    
746  | 
    24102  | 
    				    repl_beginning && repl_could_be_missing) { | 
    |
747  | 
    repl_missing = true;  | 
    ||
748  | 
    goto hunk_done;  | 
    ||
749  | 
    }  | 
    ||
750  | 
    24102  | 
    context++;  | 
    |
751  | 
    ✓✓ | 24102  | 
    if (!repl_beginning)  | 
    
752  | 
    11241  | 
    ptrn_copiable++;  | 
    |
753  | 
    24102  | 
    p_line[p_end] = savestr(buf + 2);  | 
    |
754  | 
    ✗✓ | 24102  | 
    				if (out_of_mem) { | 
    
755  | 
    p_end--;  | 
    ||
756  | 
    return false;  | 
    ||
757  | 
    }  | 
    ||
758  | 
    break;  | 
    ||
759  | 
    default:  | 
    ||
760  | 
    				if (repl_beginning && repl_could_be_missing) { | 
    ||
761  | 
    repl_missing = true;  | 
    ||
762  | 
    goto hunk_done;  | 
    ||
763  | 
    }  | 
    ||
764  | 
    malformed();  | 
    ||
765  | 
    }  | 
    ||
766  | 
    /* set up p_len for strncmp() so we don't have to */  | 
    ||
767  | 
    /* assume null termination */  | 
    ||
768  | 
    ✓✗ | 58914  | 
    if (p_line[p_end])  | 
    
769  | 
    58914  | 
    p_len[p_end] = strlen(p_line[p_end]);  | 
    |
770  | 
    else  | 
    ||
771  | 
    p_len[p_end] = 0;  | 
    ||
772  | 
    }  | 
    ||
773  | 
    |||
774  | 
    hunk_done:  | 
    ||
775  | 
    ✗✓ | 1044  | 
    if (p_end >= 0 && !repl_beginning)  | 
    
776  | 
    			fatal("no --- found in patch at line %ld\n", pch_hunk_beg()); | 
    ||
777  | 
    |||
778  | 
    ✓✓ | 1044  | 
    		if (repl_missing) { | 
    
779  | 
    |||
780  | 
    /* reset state back to just after --- */  | 
    ||
781  | 
    9  | 
    p_input_line = repl_patch_line;  | 
    |
782  | 
    ✗✓ | 18  | 
    for (p_end--; p_end > repl_beginning; p_end--)  | 
    
783  | 
    free(p_line[p_end]);  | 
    ||
784  | 
    9  | 
    fseeko(pfp, repl_backtrack_position, SEEK_SET);  | 
    |
785  | 
    |||
786  | 
    /* redundant 'new' context lines were omitted - set */  | 
    ||
787  | 
    /* up to fill them in from the old file context */  | 
    ||
788  | 
    ✗✓ | 9  | 
    			if (!p_context && p_repl_lines == 1) { | 
    
789  | 
    p_repl_lines = 0;  | 
    ||
790  | 
    p_max--;  | 
    ||
791  | 
    }  | 
    ||
792  | 
    fillsrc = 1;  | 
    ||
793  | 
    9  | 
    filldst = repl_beginning + 1;  | 
    |
794  | 
    9  | 
    fillcnt = p_repl_lines;  | 
    |
795  | 
    9  | 
    p_end = p_max;  | 
    |
796  | 
    ✗✓ | 1044  | 
    		} else if (!p_context && fillcnt == 1) { | 
    
797  | 
    /* the first hunk was a null hunk with no context */  | 
    ||
798  | 
    /* and we were expecting one line -- fix it up. */  | 
    ||
799  | 
    			while (filldst < p_end) { | 
    ||
800  | 
    p_line[filldst] = p_line[filldst + 1];  | 
    ||
801  | 
    p_char[filldst] = p_char[filldst + 1];  | 
    ||
802  | 
    p_len[filldst] = p_len[filldst + 1];  | 
    ||
803  | 
    filldst++;  | 
    ||
804  | 
    }  | 
    ||
805  | 
    #if 0  | 
    ||
806  | 
    repl_beginning--; /* this doesn't need to be fixed */  | 
    ||
807  | 
    #endif  | 
    ||
808  | 
    p_end--;  | 
    ||
809  | 
    p_first++; /* do append rather than insert */  | 
    ||
810  | 
    fillcnt = 0;  | 
    ||
811  | 
    p_ptrn_lines = 0;  | 
    ||
812  | 
    }  | 
    ||
813  | 
    ✗✓✗✗ | 
    1044  | 
    if (diff_type == CONTEXT_DIFF &&  | 
    
814  | 
    		    (fillcnt || (p_first > 1 && ptrn_copiable > 2 * p_context))) { | 
    ||
815  | 
    if (verbose)  | 
    ||
816  | 
    				say("%s\n%s\n%s\n", | 
    ||
817  | 
    "(Fascinating--this is really a new-style context diff but without",  | 
    ||
818  | 
    "the telltale extra asterisks on the *** line that usually indicate",  | 
    ||
819  | 
    "the new style...)");  | 
    ||
820  | 
    diff_type = NEW_CONTEXT_DIFF;  | 
    ||
821  | 
    }  | 
    ||
822  | 
    /* if there were omitted context lines, fill them in now */  | 
    ||
823  | 
    ✓✓ | 1044  | 
    		if (fillcnt) { | 
    
824  | 
    288  | 
    p_bfake = filldst; /* remember where not to free() */  | 
    |
825  | 
    288  | 
    p_efake = filldst + fillcnt - 1;  | 
    |
826  | 
    ✓✓ | 4032  | 
    			while (fillcnt-- > 0) { | 
    
827  | 
    ✓✗✓✓ | 
    6552  | 
    while (fillsrc <= p_end && p_char[fillsrc] != ' ')  | 
    
828  | 
    342  | 
    fillsrc++;  | 
    |
829  | 
    ✗✓ | 1728  | 
    if (fillsrc > p_end)  | 
    
830  | 
    					fatal("replacement text or line numbers mangled in hunk at line %ld\n", | 
    ||
831  | 
    p_hunk_beg);  | 
    ||
832  | 
    1728  | 
    p_line[filldst] = p_line[fillsrc];  | 
    |
833  | 
    1728  | 
    p_char[filldst] = p_char[fillsrc];  | 
    |
834  | 
    1728  | 
    p_len[filldst] = p_len[fillsrc];  | 
    |
835  | 
    1728  | 
    fillsrc++;  | 
    |
836  | 
    1728  | 
    filldst++;  | 
    |
837  | 
    }  | 
    ||
838  | 
    ✓✓✓✓ ✓✗  | 
    333  | 
    while (fillsrc <= p_end && fillsrc != repl_beginning &&  | 
    
839  | 
    9  | 
    p_char[fillsrc] != ' ')  | 
    |
840  | 
    9  | 
    fillsrc++;  | 
    |
841  | 
    #ifdef DEBUGGING  | 
    ||
842  | 
    ✗✓ | 288  | 
    if (debug & 64)  | 
    
843  | 
    				printf("fillsrc %ld, filldst %ld, rb %ld, e+1 %ld\n", | 
    ||
844  | 
    fillsrc, filldst, repl_beginning, p_end + 1);  | 
    ||
845  | 
    #endif  | 
    ||
846  | 
    ✓✓✗✓ | 
    297  | 
    if (fillsrc != p_end + 1 && fillsrc != repl_beginning)  | 
    
847  | 
    malformed();  | 
    ||
848  | 
    ✓✓✗✓ | 
    567  | 
    if (filldst != p_end + 1 && filldst != repl_beginning)  | 
    
849  | 
    malformed();  | 
    ||
850  | 
    }  | 
    ||
851  | 
    ✓✗ | 1044  | 
    		if (p_line[p_end] != NULL) { | 
    
852  | 
    ✓✓ | 1044  | 
    			if (remove_special_line()) { | 
    
853  | 
    18  | 
    p_len[p_end] -= 1;  | 
    |
854  | 
    18  | 
    (p_line[p_end])[p_len[p_end]] = 0;  | 
    |
855  | 
    18  | 
    }  | 
    |
856  | 
    }  | 
    ||
857  | 
    ✓✓ | 6264  | 
    	} else if (diff_type == UNI_DIFF) { | 
    
858  | 
    1161  | 
    off_t line_beginning = ftello(pfp); /* file pos of the current line */  | 
    |
859  | 
    LINENUM fillsrc; /* index of old lines */  | 
    ||
860  | 
    LINENUM filldst; /* index of new lines */  | 
    ||
861  | 
    char ch;  | 
    ||
862  | 
    |||
863  | 
    1161  | 
    ret = pgets(buf, sizeof buf, pfp);  | 
    |
864  | 
    1161  | 
    p_input_line++;  | 
    |
865  | 
    ✓✓✗✓ | 
    2205  | 
    		if (ret == NULL || strnNE(buf, "@@ -", 4)) { | 
    
866  | 
    117  | 
    next_intuit_at(line_beginning, p_input_line);  | 
    |
867  | 
    117  | 
    return false;  | 
    |
868  | 
    }  | 
    ||
869  | 
    1044  | 
    s = buf + 4;  | 
    |
870  | 
    ✗✓ | 1044  | 
    if (!*s)  | 
    
871  | 
    malformed();  | 
    ||
872  | 
    1044  | 
    p_first = strtolinenum(s, &s);  | 
    |
873  | 
    ✓✓ | 1044  | 
    		if (*s == ',') { | 
    
874  | 
    1035  | 
    p_ptrn_lines = strtolinenum(s + 1, &s);  | 
    |
875  | 
    1035  | 
    } else  | 
    |
876  | 
    p_ptrn_lines = 1;  | 
    ||
877  | 
    ✓✗ | 1044  | 
    if (*s == ' ')  | 
    
878  | 
    1044  | 
    s++;  | 
    |
879  | 
    ✓✗✗✓ | 
    2088  | 
    if (*s != '+' || !*++s)  | 
    
880  | 
    malformed();  | 
    ||
881  | 
    1044  | 
    p_newfirst = strtolinenum(s, &s);  | 
    |
882  | 
    ✓✓ | 1044  | 
    		if (*s == ',') { | 
    
883  | 
    1035  | 
    p_repl_lines = strtolinenum(s + 1, &s);  | 
    |
884  | 
    1035  | 
    } else  | 
    |
885  | 
    p_repl_lines = 1;  | 
    ||
886  | 
    ✓✗ | 1044  | 
    if (*s == ' ')  | 
    
887  | 
    1044  | 
    s++;  | 
    |
888  | 
    ✗✓ | 1044  | 
    if (*s != '@')  | 
    
889  | 
    malformed();  | 
    ||
890  | 
    ✓✗✗✓ | 
    2088  | 
    if (p_first >= LINENUM_MAX - p_ptrn_lines ||  | 
    
891  | 
    ✓✗ | 1044  | 
    p_newfirst > LINENUM_MAX - p_repl_lines ||  | 
    
892  | 
    1044  | 
    p_ptrn_lines >= LINENUM_MAX - p_repl_lines - 1)  | 
    |
893  | 
    malformed();  | 
    ||
894  | 
    ✓✓ | 1044  | 
    if (!p_ptrn_lines)  | 
    
895  | 
    9  | 
    p_first++; /* do append rather than insert */  | 
    |
896  | 
    1044  | 
    p_max = p_ptrn_lines + p_repl_lines + 1;  | 
    |
897  | 
    ✓✓ | 2232  | 
    while (p_max >= hunkmax)  | 
    
898  | 
    72  | 
    grow_hunkmax();  | 
    |
899  | 
    fillsrc = 1;  | 
    ||
900  | 
    1044  | 
    filldst = fillsrc + p_ptrn_lines;  | 
    |
901  | 
    1044  | 
    p_end = filldst + p_repl_lines;  | 
    |
902  | 
    2088  | 
    snprintf(buf, sizeof buf, "*** %ld,%ld ****\n", p_first,  | 
    |
903  | 
    1044  | 
    p_first + p_ptrn_lines - 1);  | 
    |
904  | 
    1044  | 
    p_line[0] = savestr(buf);  | 
    |
905  | 
    ✗✓ | 1044  | 
    		if (out_of_mem) { | 
    
906  | 
    p_end = -1;  | 
    ||
907  | 
    return false;  | 
    ||
908  | 
    }  | 
    ||
909  | 
    1044  | 
    p_char[0] = '*';  | 
    |
910  | 
    2088  | 
    snprintf(buf, sizeof buf, "--- %ld,%ld ----\n", p_newfirst,  | 
    |
911  | 
    1044  | 
    p_newfirst + p_repl_lines - 1);  | 
    |
912  | 
    1044  | 
    p_line[filldst] = savestr(buf);  | 
    |
913  | 
    ✗✓ | 1044  | 
    		if (out_of_mem) { | 
    
914  | 
    p_end = 0;  | 
    ||
915  | 
    return false;  | 
    ||
916  | 
    }  | 
    ||
917  | 
    1044  | 
    p_char[filldst++] = '=';  | 
    |
918  | 
    1044  | 
    p_context = 100;  | 
    |
919  | 
    context = 0;  | 
    ||
920  | 
    1044  | 
    p_hunk_beg = p_input_line + 1;  | 
    |
921  | 
    ✓✓✓✓ | 
    54414  | 
    		while (fillsrc <= p_ptrn_lines || filldst <= p_end) { | 
    
922  | 
    45639  | 
    line_beginning = ftello(pfp);  | 
    |
923  | 
    45639  | 
    ret = pgets(buf, sizeof buf, pfp);  | 
    |
924  | 
    45639  | 
    p_input_line++;  | 
    |
925  | 
    ✗✓ | 45639  | 
    			if (ret == NULL) { | 
    
926  | 
    				if (p_max - filldst < 3) { | 
    ||
927  | 
    /* assume blank lines got chopped */  | 
    ||
928  | 
    strlcpy(buf, " \n", sizeof buf);  | 
    ||
929  | 
    				} else { | 
    ||
930  | 
    					fatal("unexpected end of file in patch\n"); | 
    ||
931  | 
    }  | 
    ||
932  | 
    }  | 
    ||
933  | 
    ✓✗✗✓ | 
    91278  | 
    			if (*buf == '\t' || *buf == '\n') { | 
    
934  | 
    ch = ' '; /* assume the space got eaten */  | 
    ||
935  | 
    s = savestr(buf);  | 
    ||
936  | 
    			} else { | 
    ||
937  | 
    ch = *buf;  | 
    ||
938  | 
    45639  | 
    s = savestr(buf + 1);  | 
    |
939  | 
    }  | 
    ||
940  | 
    ✗✓ | 45639  | 
    			if (out_of_mem) { | 
    
941  | 
    while (--filldst > p_ptrn_lines)  | 
    ||
942  | 
    free(p_line[filldst]);  | 
    ||
943  | 
    p_end = fillsrc - 1;  | 
    ||
944  | 
    return false;  | 
    ||
945  | 
    }  | 
    ||
946  | 
    ✓✗✓✓ ✗  | 
    58554  | 
    			switch (ch) { | 
    
947  | 
    case '-':  | 
    ||
948  | 
    ✗✓ | 10512  | 
    				if (fillsrc > p_ptrn_lines) { | 
    
949  | 
    free(s);  | 
    ||
950  | 
    p_end = filldst - 1;  | 
    ||
951  | 
    malformed();  | 
    ||
952  | 
    }  | 
    ||
953  | 
    10512  | 
    p_char[fillsrc] = ch;  | 
    |
954  | 
    10512  | 
    p_line[fillsrc] = s;  | 
    |
955  | 
    10512  | 
    p_len[fillsrc++] = strlen(s);  | 
    |
956  | 
    ✓✓ | 10512  | 
    				if (fillsrc > p_ptrn_lines) { | 
    
957  | 
    ✓✓ | 54  | 
    					if (remove_special_line()) { | 
    
958  | 
    36  | 
    p_len[fillsrc - 1] -= 1;  | 
    |
959  | 
    36  | 
    s[p_len[fillsrc - 1]] = 0;  | 
    |
960  | 
    36  | 
    }  | 
    |
961  | 
    }  | 
    ||
962  | 
    break;  | 
    ||
963  | 
    case '=':  | 
    ||
964  | 
    ch = ' ';  | 
    ||
965  | 
    /* FALL THROUGH */  | 
    ||
966  | 
    case ' ':  | 
    ||
967  | 
    ✗✓ | 12915  | 
    				if (fillsrc > p_ptrn_lines) { | 
    
968  | 
    free(s);  | 
    ||
969  | 
    while (--filldst > p_ptrn_lines)  | 
    ||
970  | 
    free(p_line[filldst]);  | 
    ||
971  | 
    p_end = fillsrc - 1;  | 
    ||
972  | 
    malformed();  | 
    ||
973  | 
    }  | 
    ||
974  | 
    12915  | 
    context++;  | 
    |
975  | 
    12915  | 
    p_char[fillsrc] = ch;  | 
    |
976  | 
    12915  | 
    p_line[fillsrc] = s;  | 
    |
977  | 
    12915  | 
    p_len[fillsrc++] = strlen(s);  | 
    |
978  | 
    12915  | 
    s = savestr(s);  | 
    |
979  | 
    ✗✓ | 12915  | 
    				if (out_of_mem) { | 
    
980  | 
    while (--filldst > p_ptrn_lines)  | 
    ||
981  | 
    free(p_line[filldst]);  | 
    ||
982  | 
    p_end = fillsrc - 1;  | 
    ||
983  | 
    return false;  | 
    ||
984  | 
    }  | 
    ||
985  | 
    ✓✓ | 12915  | 
    				if (fillsrc > p_ptrn_lines) { | 
    
986  | 
    ✗✓ | 981  | 
    					if (remove_special_line()) { | 
    
987  | 
    p_len[fillsrc - 1] -= 1;  | 
    ||
988  | 
    s[p_len[fillsrc - 1]] = 0;  | 
    ||
989  | 
    }  | 
    ||
990  | 
    }  | 
    ||
991  | 
    /* FALL THROUGH */  | 
    ||
992  | 
    case '+':  | 
    ||
993  | 
    ✗✓ | 35127  | 
    				if (filldst > p_end) { | 
    
994  | 
    free(s);  | 
    ||
995  | 
    while (--filldst > p_ptrn_lines)  | 
    ||
996  | 
    free(p_line[filldst]);  | 
    ||
997  | 
    p_end = fillsrc - 1;  | 
    ||
998  | 
    malformed();  | 
    ||
999  | 
    }  | 
    ||
1000  | 
    35127  | 
    p_char[filldst] = ch;  | 
    |
1001  | 
    35127  | 
    p_line[filldst] = s;  | 
    |
1002  | 
    35127  | 
    p_len[filldst++] = strlen(s);  | 
    |
1003  | 
    ✓✓ | 35127  | 
    				if (fillsrc > p_ptrn_lines) { | 
    
1004  | 
    ✓✓ | 6624  | 
    					if (remove_special_line()) { | 
    
1005  | 
    18  | 
    p_len[filldst - 1] -= 1;  | 
    |
1006  | 
    18  | 
    s[p_len[filldst - 1]] = 0;  | 
    |
1007  | 
    18  | 
    }  | 
    |
1008  | 
    }  | 
    ||
1009  | 
    break;  | 
    ||
1010  | 
    default:  | 
    ||
1011  | 
    p_end = filldst;  | 
    ||
1012  | 
    malformed();  | 
    ||
1013  | 
    }  | 
    ||
1014  | 
    ✓✓ | 45639  | 
    			if (ch != ' ' && context > 0) { | 
    
1015  | 
    ✓✗ | 990  | 
    if (context < p_context)  | 
    
1016  | 
    990  | 
    p_context = context;  | 
    |
1017  | 
    context = -1000;  | 
    ||
1018  | 
    990  | 
    }  | 
    |
1019  | 
    } /* while */  | 
    ||
1020  | 
    ✓✓ | 1044  | 
    	} else {		/* normal diff--fake it up */ | 
    
1021  | 
    char hunk_type;  | 
    ||
1022  | 
    int i;  | 
    ||
1023  | 
    LINENUM min, max;  | 
    ||
1024  | 
    5103  | 
    off_t line_beginning = ftello(pfp);  | 
    |
1025  | 
    |||
1026  | 
    5103  | 
    p_context = 0;  | 
    |
1027  | 
    5103  | 
    ret = pgets(buf, sizeof buf, pfp);  | 
    |
1028  | 
    5103  | 
    p_input_line++;  | 
    |
1029  | 
    ✓✓✗✓ | 
    10089  | 
    		if (ret == NULL || !isdigit((unsigned char)*buf)) { | 
    
1030  | 
    117  | 
    next_intuit_at(line_beginning, p_input_line);  | 
    |
1031  | 
    117  | 
    return false;  | 
    |
1032  | 
    }  | 
    ||
1033  | 
    4986  | 
    p_first = strtolinenum(buf, &s);  | 
    |
1034  | 
    ✓✓ | 4986  | 
    		if (*s == ',') { | 
    
1035  | 
    1629  | 
    p_ptrn_lines = strtolinenum(s + 1, &s) - p_first + 1;  | 
    |
1036  | 
    ✗✓ | 1629  | 
    if (p_ptrn_lines < 0)  | 
    
1037  | 
    malformed();  | 
    ||
1038  | 
    } else  | 
    ||
1039  | 
    3357  | 
    p_ptrn_lines = (*s != 'a');  | 
    |
1040  | 
    ✗✓ | 4986  | 
    if (p_first >= LINENUM_MAX - p_ptrn_lines)  | 
    
1041  | 
    malformed();  | 
    ||
1042  | 
    4986  | 
    hunk_type = *s;  | 
    |
1043  | 
    ✓✓ | 4986  | 
    if (hunk_type == 'a')  | 
    
1044  | 
    1116  | 
    p_first++; /* do append rather than insert */  | 
    |
1045  | 
    4986  | 
    min = strtolinenum(s + 1, &s);  | 
    |
1046  | 
    ✓✓ | 4986  | 
    if (*s == ',')  | 
    
1047  | 
    1998  | 
    max = strtolinenum(s + 1, &s);  | 
    |
1048  | 
    else  | 
    ||
1049  | 
    max = min;  | 
    ||
1050  | 
    ✓✗✓✗ ✗✓  | 
    14958  | 
    if (min < 0 || min > max || max - min == LINENUM_MAX)  | 
    
1051  | 
    malformed();  | 
    ||
1052  | 
    ✓✓ | 4986  | 
    if (hunk_type == 'd')  | 
    
1053  | 
    162  | 
    min++;  | 
    |
1054  | 
    4986  | 
    p_newfirst = min;  | 
    |
1055  | 
    4986  | 
    p_repl_lines = max - min + 1;  | 
    |
1056  | 
    ✓✗✗✓ | 
    9972  | 
    if (p_newfirst > LINENUM_MAX - p_repl_lines ||  | 
    
1057  | 
    4986  | 
    p_ptrn_lines >= LINENUM_MAX - p_repl_lines - 1)  | 
    |
1058  | 
    malformed();  | 
    ||
1059  | 
    4986  | 
    p_end = p_ptrn_lines + p_repl_lines + 1;  | 
    |
1060  | 
    ✗✓ | 4986  | 
    if (p_end > MAXHUNKSIZE)  | 
    
1061  | 
    			fatal("hunk too large (%ld lines) at line %ld: %s", | 
    ||
1062  | 
    p_end, p_input_line, buf);  | 
    ||
1063  | 
    ✓✓ | 5040  | 
    while (p_end >= hunkmax)  | 
    
1064  | 
    27  | 
    grow_hunkmax();  | 
    |
1065  | 
    9972  | 
    snprintf(buf, sizeof buf, "*** %ld,%ld\n", p_first,  | 
    |
1066  | 
    4986  | 
    p_first + p_ptrn_lines - 1);  | 
    |
1067  | 
    4986  | 
    p_line[0] = savestr(buf);  | 
    |
1068  | 
    ✗✓ | 4986  | 
    		if (out_of_mem) { | 
    
1069  | 
    p_end = -1;  | 
    ||
1070  | 
    return false;  | 
    ||
1071  | 
    }  | 
    ||
1072  | 
    4986  | 
    p_char[0] = '*';  | 
    |
1073  | 
    ✓✓ | 30996  | 
    		for (i = 1; i <= p_ptrn_lines; i++) { | 
    
1074  | 
    10512  | 
    ret = pgets(buf, sizeof buf, pfp);  | 
    |
1075  | 
    10512  | 
    p_input_line++;  | 
    |
1076  | 
    ✗✓ | 10512  | 
    if (ret == NULL)  | 
    
1077  | 
    				fatal("unexpected end of file in patch at line %ld\n", | 
    ||
1078  | 
    p_input_line);  | 
    ||
1079  | 
    ✗✓ | 10512  | 
    if (*buf != '<')  | 
    
1080  | 
    				fatal("< expected at line %ld of patch\n", | 
    ||
1081  | 
    p_input_line);  | 
    ||
1082  | 
    10512  | 
    p_line[i] = savestr(buf + 2);  | 
    |
1083  | 
    ✗✓ | 10512  | 
    			if (out_of_mem) { | 
    
1084  | 
    p_end = i - 1;  | 
    ||
1085  | 
    return false;  | 
    ||
1086  | 
    }  | 
    ||
1087  | 
    10512  | 
    p_len[i] = strlen(p_line[i]);  | 
    |
1088  | 
    10512  | 
    p_char[i] = '-';  | 
    |
1089  | 
    }  | 
    ||
1090  | 
    |||
1091  | 
    ✓✓ | 4986  | 
    		if (remove_special_line()) { | 
    
1092  | 
    36  | 
    p_len[i - 1] -= 1;  | 
    |
1093  | 
    36  | 
    (p_line[i - 1])[p_len[i - 1]] = 0;  | 
    |
1094  | 
    36  | 
    }  | 
    |
1095  | 
    ✓✓ | 4986  | 
    		if (hunk_type == 'c') { | 
    
1096  | 
    3708  | 
    ret = pgets(buf, sizeof buf, pfp);  | 
    |
1097  | 
    3708  | 
    p_input_line++;  | 
    |
1098  | 
    ✗✓ | 3708  | 
    if (ret == NULL)  | 
    
1099  | 
    				fatal("unexpected end of file in patch at line %ld\n", | 
    ||
1100  | 
    p_input_line);  | 
    ||
1101  | 
    ✗✓ | 3708  | 
    if (*buf != '-')  | 
    
1102  | 
    				fatal("--- expected at line %ld of patch\n", | 
    ||
1103  | 
    p_input_line);  | 
    ||
1104  | 
    }  | 
    ||
1105  | 
    4986  | 
    snprintf(buf, sizeof(buf), "--- %ld,%ld\n", min, max);  | 
    |
1106  | 
    4986  | 
    p_line[i] = savestr(buf);  | 
    |
1107  | 
    ✗✓ | 4986  | 
    		if (out_of_mem) { | 
    
1108  | 
    p_end = i - 1;  | 
    ||
1109  | 
    return false;  | 
    ||
1110  | 
    }  | 
    ||
1111  | 
    4986  | 
    p_char[i] = '=';  | 
    |
1112  | 
    ✓✓ | 54396  | 
    		for (i++; i <= p_end; i++) { | 
    
1113  | 
    22212  | 
    ret = pgets(buf, sizeof buf, pfp);  | 
    |
1114  | 
    22212  | 
    p_input_line++;  | 
    |
1115  | 
    ✗✓ | 22212  | 
    if (ret == NULL)  | 
    
1116  | 
    				fatal("unexpected end of file in patch at line %ld\n", | 
    ||
1117  | 
    p_input_line);  | 
    ||
1118  | 
    ✗✓ | 22212  | 
    if (*buf != '>')  | 
    
1119  | 
    				fatal("> expected at line %ld of patch\n", | 
    ||
1120  | 
    p_input_line);  | 
    ||
1121  | 
    22212  | 
    p_line[i] = savestr(buf + 2);  | 
    |
1122  | 
    ✗✓ | 22212  | 
    			if (out_of_mem) { | 
    
1123  | 
    p_end = i - 1;  | 
    ||
1124  | 
    return false;  | 
    ||
1125  | 
    }  | 
    ||
1126  | 
    22212  | 
    p_len[i] = strlen(p_line[i]);  | 
    |
1127  | 
    22212  | 
    p_char[i] = '+';  | 
    |
1128  | 
    }  | 
    ||
1129  | 
    |||
1130  | 
    ✓✓ | 4986  | 
    		if (remove_special_line()) { | 
    
1131  | 
    18  | 
    p_len[i - 1] -= 1;  | 
    |
1132  | 
    18  | 
    (p_line[i - 1])[p_len[i - 1]] = 0;  | 
    |
1133  | 
    18  | 
    }  | 
    |
1134  | 
    ✓✓ | 4986  | 
    }  | 
    
1135  | 
    ✗✓ | 7074  | 
    if (reverse) /* backwards patch? */  | 
    
1136  | 
    if (!pch_swap())  | 
    ||
1137  | 
    			say("Not enough memory to swap next hunk!\n"); | 
    ||
1138  | 
    #ifdef DEBUGGING  | 
    ||
1139  | 
    ✗✓ | 7074  | 
    	if (debug & 2) { | 
    
1140  | 
    int i;  | 
    ||
1141  | 
    char special;  | 
    ||
1142  | 
    |||
1143  | 
    		for (i = 0; i <= p_end; i++) { | 
    ||
1144  | 
    if (i == p_ptrn_lines)  | 
    ||
1145  | 
    special = '^';  | 
    ||
1146  | 
    else  | 
    ||
1147  | 
    special = ' ';  | 
    ||
1148  | 
    fprintf(stderr, "%3d %c %c %s", i, p_char[i],  | 
    ||
1149  | 
    special, p_line[i]);  | 
    ||
1150  | 
    fflush(stderr);  | 
    ||
1151  | 
    }  | 
    ||
1152  | 
    }  | 
    ||
1153  | 
    #endif  | 
    ||
1154  | 
    ✓✗ | 7074  | 
    if (p_end + 1 < hunkmax)/* paranoia reigns supreme... */  | 
    
1155  | 
    7074  | 
    p_char[p_end + 1] = '^'; /* add a stopper for apply_hunk */  | 
    |
1156  | 
    7074  | 
    return true;  | 
    |
1157  | 
    7425  | 
    }  | 
    |
1158  | 
    |||
1159  | 
    /*  | 
    ||
1160  | 
    * Input a line from the patch file, worrying about indentation.  | 
    ||
1161  | 
    */  | 
    ||
1162  | 
    char *  | 
    ||
1163  | 
    pgets(char *bf, int sz, FILE *fp)  | 
    ||
1164  | 
    { | 
    ||
1165  | 
    405522  | 
    char *s, *ret = fgets(bf, sz, fp);  | 
    |
1166  | 
    int indent = 0;  | 
    ||
1167  | 
    |||
1168  | 
    ✗✓ | 202761  | 
    	if (p_indent && ret != NULL) { | 
    
1169  | 
    for (s = buf;  | 
    ||
1170  | 
    indent < p_indent && (*s == ' ' || *s == '\t' || *s == 'X');  | 
    ||
1171  | 
    		    s++) { | 
    ||
1172  | 
    if (*s == '\t')  | 
    ||
1173  | 
    indent += 8 - (indent % 7);  | 
    ||
1174  | 
    else  | 
    ||
1175  | 
    indent++;  | 
    ||
1176  | 
    }  | 
    ||
1177  | 
    if (buf != s && strlcpy(buf, s, sizeof(buf)) >= sizeof(buf))  | 
    ||
1178  | 
    			fatal("buffer too small in pgets()\n"); | 
    ||
1179  | 
    }  | 
    ||
1180  | 
    202761  | 
    return ret;  | 
    |
1181  | 
    }  | 
    ||
1182  | 
    |||
1183  | 
    /*  | 
    ||
1184  | 
    * Reverse the old and new portions of the current hunk.  | 
    ||
1185  | 
    */  | 
    ||
1186  | 
    bool  | 
    ||
1187  | 
    pch_swap(void)  | 
    ||
1188  | 
    { | 
    ||
1189  | 
    char **tp_line; /* the text of the hunk */  | 
    ||
1190  | 
    short *tp_len; /* length of each line */  | 
    ||
1191  | 
    char *tp_char; /* +, -, and ! */  | 
    ||
1192  | 
    LINENUM i;  | 
    ||
1193  | 
    LINENUM n;  | 
    ||
1194  | 
    bool blankline = false;  | 
    ||
1195  | 
    char *s;  | 
    ||
1196  | 
    |||
1197  | 
    i = p_first;  | 
    ||
1198  | 
    p_first = p_newfirst;  | 
    ||
1199  | 
    p_newfirst = i;  | 
    ||
1200  | 
    |||
1201  | 
    /* make a scratch copy */  | 
    ||
1202  | 
    |||
1203  | 
    tp_line = p_line;  | 
    ||
1204  | 
    tp_len = p_len;  | 
    ||
1205  | 
    tp_char = p_char;  | 
    ||
1206  | 
    p_line = NULL; /* force set_hunkmax to allocate again */  | 
    ||
1207  | 
    p_len = NULL;  | 
    ||
1208  | 
    p_char = NULL;  | 
    ||
1209  | 
    set_hunkmax();  | 
    ||
1210  | 
    	if (p_line == NULL || p_len == NULL || p_char == NULL) { | 
    ||
1211  | 
    |||
1212  | 
    free(p_line);  | 
    ||
1213  | 
    p_line = tp_line;  | 
    ||
1214  | 
    free(p_len);  | 
    ||
1215  | 
    p_len = tp_len;  | 
    ||
1216  | 
    free(p_char);  | 
    ||
1217  | 
    p_char = tp_char;  | 
    ||
1218  | 
    return false; /* not enough memory to swap hunk! */  | 
    ||
1219  | 
    }  | 
    ||
1220  | 
    /* now turn the new into the old */  | 
    ||
1221  | 
    |||
1222  | 
    i = p_ptrn_lines + 1;  | 
    ||
1223  | 
    	if (tp_char[i] == '\n') {	/* account for possible blank line */ | 
    ||
1224  | 
    blankline = true;  | 
    ||
1225  | 
    i++;  | 
    ||
1226  | 
    }  | 
    ||
1227  | 
    	if (p_efake >= 0) {	/* fix non-freeable ptr range */ | 
    ||
1228  | 
    if (p_efake <= i)  | 
    ||
1229  | 
    n = p_end - i + 1;  | 
    ||
1230  | 
    else  | 
    ||
1231  | 
    n = -i;  | 
    ||
1232  | 
    p_efake += n;  | 
    ||
1233  | 
    p_bfake += n;  | 
    ||
1234  | 
    }  | 
    ||
1235  | 
    	for (n = 0; i <= p_end; i++, n++) { | 
    ||
1236  | 
    p_line[n] = tp_line[i];  | 
    ||
1237  | 
    p_char[n] = tp_char[i];  | 
    ||
1238  | 
    if (p_char[n] == '+')  | 
    ||
1239  | 
    p_char[n] = '-';  | 
    ||
1240  | 
    p_len[n] = tp_len[i];  | 
    ||
1241  | 
    }  | 
    ||
1242  | 
    	if (blankline) { | 
    ||
1243  | 
    i = p_ptrn_lines + 1;  | 
    ||
1244  | 
    p_line[n] = tp_line[i];  | 
    ||
1245  | 
    p_char[n] = tp_char[i];  | 
    ||
1246  | 
    p_len[n] = tp_len[i];  | 
    ||
1247  | 
    n++;  | 
    ||
1248  | 
    }  | 
    ||
1249  | 
    if (p_char[0] != '=')  | 
    ||
1250  | 
    		fatal("Malformed patch at line %ld: expected '=' found '%c'\n", | 
    ||
1251  | 
    p_input_line, p_char[0]);  | 
    ||
1252  | 
    p_char[0] = '*';  | 
    ||
1253  | 
    for (s = p_line[0]; *s; s++)  | 
    ||
1254  | 
    if (*s == '-')  | 
    ||
1255  | 
    *s = '*';  | 
    ||
1256  | 
    |||
1257  | 
    /* now turn the old into the new */  | 
    ||
1258  | 
    |||
1259  | 
    if (p_char[0] != '*')  | 
    ||
1260  | 
    		fatal("Malformed patch at line %ld: expected '*' found '%c'\n", | 
    ||
1261  | 
    p_input_line, p_char[0]);  | 
    ||
1262  | 
    tp_char[0] = '=';  | 
    ||
1263  | 
    for (s = tp_line[0]; *s; s++)  | 
    ||
1264  | 
    if (*s == '*')  | 
    ||
1265  | 
    *s = '-';  | 
    ||
1266  | 
    	for (i = 0; n <= p_end; i++, n++) { | 
    ||
1267  | 
    p_line[n] = tp_line[i];  | 
    ||
1268  | 
    p_char[n] = tp_char[i];  | 
    ||
1269  | 
    if (p_char[n] == '-')  | 
    ||
1270  | 
    p_char[n] = '+';  | 
    ||
1271  | 
    p_len[n] = tp_len[i];  | 
    ||
1272  | 
    }  | 
    ||
1273  | 
    |||
1274  | 
    if (i != p_ptrn_lines + 1)  | 
    ||
1275  | 
    		fatal("Malformed patch at line %ld: expected %ld lines, " | 
    ||
1276  | 
    "got %ld\n",  | 
    ||
1277  | 
    p_input_line, p_ptrn_lines + 1, i);  | 
    ||
1278  | 
    |||
1279  | 
    i = p_ptrn_lines;  | 
    ||
1280  | 
    p_ptrn_lines = p_repl_lines;  | 
    ||
1281  | 
    p_repl_lines = i;  | 
    ||
1282  | 
    |||
1283  | 
    free(tp_line);  | 
    ||
1284  | 
    free(tp_len);  | 
    ||
1285  | 
    free(tp_char);  | 
    ||
1286  | 
    |||
1287  | 
    return true;  | 
    ||
1288  | 
    }  | 
    ||
1289  | 
    |||
1290  | 
    /*  | 
    ||
1291  | 
    * Return the specified line position in the old file of the old context.  | 
    ||
1292  | 
    */  | 
    ||
1293  | 
    LINENUM  | 
    ||
1294  | 
    pch_first(void)  | 
    ||
1295  | 
    { | 
    ||
1296  | 
    14148  | 
    return p_first;  | 
    |
1297  | 
    }  | 
    ||
1298  | 
    |||
1299  | 
    /*  | 
    ||
1300  | 
    * Return the number of lines of old context.  | 
    ||
1301  | 
    */  | 
    ||
1302  | 
    LINENUM  | 
    ||
1303  | 
    pch_ptrn_lines(void)  | 
    ||
1304  | 
    { | 
    ||
1305  | 
    40176  | 
    return p_ptrn_lines;  | 
    |
1306  | 
    }  | 
    ||
1307  | 
    |||
1308  | 
    /*  | 
    ||
1309  | 
    * Return the probable line position in the new file of the first line.  | 
    ||
1310  | 
    */  | 
    ||
1311  | 
    LINENUM  | 
    ||
1312  | 
    pch_newfirst(void)  | 
    ||
1313  | 
    { | 
    ||
1314  | 
    14148  | 
    return p_newfirst;  | 
    |
1315  | 
    }  | 
    ||
1316  | 
    |||
1317  | 
    /*  | 
    ||
1318  | 
    * Return the number of lines in the replacement text including context.  | 
    ||
1319  | 
    */  | 
    ||
1320  | 
    LINENUM  | 
    ||
1321  | 
    pch_repl_lines(void)  | 
    ||
1322  | 
    { | 
    ||
1323  | 
    return p_repl_lines;  | 
    ||
1324  | 
    }  | 
    ||
1325  | 
    |||
1326  | 
    /*  | 
    ||
1327  | 
    * Return the number of lines in the whole hunk.  | 
    ||
1328  | 
    */  | 
    ||
1329  | 
    LINENUM  | 
    ||
1330  | 
    pch_end(void)  | 
    ||
1331  | 
    { | 
    ||
1332  | 
    14148  | 
    return p_end;  | 
    |
1333  | 
    }  | 
    ||
1334  | 
    |||
1335  | 
    /*  | 
    ||
1336  | 
    * Return the number of context lines before the first changed line.  | 
    ||
1337  | 
    */  | 
    ||
1338  | 
    LINENUM  | 
    ||
1339  | 
    pch_context(void)  | 
    ||
1340  | 
    { | 
    ||
1341  | 
    28296  | 
    return p_context;  | 
    |
1342  | 
    }  | 
    ||
1343  | 
    |||
1344  | 
    /*  | 
    ||
1345  | 
    * Return the length of a particular patch line.  | 
    ||
1346  | 
    */  | 
    ||
1347  | 
    short  | 
    ||
1348  | 
    pch_line_len(LINENUM line)  | 
    ||
1349  | 
    { | 
    ||
1350  | 
    114732  | 
    return p_len[line];  | 
    |
1351  | 
    }  | 
    ||
1352  | 
    |||
1353  | 
    /*  | 
    ||
1354  | 
    * Return the control character (+, -, *, !, etc) for a patch line.  | 
    ||
1355  | 
    */  | 
    ||
1356  | 
    char  | 
    ||
1357  | 
    pch_char(LINENUM line)  | 
    ||
1358  | 
    { | 
    ||
1359  | 
    658242  | 
    return p_char[line];  | 
    |
1360  | 
    }  | 
    ||
1361  | 
    |||
1362  | 
    /*  | 
    ||
1363  | 
    * Return a pointer to a particular patch line.  | 
    ||
1364  | 
    */  | 
    ||
1365  | 
    char *  | 
    ||
1366  | 
    pfetch(LINENUM line)  | 
    ||
1367  | 
    { | 
    ||
1368  | 
    248004  | 
    return p_line[line];  | 
    |
1369  | 
    }  | 
    ||
1370  | 
    |||
1371  | 
    /*  | 
    ||
1372  | 
    * Return where in the patch file this hunk began, for error messages.  | 
    ||
1373  | 
    */  | 
    ||
1374  | 
    LINENUM  | 
    ||
1375  | 
    pch_hunk_beg(void)  | 
    ||
1376  | 
    { | 
    ||
1377  | 
    return p_hunk_beg;  | 
    ||
1378  | 
    }  | 
    ||
1379  | 
    |||
1380  | 
    /*  | 
    ||
1381  | 
    * Choose the name of the file to be patched based on POSIX rules.  | 
    ||
1382  | 
    * NOTE: the POSIX rules are amazingly stupid and we only follow them  | 
    ||
1383  | 
    * if the user specified --posix or set POSIXLY_CORRECT.  | 
    ||
1384  | 
    */  | 
    ||
1385  | 
    static char *  | 
    ||
1386  | 
    posix_name(const struct file_name *names, bool assume_exists)  | 
    ||
1387  | 
    { | 
    ||
1388  | 
    char *path = NULL;  | 
    ||
1389  | 
    int i;  | 
    ||
1390  | 
    |||
1391  | 
    /*  | 
    ||
1392  | 
    * POSIX states that the filename will be chosen from one  | 
    ||
1393  | 
    * of the old, new and index names (in that order) if  | 
    ||
1394  | 
    * the file exists relative to CWD after -p stripping.  | 
    ||
1395  | 
    */  | 
    ||
1396  | 
    	for (i = 0; i < MAX_FILE; i++) { | 
    ||
1397  | 
    		if (names[i].path != NULL && names[i].exists) { | 
    ||
1398  | 
    path = names[i].path;  | 
    ||
1399  | 
    break;  | 
    ||
1400  | 
    }  | 
    ||
1401  | 
    }  | 
    ||
1402  | 
    	if (path == NULL && !assume_exists) { | 
    ||
1403  | 
    /*  | 
    ||
1404  | 
    * No files found, check to see if the diff could be  | 
    ||
1405  | 
    * creating a new file.  | 
    ||
1406  | 
    */  | 
    ||
1407  | 
    if (path == NULL && ok_to_create_file &&  | 
    ||
1408  | 
    names[NEW_FILE].path != NULL)  | 
    ||
1409  | 
    path = names[NEW_FILE].path;  | 
    ||
1410  | 
    }  | 
    ||
1411  | 
    |||
1412  | 
    return path ? xstrdup(path) : NULL;  | 
    ||
1413  | 
    }  | 
    ||
1414  | 
    |||
1415  | 
    static char *  | 
    ||
1416  | 
    compare_names(const struct file_name *names, bool assume_exists)  | 
    ||
1417  | 
    { | 
    ||
1418  | 
    size_t min_components, min_baselen, min_len, tmp;  | 
    ||
1419  | 
    char *best = NULL;  | 
    ||
1420  | 
    char *path;  | 
    ||
1421  | 
    int i;  | 
    ||
1422  | 
    |||
1423  | 
    /*  | 
    ||
1424  | 
    * The "best" name is the one with the fewest number of path  | 
    ||
1425  | 
    * components, the shortest basename length, and the shortest  | 
    ||
1426  | 
    * overall length (in that order). We only use the Index: file  | 
    ||
1427  | 
    * if neither of the old or new files could be intuited from  | 
    ||
1428  | 
    * the diff header.  | 
    ||
1429  | 
    */  | 
    ||
1430  | 
    min_components = min_baselen = min_len = SIZE_MAX;  | 
    ||
1431  | 
    	for (i = INDEX_FILE; i >= OLD_FILE; i--) { | 
    ||
1432  | 
    path = names[i].path;  | 
    ||
1433  | 
    if (path == NULL || (!names[i].exists && !assume_exists))  | 
    ||
1434  | 
    continue;  | 
    ||
1435  | 
    if ((tmp = num_components(path)) > min_components)  | 
    ||
1436  | 
    continue;  | 
    ||
1437  | 
    		if (tmp < min_components) { | 
    ||
1438  | 
    min_components = tmp;  | 
    ||
1439  | 
    best = path;  | 
    ||
1440  | 
    }  | 
    ||
1441  | 
    if ((tmp = strlen(basename(path))) > min_baselen)  | 
    ||
1442  | 
    continue;  | 
    ||
1443  | 
    		if (tmp < min_baselen) { | 
    ||
1444  | 
    min_baselen = tmp;  | 
    ||
1445  | 
    best = path;  | 
    ||
1446  | 
    }  | 
    ||
1447  | 
    if ((tmp = strlen(path)) > min_len)  | 
    ||
1448  | 
    continue;  | 
    ||
1449  | 
    min_len = tmp;  | 
    ||
1450  | 
    best = path;  | 
    ||
1451  | 
    }  | 
    ||
1452  | 
    return best;  | 
    ||
1453  | 
    }  | 
    ||
1454  | 
    |||
1455  | 
    /*  | 
    ||
1456  | 
    * Choose the name of the file to be patched based the "best" one  | 
    ||
1457  | 
    * available.  | 
    ||
1458  | 
    */  | 
    ||
1459  | 
    static char *  | 
    ||
1460  | 
    best_name(const struct file_name *names, bool assume_exists)  | 
    ||
1461  | 
    { | 
    ||
1462  | 
    char *best;  | 
    ||
1463  | 
    |||
1464  | 
    best = compare_names(names, assume_exists);  | 
    ||
1465  | 
    |||
1466  | 
    /* No match? Check to see if the diff could be creating a new file. */  | 
    ||
1467  | 
    if (best == NULL && ok_to_create_file)  | 
    ||
1468  | 
    best = names[NEW_FILE].path;  | 
    ||
1469  | 
    |||
1470  | 
    return best ? xstrdup(best) : NULL;  | 
    ||
1471  | 
    }  | 
    ||
1472  | 
    |||
1473  | 
    static size_t  | 
    ||
1474  | 
    num_components(const char *path)  | 
    ||
1475  | 
    { | 
    ||
1476  | 
    size_t n;  | 
    ||
1477  | 
    const char *cp;  | 
    ||
1478  | 
    |||
1479  | 
    	for (n = 0, cp = path; (cp = strchr(cp, '/')) != NULL; n++, cp++) { | 
    ||
1480  | 
    while (*cp == '/')  | 
    ||
1481  | 
    cp++; /* skip consecutive slashes */  | 
    ||
1482  | 
    }  | 
    ||
1483  | 
    return n;  | 
    ||
1484  | 
    }  | 
    ||
1485  | 
    |||
1486  | 
    /*  | 
    ||
1487  | 
    * Convert number at NPTR into LINENUM and save address of first  | 
    ||
1488  | 
    * character that is not a digit in ENDPTR. If conversion is not  | 
    ||
1489  | 
    * possible, call fatal.  | 
    ||
1490  | 
    */  | 
    ||
1491  | 
    LINENUM  | 
    ||
1492  | 
    strtolinenum(char *nptr, char **endptr)  | 
    ||
1493  | 
    { | 
    ||
1494  | 
    LINENUM rv;  | 
    ||
1495  | 
    char c;  | 
    ||
1496  | 
    char *p;  | 
    ||
1497  | 
    57276  | 
    const char *errstr;  | 
    |
1498  | 
    |||
1499  | 
    ✓✓ | 228816  | 
    for (p = nptr; isdigit((unsigned char)*p); p++)  | 
    
1500  | 
    ;  | 
    ||
1501  | 
    |||
1502  | 
    ✗✓ | 28638  | 
    if (p == nptr)  | 
    
1503  | 
    malformed();  | 
    ||
1504  | 
    |||
1505  | 
    28638  | 
    c = *p;  | 
    |
1506  | 
    28638  | 
    *p = '\0';  | 
    |
1507  | 
    |||
1508  | 
    28638  | 
    rv = strtonum(nptr, 0, LINENUM_MAX, &errstr);  | 
    |
1509  | 
    ✗✓ | 28638  | 
    if (errstr != NULL)  | 
    
1510  | 
    		fatal("invalid line number at line %ld: `%s' is %s\n", | 
    ||
1511  | 
    p_input_line, nptr, errstr);  | 
    ||
1512  | 
    |||
1513  | 
    28638  | 
    *p = c;  | 
    |
1514  | 
    28638  | 
    *endptr = p;  | 
    |
1515  | 
    |||
1516  | 
    28638  | 
    return rv;  | 
    |
1517  | 
    28638  | 
    }  | 
    
| Generated by: GCOVR (Version 3.3) |