Mercurial > repo
diff src/ploki/venus.c @ 4223:ac0403686959
<oerjan> rm -rf src/ploki; mv ploki src
author | HackBot |
---|---|
date | Fri, 20 Dec 2013 22:18:50 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ploki/venus.c Fri Dec 20 22:18:50 2013 +0000 @@ -0,0 +1,146 @@ +#include "Str.h" +#include "hash.h" +#include "op.h" +#include "venus.h" +#include "xmalloc.h" +#include "zz.h" + +#include <stddef.h> +#include <stdio.h> +#include <string.h> + +enum {MAGIC = 23}; + +struct sorted { + size_t size, length; + struct op **array; +}; + +static size_t hash(const void *p, size_t seed) { + return St_hash(p, seed); +} + +static int compar(const void *a, const void *b) { + return St_cmp(a, b); +} + +static void delk(void *k) { + St_clear(k); + xfree(k); +} + +static void delv(void *v) { + xfree(((struct sorted *)v)->array); + xfree(v); +} + +void ve_init(struct venus *v) { + h_init(&v->table, hash, compar, delk, delv); +} + +void ve_end(struct venus *v) { + h_end(&v->table); +} + +void ve_enter(struct venus *v, const String *s, struct op *o) { + struct sorted *x; + void *tmp; + size_t a, z; + + if (h_get(&v->table, s, &tmp) == H_NOENT) { + String *label; + x = xmalloc(1, sizeof *x); + x->array = xmalloc(x->size = MAGIC, sizeof *x->array); + x->array[0] = o; + x->length = 1; + label = xmalloc(1, sizeof *label); + St_init(label); + St_cpy(label, s); + h_put(&v->table, label, x, 1); + return; + } + x = tmp; + + for (a = 0, z = x->length; a < z; ) { + if (x->array[(a + z) / 2]->line < o->line) { + a = (a + z) / 2 + 1u; + } else if (x->array[(a + z) / 2]->line > o->line) { + z = (a + z) / 2; + } else { + NOTREACHED; + } + } + + if (x->length >= x->size) { + x->array = xrealloc(x->array, x->size *= 2); + } + memmove(x->array + a + 1u, x->array + a, x->length - a); + x->array[a] = o; + x->length++; +} + +struct op *ve_findnext(struct venus *v, const String *s, size_t line) { + struct sorted *x; + void *tmp; + size_t a, z; + + if (h_get(&v->table, s, &tmp) == H_NOENT) { + return NULL; + } + x = tmp; + + for (a = 0, z = x->length; a < z; ) { + if (x->array[(a + z) / 2]->line < line) { + a = (a + z) / 2 + 1u; + } else if (x->array[(a + z) / 2]->line > line) { + z = (a + z) / 2; + } else { + a = (a + z) / 2 + 1u; + break; + } + } + + return x->array[a % x->length]; +} + +struct op *ve_findprev(struct venus *v, const String *s, size_t line) { + struct sorted *x; + void *tmp; + size_t a, z; + + if (h_get(&v->table, s, &tmp) == H_NOENT) { + return NULL; + } + x = tmp; + + for (a = 0, z = x->length; a < z; ) { + if (x->array[(a + z) / 2]->line < line) { + a = (a + z) / 2 + 1u; + } else if (x->array[(a + z) / 2]->line > line) { + z = (a + z) / 2; + } else { + a = (a + z) / 2; + break; + } + } + a += x->length - 1u; + return x->array[a % x->length]; +} + +const String *ve_label(struct venus *v, const struct op *op) { + void *key, *value; + + h_reset(&v->table); + while (h_nextkv(&v->table, &key, &value) == H_OK) { + const struct sorted *x = value; + size_t i; + + for (i = 0; i < x->length; ++i) { + if (x->array[i] == op) { + return key; + } + } + } + + return NULL; +}