diff options
-rw-r--r-- | editors/patch.c | 74 |
1 files changed, 32 insertions, 42 deletions
diff --git a/editors/patch.c b/editors/patch.c index 4fadbb8fe..1d4a2554e 100644 --- a/editors/patch.c +++ b/editors/patch.c | |||
@@ -56,75 +56,64 @@ | |||
56 | 56 | ||
57 | #include "libbb.h" | 57 | #include "libbb.h" |
58 | 58 | ||
59 | |||
60 | // libbb candidate? | ||
61 | |||
59 | struct double_list { | 62 | struct double_list { |
60 | struct double_list *next; | 63 | struct double_list *next; |
61 | struct double_list *prev; | 64 | struct double_list *prev; |
62 | char *data; | 65 | char *data; |
63 | }; | 66 | }; |
64 | 67 | ||
65 | // Return the first item from the list, advancing the list (which must be called | ||
66 | // as &list) | ||
67 | static | ||
68 | void *TOY_llist_pop(void *list) | ||
69 | { | ||
70 | // I'd use a void ** for the argument, and even accept the typecast in all | ||
71 | // callers as documentation you need the &, except the stupid compiler | ||
72 | // would then scream about type-punned pointers. Screw it. | ||
73 | void **llist = (void **)list; | ||
74 | void **next = (void **)*llist; | ||
75 | *llist = *next; | ||
76 | |||
77 | return (void *)next; | ||
78 | } | ||
79 | |||
80 | // Free all the elements of a linked list | 68 | // Free all the elements of a linked list |
81 | // if freeit!=NULL call freeit() on each element before freeing it. | 69 | // Call freeit() on each element before freeing it. |
82 | static | 70 | static |
83 | void TOY_llist_free(void *list, void (*freeit)(void *data)) | 71 | void dlist_free(struct double_list *list, void (*freeit)(void *data)) |
84 | { | 72 | { |
85 | while (list) { | 73 | while (list) { |
86 | void *pop = TOY_llist_pop(&list); | 74 | void *pop = list; |
87 | if (freeit) freeit(pop); | 75 | list = list->next; |
88 | else free(pop); | 76 | freeit(pop); |
89 | 77 | // Bail out also if list is circular. | |
90 | // End doubly linked list too. | 78 | if (list == pop) break; |
91 | if (list==pop) break; | ||
92 | } | 79 | } |
93 | } | 80 | } |
94 | //Override bbox's names | ||
95 | #define llist_pop TOY_llist_pop | ||
96 | #define llist_free TOY_llist_free | ||
97 | 81 | ||
98 | // Add an entry to the end off a doubly linked list | 82 | // Add an entry before "list" element in (circular) doubly linked list |
99 | static | 83 | static |
100 | struct double_list *dlist_add(struct double_list **list, char *data) | 84 | struct double_list *dlist_add(struct double_list **list, char *data) |
101 | { | 85 | { |
102 | struct double_list *line = xmalloc(sizeof(struct double_list)); | 86 | struct double_list *llist; |
87 | struct double_list *line = xmalloc(sizeof(*line)); | ||
103 | 88 | ||
104 | line->data = data; | 89 | line->data = data; |
105 | if (*list) { | 90 | llist = *list; |
106 | line->next = *list; | 91 | if (llist) { |
107 | line->prev = (*list)->prev; | 92 | struct double_list *p; |
108 | (*list)->prev->next = line; | 93 | line->next = llist; |
109 | (*list)->prev = line; | 94 | p = line->prev = llist->prev; |
110 | } else *list = line->next = line->prev = line; | 95 | // (list is circular, we assume p is never NULL) |
96 | p->next = line; | ||
97 | llist->prev = line; | ||
98 | } else | ||
99 | *list = line->next = line->prev = line; | ||
111 | 100 | ||
112 | return line; | 101 | return line; |
113 | } | 102 | } |
114 | 103 | ||
115 | 104 | ||
116 | |||
117 | struct globals { | 105 | struct globals { |
118 | char *infile; | 106 | char *infile; |
119 | long prefix; | 107 | long prefix; |
120 | 108 | ||
121 | struct double_list *current_hunk; | 109 | struct double_list *current_hunk; |
110 | |||
122 | long oldline, oldlen, newline, newlen; | 111 | long oldline, oldlen, newline, newlen; |
123 | long linenum; | 112 | long linenum; |
124 | int context, state, filein, fileout, hunknum; | 113 | int context, state, hunknum; |
114 | int filein, fileout; | ||
125 | char *tempname; | 115 | char *tempname; |
126 | 116 | ||
127 | // was toys.foo: | ||
128 | int exitval; | 117 | int exitval; |
129 | }; | 118 | }; |
130 | #define TT (*ptr_to_globals) | 119 | #define TT (*ptr_to_globals) |
@@ -193,7 +182,6 @@ static void finish_oldfile(void) | |||
193 | static void fail_hunk(void) | 182 | static void fail_hunk(void) |
194 | { | 183 | { |
195 | if (!TT.current_hunk) return; | 184 | if (!TT.current_hunk) return; |
196 | TT.current_hunk->prev->next = NULL; | ||
197 | 185 | ||
198 | fdprintf(2, "Hunk %d FAILED %ld/%ld.\n", TT.hunknum, TT.oldline, TT.newline); | 186 | fdprintf(2, "Hunk %d FAILED %ld/%ld.\n", TT.hunknum, TT.oldline, TT.newline); |
199 | TT.exitval = 1; | 187 | TT.exitval = 1; |
@@ -202,7 +190,8 @@ static void fail_hunk(void) | |||
202 | // this file and advance to next file. | 190 | // this file and advance to next file. |
203 | 191 | ||
204 | TT.state = 2; | 192 | TT.state = 2; |
205 | llist_free(TT.current_hunk, do_line); | 193 | TT.current_hunk->prev->next = NULL; |
194 | dlist_free(TT.current_hunk, do_line); | ||
206 | TT.current_hunk = NULL; | 195 | TT.current_hunk = NULL; |
207 | 196 | ||
208 | // Abort the copy and delete the temporary file. | 197 | // Abort the copy and delete the temporary file. |
@@ -308,7 +297,8 @@ static int apply_one_hunk(void) | |||
308 | fdprintf(2, "NOT: %s\n", plist->data); | 297 | fdprintf(2, "NOT: %s\n", plist->data); |
309 | 298 | ||
310 | TT.state = 3; | 299 | TT.state = 3; |
311 | check = llist_pop(&buf); | 300 | check = buf; |
301 | buf = buf->next; | ||
312 | check->prev->next = buf; | 302 | check->prev->next = buf; |
313 | buf->prev = check->prev; | 303 | buf->prev = check->prev; |
314 | do_line(check); | 304 | do_line(check); |
@@ -335,13 +325,13 @@ static int apply_one_hunk(void) | |||
335 | out: | 325 | out: |
336 | // We have a match. Emit changed data. | 326 | // We have a match. Emit changed data. |
337 | TT.state = "-+"[reverse ^ dummy_revert]; | 327 | TT.state = "-+"[reverse ^ dummy_revert]; |
338 | llist_free(TT.current_hunk, do_line); | 328 | dlist_free(TT.current_hunk, do_line); |
339 | TT.current_hunk = NULL; | 329 | TT.current_hunk = NULL; |
340 | TT.state = 1; | 330 | TT.state = 1; |
341 | done: | 331 | done: |
342 | if (buf) { | 332 | if (buf) { |
343 | buf->prev->next = NULL; | 333 | buf->prev->next = NULL; |
344 | llist_free(buf, do_line); | 334 | dlist_free(buf, do_line); |
345 | } | 335 | } |
346 | 336 | ||
347 | return TT.state; | 337 | return TT.state; |