xref: /openbsd-src/libexec/tradcpp/utils.c (revision 2fbb987bd63ae720fed1fbf320a3ed9498a8fe65)
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