diff options
Diffstat (limited to 'moon-abe/pbc-0.5.14/misc')
-rw-r--r-- | moon-abe/pbc-0.5.14/misc/darray.c | 176 | ||||
-rw-r--r-- | moon-abe/pbc-0.5.14/misc/darray.h | 92 | ||||
-rw-r--r-- | moon-abe/pbc-0.5.14/misc/extend_printf.c | 188 | ||||
-rw-r--r-- | moon-abe/pbc-0.5.14/misc/get_time.c | 21 | ||||
-rw-r--r-- | moon-abe/pbc-0.5.14/misc/get_time.win32.c | 42 | ||||
-rw-r--r-- | moon-abe/pbc-0.5.14/misc/memory.c | 131 | ||||
-rw-r--r-- | moon-abe/pbc-0.5.14/misc/symtab.c | 67 | ||||
-rw-r--r-- | moon-abe/pbc-0.5.14/misc/symtab.h | 43 | ||||
-rw-r--r-- | moon-abe/pbc-0.5.14/misc/utils.c | 101 |
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); +} |