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