1 /*
2  * malloc.c: safe wrappers around malloc, realloc, free, strdup
3  */
4 
5 #include <stdlib.h>
6 #include <stdarg.h>
7 #include "halibut.h"
8 
9 #ifdef LOGALLOC
10 #define LOGPARAMS char *file, int line,
11 static FILE *logallocfp = NULL;
12 static int logline = 2;		       /* off by 1: `null pointer is' */
loginc(void)13 static void loginc(void) { }
logallocinit(void)14 static void logallocinit(void) {
15     if (!logallocfp) {
16 	logallocfp = fopen("malloc.log", "w");
17 	if (!logallocfp) {
18 	    fprintf(stderr, "panic: unable to open malloc.log\n");
19 	    exit(10);
20 	}
21 	setvbuf (logallocfp, NULL, _IOLBF, BUFSIZ);
22 	fprintf(logallocfp, "null pointer is %p\n", NULL);
23     }
24 }
logprintf(char * fmt,...)25 static void logprintf(char *fmt, ...) {
26     va_list ap;
27     va_start(ap, fmt);
28     vfprintf(logallocfp, fmt, ap);
29     va_end(ap);
30 }
31 #define LOGPRINT(x) ( logallocinit(), logprintf x )
32 #define LOGINC do { loginc(); logline++; } while (0)
33 #else
34 #define LOGPARAMS
35 #define LOGPRINT(x)
36 #define LOGINC ((void)0)
37 #endif
38 
39 /*
40  * smalloc should guarantee to return a useful pointer - Halibut
41  * can do nothing except die when it's out of memory anyway.
42  */
43 void *(smalloc)(LOGPARAMS int size) {
44     void *p;
45     LOGINC;
46     LOGPRINT(("%s %d malloc(%ld)",
47 	      file, line, (long)size));
48     p = malloc(size);
49     if (!p)
50 	fatalerr_nomemory();
51     LOGPRINT((" returns %p\n", p));
52     return p;
53 }
54 
55 /*
56  * sfree should guaranteeably deal gracefully with freeing NULL
57  */
58 void (sfree)(LOGPARAMS void *p) {
59     if (p) {
60 	LOGINC;
61 	LOGPRINT(("%s %d free(%p)\n",
62 		  file, line, p));
63 	free(p);
64     }
65 }
66 
67 /*
68  * srealloc should guaranteeably be able to realloc NULL
69  */
70 void *(srealloc)(LOGPARAMS void *p, int size) {
71     void *q;
72     if (p) {
73 	LOGINC;
74 	LOGPRINT(("%s %d realloc(%p,%ld)",
75 		  file, line, p, (long)size));
76 	q = realloc(p, size);
77 	LOGPRINT((" returns %p\n", q));
78     } else {
79 	LOGINC;
80 	LOGPRINT(("%s %d malloc(%ld)",
81 		  file, line, (long)size));
82 	q = malloc(size);
83 	LOGPRINT((" returns %p\n", q));
84     }
85     if (!q)
86 	fatalerr_nomemory();
87     return q;
88 }
89 
90 /*
91  * dupstr is like strdup, but with the never-return-NULL property
92  * of smalloc (and also reliably defined in all environments :-)
93  */
dupstr(char const * s)94 char *dupstr(char const *s) {
95     char *r = smalloc(1+strlen(s));
96     strcpy(r,s);
97     return r;
98 }
99 
100 /*
101  * Duplicate a linked list of words
102  */
dup_word_list(word * w)103 word *dup_word_list(word *w) {
104     word *head = NULL, **eptr = &head;
105 
106     while (w) {
107 	word *newwd = snew(word);
108 	*newwd = *w;		       /* structure copy */
109 	newwd->text = ustrdup(w->text);
110 	if (w->alt)
111 	    newwd->alt = dup_word_list(w->alt);
112 	*eptr = newwd;
113 	newwd->next = NULL;
114 	eptr = &newwd->next;
115 
116 	w = w->next;
117     }
118 
119     return head;
120 }
121 
122 /*
123  * Free a linked list of words
124  */
free_word_list(word * w)125 void free_word_list(word *w) {
126     word *t;
127     while (w) {
128 	t = w;
129 	w = w->next;
130 	sfree(t->text);
131 	if (t->alt)
132 	    free_word_list(t->alt);
133 	sfree(t);
134     }
135 }
136 
137 /*
138  * Free a linked list of paragraphs
139  */
free_para_list(paragraph * p)140 void free_para_list(paragraph *p) {
141     paragraph *t;
142     while (p) {
143 	t = p;
144 	p = p->next;
145 	sfree(t->keyword);
146 	free_word_list(t->words);
147 	sfree(t);
148     }
149 }
150