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