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>
This commit is contained in:
Denys Vlasenko 2010-11-21 05:54:28 +01:00
parent b82ae98ea4
commit 400ff226c2

View File

@ -56,75 +56,64 @@
#include "libbb.h" #include "libbb.h"
// libbb candidate?
struct double_list { struct double_list {
struct double_list *next; struct double_list *next;
struct double_list *prev; struct double_list *prev;
char *data; 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 // 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 static
void TOY_llist_free(void *list, void (*freeit)(void *data)) void dlist_free(struct double_list *list, void (*freeit)(void *data))
{ {
while (list) { while (list) {
void *pop = TOY_llist_pop(&list); void *pop = list;
if (freeit) freeit(pop); list = list->next;
else free(pop); freeit(pop);
// Bail out also if list is circular.
// End doubly linked list too. if (list == pop) break;
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 static
struct double_list *dlist_add(struct double_list **list, char *data) 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; line->data = data;
if (*list) { llist = *list;
line->next = *list; if (llist) {
line->prev = (*list)->prev; struct double_list *p;
(*list)->prev->next = line; line->next = llist;
(*list)->prev = line; p = line->prev = llist->prev;
} else *list = line->next = line->prev = line; // (list is circular, we assume p is never NULL)
p->next = line;
llist->prev = line;
} else
*list = line->next = line->prev = line;
return line; return line;
} }
struct globals { struct globals {
char *infile; char *infile;
long prefix; long prefix;
struct double_list *current_hunk; struct double_list *current_hunk;
long oldline, oldlen, newline, newlen; long oldline, oldlen, newline, newlen;
long linenum; long linenum;
int context, state, filein, fileout, hunknum; int context, state, hunknum;
int filein, fileout;
char *tempname; char *tempname;
// was toys.foo:
int exitval; int exitval;
}; };
#define TT (*ptr_to_globals) #define TT (*ptr_to_globals)
@ -193,7 +182,6 @@ static void finish_oldfile(void)
static void fail_hunk(void) static void fail_hunk(void)
{ {
if (!TT.current_hunk) return; 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); fdprintf(2, "Hunk %d FAILED %ld/%ld.\n", TT.hunknum, TT.oldline, TT.newline);
TT.exitval = 1; TT.exitval = 1;
@ -202,7 +190,8 @@ static void fail_hunk(void)
// this file and advance to next file. // this file and advance to next file.
TT.state = 2; 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; TT.current_hunk = NULL;
// Abort the copy and delete the temporary file. // Abort the copy and delete the temporary file.
@ -308,7 +297,8 @@ static int apply_one_hunk(void)
fdprintf(2, "NOT: %s\n", plist->data); fdprintf(2, "NOT: %s\n", plist->data);
TT.state = 3; TT.state = 3;
check = llist_pop(&buf); check = buf;
buf = buf->next;
check->prev->next = buf; check->prev->next = buf;
buf->prev = check->prev; buf->prev = check->prev;
do_line(check); do_line(check);
@ -335,13 +325,13 @@ static int apply_one_hunk(void)
out: out:
// We have a match. Emit changed data. // We have a match. Emit changed data.
TT.state = "-+"[reverse ^ dummy_revert]; TT.state = "-+"[reverse ^ dummy_revert];
llist_free(TT.current_hunk, do_line); dlist_free(TT.current_hunk, do_line);
TT.current_hunk = NULL; TT.current_hunk = NULL;
TT.state = 1; TT.state = 1;
done: done:
if (buf) { if (buf) {
buf->prev->next = NULL; buf->prev->next = NULL;
llist_free(buf, do_line); dlist_free(buf, do_line);
} }
return TT.state; return TT.state;