]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/nvi/common/mem.h
Update nvi to 2.2.0
[FreeBSD/FreeBSD.git] / contrib / nvi / common / mem.h
1 /*-
2  * Copyright (c) 1993, 1994
3  *      The Regents of the University of California.  All rights reserved.
4  * Copyright (c) 1993, 1994, 1995, 1996
5  *      Keith Bostic.  All rights reserved.
6  *
7  * See the LICENSE file for redistribution information.
8  */
9
10 #ifdef DEBUG
11 #define CHECK_TYPE(type, var)                                           \
12         type L__lp __attribute__((unused)) = var;
13 #else
14 #define CHECK_TYPE(type, var)
15 #endif
16
17 /* Increase the size of a malloc'd buffer.  Two versions, one that
18  * returns, one that jumps to an error label.
19  */
20 #define BINC_GOTO(sp, type, lp, llen, nlen) {                           \
21         CHECK_TYPE(type *, lp)                                          \
22         void *L__bincp;                                                 \
23         if ((nlen) > llen) {                                            \
24                 if ((L__bincp = binc(sp, lp, &(llen), nlen)) == NULL)   \
25                         goto alloc_err;                                 \
26                 /*                                                      \
27                  * !!!                                                  \
28                  * Possible pointer conversion.                         \
29                  */                                                     \
30                 lp = L__bincp;                                          \
31         }                                                               \
32 }
33 #define BINC_GOTOC(sp, lp, llen, nlen)                                  \
34         BINC_GOTO(sp, char, lp, llen, nlen)
35 #define BINC_GOTOW(sp, lp, llen, nlen)                                  \
36         BINC_GOTO(sp, CHAR_T, lp, llen, (nlen) * sizeof(CHAR_T))
37 #define BINC_RET(sp, type, lp, llen, nlen) {                            \
38         CHECK_TYPE(type *, lp)                                          \
39         void *L__bincp;                                                 \
40         if ((nlen) > llen) {                                            \
41                 if ((L__bincp = binc(sp, lp, &(llen), nlen)) == NULL)   \
42                         return (1);                                     \
43                 /*                                                      \
44                  * !!!                                                  \
45                  * Possible pointer conversion.                         \
46                  */                                                     \
47                 lp = L__bincp;                                          \
48         }                                                               \
49 }
50 #define BINC_RETC(sp, lp, llen, nlen)                                   \
51         BINC_RET(sp, char, lp, llen, nlen)
52 #define BINC_RETW(sp, lp, llen, nlen)                                   \
53         BINC_RET(sp, CHAR_T, lp, llen, (nlen) * sizeof(CHAR_T))
54
55 /*
56  * Get some temporary space, preferably from the global temporary buffer,
57  * from a malloc'd buffer otherwise.  Two versions, one that returns, one
58  * that jumps to an error label.
59  */
60 #define GET_SPACE_GOTO(sp, type, bp, blen, nlen) {                      \
61         CHECK_TYPE(type *, bp)                                          \
62         GS *L__gp = (sp) == NULL ? NULL : (sp)->gp;                     \
63         if (L__gp == NULL || F_ISSET(L__gp, G_TMP_INUSE)) {             \
64                 bp = NULL;                                              \
65                 blen = 0;                                               \
66                 BINC_GOTO(sp, type, bp, blen, nlen);                    \
67         } else {                                                        \
68                 BINC_GOTOC(sp, L__gp->tmp_bp, L__gp->tmp_blen, nlen);   \
69                 bp = (type *) L__gp->tmp_bp;                            \
70                 blen = L__gp->tmp_blen;                                 \
71                 F_SET(L__gp, G_TMP_INUSE);                              \
72         }                                                               \
73 }
74 #define GET_SPACE_GOTOC(sp, bp, blen, nlen)                             \
75         GET_SPACE_GOTO(sp, char, bp, blen, nlen)
76 #define GET_SPACE_GOTOW(sp, bp, blen, nlen)                             \
77         GET_SPACE_GOTO(sp, CHAR_T, bp, blen, (nlen) * sizeof(CHAR_T))
78 #define GET_SPACE_RET(sp, type, bp, blen, nlen) {                       \
79         CHECK_TYPE(type *, bp)                                          \
80         GS *L__gp = (sp) == NULL ? NULL : (sp)->gp;                     \
81         if (L__gp == NULL || F_ISSET(L__gp, G_TMP_INUSE)) {             \
82                 bp = NULL;                                              \
83                 blen = 0;                                               \
84                 BINC_RET(sp, type, bp, blen, nlen);                     \
85         } else {                                                        \
86                 BINC_RETC(sp, L__gp->tmp_bp, L__gp->tmp_blen, nlen);    \
87                 bp = (type *) L__gp->tmp_bp;                            \
88                 blen = L__gp->tmp_blen;                                 \
89                 F_SET(L__gp, G_TMP_INUSE);                              \
90         }                                                               \
91 }
92 #define GET_SPACE_RETC(sp, bp, blen, nlen)                              \
93         GET_SPACE_RET(sp, char, bp, blen, nlen)
94 #define GET_SPACE_RETW(sp, bp, blen, nlen)                              \
95         GET_SPACE_RET(sp, CHAR_T, bp, blen, (nlen) * sizeof(CHAR_T))
96
97 /*
98  * Add space to a GET_SPACE returned buffer.  Two versions, one that
99  * returns, one that jumps to an error label.
100  */
101 #define ADD_SPACE_GOTO(sp, type, bp, blen, nlen) {                      \
102         CHECK_TYPE(type *, bp)                                          \
103         GS *L__gp = (sp) == NULL ? NULL : (sp)->gp;                     \
104         if (L__gp == NULL || bp == (type *)L__gp->tmp_bp) {             \
105                 F_CLR(L__gp, G_TMP_INUSE);                              \
106                 BINC_GOTOC(sp, L__gp->tmp_bp, L__gp->tmp_blen, nlen);   \
107                 bp = (type *) L__gp->tmp_bp;                            \
108                 blen = L__gp->tmp_blen;                                 \
109                 F_SET(L__gp, G_TMP_INUSE);                              \
110         } else                                                          \
111                 BINC_GOTO(sp, type, bp, blen, nlen);                    \
112 }
113 #define ADD_SPACE_GOTOC(sp, bp, blen, nlen)                             \
114         ADD_SPACE_GOTO(sp, char, bp, blen, nlen)
115 #define ADD_SPACE_GOTOW(sp, bp, blen, nlen)                             \
116         ADD_SPACE_GOTO(sp, CHAR_T, bp, blen, (nlen) * sizeof(CHAR_T))
117 #define ADD_SPACE_RET(sp, type, bp, blen, nlen) {                       \
118         CHECK_TYPE(type *, bp)                                          \
119         GS *L__gp = (sp) == NULL ? NULL : (sp)->gp;                     \
120         if (L__gp == NULL || bp == (type *)L__gp->tmp_bp) {             \
121                 F_CLR(L__gp, G_TMP_INUSE);                              \
122                 BINC_RETC(sp, L__gp->tmp_bp, L__gp->tmp_blen, nlen);    \
123                 bp = (type *) L__gp->tmp_bp;                            \
124                 blen = L__gp->tmp_blen;                                 \
125                 F_SET(L__gp, G_TMP_INUSE);                              \
126         } else                                                          \
127                 BINC_RET(sp, type, bp, blen, nlen);                     \
128 }
129 #define ADD_SPACE_RETC(sp, bp, blen, nlen)                              \
130         ADD_SPACE_RET(sp, char, bp, blen, nlen)
131 #define ADD_SPACE_RETW(sp, bp, blen, nlen)                              \
132         ADD_SPACE_RET(sp, CHAR_T, bp, blen, (nlen) * sizeof(CHAR_T))
133
134 /* Free a GET_SPACE returned buffer. */
135 #define FREE_SPACE(sp, bp, blen) {                                      \
136         GS *L__gp = (sp) == NULL ? NULL : (sp)->gp;                     \
137         if (L__gp != NULL && bp == L__gp->tmp_bp)                       \
138                 F_CLR(L__gp, G_TMP_INUSE);                              \
139         else                                                            \
140                 free(bp);                                               \
141 }
142 #define FREE_SPACEW(sp, bp, blen) {                                     \
143         CHECK_TYPE(CHAR_T *, bp)                                        \
144         FREE_SPACE(sp, (char *)bp, blen);                               \
145 }
146
147 /*
148  * Malloc a buffer, casting the return pointer.  Various versions.
149  */
150 #define CALLOC(sp, p, nmemb, size) {                                    \
151         if ((p = calloc(nmemb, size)) == NULL)                          \
152                 msgq(sp, M_SYSERR, NULL);                               \
153 }
154 #define CALLOC_GOTO(sp, p, nmemb, size) {                               \
155         if ((p = calloc(nmemb, size)) == NULL)                          \
156                 goto alloc_err;                                         \
157 }
158 #define CALLOC_RET(sp, p, nmemb, size) {                                \
159         if ((p = calloc(nmemb, size)) == NULL) {                        \
160                 msgq(sp, M_SYSERR, NULL);                               \
161                 return (1);                                             \
162         }                                                               \
163 }
164
165 #define MALLOC(sp, p, size) {                                           \
166         if ((p = malloc(size)) == NULL)                                 \
167                 msgq(sp, M_SYSERR, NULL);                               \
168 }
169 #define MALLOC_GOTO(sp, p, size) {                                      \
170         if ((p = malloc(size)) == NULL)                                 \
171                 goto alloc_err;                                         \
172 }
173 #define MALLOC_RET(sp, p, size) {                                       \
174         if ((p = malloc(size)) == NULL) {                               \
175                 msgq(sp, M_SYSERR, NULL);                               \
176                 return (1);                                             \
177         }                                                               \
178 }
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) {                                    \
185         cast newp;                                                      \
186         if ((newp = realloc(p, size)) == NULL) {                        \
187                 free(p);                                                \
188                 msgq(sp, M_SYSERR, NULL);                               \
189         }                                                               \
190         p = newp;                                                       \
191 }
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
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)