xref: /netbsd-src/external/bsd/tradcpp/dist/utils.c (revision 31615c9617fab4df7f5e221552df7da87f14320d)
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