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;