From 35c0995dde0c37486681630acdd8d26659a4732e Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Wed, 19 Jun 2013 01:43:57 +0100 Subject: [PATCH] progs/pixie.c: Rewrite list hacking to avoid strict-aliasing badness. The circular list stuff was quite pretty but involved some really unpleasant casting which modern GCC (quite properly) complains about vociferously. Replace it with more traditional doubly-linked-list hacking with null-pointer sentinels, with the slightly nasty pointer swizzling tucked away in useful macros. Some of the uses of these macros (e.g., unlinking the first or last item in a list) could be made more efficient by using special-case versions, but it doesn't seem worthwhile. --- progs/pixie.c | 48 ++++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/progs/pixie.c b/progs/pixie.c index 1198fcb..667a588 100644 --- a/progs/pixie.c +++ b/progs/pixie.c @@ -125,8 +125,7 @@ static void pxlog(const char *p, ...) /* --- Data structures --- */ typedef struct phrase { - struct phrase *next; - struct phrase *prev; + struct phrase *next, *prev; char *tag; char *p; unsigned long t; @@ -136,8 +135,21 @@ typedef struct phrase { /* --- Variables --- */ -#define P_ROOT ((phrase *)&p_root) -static struct { phrase *next; phrase *prev; } p_root = { P_ROOT, P_ROOT }; +static phrase *p_head = 0, *p_tail = 0; + +/* --- Utility macros --- */ + +#define P_LINKTAIL(p) do { \ + (p)->next = 0; \ + (p)->prev = p_tail; \ + *(p_tail ? &p_tail->next : &p_head) = (p); \ + p_tail = (p); \ +} while (0) + +#define P_UNLINK(p) do { \ + *((p)->next ? &(p)->next->prev : &p_tail) = (p)->prev; \ + *((p)->prev ? &(p)->prev->next : &p_head) = (p)->next; \ +} while (0) /* --- @p_free@ --- * * @@ -154,8 +166,7 @@ static void p_free(phrase *p) sel_rmtimer(&p->timer); xfree(p->tag); l_free(&lm, p->p); - p->next->prev = p->prev; - p->prev->next = p->next; + P_UNLINK(p); DESTROY(p); } @@ -193,13 +204,13 @@ static void *p_alloc(size_t sz) char *p; if ((p = l_alloc(&lm, sz)) != 0) return (p); - if (P_ROOT->next == P_ROOT) + if (!p_head) return (0); if (verbose) { pxlog("flushing passphrase `%s' to free up needed space", p_head->tag); } - p_free(P_ROOT->next); + p_free(p_head); } } @@ -216,7 +227,7 @@ static phrase *p_find(const char *tag) { phrase *p; - for (p = P_ROOT->next; p != P_ROOT; p = p->next) { + for (p = p_head; p; p = p->next) { if (strcmp(p->tag, tag) == 0) { if (p->t) { struct timeval tv; @@ -225,12 +236,8 @@ static phrase *p_find(const char *tag) tv.tv_sec += p->t; sel_addtimer(&sel, &p->timer, &tv, p_timer, p); } - p->next->prev = p->prev; - p->prev->next = p->next; - p->next = P_ROOT; - p->prev = P_ROOT->prev; - P_ROOT->prev->next = p; - P_ROOT->prev = p; + P_UNLINK(p); + P_LINKTAIL(p); return (p); } } @@ -279,10 +286,7 @@ static phrase *p_add(const char *tag, const char *p, unsigned long t) /* --- Link the block into the chain --- */ - pp->next = P_ROOT; - pp->prev = P_ROOT->prev; - P_ROOT->prev->next = pp; - P_ROOT->prev = pp; + P_LINKTAIL(pp); return (pp); } @@ -301,8 +305,8 @@ static void p_flush(const char *tag) if (!tag && verbose > 1) pxlog("flushing all passphrases"); - p = P_ROOT->next; - while (p != P_ROOT) { + p = p_head; + while (p) { phrase *pp = p->next; if (!tag) p_free(p); @@ -695,7 +699,7 @@ OK\n\ else if (strcmp(q, "list") == 0) { phrase *p; - for (p = P_ROOT->next; p != P_ROOT; p = p->next) { + for (p = p_head; p; p = p->next) { if (!p->t) pixserv_write(px, "ITEM %s no-expire\n", p->tag); else { -- 2.11.0