aboutsummaryrefslogtreecommitdiffstats
path: root/moon-abe/pbc-0.5.14/misc
diff options
context:
space:
mode:
Diffstat (limited to 'moon-abe/pbc-0.5.14/misc')
-rw-r--r--moon-abe/pbc-0.5.14/misc/darray.c176
-rw-r--r--moon-abe/pbc-0.5.14/misc/darray.h92
-rw-r--r--moon-abe/pbc-0.5.14/misc/extend_printf.c188
-rw-r--r--moon-abe/pbc-0.5.14/misc/get_time.c21
-rw-r--r--moon-abe/pbc-0.5.14/misc/get_time.win32.c42
-rw-r--r--moon-abe/pbc-0.5.14/misc/memory.c131
-rw-r--r--moon-abe/pbc-0.5.14/misc/symtab.c67
-rw-r--r--moon-abe/pbc-0.5.14/misc/symtab.h43
-rw-r--r--moon-abe/pbc-0.5.14/misc/utils.c101
9 files changed, 861 insertions, 0 deletions
diff --git a/moon-abe/pbc-0.5.14/misc/darray.c b/moon-abe/pbc-0.5.14/misc/darray.c
new file mode 100644
index 00000000..50b127f3
--- /dev/null
+++ b/moon-abe/pbc-0.5.14/misc/darray.c
@@ -0,0 +1,176 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "pbc_memory.h"
+#include "darray.h"
+
+#define NDEBUG
+#include <assert.h>
+
+enum {
+ max_init = 8
+};
+
+void darray_init(darray_ptr a)
+{
+ a->max = max_init;
+ a->count = 0;
+ a->item = pbc_malloc(sizeof(void *) * a->max);
+}
+
+darray_ptr darray_new(void)
+{
+ darray_ptr res = pbc_malloc(sizeof(darray_t));
+ darray_init(res);
+ return res;
+}
+
+void darray_remove_all(darray_ptr a)
+{
+ a->max = max_init;
+ a->count = 0;
+ pbc_free(a->item);
+ a->item = pbc_malloc(sizeof(void *) * a->max);
+}
+
+void darray_remove_last(darray_ptr a)
+{
+ assert(a->count > 0);
+ a->count--;
+}
+
+static void darray_realloc(darray_ptr a, int size)
+{
+ a->max = size;
+ a->item = pbc_realloc(a->item, sizeof(void *) * a->max);
+}
+
+void darray_append(darray_ptr a, void *p)
+{
+ if (a->count == a->max) {
+ if (!a->max) a->max = max_init;
+ else a->max *= 2;
+ a->item = pbc_realloc(a->item, sizeof(void *) * a->max);
+ }
+ a->item[a->count] = p;
+ a->count++;
+}
+
+int darray_index_of(darray_ptr a, void *p)
+{
+ int i;
+ for (i=0; i<a->count; i++) {
+ if (a->item[i] == p) return i;
+ }
+ return -1;
+}
+
+void darray_clear(darray_t a)
+{
+ pbc_free(a->item);
+ a->max = 0;
+ a->count = 0;
+}
+
+void darray_free(darray_ptr a) {
+ darray_clear(a);
+ pbc_free(a);
+}
+
+void darray_remove_index(darray_ptr a, int n)
+{
+ assert(a->count >= n-1);
+ a->count--;
+ memmove(&a->item[n], &a->item[n+1], sizeof(void *) * (a->count - n));
+}
+
+void darray_remove(darray_ptr a, void *p)
+{
+ int i;
+ for (i=0; i<a->count; i++) {
+ if (a->item[i] == p) {
+ a->count--;
+ memmove(&a->item[i], &a->item[i+1], sizeof(void *) * (a->count - i));
+ return;
+ }
+ }
+ assert(0);
+}
+
+void darray_remove_with_test(darray_ptr a, int (*test)(void *))
+{
+ int i;
+ for (i=0; i<a->count; i++) {
+ if (test(a->item[i])) {
+ for (;i<a->count; i++) {
+ a->item[i] = a->item[i+1];
+ }
+ a->count--;
+ }
+ }
+}
+
+void darray_copy(darray_ptr dst, darray_ptr src)
+{
+ darray_realloc(dst, src->count);
+ memcpy(dst->item, src->item, src->count * sizeof(void *));
+ dst->count = src->count;
+}
+
+void darray_forall(darray_t a, void (*func)(void *))
+{
+ int i, n = a->count;
+ for (i=0; i<n; i++) {
+ func(a->item[i]);
+ }
+}
+
+void darray_forall2(darray_t a,
+ void (*func)(void *darray_item, void *scope_ptr),
+ void *scope_ptr)
+{
+ int i, n = a->count;
+ for (i=0; i<n; i++) {
+ func(a->item[i], scope_ptr);
+ }
+}
+
+void darray_forall3(darray_t a,
+ void (*func)(void *darray_item,
+ void *scope_ptr1,
+ void *scope_ptr2),
+ void *scope_ptr1,
+ void *scope_ptr2)
+{
+ int i, n = a->count;
+ for (i=0; i<n; i++) {
+ func(a->item[i], scope_ptr1, scope_ptr2);
+ }
+}
+
+void darray_forall4(darray_t a,
+ void (*func)(void *darray_item,
+ void *scope_ptr1,
+ void *scope_ptr2,
+ void *scope_ptr3),
+ void *scope_ptr1,
+ void *scope_ptr2,
+ void *scope_ptr3)
+{
+ int i, n = a->count;
+ for (i=0; i<n; i++) {
+ func(a->item[i], scope_ptr1, scope_ptr2, scope_ptr3);
+ }
+}
+
+void *darray_at_test(darray_ptr a,
+ int (*test)(void *data, void *scope_ptr),
+ void *scope_ptr)
+{
+ int i;
+ for (i = 0; i < a->count; i++) {
+ void *p = a->item[i];
+ if (test(p, scope_ptr)) return p;
+ }
+ return NULL;
+}
diff --git a/moon-abe/pbc-0.5.14/misc/darray.h b/moon-abe/pbc-0.5.14/misc/darray.h
new file mode 100644
index 00000000..ecbd04ad
--- /dev/null
+++ b/moon-abe/pbc-0.5.14/misc/darray.h
@@ -0,0 +1,92 @@
+// darray = "dynamic array"
+// A linked-list implementation using C arrays.
+
+#ifndef __PBC_DARRAY_H__
+#define __PBC_DARRAY_H__
+
+#pragma GCC visibility push(hidden)
+
+struct darray_s {
+ void **item;
+ int count;
+ int max;
+};
+
+typedef struct darray_s darray_t[1];
+typedef struct darray_s *darray_ptr;
+
+/*@manual darray
+Initialize a dynamic array 'a'. Must be called before 'a' is used.
+*/
+void darray_init(darray_t a);
+darray_ptr darray_new(void);
+
+void darray_free(darray_ptr a);
+
+/*@manual darray
+Clears a dynamic array 'a'. Should be called after 'a' is no longer needed.
+*/
+void darray_clear(darray_t a);
+
+/*@manual darray
+Appends 'p' to the dynamic array 'a'.
+*/
+void darray_append(darray_t a, void *p);
+
+/*@manual darray
+Returns the pointer at index 'i' in the dynamic array 'a'.
+*/
+static inline void *darray_at(darray_t a, int i) {
+ return a->item[i];
+}
+
+int darray_index_of(darray_ptr a, void *p);
+void darray_remove(darray_ptr a, void *p);
+void darray_remove_last(darray_ptr a);
+void darray_remove_with_test(darray_ptr a, int (*test)(void *));
+
+/*@manual darray
+Removes the pointer at index 'i' in the dynamic array 'a'.
+*/
+void darray_remove_index(darray_ptr a, int n);
+void darray_copy(darray_ptr dst, darray_ptr src);
+void darray_remove_all(darray_ptr d);
+void darray_forall(darray_t a, void (*func)(void *));
+void darray_forall2(darray_t a,
+ void (*func)(void *darray_item, void *scope_ptr),
+ void *scope_ptr);
+void darray_forall3(darray_t a,
+ void (*func)(void *darray_item,
+ void *scope_ptr1,
+ void *scope_ptr2),
+ void *scope_ptr1,
+ void *scope_ptr2);
+void darray_forall4(darray_t a,
+ void (*func)(void *darray_item,
+ void *scope_ptr1,
+ void *scope_ptr2,
+ void *scope_ptr3),
+ void *scope_ptr1,
+ void *scope_ptr2,
+ void *scope_ptr3);
+
+void *darray_at_test(darray_ptr a, int (*test)(void *,void *), void *scope_ptr);
+
+/*@manual darray
+Returns the number of pointers held in 'a'.
+*/
+static inline int darray_count(darray_ptr a) {
+ return a->count;
+}
+
+static inline int darray_is_empty(darray_ptr a) {
+ return !a->count;
+}
+
+static inline void *darray_last(darray_t a) {
+ return a->item[a->count - 1];
+}
+
+#pragma GCC visibility pop
+
+#endif //__PBC_DARRAY_H__
diff --git a/moon-abe/pbc-0.5.14/misc/extend_printf.c b/moon-abe/pbc-0.5.14/misc/extend_printf.c
new file mode 100644
index 00000000..5e6537e2
--- /dev/null
+++ b/moon-abe/pbc-0.5.14/misc/extend_printf.c
@@ -0,0 +1,188 @@
+/*
+ * Behaves as gmp_printf with new conversion specifier %B for element_t types
+ */
+
+#include <stdio.h>
+#include <stdint.h> // for intptr_t
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <gmp.h>
+#include "pbc_utils.h"
+#include "pbc_field.h"
+#include "pbc_memory.h"
+
+struct sninfo_s {
+ char *s;
+ size_t size;
+ size_t left;
+ size_t result;
+};
+
+// TODO: remove repeated code for error handling
+static int do_print(int (*strcb)(void *, char *s),
+ int (*fstrcb)(void *, char *s, void *),
+ int (*elcb)(void *, element_ptr e),
+ void *data,
+ const char *format, va_list ap) {
+ // A primitive front-end for printf()-family functions. Only handles types
+ // in specifiers, and assumes they all take void * arguments.
+ //
+ // I wish register_printf_specifier() were more widespread.
+ int count = 0, status;
+ char *copy, *c, *start, *next;
+ element_ptr e;
+ int found;
+
+ copy = pbc_strdup(format);
+ start = next = copy;
+
+ for(;;) {
+ for(;;) {
+ c = strchr(next, '%');
+ if (!c) {
+ status = strcb(data, start);
+ if (status < 0) {
+ count = -1;
+ } else count += status;
+ goto done;
+ }
+ if (!*(c + 1)) goto done;
+ if (*(c + 1) != '%') break;
+ next = c + 2;
+ }
+ *c = 0;
+ status = strcb(data, start);
+ if (status < 0) {
+ count = -1;
+ goto done;
+ } else count += status;
+ *c = '%';
+ start = c;
+ found = 0;
+ while(!found) {
+ c++;
+ switch (*c) {
+ case '\0':
+ goto done;
+ case 'B':
+ e = va_arg(ap, element_ptr);
+ status = elcb(data, e);
+ if (status < 0) {
+ count = -1;
+ goto done;
+ } else count += status;
+ found = 1;
+ break;
+ default:
+ if (strchr("diouxXeEfFgGaAcspnmZ", *c)) {
+ if (*c == 'Z') c++;
+ char ch = *(c+1);
+ *(c+1) = '\0';
+ status = fstrcb(data, start, va_arg(ap, void *));
+ if (status < 0) {
+ count = -1;
+ goto done;
+ } else count += status;
+ *(c+1) = ch;
+ found = 1;
+ }
+ break;
+ }
+ }
+ next = start = c + 1;
+ }
+
+done:
+ pbc_free(copy);
+
+ return count;
+}
+
+static int string_cb(void *file, char *s) {
+ if (fputs(s, file) == EOF) return -1;
+ return strlen(s);
+}
+
+static int format_cb(void *file, char *fstring, void *ptr) {
+ return gmp_fprintf(file, fstring, ptr);
+}
+
+static int element_cb(void *file, element_ptr e) {
+ return element_out_str(file, 0, e);
+}
+
+int element_vfprintf(FILE *stream, const char *format, va_list ap) {
+ return do_print(string_cb, format_cb, element_cb, stream, format, ap);
+}
+
+int element_fprintf(FILE *stream, const char *format, ...) {
+ int status;
+ va_list ap;
+
+ va_start(ap, format);
+ status = element_vfprintf(stream, format, ap);
+ va_end(ap);
+ return status;
+}
+
+int element_printf(const char *format, ...) {
+ int status;
+ va_list ap;
+
+ va_start(ap, format);
+ status = element_vfprintf(stdout, format, ap);
+ va_end(ap);
+ return status;
+}
+
+static void next(struct sninfo_s *p, int status) {
+ p->result += status;
+ p->left = p->result >= p->size ? 0 : p->size - p->result;
+}
+
+static int string_cbv(void *data, char *s) {
+ struct sninfo_s *p = data;
+ int status = snprintf(p->s + p->result, p->left, "%s", s);
+ if (status < 0) return status;
+ next(data, status);
+ return status;
+}
+
+static int format_cbv(void *data, char *fstring, void *ptr) {
+ struct sninfo_s *p = data;
+ int status = gmp_snprintf(p->s + p->result, p->left, fstring, ptr);
+ if (status < 0) return status;
+ next(data, status);
+ return status;
+}
+
+static int element_cbv(void *data, element_ptr e) {
+ struct sninfo_s *p = data;
+ int status = element_snprint(p->s + p->result, p->left, e);
+ if (status < 0) return status;
+ next(data, status);
+ return status;
+}
+
+int element_vsnprintf(char *buf, size_t size, const char *fmt, va_list ap) {
+ struct sninfo_s info;
+
+ info.s = buf;
+ info.left = info.size = size;
+ info.result = 0;
+
+ do_print(string_cbv, format_cbv, element_cbv, &info, fmt, ap);
+
+ return info.result;
+}
+
+int element_snprintf(char *buf, size_t size, const char *fmt, ...) {
+ int status;
+ va_list ap;
+
+ va_start(ap, fmt);
+ status = element_vsnprintf(buf, size, fmt, ap);
+ va_end(ap);
+ return status;
+}
diff --git a/moon-abe/pbc-0.5.14/misc/get_time.c b/moon-abe/pbc-0.5.14/misc/get_time.c
new file mode 100644
index 00000000..8932364b
--- /dev/null
+++ b/moon-abe/pbc-0.5.14/misc/get_time.c
@@ -0,0 +1,21 @@
+#include <sys/time.h>
+#include <time.h>
+
+double pbc_get_time(void) {
+ static struct timeval last_tv, tv;
+ static int first = 1;
+ static double res = 0;
+
+ if (first) {
+ gettimeofday(&last_tv, NULL);
+ first = 0;
+ return 0;
+ } else {
+ gettimeofday(&tv, NULL);
+ res += tv.tv_sec - last_tv.tv_sec;
+ res += (tv.tv_usec - last_tv.tv_usec) / 1000000.0;
+ last_tv = tv;
+
+ return res;
+ }
+}
diff --git a/moon-abe/pbc-0.5.14/misc/get_time.win32.c b/moon-abe/pbc-0.5.14/misc/get_time.win32.c
new file mode 100644
index 00000000..98463198
--- /dev/null
+++ b/moon-abe/pbc-0.5.14/misc/get_time.win32.c
@@ -0,0 +1,42 @@
+#include <stdint.h> // for intptr_t
+#include <sys/time.h>
+#include "pbc_utils.h"
+
+typedef struct _FILETIME {
+ unsigned long dwLowDateTime;
+ unsigned long dwHighDateTime;
+} FILETIME;
+
+void __stdcall GetSystemTimeAsFileTime(FILETIME*);
+
+int __cdecl gettimeofday(struct timeval* p, void* tz) {
+ UNUSED_VAR(tz);
+ union {
+ long long ns100; // Time since 1 Jan 1601 in 100ns units.
+ FILETIME ft;
+ } _now;
+
+ GetSystemTimeAsFileTime( &(_now.ft) );
+ p->tv_usec=(long)((_now.ns100 / 10LL) % 1000000LL );
+ p->tv_sec= (long)((_now.ns100-(116444736000000000LL))/10000000LL);
+ return 0; // Assume success?
+}
+
+double pbc_get_time(void) {
+ static struct timeval last_tv, tv;
+ static int first = 1;
+ static double res = 0;
+
+ if (first) {
+ gettimeofday(&last_tv, NULL);
+ first = 0;
+ return 0;
+ } else {
+ gettimeofday(&tv, NULL);
+ res += tv.tv_sec - last_tv.tv_sec;
+ res += (tv.tv_usec - last_tv.tv_usec) / 1000000.0;
+ last_tv = tv;
+
+ return res;
+ }
+}
diff --git a/moon-abe/pbc-0.5.14/misc/memory.c b/moon-abe/pbc-0.5.14/misc/memory.c
new file mode 100644
index 00000000..cfe80ecc
--- /dev/null
+++ b/moon-abe/pbc-0.5.14/misc/memory.c
@@ -0,0 +1,131 @@
+#include <stdlib.h>
+#include <stdint.h> // for intptr_t
+#include <stdio.h>
+#include <string.h>
+#include "pbc_utils.h"
+#include "pbc_memory.h"
+
+#ifdef SAFE_CLEAN
+/* guarantee zeroing the memory */
+static void gmp_free(void *ptr, size_t size) {
+ if(ptr)
+ memset(ptr, 0, size);
+ free(ptr);
+}
+
+static void* gmp_malloc(size_t size) {
+ return malloc(size);
+}
+
+/* guarantee zeroing the memory
+ * realloc() is not suitable for use with secure memory
+ * because memory contents are not zeroed out. */
+static void* gmp_realloc(void *old_ptr, size_t old_size, size_t new_size) {
+ void *new_ptr = malloc(new_size);
+ if(new_ptr && old_ptr)
+ memcpy(new_ptr, old_ptr, old_size);
+ gmp_free(old_ptr, old_size);
+ return new_ptr;
+}
+
+static void gmp_guarantee_zero_memory(void) {
+ __gmp_set_memory_functions(gmp_malloc, gmp_realloc, gmp_free);
+}
+
+__attribute__((constructor)) void init(void) {
+ gmp_guarantee_zero_memory();
+}
+
+/* pbc_mem is a continuous memory keeping track of its size */
+static inline size_t pbc_mem_get_size(size_t *p) {
+ return *p;
+}
+
+static inline void pbc_mem_set_size(size_t *p, size_t size) {
+ *p = size;
+}
+
+static inline void *pbc_mem_to_ptr(size_t *p) {
+ return p + 1;
+}
+
+static inline void *pbc_ptr_to_mem(size_t *p) {
+ return p - 1;
+}
+
+static void *pbc_mem_malloc(size_t size) {
+ void *ptr = malloc(size + sizeof(size_t));
+ if(ptr)
+ pbc_mem_set_size(ptr, size);
+ return ptr;
+}
+
+static void pbc_mem_free(void *ptr) {
+ memset(ptr, 0, pbc_mem_get_size(ptr) + sizeof(size_t));
+ free(ptr);
+}
+
+static void *default_pbc_malloc(size_t size) {
+ void *ptr = pbc_mem_malloc(size);
+ if(!ptr) pbc_die("malloc() error");
+ return pbc_mem_to_ptr(ptr);
+}
+
+static void *default_pbc_realloc(void *old, size_t new_size) {
+ void *new = pbc_mem_malloc(new_size);
+ if(!new) pbc_die("realloc() error");
+ if(old) {
+ old = pbc_ptr_to_mem(old);
+ memcpy(pbc_mem_to_ptr(new), pbc_mem_to_ptr(old), pbc_mem_get_size(old));
+ pbc_mem_free(old);
+ }
+ return pbc_mem_to_ptr(new);
+}
+
+static void default_pbc_free(void *ptr) {
+ if(ptr)
+ pbc_mem_free(pbc_ptr_to_mem(ptr));
+}
+#else
+static void *default_pbc_malloc(size_t size) {
+ void *res = malloc(size);
+ if (!res) pbc_die("malloc() error");
+ return res;
+}
+
+static void *default_pbc_realloc(void *ptr, size_t size) {
+ void *res = realloc(ptr, size);
+ if (!res) pbc_die("realloc() error");
+ return res;
+}
+
+static void default_pbc_free(void *ptr) { free(ptr); }
+#endif
+
+/* release memory got from pbc_malloc only by pbc_free(), do not use free() */
+void *(*pbc_malloc)(size_t) = default_pbc_malloc;
+/* pbc_realloc guarantees zeroing out the memory before moving old memory */
+void *(*pbc_realloc)(void *, size_t) = default_pbc_realloc;
+/* pbc_free guarantees zeroing out the memory */
+void (*pbc_free)(void *) = default_pbc_free;
+
+void pbc_set_memory_functions(void *(*malloc_fn)(size_t),
+ void *(*realloc_fn)(void *, size_t), void (*free_fn)(void *)) {
+ pbc_malloc = malloc_fn;
+ pbc_realloc = realloc_fn;
+ pbc_free = free_fn;
+}
+
+void *pbc_calloc(size_t nmemb, size_t size) {
+ void *res = pbc_malloc(nmemb * size);
+ if (!res) pbc_die("calloc() error");
+ memset(res, 0, nmemb * size);
+ return res;
+}
+
+char *pbc_strdup(const char *s) {
+ int len = strlen(s);
+ char *res = pbc_malloc(len + 1);
+ strcpy(res, s);
+ return res;
+}
diff --git a/moon-abe/pbc-0.5.14/misc/symtab.c b/moon-abe/pbc-0.5.14/misc/symtab.c
new file mode 100644
index 00000000..9d62f590
--- /dev/null
+++ b/moon-abe/pbc-0.5.14/misc/symtab.c
@@ -0,0 +1,67 @@
+#include <stdlib.h>
+#include <string.h>
+#include "pbc_memory.h"
+
+#include "symtab.h"
+
+struct entry_s {
+ char *key;
+ void *data;
+};
+typedef struct entry_s *entry_ptr;
+typedef struct entry_s entry_t[1];
+
+void symtab_init(symtab_t t) {
+ darray_init(t->list);
+}
+
+static void clear(void *data) {
+ entry_ptr e = data;
+ pbc_free(e->key);
+ pbc_free(e);
+}
+
+void symtab_clear(symtab_t t) {
+ darray_forall(t->list, clear);
+ darray_clear(t->list);
+}
+
+void symtab_put(symtab_t t, void *data, const char *key) {
+ int i, n = t->list->count;
+ entry_ptr e;
+ for (i=0; i<n; i++) {
+ e = t->list->item[i];
+ if (!strcmp(e->key, key)) goto doit;
+ }
+ e = pbc_malloc(sizeof(entry_t));
+ e->key = pbc_strdup(key);
+ darray_append(t->list, e);
+doit:
+ e->data = data;
+}
+
+int symtab_has(symtab_t t, const char *key) {
+ int i, n = t->list->count;
+ for (i = 0; i < n; i++) {
+ entry_ptr e = t->list->item[i];
+ if (!strcmp(e->key, key)) return 1;
+ }
+ return 0;
+}
+
+void *symtab_at(symtab_t t, const char *key) {
+ int i, n = t->list->count;
+ for (i=0; i<n; i++) {
+ entry_ptr e = t->list->item[i];
+ if (!strcmp(e->key, key)) return e->data;
+ }
+ return NULL;
+}
+
+void symtab_forall_data(symtab_t t, void (*func)(void *)) {
+ int i, n = t->list->count;
+ for (i=0; i<n; i++) {
+ entry_ptr e = t->list->item[i];
+ func(e->data);
+ }
+}
diff --git a/moon-abe/pbc-0.5.14/misc/symtab.h b/moon-abe/pbc-0.5.14/misc/symtab.h
new file mode 100644
index 00000000..39f255c3
--- /dev/null
+++ b/moon-abe/pbc-0.5.14/misc/symtab.h
@@ -0,0 +1,43 @@
+#ifndef __PBC_SYMTAB_H__
+#define __PBC_SYMTAB_H__
+
+#include "darray.h"
+
+#pragma GCC visibility push(hidden)
+
+struct symtab_s {
+ darray_t list;
+};
+typedef struct symtab_s symtab_t[1];
+typedef struct symtab_s *symtab_ptr;
+
+/*@manual symtab
+Initialize symbol table 't'. Must be called before 't' is used.
+*/
+void symtab_init(symtab_t t);
+
+/*@manual symtab
+Clears symbol table 't'. Should be called after 't' is no longer needed.
+*/
+void symtab_clear(symtab_t t);
+
+/*@manual symtab
+Puts 'value' at 'key' in 't'.
+*/
+void symtab_put(symtab_t t, void *value, const char *key);
+
+/*@manual symtab
+Returns true if 't' contains key 'key'.
+*/
+int symtab_has(symtab_t t, const char *key);
+
+/*@manual symtab
+Returns pointer at key 'key' in 't'.
+*/
+void *symtab_at(symtab_t t, const char *key);
+
+void symtab_forall_data(symtab_t t, void (*func)(void *));
+
+#pragma GCC visibility pop
+
+#endif //__PBC_SYMTAB_H__
diff --git a/moon-abe/pbc-0.5.14/misc/utils.c b/moon-abe/pbc-0.5.14/misc/utils.c
new file mode 100644
index 00000000..1a808256
--- /dev/null
+++ b/moon-abe/pbc-0.5.14/misc/utils.c
@@ -0,0 +1,101 @@
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h> // for intptr_t
+#include <gmp.h>
+
+#include "pbc_utils.h"
+#include "pbc_field.h"
+
+static int pbc_msg_to_stderr = 1;
+
+int pbc_set_msg_to_stderr(int i) {
+ return pbc_msg_to_stderr = i;
+}
+
+static int out(const char *format, ...) {
+ if (!pbc_msg_to_stderr) return 0;
+ va_list params;
+
+ va_start(params, format);
+ int res = vfprintf(stderr, format, params);
+ va_end(params);
+ return res;
+}
+
+static void print_warning(void) {
+ static int first = 1;
+ if (first) {
+ out("*** PBC asserts enabled: potential performance penalties ***\n");
+ first = 0;
+ }
+}
+
+void pbc_assert(int expr, char *msg, const char *func) {
+ print_warning();
+ if (!expr) {
+ out("PBC assert failed: %s(): %s\n", func, msg);
+ abort();
+ }
+}
+
+void pbc_assert_match2(element_ptr a, element_ptr b, const char *func) {
+ print_warning();
+ if (a->field != b->field) {
+ out("PBC assert failed: %s(): field mismatch\n", func);
+ abort();
+ }
+}
+
+void pbc_assert_match3(element_ptr a, element_ptr b, element_ptr c,
+ const char *func) {
+ print_warning();
+ if (a->field != b->field) {
+ out("PBC assert failed: %s(): first two args field mismatch\n", func);
+ abort();
+ }
+ if (b->field != c->field) {
+ out("PBC assert failed: %s(): last two args field mismatch\n", func);
+ abort();
+ }
+}
+
+// Print at most the first 1024 bytes of an error message.
+static void report(const char *prefix, const char *err, va_list params) {
+ char msg[1024];
+ element_vsnprintf(msg, sizeof(msg), err, params);
+ out("%s%s\n", prefix, msg);
+}
+
+void pbc_die(const char *err, ...) {
+ va_list params;
+
+ va_start(params, err);
+ report("fatal: ", err, params);
+ va_end(params);
+ exit(128);
+}
+
+void pbc_info(const char *err, ...) {
+ va_list params;
+
+ va_start(params, err);
+ report("", err, params);
+ va_end(params);
+}
+
+void pbc_warn(const char *err, ...) {
+ va_list params;
+
+ va_start(params, err);
+ report("warning: ", err, params);
+ va_end(params);
+}
+
+void pbc_error(const char *err, ...) {
+ va_list params;
+
+ va_start(params, err);
+ report("error: ", err, params);
+ va_end(params);
+}