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
38const char ws[] =
39	" \t\f\v"
40;
41const 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
55struct mallocheader {
56	struct mallocheader *self;
57	size_t len;
58};
59
60static
61size_t
62adjustsize(size_t len)
63{
64	const size_t sz = sizeof(struct mallocheader);
65	return ROUNDUP(len, sz) + 2*sz;
66}
67
68static
69void *
70placeheaders(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
87static
88void *
89checkheaders(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
118void *
119domalloc(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
134void *
135dorealloc(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
153void
154dofree(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
165char *
166dostrdup(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
177char *
178dostrdup2(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
190char *
191dostrdup3(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
204char *
205dostrndup(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
215void
216dostrfree(char *s)
217{
218	dofree(s, strlen(s)+1);
219}
220
221////////////////////////////////////////////////////////////
222// other stuff
223
224size_t
225notrailingws(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
233bool
234is_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