summaryrefslogtreecommitdiff
path: root/app/tools/halibut/malloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/tools/halibut/malloc.c')
-rw-r--r--app/tools/halibut/malloc.c149
1 files changed, 149 insertions, 0 deletions
diff --git a/app/tools/halibut/malloc.c b/app/tools/halibut/malloc.c
new file mode 100644
index 0000000..2ff22fd
--- /dev/null
+++ b/app/tools/halibut/malloc.c
@@ -0,0 +1,149 @@
+/*
+ * malloc.c: safe wrappers around malloc, realloc, free, strdup
+ */
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include "halibut.h"
+
+#ifdef LOGALLOC
+#define LOGPARAMS char *file, int line,
+static FILE *logallocfp = NULL;
+static int logline = 2; /* off by 1: `null pointer is' */
+static void loginc(void) { }
+static void logallocinit(void) {
+ if (!logallocfp) {
+ logallocfp = fopen("malloc.log", "w");
+ if (!logallocfp) {
+ fprintf(stderr, "panic: unable to open malloc.log\n");
+ exit(10);
+ }
+ setvbuf (logallocfp, NULL, _IOLBF, BUFSIZ);
+ fprintf(logallocfp, "null pointer is %p\n", NULL);
+ }
+}
+static void logprintf(char *fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ vfprintf(logallocfp, fmt, ap);
+ va_end(ap);
+}
+#define LOGPRINT(x) ( logallocinit(), logprintf x )
+#define LOGINC do { loginc(); logline++; } while (0)
+#else
+#define LOGPARAMS
+#define LOGPRINT(x)
+#define LOGINC ((void)0)
+#endif
+
+/*
+ * smalloc should guarantee to return a useful pointer - Halibut
+ * can do nothing except die when it's out of memory anyway.
+ */
+void *(smalloc)(LOGPARAMS int size) {
+ void *p;
+ LOGINC;
+ LOGPRINT(("%s %d malloc(%ld)",
+ file, line, (long)size));
+ p = malloc(size);
+ if (!p)
+ fatal(err_nomemory);
+ LOGPRINT((" returns %p\n", p));
+ return p;
+}
+
+/*
+ * sfree should guaranteeably deal gracefully with freeing NULL
+ */
+void (sfree)(LOGPARAMS void *p) {
+ if (p) {
+ LOGINC;
+ LOGPRINT(("%s %d free(%p)\n",
+ file, line, p));
+ free(p);
+ }
+}
+
+/*
+ * srealloc should guaranteeably be able to realloc NULL
+ */
+void *(srealloc)(LOGPARAMS void *p, int size) {
+ void *q;
+ if (p) {
+ LOGINC;
+ LOGPRINT(("%s %d realloc(%p,%ld)",
+ file, line, p, (long)size));
+ q = realloc(p, size);
+ LOGPRINT((" returns %p\n", q));
+ } else {
+ LOGINC;
+ LOGPRINT(("%s %d malloc(%ld)",
+ file, line, (long)size));
+ q = malloc(size);
+ LOGPRINT((" returns %p\n", q));
+ }
+ if (!q)
+ fatal(err_nomemory);
+ return q;
+}
+
+/*
+ * dupstr is like strdup, but with the never-return-NULL property
+ * of smalloc (and also reliably defined in all environments :-)
+ */
+char *dupstr(char *s) {
+ char *r = smalloc(1+strlen(s));
+ strcpy(r,s);
+ return r;
+}
+
+/*
+ * Duplicate a linked list of words
+ */
+word *dup_word_list(word *w) {
+ word *head = NULL, **eptr = &head;
+
+ while (w) {
+ word *newwd = snew(word);
+ *newwd = *w; /* structure copy */
+ newwd->text = ustrdup(w->text);
+ if (w->alt)
+ newwd->alt = dup_word_list(w->alt);
+ *eptr = newwd;
+ newwd->next = NULL;
+ eptr = &newwd->next;
+
+ w = w->next;
+ }
+
+ return head;
+}
+
+/*
+ * Free a linked list of words
+ */
+void free_word_list(word *w) {
+ word *t;
+ while (w) {
+ t = w;
+ w = w->next;
+ sfree(t->text);
+ if (t->alt)
+ free_word_list(t->alt);
+ sfree(t);
+ }
+}
+
+/*
+ * Free a linked list of paragraphs
+ */
+void free_para_list(paragraph *p) {
+ paragraph *t;
+ while (p) {
+ t = p;
+ p = p->next;
+ sfree(t->keyword);
+ free_word_list(t->words);
+ sfree(t);
+ }
+}