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