patch: simplify double list helpers
function old new delta
dlist_free - 29 +29
fail_hunk 130 132 +2
patch_main 1987 1982 -5
dlist_add 59 54 -5
TOY_llist_pop 9 - -9
TOY_llist_free 54 - -54
------------------------------------------------------------------------------
(add/remove: 1/2 grow/shrink: 1/2 up/down: 31/-73) Total: -42 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
diff --git a/editors/patch.c b/editors/patch.c
index 4fadbb8..1d4a255 100644
--- a/editors/patch.c
+++ b/editors/patch.c
@@ -56,75 +56,64 @@
#include "libbb.h"
+
+// libbb candidate?
+
struct double_list {
struct double_list *next;
struct double_list *prev;
char *data;
};
-// Return the first item from the list, advancing the list (which must be called
-// as &list)
-static
-void *TOY_llist_pop(void *list)
-{
- // I'd use a void ** for the argument, and even accept the typecast in all
- // callers as documentation you need the &, except the stupid compiler
- // would then scream about type-punned pointers. Screw it.
- void **llist = (void **)list;
- void **next = (void **)*llist;
- *llist = *next;
-
- return (void *)next;
-}
-
// Free all the elements of a linked list
-// if freeit!=NULL call freeit() on each element before freeing it.
+// Call freeit() on each element before freeing it.
static
-void TOY_llist_free(void *list, void (*freeit)(void *data))
+void dlist_free(struct double_list *list, void (*freeit)(void *data))
{
while (list) {
- void *pop = TOY_llist_pop(&list);
- if (freeit) freeit(pop);
- else free(pop);
-
- // End doubly linked list too.
- if (list==pop) break;
+ void *pop = list;
+ list = list->next;
+ freeit(pop);
+ // Bail out also if list is circular.
+ if (list == pop) break;
}
}
-//Override bbox's names
-#define llist_pop TOY_llist_pop
-#define llist_free TOY_llist_free
-// Add an entry to the end off a doubly linked list
+// Add an entry before "list" element in (circular) doubly linked list
static
struct double_list *dlist_add(struct double_list **list, char *data)
{
- struct double_list *line = xmalloc(sizeof(struct double_list));
+ struct double_list *llist;
+ struct double_list *line = xmalloc(sizeof(*line));
line->data = data;
- if (*list) {
- line->next = *list;
- line->prev = (*list)->prev;
- (*list)->prev->next = line;
- (*list)->prev = line;
- } else *list = line->next = line->prev = line;
+ llist = *list;
+ if (llist) {
+ struct double_list *p;
+ line->next = llist;
+ p = line->prev = llist->prev;
+ // (list is circular, we assume p is never NULL)
+ p->next = line;
+ llist->prev = line;
+ } else
+ *list = line->next = line->prev = line;
return line;
}
-
struct globals {
char *infile;
long prefix;
struct double_list *current_hunk;
+
long oldline, oldlen, newline, newlen;
long linenum;
- int context, state, filein, fileout, hunknum;
+ int context, state, hunknum;
+ int filein, fileout;
char *tempname;
- // was toys.foo:
int exitval;
};
#define TT (*ptr_to_globals)
@@ -193,7 +182,6 @@
static void fail_hunk(void)
{
if (!TT.current_hunk) return;
- TT.current_hunk->prev->next = NULL;
fdprintf(2, "Hunk %d FAILED %ld/%ld.\n", TT.hunknum, TT.oldline, TT.newline);
TT.exitval = 1;
@@ -202,7 +190,8 @@
// this file and advance to next file.
TT.state = 2;
- llist_free(TT.current_hunk, do_line);
+ TT.current_hunk->prev->next = NULL;
+ dlist_free(TT.current_hunk, do_line);
TT.current_hunk = NULL;
// Abort the copy and delete the temporary file.
@@ -308,7 +297,8 @@
fdprintf(2, "NOT: %s\n", plist->data);
TT.state = 3;
- check = llist_pop(&buf);
+ check = buf;
+ buf = buf->next;
check->prev->next = buf;
buf->prev = check->prev;
do_line(check);
@@ -335,13 +325,13 @@
out:
// We have a match. Emit changed data.
TT.state = "-+"[reverse ^ dummy_revert];
- llist_free(TT.current_hunk, do_line);
+ dlist_free(TT.current_hunk, do_line);
TT.current_hunk = NULL;
TT.state = 1;
done:
if (buf) {
buf->prev->next = NULL;
- llist_free(buf, do_line);
+ dlist_free(buf, do_line);
}
return TT.state;