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 <stdio.h> 33 #include <assert.h> 34 35 #include "utils.h" 36 37 #define MALLOCDEBUG 38 39 const char ws[] = 40 " \t\f\v" 41 ; 42 const char alnum[] = 43 "0123456789" 44 "abcdefghijklmnopqrstuvwxyz" 45 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 46 "_" 47 ; 48 49 //////////////////////////////////////////////////////////// 50 // malloc 51 52 #define ROUNDUP(len, size) ((size) * (((len) + (size) - 1) / (size))) 53 54 #ifdef MALLOCDEBUG 55 56 struct mallocheader { 57 struct mallocheader *self; 58 size_t len; 59 }; 60 61 static 62 size_t 63 adjustsize(size_t len) 64 { 65 const size_t sz = sizeof(struct mallocheader); 66 return ROUNDUP(len, sz) + 2*sz; 67 } 68 69 static 70 void * 71 placeheaders(void *block, size_t len) 72 { 73 struct mallocheader *bothdr, *tophdr; 74 size_t roundedlen; 75 void *ret; 76 77 roundedlen = ROUNDUP(len, sizeof(struct mallocheader)); 78 bothdr = block; 79 bothdr->len = len; 80 bothdr->self = block; 81 ret = bothdr + 1; 82 tophdr = (void *)(((unsigned char *)ret) + roundedlen); 83 tophdr->len = len; 84 tophdr->self = bothdr; 85 return ret; 86 } 87 88 static 89 void * 90 checkheaders(void *block, size_t len) 91 { 92 struct mallocheader *bothdr, *tophdr; 93 size_t roundedlen; 94 95 if (block == NULL) { 96 assert(len == 0); 97 return block; 98 } 99 100 roundedlen = ROUNDUP(len, sizeof(struct mallocheader)); 101 bothdr = block; 102 bothdr--; 103 assert(bothdr->self == bothdr); 104 assert(bothdr->len == len); 105 tophdr = (void *)(((unsigned char *)(bothdr + 1)) + roundedlen); 106 assert(tophdr->self == bothdr); 107 assert(tophdr->len == len); 108 return bothdr; 109 } 110 111 #else 112 113 #define adjustsize(len) (len) 114 #define placeheaders(block, len) ((void)(len), (block)) 115 #define checkheaders(ptr, len) ((void)(len), (ptr)) 116 117 #endif /* MALLOCDEBUG */ 118 119 void * 120 domalloc(size_t len) 121 { 122 void *ret; 123 size_t blocklen; 124 125 blocklen = adjustsize(len); 126 ret = malloc(blocklen); 127 if (ret == NULL) { 128 complain(NULL, "Out of memory"); 129 die(); 130 } 131 132 return placeheaders(ret, len); 133 } 134 135 void * 136 dorealloc(void *ptr, size_t oldlen, size_t newlen) 137 { 138 void *ret; 139 void *blockptr; 140 size_t newblocklen; 141 142 blockptr = checkheaders(ptr, oldlen); 143 newblocklen = adjustsize(newlen); 144 145 ret = realloc(blockptr, newblocklen); 146 if (ret == NULL) { 147 complain(NULL, "Out of memory"); 148 die(); 149 } 150 151 return placeheaders(ret, newlen); 152 } 153 154 void 155 dofree(void *ptr, size_t len) 156 { 157 void *blockptr; 158 159 blockptr = checkheaders(ptr, len); 160 free(blockptr); 161 } 162 163 //////////////////////////////////////////////////////////// 164 // string allocators 165 166 char * 167 dostrdup(const char *s) 168 { 169 char *ret; 170 size_t len; 171 172 len = strlen(s); 173 ret = domalloc(len+1); 174 strlcpy(ret, s, len+1); 175 return ret; 176 } 177 178 char * 179 dostrdup2(const char *s, const char *t) 180 { 181 char *ret; 182 size_t len; 183 184 len = strlen(s) + strlen(t); 185 ret = domalloc(len+1); 186 snprintf(ret, len+1, "%s%s", s, t); 187 return ret; 188 } 189 190 char * 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 snprintf(ret, len+1, "%s%s%s", s, t, u); 199 return ret; 200 } 201 202 char * 203 dostrndup(const char *s, size_t len) 204 { 205 char *ret; 206 207 ret = domalloc(len+1); 208 memcpy(ret, s, len); 209 ret[len] = '\0'; 210 return ret; 211 } 212 213 void 214 dostrfree(char *s) 215 { 216 dofree(s, strlen(s)+1); 217 } 218 219 //////////////////////////////////////////////////////////// 220 // other stuff 221 222 size_t 223 notrailingws(char *buf, size_t len) 224 { 225 while (len > 0 && strchr(ws, buf[len-1])) { 226 buf[--len] = '\0'; 227 } 228 return len; 229 } 230 231 bool 232 is_identifier(const char *str) 233 { 234 size_t len; 235 236 len = strlen(str); 237 if (len != strspn(str, alnum)) { 238 return false; 239 } 240 if (str[0] >= '0' && str[0] <= '9') { 241 return false; 242 } 243 return true; 244 } 245