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"
// 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 finish_oldfile(void)
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 @@ static void fail_hunk(void)
// 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 @@ static int apply_one_hunk(void)
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 @@ static int apply_one_hunk(void)
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;