Home | History | Annotate | Line # | Download | only in dist
      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
     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 *
     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 *
     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 *
    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 *
    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
    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 *
    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 *
    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 *
    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 *
    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
    216 dostrfree(char *s)
    217 {
    218 	dofree(s, strlen(s)+1);
    219 }
    220 
    221 ////////////////////////////////////////////////////////////
    222 // other stuff
    223 
    224 size_t
    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
    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