1 /*-
2 * Copyright (c) 2010, 2013 The NetBSD Foundation, Inc.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to The NetBSD Foundation
6 * by David A. Holland.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include <stdlib.h>
31 #include <string.h>
32 #include <assert.h>
33
34 #include "utils.h"
35
36 #define MALLOCDEBUG
37
38 const char ws[] =
39 " \t\f\v"
40 ;
41 const char alnum[] =
42 "0123456789"
43 "abcdefghijklmnopqrstuvwxyz"
44 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
45 "_"
46 ;
47
48 ////////////////////////////////////////////////////////////
49 // malloc
50
51 #define ROUNDUP(len, size) ((size) * (((len) + (size) - 1) / (size)))
52
53 #ifdef MALLOCDEBUG
54
55 struct mallocheader {
56 struct mallocheader *self;
57 size_t len;
58 };
59
60 static
61 size_t
adjustsize(size_t len)62 adjustsize(size_t len)
63 {
64 const size_t sz = sizeof(struct mallocheader);
65 return ROUNDUP(len, sz) + 2*sz;
66 }
67
68 static
69 void *
placeheaders(void * block,size_t len)70 placeheaders(void *block, size_t len)
71 {
72 struct mallocheader *bothdr, *tophdr;
73 size_t roundedlen;
74 void *ret;
75
76 roundedlen = ROUNDUP(len, sizeof(struct mallocheader));
77 bothdr = block;
78 bothdr->len = len;
79 bothdr->self = block;
80 ret = bothdr + 1;
81 tophdr = (void *)(((unsigned char *)ret) + roundedlen);
82 tophdr->len = len;
83 tophdr->self = bothdr;
84 return ret;
85 }
86
87 static
88 void *
checkheaders(void * block,size_t len)89 checkheaders(void *block, size_t len)
90 {
91 struct mallocheader *bothdr, *tophdr;
92 size_t roundedlen;
93
94 if (block == NULL) {
95 assert(len == 0);
96 return block;
97 }
98
99 roundedlen = ROUNDUP(len, sizeof(struct mallocheader));
100 bothdr = block;
101 bothdr--;
102 assert(bothdr->self == bothdr);
103 assert(bothdr->len == len);
104 tophdr = (void *)(((unsigned char *)(bothdr + 1)) + roundedlen);
105 assert(tophdr->self == bothdr);
106 assert(tophdr->len == len);
107 return bothdr;
108 }
109
110 #else
111
112 #define adjustsize(len) (len)
113 #define placeheaders(block, len) ((void)(len), (block))
114 #define checkheaders(ptr, len) ((void)(len), (ptr))
115
116 #endif /* MALLOCDEBUG */
117
118 void *
domalloc(size_t len)119 domalloc(size_t len)
120 {
121 void *ret;
122 size_t blocklen;
123
124 blocklen = adjustsize(len);
125 ret = malloc(blocklen);
126 if (ret == NULL) {
127 complain(NULL, "Out of memory");
128 die();
129 }
130
131 return placeheaders(ret, len);
132 }
133
134 void *
dorealloc(void * ptr,size_t oldlen,size_t newlen)135 dorealloc(void *ptr, size_t oldlen, size_t newlen)
136 {
137 void *ret;
138 void *blockptr;
139 size_t newblocklen;
140
141 blockptr = checkheaders(ptr, oldlen);
142 newblocklen = adjustsize(newlen);
143
144 ret = realloc(blockptr, newblocklen);
145 if (ret == NULL) {
146 complain(NULL, "Out of memory");
147 die();
148 }
149
150 return placeheaders(ret, newlen);
151 }
152
153 void
dofree(void * ptr,size_t len)154 dofree(void *ptr, size_t len)
155 {
156 void *blockptr;
157
158 blockptr = checkheaders(ptr, len);
159 free(blockptr);
160 }
161
162 ////////////////////////////////////////////////////////////
163 // string allocators
164
165 char *
dostrdup(const char * s)166 dostrdup(const char *s)
167 {
168 char *ret;
169 size_t len;
170
171 len = strlen(s);
172 ret = domalloc(len+1);
173 strcpy(ret, s);
174 return ret;
175 }
176
177 char *
dostrdup2(const char * s,const char * t)178 dostrdup2(const char *s, const char *t)
179 {
180 char *ret;
181 size_t len;
182
183 len = strlen(s) + strlen(t);
184 ret = domalloc(len+1);
185 strcpy(ret, s);
186 strcat(ret, t);
187 return ret;
188 }
189
190 char *
dostrdup3(const char * s,const char * t,const char * u)191 dostrdup3(const char *s, const char *t, const char *u)
192 {
193 char *ret;
194 size_t len;
195
196 len = strlen(s) + strlen(t) + strlen(u);
197 ret = domalloc(len+1);
198 strcpy(ret, s);
199 strcat(ret, t);
200 strcat(ret, u);
201 return ret;
202 }
203
204 char *
dostrndup(const char * s,size_t len)205 dostrndup(const char *s, size_t len)
206 {
207 char *ret;
208
209 ret = domalloc(len+1);
210 memcpy(ret, s, len);
211 ret[len] = '\0';
212 return ret;
213 }
214
215 void
dostrfree(char * s)216 dostrfree(char *s)
217 {
218 dofree(s, strlen(s)+1);
219 }
220
221 ////////////////////////////////////////////////////////////
222 // other stuff
223
224 size_t
notrailingws(char * buf,size_t len)225 notrailingws(char *buf, size_t len)
226 {
227 while (len > 0 && strchr(ws, buf[len-1])) {
228 buf[--len] = '\0';
229 }
230 return len;
231 }
232
233 bool
is_identifier(const char * str)234 is_identifier(const char *str)
235 {
236 size_t len;
237
238 len = strlen(str);
239 if (len != strspn(str, alnum)) {
240 return false;
241 }
242 if (str[0] >= '0' && str[0] <= '9') {
243 return false;
244 }
245 return true;
246 }
247