d7482997 |
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' */ |
13 | static void loginc(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 | } |
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 | fatal(err_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 | fatal(err_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 | */ |
8333e399 |
94 | char *dupstr(char const *s) { |
d7482997 |
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 | */ |
103 | word *dup_word_list(word *w) { |
8ff28c12 |
104 | word *head = NULL, **eptr = &head; |
d7482997 |
105 | |
106 | while (w) { |
f1530049 |
107 | word *newwd = snew(word); |
d7482997 |
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 | */ |
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 | */ |
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 | } |