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 39const char ws[] = 40 " \t\f\v" 41; 42const 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 56struct mallocheader { 57 struct mallocheader *self; 58 size_t len; 59}; 60 61static 62size_t 63adjustsize(size_t len) 64{ 65 const size_t sz = sizeof(struct mallocheader); 66 return ROUNDUP(len, sz) + 2*sz; 67} 68 69static 70void * 71placeheaders(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 88static 89void * 90checkheaders(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 119void * 120domalloc(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 135void * 136dorealloc(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 154void 155dofree(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 166char * 167dostrdup(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 178char * 179dostrdup2(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 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 snprintf(ret, len+1, "%s%s%s", s, t, u); 199 return ret; 200} 201 202char * 203dostrndup(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 213void 214dostrfree(char *s) 215{ 216 dofree(s, strlen(s)+1); 217} 218 219//////////////////////////////////////////////////////////// 220// other stuff 221 222size_t 223notrailingws(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 231bool 232is_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