1241823Smarcel/*- 2241823Smarcel * Copyright (c) 1993, 1994 3241823Smarcel * The Regents of the University of California. All rights reserved. 4241823Smarcel * Copyright (c) 1993, 1994, 1995, 1996 5241823Smarcel * Keith Bostic. All rights reserved. 6241823Smarcel * 7241823Smarcel * See the LICENSE file for redistribution information. 8241823Smarcel * 9241823Smarcel * $Id: mem.h,v 10.17 2012/10/07 00:40:29 zy Exp $ 10241823Smarcel */ 11241823Smarcel 12241823Smarcel#ifdef DEBUG 13241823Smarcel#define CHECK_TYPE(type, var) \ 14241823Smarcel type L__lp __attribute__((unused)) = var; 15241823Smarcel#else 16241823Smarcel#define CHECK_TYPE(type, var) 17241823Smarcel#endif 18241823Smarcel 19241823Smarcel/* Increase the size of a malloc'd buffer. Two versions, one that 20241823Smarcel * returns, one that jumps to an error label. 21241823Smarcel */ 22241823Smarcel#define BINC_GOTO(sp, type, lp, llen, nlen) { \ 23241823Smarcel CHECK_TYPE(type *, lp) \ 24241823Smarcel void *L__bincp; \ 25241823Smarcel if ((nlen) > llen) { \ 26241823Smarcel if ((L__bincp = binc(sp, lp, &(llen), nlen)) == NULL) \ 27241823Smarcel goto alloc_err; \ 28241823Smarcel /* \ 29241823Smarcel * !!! \ 30241823Smarcel * Possible pointer conversion. \ 31270905Sngie */ \ 32270905Sngie lp = L__bincp; \ 33241823Smarcel } \ 34241823Smarcel} 35270286Sngie#define BINC_GOTOC(sp, lp, llen, nlen) \ 36242684Smarcel BINC_GOTO(sp, char, lp, llen, nlen) 37241823Smarcel#define BINC_GOTOW(sp, lp, llen, nlen) \ 38242684Smarcel BINC_GOTO(sp, CHAR_T, lp, llen, (nlen) * sizeof(CHAR_T)) 39242684Smarcel#define BINC_RET(sp, type, lp, llen, nlen) { \ 40260024Sjmmv CHECK_TYPE(type *, lp) \ 41241823Smarcel void *L__bincp; \ 42241823Smarcel if ((nlen) > llen) { \ 43241823Smarcel if ((L__bincp = binc(sp, lp, &(llen), nlen)) == NULL) \ 44241823Smarcel return (1); \ 45241823Smarcel /* \ 46241823Smarcel * !!! \ 47241823Smarcel * Possible pointer conversion. \ 48241823Smarcel */ \ 49241823Smarcel lp = L__bincp; \ 50241823Smarcel } \ 51241823Smarcel} 52241823Smarcel#define BINC_RETC(sp, lp, llen, nlen) \ 53241823Smarcel BINC_RET(sp, char, lp, llen, nlen) 54241823Smarcel#define BINC_RETW(sp, lp, llen, nlen) \ 55241823Smarcel BINC_RET(sp, CHAR_T, lp, llen, (nlen) * sizeof(CHAR_T)) 56241823Smarcel 57241823Smarcel/* 58241823Smarcel * Get some temporary space, preferably from the global temporary buffer, 59241823Smarcel * from a malloc'd buffer otherwise. Two versions, one that returns, one 60241823Smarcel * that jumps to an error label. 61260029Sjmmv */ 62241823Smarcel#define GET_SPACE_GOTO(sp, type, bp, blen, nlen) { \ 63241823Smarcel CHECK_TYPE(type *, bp) \ 64241823Smarcel GS *L__gp = (sp) == NULL ? NULL : (sp)->gp; \ 65241823Smarcel if (L__gp == NULL || F_ISSET(L__gp, G_TMP_INUSE)) { \ 66241823Smarcel bp = NULL; \ 67241823Smarcel blen = 0; \ 68241823Smarcel BINC_GOTO(sp, type, bp, blen, nlen); \ 69241823Smarcel } else { \ 70241823Smarcel BINC_GOTOC(sp, L__gp->tmp_bp, L__gp->tmp_blen, nlen); \ 71241823Smarcel bp = (type *) L__gp->tmp_bp; \ 72241823Smarcel blen = L__gp->tmp_blen; \ 73241823Smarcel F_SET(L__gp, G_TMP_INUSE); \ 74241823Smarcel } \ 75241823Smarcel} 76260024Sjmmv#define GET_SPACE_GOTOC(sp, bp, blen, nlen) \ 77260024Sjmmv GET_SPACE_GOTO(sp, char, bp, blen, nlen) 78260024Sjmmv#define GET_SPACE_GOTOW(sp, bp, blen, nlen) \ 79260024Sjmmv GET_SPACE_GOTO(sp, CHAR_T, bp, blen, (nlen) * sizeof(CHAR_T)) 80262849Sjmmv#define GET_SPACE_RET(sp, type, bp, blen, nlen) { \ 81241823Smarcel CHECK_TYPE(type *, bp) \ 82 GS *L__gp = (sp) == NULL ? NULL : (sp)->gp; \ 83 if (L__gp == NULL || F_ISSET(L__gp, G_TMP_INUSE)) { \ 84 bp = NULL; \ 85 blen = 0; \ 86 BINC_RET(sp, type, bp, blen, nlen); \ 87 } else { \ 88 BINC_RETC(sp, L__gp->tmp_bp, L__gp->tmp_blen, nlen); \ 89 bp = (type *) L__gp->tmp_bp; \ 90 blen = L__gp->tmp_blen; \ 91 F_SET(L__gp, G_TMP_INUSE); \ 92 } \ 93} 94#define GET_SPACE_RETC(sp, bp, blen, nlen) \ 95 GET_SPACE_RET(sp, char, bp, blen, nlen) 96#define GET_SPACE_RETW(sp, bp, blen, nlen) \ 97 GET_SPACE_RET(sp, CHAR_T, bp, blen, (nlen) * sizeof(CHAR_T)) 98 99/* 100 * Add space to a GET_SPACE returned buffer. Two versions, one that 101 * returns, one that jumps to an error label. 102 */ 103#define ADD_SPACE_GOTO(sp, type, bp, blen, nlen) { \ 104 CHECK_TYPE(type *, bp) \ 105 GS *L__gp = (sp) == NULL ? NULL : (sp)->gp; \ 106 if (L__gp == NULL || bp == (type *)L__gp->tmp_bp) { \ 107 F_CLR(L__gp, G_TMP_INUSE); \ 108 BINC_GOTOC(sp, L__gp->tmp_bp, L__gp->tmp_blen, nlen); \ 109 bp = (type *) L__gp->tmp_bp; \ 110 blen = L__gp->tmp_blen; \ 111 F_SET(L__gp, G_TMP_INUSE); \ 112 } else \ 113 BINC_GOTO(sp, type, bp, blen, nlen); \ 114} 115#define ADD_SPACE_GOTOC(sp, bp, blen, nlen) \ 116 ADD_SPACE_GOTO(sp, char, bp, blen, nlen) 117#define ADD_SPACE_GOTOW(sp, bp, blen, nlen) \ 118 ADD_SPACE_GOTO(sp, CHAR_T, bp, blen, (nlen) * sizeof(CHAR_T)) 119#define ADD_SPACE_RET(sp, type, bp, blen, nlen) { \ 120 CHECK_TYPE(type *, bp) \ 121 GS *L__gp = (sp) == NULL ? NULL : (sp)->gp; \ 122 if (L__gp == NULL || bp == (type *)L__gp->tmp_bp) { \ 123 F_CLR(L__gp, G_TMP_INUSE); \ 124 BINC_RETC(sp, L__gp->tmp_bp, L__gp->tmp_blen, nlen); \ 125 bp = (type *) L__gp->tmp_bp; \ 126 blen = L__gp->tmp_blen; \ 127 F_SET(L__gp, G_TMP_INUSE); \ 128 } else \ 129 BINC_RET(sp, type, bp, blen, nlen); \ 130} 131#define ADD_SPACE_RETC(sp, bp, blen, nlen) \ 132 ADD_SPACE_RET(sp, char, bp, blen, nlen) 133#define ADD_SPACE_RETW(sp, bp, blen, nlen) \ 134 ADD_SPACE_RET(sp, CHAR_T, bp, blen, (nlen) * sizeof(CHAR_T)) 135 136/* Free a GET_SPACE returned buffer. */ 137#define FREE_SPACE(sp, bp, blen) { \ 138 GS *L__gp = (sp) == NULL ? NULL : (sp)->gp; \ 139 if (L__gp != NULL && bp == L__gp->tmp_bp) \ 140 F_CLR(L__gp, G_TMP_INUSE); \ 141 else \ 142 free(bp); \ 143} 144#define FREE_SPACEW(sp, bp, blen) { \ 145 CHECK_TYPE(CHAR_T *, bp) \ 146 FREE_SPACE(sp, (char *)bp, blen); \ 147} 148 149/* 150 * Malloc a buffer, casting the return pointer. Various versions. 151 * 152 * !!! 153 * The cast should be unnecessary, malloc(3) and friends return void *'s, 154 * which is all we need. However, some systems that nvi needs to run on 155 * don't do it right yet, resulting in the compiler printing out roughly 156 * a million warnings. After awhile, it seemed easier to put the casts 157 * in instead of explaining it all the time. 158 */ 159#define CALLOC(sp, p, cast, nmemb, size) { \ 160 if ((p = (cast)calloc(nmemb, size)) == NULL) \ 161 msgq(sp, M_SYSERR, NULL); \ 162} 163#define CALLOC_GOTO(sp, p, cast, nmemb, size) { \ 164 if ((p = (cast)calloc(nmemb, size)) == NULL) \ 165 goto alloc_err; \ 166} 167#define CALLOC_NOMSG(sp, p, cast, nmemb, size) { \ 168 p = (cast)calloc(nmemb, size); \ 169} 170#define CALLOC_RET(sp, p, cast, nmemb, size) { \ 171 if ((p = (cast)calloc(nmemb, size)) == NULL) { \ 172 msgq(sp, M_SYSERR, NULL); \ 173 return (1); \ 174 } \ 175} 176 177#define MALLOC(sp, p, cast, size) { \ 178 if ((p = (cast)malloc(size)) == NULL) \ 179 msgq(sp, M_SYSERR, NULL); \ 180} 181#define MALLOC_GOTO(sp, p, cast, size) { \ 182 if ((p = (cast)malloc(size)) == NULL) \ 183 goto alloc_err; \ 184} 185#define MALLOC_NOMSG(sp, p, cast, size) { \ 186 p = (cast)malloc(size); \ 187} 188#define MALLOC_RET(sp, p, cast, size) { \ 189 if ((p = (cast)malloc(size)) == NULL) { \ 190 msgq(sp, M_SYSERR, NULL); \ 191 return (1); \ 192 } \ 193} 194 195/* 196 * Resize a buffer, free any already held memory if we can't get more. 197 * FreeBSD's reallocf(3) does the same thing, but it's not portable yet. 198 */ 199#define REALLOC(sp, p, cast, size) { \ 200 cast newp; \ 201 if ((newp = (cast)realloc(p, size)) == NULL) { \ 202 if (p != NULL) \ 203 free(p); \ 204 msgq(sp, M_SYSERR, NULL); \ 205 } \ 206 p = newp; \ 207} 208 209/* 210 * Versions of bcopy(3) and bzero(3) that use the size of the 211 * initial pointer to figure out how much memory to manipulate. 212 */ 213#define BCOPY(p, t, len) bcopy(p, t, (len) * sizeof(*(p))) 214#define BZERO(p, len) bzero(p, (len) * sizeof(*(p))) 215 216/* 217 * p2roundup -- 218 * Get next power of 2; convenient for realloc. 219 * 220 * Reference: FreeBSD /usr/src/lib/libc/stdio/getdelim.c 221 */ 222static __inline size_t 223p2roundup(size_t n) 224{ 225 n--; 226 n |= n >> 1; 227 n |= n >> 2; 228 n |= n >> 4; 229 n |= n >> 8; 230 n |= n >> 16; 231#if SIZE_T_MAX > 0xffffffffU 232 n |= n >> 32; 233#endif 234 n++; 235 return (n); 236} 237 238/* Additional TAILQ helper. */ 239#define TAILQ_ENTRY_ISVALID(elm, field) \ 240 ((elm)->field.tqe_prev != NULL) 241