xref: /freebsd/contrib/nvi/common/mem.h (revision b8ba871b)
1b8ba871bSPeter Wemm /*-
2b8ba871bSPeter Wemm  * Copyright (c) 1993, 1994
3b8ba871bSPeter Wemm  *	The Regents of the University of California.  All rights reserved.
4b8ba871bSPeter Wemm  * Copyright (c) 1993, 1994, 1995, 1996
5b8ba871bSPeter Wemm  *	Keith Bostic.  All rights reserved.
6b8ba871bSPeter Wemm  *
7b8ba871bSPeter Wemm  * See the LICENSE file for redistribution information.
8b8ba871bSPeter Wemm  */
9b8ba871bSPeter Wemm 
10b8ba871bSPeter Wemm #ifdef DEBUG
11b8ba871bSPeter Wemm #define CHECK_TYPE(type, var)						\
12b8ba871bSPeter Wemm 	type L__lp __attribute__((unused)) = var;
13b8ba871bSPeter Wemm #else
14b8ba871bSPeter Wemm #define CHECK_TYPE(type, var)
15b8ba871bSPeter Wemm #endif
16b8ba871bSPeter Wemm 
17b8ba871bSPeter Wemm /* Increase the size of a malloc'd buffer.  Two versions, one that
18b8ba871bSPeter Wemm  * returns, one that jumps to an error label.
19b8ba871bSPeter Wemm  */
20b8ba871bSPeter Wemm #define	BINC_GOTO(sp, type, lp, llen, nlen) do {			\
21b8ba871bSPeter Wemm 	CHECK_TYPE(type *, lp)						\
22b8ba871bSPeter Wemm 	void *L__bincp;							\
23b8ba871bSPeter Wemm 	if ((nlen) > llen) {						\
24b8ba871bSPeter Wemm 		if ((L__bincp = binc(sp, lp, &(llen), nlen)) == NULL)	\
25b8ba871bSPeter Wemm 			goto alloc_err;					\
26b8ba871bSPeter Wemm 		/*							\
27b8ba871bSPeter Wemm 		 * !!!							\
28b8ba871bSPeter Wemm 		 * Possible pointer conversion.				\
29b8ba871bSPeter Wemm 		 */							\
30b8ba871bSPeter Wemm 		lp = L__bincp;						\
31b8ba871bSPeter Wemm 	}								\
32b8ba871bSPeter Wemm } while (0)
33b8ba871bSPeter Wemm #define	BINC_GOTOC(sp, lp, llen, nlen)					\
34b8ba871bSPeter Wemm 	BINC_GOTO(sp, char, lp, llen, nlen)
35b8ba871bSPeter Wemm #define	BINC_GOTOW(sp, lp, llen, nlen)					\
36b8ba871bSPeter Wemm 	BINC_GOTO(sp, CHAR_T, lp, llen, (nlen) * sizeof(CHAR_T))
37b8ba871bSPeter Wemm #define	BINC_RET(sp, type, lp, llen, nlen) do {				\
38b8ba871bSPeter Wemm 	CHECK_TYPE(type *, lp)						\
39b8ba871bSPeter Wemm 	void *L__bincp;							\
40b8ba871bSPeter Wemm 	if ((nlen) > llen) {						\
41b8ba871bSPeter Wemm 		if ((L__bincp = binc(sp, lp, &(llen), nlen)) == NULL)	\
42b8ba871bSPeter Wemm 			return (1);					\
43b8ba871bSPeter Wemm 		/*							\
44b8ba871bSPeter Wemm 		 * !!!							\
45b8ba871bSPeter Wemm 		 * Possible pointer conversion.				\
46b8ba871bSPeter Wemm 		 */							\
47b8ba871bSPeter Wemm 		lp = L__bincp;						\
48b8ba871bSPeter Wemm 	}								\
49b8ba871bSPeter Wemm } while (0)
50b8ba871bSPeter Wemm #define	BINC_RETC(sp, lp, llen, nlen)					\
51b8ba871bSPeter Wemm 	BINC_RET(sp, char, lp, llen, nlen)
52b8ba871bSPeter Wemm #define	BINC_RETW(sp, lp, llen, nlen)					\
53b8ba871bSPeter Wemm 	BINC_RET(sp, CHAR_T, lp, llen, (nlen) * sizeof(CHAR_T))
54b8ba871bSPeter Wemm 
55b8ba871bSPeter Wemm /*
56b8ba871bSPeter Wemm  * Get some temporary space, preferably from the global temporary buffer,
57b8ba871bSPeter Wemm  * from a malloc'd buffer otherwise.  Two versions, one that returns, one
58b8ba871bSPeter Wemm  * that jumps to an error label.
59b8ba871bSPeter Wemm  */
60b8ba871bSPeter Wemm #define	GET_SPACE_GOTO(sp, type, bp, blen, nlen) do {			\
61b8ba871bSPeter Wemm 	CHECK_TYPE(type *, bp)						\
62b8ba871bSPeter Wemm 	GS *L__gp = (sp) == NULL ? NULL : (sp)->gp;			\
63b8ba871bSPeter Wemm 	if (L__gp == NULL || F_ISSET(L__gp, G_TMP_INUSE)) {		\
64b8ba871bSPeter Wemm 		bp = NULL;						\
65b8ba871bSPeter Wemm 		blen = 0;						\
66b8ba871bSPeter Wemm 		BINC_GOTO(sp, type, bp, blen, nlen); 			\
67b8ba871bSPeter Wemm 	} else {							\
68b8ba871bSPeter Wemm 		BINC_GOTOC(sp, L__gp->tmp_bp, L__gp->tmp_blen, nlen);	\
69b8ba871bSPeter Wemm 		bp = (type *) L__gp->tmp_bp;				\
70b8ba871bSPeter Wemm 		blen = L__gp->tmp_blen;					\
71b8ba871bSPeter Wemm 		F_SET(L__gp, G_TMP_INUSE);				\
72b8ba871bSPeter Wemm 	}								\
73b8ba871bSPeter Wemm } while (0)
74b8ba871bSPeter Wemm #define	GET_SPACE_GOTOC(sp, bp, blen, nlen)				\
75b8ba871bSPeter Wemm 	GET_SPACE_GOTO(sp, char, bp, blen, nlen)
76b8ba871bSPeter Wemm #define	GET_SPACE_GOTOW(sp, bp, blen, nlen)				\
77b8ba871bSPeter Wemm 	GET_SPACE_GOTO(sp, CHAR_T, bp, blen, (nlen) * sizeof(CHAR_T))
78b8ba871bSPeter Wemm #define	GET_SPACE_RET(sp, type, bp, blen, nlen) do {			\
79b8ba871bSPeter Wemm 	CHECK_TYPE(type *, bp)						\
80b8ba871bSPeter Wemm 	GS *L__gp = (sp) == NULL ? NULL : (sp)->gp;			\
81b8ba871bSPeter Wemm 	if (L__gp == NULL || F_ISSET(L__gp, G_TMP_INUSE)) {		\
82b8ba871bSPeter Wemm 		bp = NULL;						\
83b8ba871bSPeter Wemm 		blen = 0;						\
84b8ba871bSPeter Wemm 		BINC_RET(sp, type, bp, blen, nlen);			\
85b8ba871bSPeter Wemm 	} else {							\
86b8ba871bSPeter Wemm 		BINC_RETC(sp, L__gp->tmp_bp, L__gp->tmp_blen, nlen);	\
87b8ba871bSPeter Wemm 		bp = (type *) L__gp->tmp_bp;				\
88b8ba871bSPeter Wemm 		blen = L__gp->tmp_blen;					\
89b8ba871bSPeter Wemm 		F_SET(L__gp, G_TMP_INUSE);				\
90b8ba871bSPeter Wemm 	}								\
91b8ba871bSPeter Wemm } while (0)
92b8ba871bSPeter Wemm #define	GET_SPACE_RETC(sp, bp, blen, nlen)				\
93b8ba871bSPeter Wemm 	GET_SPACE_RET(sp, char, bp, blen, nlen)
94b8ba871bSPeter Wemm #define	GET_SPACE_RETW(sp, bp, blen, nlen)				\
95b8ba871bSPeter Wemm 	GET_SPACE_RET(sp, CHAR_T, bp, blen, (nlen) * sizeof(CHAR_T))
96b8ba871bSPeter Wemm 
97b8ba871bSPeter Wemm /*
98b8ba871bSPeter Wemm  * Add space to a GET_SPACE returned buffer.  Two versions, one that
99b8ba871bSPeter Wemm  * returns, one that jumps to an error label.
100b8ba871bSPeter Wemm  */
101b8ba871bSPeter Wemm #define	ADD_SPACE_GOTO(sp, type, bp, blen, nlen) do {			\
102b8ba871bSPeter Wemm 	CHECK_TYPE(type *, bp)						\
103b8ba871bSPeter Wemm 	GS *L__gp = (sp) == NULL ? NULL : (sp)->gp;			\
104b8ba871bSPeter Wemm 	if (L__gp == NULL || bp == (type *)L__gp->tmp_bp) {		\
105b8ba871bSPeter Wemm 		F_CLR(L__gp, G_TMP_INUSE);				\
106b8ba871bSPeter Wemm 		BINC_GOTOC(sp, L__gp->tmp_bp, L__gp->tmp_blen, nlen);	\
107b8ba871bSPeter Wemm 		bp = (type *) L__gp->tmp_bp;				\
108b8ba871bSPeter Wemm 		blen = L__gp->tmp_blen;					\
109b8ba871bSPeter Wemm 		F_SET(L__gp, G_TMP_INUSE);				\
110b8ba871bSPeter Wemm 	} else								\
111b8ba871bSPeter Wemm 		BINC_GOTO(sp, type, bp, blen, nlen);			\
112b8ba871bSPeter Wemm } while (0)
113b8ba871bSPeter Wemm #define	ADD_SPACE_GOTOC(sp, bp, blen, nlen)				\
114b8ba871bSPeter Wemm 	ADD_SPACE_GOTO(sp, char, bp, blen, nlen)
115b8ba871bSPeter Wemm #define	ADD_SPACE_GOTOW(sp, bp, blen, nlen)				\
116b8ba871bSPeter Wemm 	ADD_SPACE_GOTO(sp, CHAR_T, bp, blen, (nlen) * sizeof(CHAR_T))
117b8ba871bSPeter Wemm #define	ADD_SPACE_RET(sp, type, bp, blen, nlen) do {			\
118b8ba871bSPeter Wemm 	CHECK_TYPE(type *, bp)						\
119b8ba871bSPeter Wemm 	GS *L__gp = (sp) == NULL ? NULL : (sp)->gp;			\
120b8ba871bSPeter Wemm 	if (L__gp == NULL || bp == (type *)L__gp->tmp_bp) {		\
121b8ba871bSPeter Wemm 		F_CLR(L__gp, G_TMP_INUSE);				\
122b8ba871bSPeter Wemm 		BINC_RETC(sp, L__gp->tmp_bp, L__gp->tmp_blen, nlen);	\
123b8ba871bSPeter Wemm 		bp = (type *) L__gp->tmp_bp;				\
124b8ba871bSPeter Wemm 		blen = L__gp->tmp_blen;					\
125b8ba871bSPeter Wemm 		F_SET(L__gp, G_TMP_INUSE);				\
126b8ba871bSPeter Wemm 	} else								\
127b8ba871bSPeter Wemm 		BINC_RET(sp, type, bp, blen, nlen);			\
128b8ba871bSPeter Wemm } while (0)
129b8ba871bSPeter Wemm #define	ADD_SPACE_RETC(sp, bp, blen, nlen)				\
130b8ba871bSPeter Wemm 	ADD_SPACE_RET(sp, char, bp, blen, nlen)
131b8ba871bSPeter Wemm #define	ADD_SPACE_RETW(sp, bp, blen, nlen)				\
132b8ba871bSPeter Wemm 	ADD_SPACE_RET(sp, CHAR_T, bp, blen, (nlen) * sizeof(CHAR_T))
133b8ba871bSPeter Wemm 
134b8ba871bSPeter Wemm /* Free a GET_SPACE returned buffer. */
135b8ba871bSPeter Wemm #define	FREE_SPACE(sp, bp, blen) do {					\
136b8ba871bSPeter Wemm 	GS *L__gp = (sp) == NULL ? NULL : (sp)->gp;			\
137b8ba871bSPeter Wemm 	if (L__gp != NULL && bp == L__gp->tmp_bp)			\
138b8ba871bSPeter Wemm 		F_CLR(L__gp, G_TMP_INUSE);				\
139b8ba871bSPeter Wemm 	else								\
140b8ba871bSPeter Wemm 		free(bp);						\
141b8ba871bSPeter Wemm } while (0)
142b8ba871bSPeter Wemm #define	FREE_SPACEW(sp, bp, blen) do {					\
143b8ba871bSPeter Wemm 	CHECK_TYPE(CHAR_T *, bp)					\
144b8ba871bSPeter Wemm 	FREE_SPACE(sp, (char *)bp, blen);				\
145b8ba871bSPeter Wemm } while (0)
146b8ba871bSPeter Wemm 
147b8ba871bSPeter Wemm /*
148b8ba871bSPeter Wemm  * Malloc a buffer, casting the return pointer.  Various versions.
149b8ba871bSPeter Wemm  */
150b8ba871bSPeter Wemm #define	CALLOC(sp, p, nmemb, size) do {					\
151b8ba871bSPeter Wemm 	if ((p = calloc(nmemb, size)) == NULL)				\
152b8ba871bSPeter Wemm 		msgq(sp, M_SYSERR, NULL);				\
153b8ba871bSPeter Wemm } while (0)
154b8ba871bSPeter Wemm #define	CALLOC_GOTO(sp, p, nmemb, size) do {				\
155b8ba871bSPeter Wemm 	if ((p = calloc(nmemb, size)) == NULL)				\
156b8ba871bSPeter Wemm 		goto alloc_err;						\
157b8ba871bSPeter Wemm } while (0)
158b8ba871bSPeter Wemm #define	CALLOC_RET(sp, p, nmemb, size) do {				\
159b8ba871bSPeter Wemm 	if ((p = calloc(nmemb, size)) == NULL) {			\
160b8ba871bSPeter Wemm 		msgq(sp, M_SYSERR, NULL);				\
161b8ba871bSPeter Wemm 		return (1);						\
162b8ba871bSPeter Wemm 	}								\
163b8ba871bSPeter Wemm } while (0)
164b8ba871bSPeter Wemm 
165b8ba871bSPeter Wemm #define	MALLOC(sp, p, size) do {					\
166b8ba871bSPeter Wemm 	if ((p = malloc(size)) == NULL)					\
167b8ba871bSPeter Wemm 		msgq(sp, M_SYSERR, NULL);				\
168b8ba871bSPeter Wemm } while (0)
169 #define	MALLOC_GOTO(sp, p, size) do {					\
170 	if ((p = malloc(size)) == NULL)					\
171 		goto alloc_err;						\
172 } while (0)
173 #define	MALLOC_RET(sp, p, size) do {					\
174 	if ((p = malloc(size)) == NULL) {				\
175 		msgq(sp, M_SYSERR, NULL);				\
176 		return (1);						\
177 	}								\
178 } while (0)
179 
180 /*
181  * Resize a buffer, free any already held memory if we can't get more.
182  * FreeBSD's reallocf(3) does the same thing, but it's not portable yet.
183  */
184 #define	REALLOC(sp, p, cast, size) do {					\
185 	cast newp;							\
186 	if ((newp = realloc(p, size)) == NULL) {			\
187 		free(p);						\
188 		msgq(sp, M_SYSERR, NULL);				\
189 	}								\
190 	p = newp;							\
191 } while (0)
192 
193 /*
194  * p2roundup --
195  *	Get next power of 2; convenient for realloc.
196  *
197  * Reference: FreeBSD /usr/src/lib/libc/stdio/getdelim.c
198  */
199 static __inline size_t
p2roundup(size_t n)200 p2roundup(size_t n)
201 {
202 	n--;
203 	n |= n >> 1;
204 	n |= n >> 2;
205 	n |= n >> 4;
206 	n |= n >> 8;
207 	n |= n >> 16;
208 #if SIZE_T_MAX > 0xffffffffU
209 	n |= n >> 32;
210 #endif
211 	n++;
212 	return (n);
213 }
214 
215 /* Additional TAILQ helper. */
216 #define TAILQ_ENTRY_ISVALID(elm, field)					\
217 	((elm)->field.tqe_prev != NULL)
218