+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "assoc.h"
+#include "atom.h"
+
+typedef struct word {
+ assoc_base _b;
+ int i;
+} word;
+
+static int cmp(const void *a, const void *b)
+{
+ const word *const *v = b;
+ const word *const *w = a;
+ return (strcmp(ATOM_NAME((*w)->_b.a), ATOM_NAME((*v)->_b.a)));
+}
+
+int main(void)
+{
+ char buf[256];
+ char *p;
+ atom_table at;
+ assoc_table t;
+ size_t n = 0;
+
+ atom_createtable(&at);
+ assoc_create(&t);
+
+ while (fgets(buf, sizeof(buf), stdin)) {
+ buf[strlen(buf) - 1] = 0;
+/* printf("# %s\n", buf); */
+ p = strtok(buf, " ");
+
+ if (strcmp(p, "set") == 0) {
+ char *k = strtok(0, " ");
+ int i = atoi(strtok(0, " "));
+ unsigned f;
+ word *w = assoc_find(&t, atom_intern(&at, k), sizeof(word), &f);
+ w->i = i;
+ if (!f)
+ n++;
+ } else if (strcmp(p, "get") == 0) {
+ char *k = strtok(0, " ");
+ word *w = assoc_find(&t, atom_intern(&at, k), 0, 0);
+ if (w)
+ printf("%i\n", w->i);
+ else
+ puts("*MISSING*");
+ } else if (strcmp(p, "del") == 0) {
+ char *k = strtok(0, " ");
+ word *w = assoc_find(&t, atom_intern(&at, k), 0, 0);
+ if (w) {
+ assoc_remove(&t, w);
+ n--;
+ } else
+ puts("*MISSING*");
+ } else if (strcmp(p, "count") == 0) {
+ printf("%i\n", n);
+ } else if (strcmp(p, "show") == 0) {
+ assoc_iter i;
+ word *w;
+ word **v, **vv;
+
+ if (!n)
+ puts("*EMPTY*");
+ else {
+ v = malloc(n * sizeof(*v));
+ if (!v) {
+ puts("*NOMEM*");
+ continue;
+ }
+ for (vv = v, assoc_mkiter(&i, &t); (w = assoc_next(&i)) != 0; vv++)
+ *vv = w;
+ qsort(v, n, sizeof(*v), cmp);
+ printf("%s:%i", ATOM_NAME((*v)->_b.a), (*v)->i);
+ for (vv = v + 1; --n; vv++)
+ printf(" %s:%i", ATOM_NAME((*vv)->_b.a), (*vv)->i);
+ free(v);
+ putchar('\n');
+ }
+ } else
+ puts("*BAD*");
+ }
+
+ assoc_destroy(&t);
+ return (0);
+}