chiark / gitweb /
@@@ tty mess
[mLib] / struct / buf.h
1 /* -*-c-*-
2  *
3  * Reading and writing packet buffers
4  *
5  * (c) 2001 Straylight/Edgeware
6  */
7
8 /*----- Licensing notice --------------------------------------------------*
9  *
10  * This file is part of the mLib utilities library.
11  *
12  * mLib is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU Library General Public License as
14  * published by the Free Software Foundation; either version 2 of the
15  * License, or (at your option) any later version.
16  *
17  * mLib is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU Library General Public License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public
23  * License along with mLib; if not, write to the Free
24  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25  * MA 02111-1307, USA.
26  */
27
28 #ifndef MLIB_BUF_H
29 #define MLIB_BUF_H
30
31 #ifdef __cplusplus
32   extern "C" {
33 #endif
34
35 /*----- Header files ------------------------------------------------------*/
36
37 #include <stdarg.h>
38 #include <stddef.h>
39
40 #ifndef MLIB_BITS_H
41 #  include "bits.h"
42 #endif
43
44 #ifndef MLIB_CONTROL_H
45 #  include "control.h"
46 #endif
47
48 #ifndef MLIB_DSTR_H
49 #  include "dstr.h"
50 #endif
51
52 #ifndef MLIB_MACROS_H
53 #  include "macros.h"
54 #endif
55
56 /*----- Data structures ---------------------------------------------------*/
57
58 /* --- Buffers --- *
59  *
60  * Buffers provide a simple stream-like interface for building and parsing
61  * packets.
62  */
63
64 typedef struct buf {
65   octet *base, *p, *limit;              /* Pointers to the buffer */
66   unsigned f;                           /* Various flags */
67 } buf;
68
69 #define BF_BROKEN 1u                    /* Buffer is broken */
70 #define BF_ALLOC 2u                     /* Buffer is dynamic */
71 #define BF_WRITE 4u                     /* Currently writing to buffer */
72
73 typedef struct dbuf {
74   buf _b;
75   arena *a;                             /* Allocation arena */
76   size_t sz;                            /* Allocated size */
77 } dbuf;
78
79 #define DBUF_INIT { { 0, 0, 0, BF_ALLOC | BF_WRITE}, &arena_stdlib, 0 }
80 #define DBUF_BUF(db) (&(db)->_b)
81
82 extern const struct gprintf_ops buf_printops;
83
84 /*----- Useful macros -----------------------------------------------------*/
85
86 #define BBASE(b) ((b)->base)
87 #define BLIM(b) ((b)->limit)
88 #define BCUR(b) ((b)->p)
89 #define BSZ(b) ((b)->limit - (b)->base)
90 #define BLEN(b) ((b)->p - (b)->base)
91 #define BLEFT(b) ((b)->limit - (b)->p)
92 #define BSTEP(b, sz) ((b)->p += (sz))
93 #define BBAD(b) ((b)->f & BF_BROKEN)
94 #define BOK(b) (!BBAD(b))
95
96 #define BENSURE(b, sz)                                          \
97      (BBAD(b) ? -1 : (sz) > BLEFT(b) ? buf_tryextend(b, sz) : 0)
98
99 #define DBBASE(db) BBASE(DBUF_BUF(db))
100 #define DBLIM(db) BLIM(DBUF_BUF(db))
101 #define DBCUR(db) BCUR(DBUF_BUF(db))
102 #define DBSZ(db) BSZ(DBUF_BUF(db))
103 #define DBLEN(db) BLEN(DBUF_BUF(db))
104 #define DBLEFT(db) BLEFT(DBUF_BUF(db))
105 #define DBSTEP(db, sz) BSTEP(DBUF_BUF(db), (sz))
106 #define DBBAD(db) BBAD(DBUF_BUF(db))
107 #define DBOK(db) BOK(DBUF_BUF(db))
108 #define DBENSURE(b, sz) BENSURE(DBUF_BUF(db), (sz))
109
110 #ifdef HAVE_UINT64
111 #  define BUF_DOKLUDGESUFFIXES(_)
112 #else
113 #  define BUF_DOKLUDGESUFFIXES(_)                                       \
114         _(64, 64, 64) _(64, 64_B, 64b) _(64, 64_L, 64l)
115 #endif
116
117 #define BUF_DOSUFFIXES(_) DOUINTCONV(_) BUF_DOKLUDGESUFFIXES(_) _(z, z, z)
118
119 /*----- Functions provided ------------------------------------------------*/
120
121 /* --- @buf_init@ --- *
122  *
123  * Arguments:   @buf *b@ = pointer to a buffer block
124  *              @void *p@ = pointer to a buffer
125  *              @size_t sz@ = size of the buffer
126  *
127  * Returns:     ---
128  *
129  * Use:         Initializes the buffer block appropriately.
130  */
131
132 extern void buf_init(buf */*b*/, void */*p*/, size_t /*sz*/);
133
134 /* --- @dbuf_create@ --- *
135  *
136  * Arguments:   @dbuf *db@ = pointer to a dynamic buffer block
137  *
138  * Returns:     ---
139  *
140  * Use:         Initializes a dynamic buffer.  The buffer is initially empty,
141  *              and ready for writing.
142  */
143
144 extern void dbuf_create(dbuf */*db*/);
145 #define DBCREATE(db) do {                                               \
146   (db)->_b.base = (db)->_b.p = (db)->_b.limit = 0;                      \
147   (db)->_b.f = BF_ALLOC | BF_WRITE;                                     \
148   (db)->a = &arena_stdlib; (db)->sz = 0;                                \
149 } while (0)
150
151 /* --- @dbuf_reset@ --- *
152  *
153  * Arguments:   @dbuf *db@ = pointer to a buffer block
154  *
155  * Returns:     ---
156  *
157  * Use:         Resets a buffer so that it can be written again.
158  */
159
160 extern void dbuf_reset(dbuf */*db*/);
161 #define DBRESET(db) do {                                                \
162   (db)->_b.p = (db)->_b.base; (db)->_b.limit = (db)->_b.base + (db)->sz; \
163   (db)->_b.f = ((db)->_b.f&~BF_BROKEN) | BF_WRITE;                      \
164 } while (0)
165
166 /* --- @dbuf_destroy@ --- *
167  *
168  * Arguments:   @dbuf *db@ = pointer to a buffer block
169  *
170  * Returns:     ---
171  *
172  * Use:         Release all of the resources held by a dynamic buffer.
173  */
174
175 extern void dbuf_destroy(dbuf */*db*/);
176 #define DBDESTROY(db) do {                                              \
177   if ((db)->_b.base) x_free((db)->a, (db)->_b.base);                    \
178   (db)->_b.base = (db)->_b.p = (db)->_b.limit = 0;                      \
179   (db)->_b.f = BF_ALLOC | BF_WRITE; (db)->sz = 0;                       \
180 } while (0)
181
182 /* --- @{,d}buf_break@ --- *
183  *
184  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
185  *
186  * Returns:     Some negative value.
187  *
188  * Use:         Marks a buffer as broken.
189  */
190
191 extern int buf_break(buf */*b*/);
192 extern int dbuf_break(dbuf */*db*/);
193 #define dbuf_break(db) (buf_break(DBUF_BUF(db)))
194 #define BBREAK(b) do { (b)->f |= BF_BROKEN; } while (0)
195 #define DBBREAK(db) BBREAK(DBUF_BUF(db))
196
197 /* --- @{,d}buf_flip@ --- *
198  *
199  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
200  *
201  * Returns:     ---
202  *
203  * Use:         Flips a buffer so that if you've just been writing to it,
204  *              you can now read from the bit you've written.
205  */
206
207 extern void buf_flip(buf */*b*/);
208 extern void dbuf_flip(dbuf */*db*/);
209 #define dbuf_flip(db) (buf_flip(DBUF_BUF(db)))
210
211 #define BFLIP(b) do {                                                   \
212   (b)->limit = (b)->p; (b)->p = (b)->base;                              \
213   (b)->f &= ~BF_WRITE;                                                  \
214 } while (0)
215 #define DBFLIP(db) BFLIP(DBUF_BUF(db))
216
217 /* --- @{,d}buf_ensure@ --- *
218  *
219  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
220  *              @size_t sz@ = size of data wanted
221  *
222  * Returns:     Zero if it worked, nonzero if there wasn't enough space.
223  *
224  * Use:         Ensures that there are @sz@ bytes still in the buffer.
225  */
226
227 extern int buf_ensure(buf */*b*/, size_t /*sz*/);
228 extern int dbuf_ensure(dbuf */*db*/, size_t /*sz*/);
229 #define dbuf_ensure(db, sz) (buf_ensure(DBUF_BUF(db), (sz)))
230
231 /* --- @{,d}buf_tryextend@ --- *
232  *
233  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
234  *              @size_t sz@ = size of data wanted
235  *
236  * Returns:     Zero if it worked, nonzero if the buffer won't grow.
237  *
238  * Use:         Extend the buffer so that at least @sz@ bytes are available.
239  *              This only works if the buffer is allocated.
240  */
241
242 extern int buf_tryextend(buf */*b*/, size_t /*sz*/);
243 extern int dbuf_tryextend(dbuf */*db*/, size_t /*sz*/);
244 #define dbuf_tryextend(db, sz) (buf_tryextend(DBUF_BUF(db), (sz)))
245
246 /* --- @{,d}buf_get@ --- *
247  *
248  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
249  *              @size_t sz@ = size of the buffer
250  *
251  * Returns:     Pointer to the place in the buffer.
252  *
253  * Use:         Reserves a space in the buffer of the requested size, and
254  *              returns its start address.
255  */
256
257 extern void *buf_get(buf */*b*/, size_t /*sz*/);
258 extern void *dbuf_get(dbuf */*db*/, size_t /*sz*/);
259 #define dbuf_get(db, sz) (buf_get(DBUF_BUF(db), (sz)))
260
261 /* --- @{,d}buf_put@ --- *
262  *
263  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
264  *              @const void *p@ = pointer to a buffer
265  *              @size_t sz@ = size of the buffer
266  *
267  * Returns:     Zero if it worked, nonzero if there wasn't enough space.
268  *
269  * Use:         Fetches data from some place and puts it in the buffer
270  */
271
272 extern int buf_put(buf */*b*/, const void */*p*/, size_t /*sz*/);
273 extern int dbuf_put(dbuf */*db*/, const void */*p*/, size_t /*sz*/);
274 #define dbuf_put(db, p, sz) (buf_put(DBUF_BUF(db), (p), (sz)))
275
276 /* --- @{,d}buf_fill@ --- *
277  *
278  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
279  *              @int ch@ = fill character
280  *              @size_t sz@ = size to fill
281  *
282  * Returns:     Zero if it worked, nonzero if there wasn't enough space.
283  *
284  * Use:         Write @sz@ bytes with value @ch@ to the buffer, as if with
285  *              @memset@.
286  */
287
288 extern int buf_fill(buf */*b*/, int /*ch*/, size_t /*sz*/);
289 extern int dbuf_fill(dbuf */*db*/, int /*ch*/, size_t /*sz*/);
290 #define dbuf_fill(db, ch, sz) (buf_fill(DBUF_BUF(db), (ch), (sz)))
291
292 /* --- @{,d}buf_align@ --- *
293  *
294  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
295  *              @size_t m, a@ = alignment multiple and offset
296  *              @size_t *sz_out@ = where to put the length
297  *
298  * Returns:     Pointer to previous buffer position, or null on error.
299  *
300  * Use:         Advance the buffer position as little as possible such that
301  *              it is @a@ greater than a multiple of @m@, returning the
302  *              (possibly empty) portion of the buffer passed over.
303  */
304
305 extern void *buf_align(buf */*b*/, size_t /*m*/, size_t /*a*/,
306                        size_t */*sz_out*/);
307 extern void *dbuf_align(dbuf */*db*/, size_t /*m*/, size_t /*a*/,
308                         size_t */*sz_out*/);
309 #define dbuf_align(db, m, a, sz_out)                                    \
310   (buf_align(DBUF_BUF(db), (m), (a), (sz_out)))
311
312 /* --- @{,d}buf_alignskip@ --- *
313  *
314  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
315  *              @size_t m, a@ = alignment multiple and offset
316  *
317  * Returns:     Zero if it worked, nonzero if there wasn't enough space.
318  *
319  * Use:         Advance the buffer position as little as possible such that
320  *              it is @a@ greater than a multiple of @m@.  This doesn't write
321  *              anything to the buffer, so it's probably not suitable for
322  *              output: use @buf_alignfill@ instead.
323  */
324
325 extern int buf_alignskip(buf */*b*/, size_t /*m*/, size_t /*a*/);
326 extern int dbuf_alignskip(dbuf */*db*/, size_t /*m*/, size_t /*a*/);
327 #define dbuf_alignskip(db, m, a) (buf_alignskip(DBUF_BUF(db), (m), (a)))
328
329 /* --- @{,d}buf_alignfill@ --- *
330  *
331  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
332  *              @int ch@ = fill character
333  *              @size_t m, a@ = alignment multiple and offset
334  *
335  * Returns:     Zero if it worked, nonzero if there wasn't enough space.
336  *
337  * Use:         Fill the buffer with as few copies of @ch@ as possible, as if
338  *              by @memset@, to advance the buffer position to a value @a@
339  *              greater than a multiple of @m@.
340  */
341
342 extern int buf_alignfill(buf */*b*/, int /*ch*/, size_t /*m*/, size_t /*a*/);
343 extern int (dbuf_alignfill)(dbuf */*db*/, int /*ch*/,
344                             size_t /*m*/, size_t /*a*/);
345 #define dbuf_alignfill(db, ch, m, a)                                    \
346   (buf_alignfill(DBUF_BUF(db), (ch), (a), (m)))
347
348 /* --- @{,d}buf_getbyte@ --- *
349  *
350  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
351  *
352  * Returns:     A byte, or less than zero if there wasn't a byte there.
353  *
354  * Use:         Gets a single byte from a buffer.
355  */
356
357 extern int buf_getbyte(buf */*b*/);
358 extern int dbuf_getbyte(dbuf */*db*/);
359 #define dbuf_getbyte(db) (buf_getbyte(DBUF_BUF(db)))
360
361 /* --- @{,d}buf_putbyte@ --- *
362  *
363  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
364  *              @int ch@ = byte to write
365  *
366  * Returns:     Zero if OK, nonzero if there wasn't enough space.
367  *
368  * Use:         Puts a single byte in a buffer.
369  */
370
371 extern int buf_putbyte(buf */*b*/, int /*ch*/);
372 extern int dbuf_putbyte(dbuf */*db*/, int /*ch*/);
373 #define dbuf_putbyte(db, ch) (buf_putbyte(DBUF_BUF(db), (ch)))
374
375 /* --- @{,d}buf_getu{8,{16,24,32,64}{,l,b}}@ --- *
376  *
377  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
378  *              @uintSZ *w@ = where to put the word
379  *
380  * Returns:     Zero if OK, or nonzero if there wasn't a word there.
381  *
382  * Use:         Gets a word of appropriate size and order from a buffer.
383  */
384
385 #define BUF_DECL_GETU_(n, W, w)                                         \
386   extern int buf_getu##w(buf */*b*/, uint##n */*w*/);                   \
387   extern int dbuf_getu##w(dbuf */*db*/, uint##n */*w*/);
388 DOUINTCONV(BUF_DECL_GETU_)
389 #define dbuf_getu8(db, w) (buf_getu8(DBUF_BUF(db), (w)))
390 #define dbuf_getu16(db, w) (buf_getu16(DBUF_BUF(db), (w)))
391 #define dbuf_getu16l(db, w) (buf_getu16l(DBUF_BUF(db), (w)))
392 #define dbuf_getu16b(db, w) (buf_getu16b(DBUF_BUF(db), (w)))
393 #define dbuf_getu24(db, w) (buf_getu24(DBUF_BUF(db), (w)))
394 #define dbuf_getu24l(db, w) (buf_getu24l(DBUF_BUF(db), (w)))
395 #define dbuf_getu24b(db, w) (buf_getu24b(DBUF_BUF(db), (w)))
396 #define dbuf_getu32(db, w) (buf_getu32(DBUF_BUF(db), (w)))
397 #define dbuf_getu32l(db, w) (buf_getu32l(DBUF_BUF(db), (w)))
398 #define dbuf_getu32b(db, w) (buf_getu32b(DBUF_BUF(db), (w)))
399 #ifdef HAVE_UINT64
400 #  define dbuf_getu64(db, w) (buf_getu64(DBUF_BUF(db), (w)))
401 #  define dbuf_getu64l(db, w) (buf_getu64l(DBUF_BUF(db), (w)))
402 #  define dbuf_getu64b(db, w) (buf_getu64b(DBUF_BUF(db), (w)))
403 #endif
404
405 /* --- @{,d}buf_getk64{,l,b}@ --- *
406  *
407  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
408  *              @kludge64 *w@ = where to put the word
409  *
410  * Returns:     Zero if OK, or nonzero if there wasn't a word there.
411  *
412  * Use:         Gets a word of appropriate size and order from a buffer.
413  */
414
415 extern int buf_getk64(buf */*b*/, kludge64 */*w*/);
416 extern int buf_getk64l(buf */*b*/, kludge64 */*w*/);
417 extern int buf_getk64b(buf */*b*/, kludge64 */*w*/);
418 extern int dbuf_getk64(dbuf */*db*/, kludge64 */*w*/);
419 extern int dbuf_getk64l(dbuf */*db*/, kludge64 */*w*/);
420 extern int dbuf_getk64b(dbuf */*db*/, kludge64 */*w*/);
421 #define dbuf_getk64(db, w) (buf_getk64(DBUF_BUF(db), (w)))
422 #define dbuf_getk64l(db, w) (buf_getk64l(DBUF_BUF(db), (w)))
423 #define dbuf_getk64b(db, w) (buf_getk64b(DBUF_BUF(db), (w)))
424
425 /* --- @{,d}buf_putu{8,{16,24,32,64}{,l,b}}@ --- *
426  *
427  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
428  *              @uintSZ w@ = word to write
429  *
430  * Returns:     Zero if OK, or nonzero if there wasn't enough space
431  *
432  * Use:         Puts a word into a buffer with appropriate size and order.
433  */
434
435 #define BUF_DECL_PUTU_(n, W, w)                                         \
436   extern int buf_putu##w(buf */*b*/, uint##n /*w*/);                    \
437   extern int dbuf_putu##w(dbuf */*db*/, uint##n /*w*/);
438 DOUINTCONV(BUF_DECL_PUTU_)
439 #define dbuf_putu8(db, w) (buf_putu8(DBUF_BUF(db), (w)))
440 #define dbuf_putu16(db, w) (buf_putu16(DBUF_BUF(db), (w)))
441 #define dbuf_putu16l(db, w) (buf_putu16l(DBUF_BUF(db), (w)))
442 #define dbuf_putu16b(db, w) (buf_putu16b(DBUF_BUF(db), (w)))
443 #define dbuf_putu24(db, w) (buf_putu24(DBUF_BUF(db), (w)))
444 #define dbuf_putu24l(db, w) (buf_putu24l(DBUF_BUF(db), (w)))
445 #define dbuf_putu24b(db, w) (buf_putu24b(DBUF_BUF(db), (w)))
446 #define dbuf_putu32(db, w) (buf_putu32(DBUF_BUF(db), (w)))
447 #define dbuf_putu32l(db, w) (buf_putu32l(DBUF_BUF(db), (w)))
448 #define dbuf_putu32b(db, w) (buf_putu32b(DBUF_BUF(db), (w)))
449 #ifdef HAVE_UINT64
450 #  define dbuf_putu64(db, w) (buf_putu64(DBUF_BUF(db), (w)))
451 #  define dbuf_putu64l(db, w) (buf_putu64l(DBUF_BUF(db), (w)))
452 #  define dbuf_putu64b(db, w) (buf_putu64b(DBUF_BUF(db), (w)))
453 #endif
454
455 /* --- @{,d}buf_putk64{,l,b}@ --- *
456  *
457  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
458  *              @kludge64 w@ = word to write
459  *
460  * Returns:     Zero if OK, or nonzero if there wasn't enough space
461  *
462  * Use:         Gets a word of appropriate size and order from a buffer.
463  */
464
465 extern int buf_putk64(buf */*b*/, kludge64 /*w*/);
466 extern int buf_putk64l(buf */*b*/, kludge64 /*w*/);
467 extern int buf_putk64b(buf */*b*/, kludge64 /*w*/);
468 extern int dbuf_putk64(dbuf */*db*/, kludge64 /*w*/);
469 extern int dbuf_putk64l(dbuf */*db*/, kludge64 /*w*/);
470 extern int dbuf_putk64b(dbuf */*db*/, kludge64 /*w*/);
471 #define dbuf_putk64(db, w) (buf_putk64(DBUF_BUF(db), (w)))
472 #define dbuf_putk64l(db, w) (buf_putk64l(DBUF_BUF(db), (w)))
473 #define dbuf_putk64b(db, w) (buf_putk64b(DBUF_BUF(db), (w)))
474
475 /* --- @buf_getf{32,64}{,l,b} --- *
476  *
477  * Arguments:   @buf *b@ = a buffer to read from
478  *              @float *x_out@, @double *x_out@ = where to put the result
479  *
480  * Returns:     Zero on success, %$-1$% on failure (and the buffer is
481  *              broken).
482  *
483  * Use:         Get an IEEE Binary32 or Binary64 value from the buffer.
484  *              Conversion is performed using the `fltfmt' machinery, with
485  *              the usual round-to-nearest/ties-to-even rounding mode.
486  */
487
488 extern int buf_getf32(buf */*b*/, float */*x_out*/);
489 extern int buf_getf32l(buf */*b*/, float */*x_out*/);
490 extern int buf_getf32b(buf */*b*/, float */*x_out*/);
491 #define dbuf_getf32(db, x_out) (buf_getf32(DBUF_BUF(db), (x_out)))
492 #define dbuf_getf32l(db, x_out) (buf_getf32l(DBUF_BUF(db), (x_out)))
493 #define dbuf_getf32b(db, x_out) (buf_getf32b(DBUF_BUF(db), (x_out)))
494
495 extern int buf_getf64(buf */*b*/, double */*x_out*/);
496 extern int buf_getf64l(buf */*b*/, double */*x_out*/);
497 extern int buf_getf64b(buf */*b*/, double */*x_out*/);
498 #define dbuf_getf64(db, x_out) (buf_getf64(DBUF_BUF(db), (x_out)))
499 #define dbuf_getf64l(db, x_out) (buf_getf64l(DBUF_BUF(db), (x_out)))
500 #define dbuf_getf64b(db, x_out) (buf_getf64b(DBUF_BUF(db), (x_out)))
501
502 /* --- @buf_putf{32,64}{,l,b} --- *
503  *
504  * Arguments:   @buf *b@ = a buffer to write to
505  *              @double x@ = a number to write
506  *
507  * Returns:     Zero on success, %$-1$% on failure (and the buffer is
508  *              broken).
509  *
510  * Use:         Get an IEEE Binary32 or Binary64 value from the buffer.
511  *              Conversion is performed using the `fltfmt' machinery, with
512  *              the usual round-to-nearest/ties-to-even rounding mode.
513  */
514
515 extern int buf_putf32(buf */*b*/, float /*x*/);
516 extern int buf_putf32l(buf */*b*/, float /*x*/);
517 extern int buf_putf32b(buf */*b*/, float /*x*/);
518 #define dbuf_putf32(db, x) (buf_putf32(DBUF_BUF(db), (x)))
519 #define dbuf_putf32l(db, x) (buf_putf32l(DBUF_BUF(db), (x)))
520 #define dbuf_putf32b(db, x) (buf_putf32b(DBUF_BUF(db), (x)))
521
522 extern int buf_putf64(buf */*b*/, double /*x*/);
523 extern int buf_putf64l(buf */*b*/, double /*x*/);
524 extern int buf_putf64b(buf */*b*/, double /*x*/);
525 #define dbuf_putf64(db, x) (buf_putf64(DBUF_BUF(db), (x)))
526 #define dbuf_putf64l(db, x) (buf_putf64l(DBUF_BUF(db), (x)))
527 #define dbuf_putf64b(db, x) (buf_putf64b(DBUF_BUF(db), (x)))
528
529 /* --- @{,d}buf_getmem{8,{16,24,32,64}{,l,b},z} --- *
530  *
531  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
532  *              @size_t *nn@ = where to put the length
533  *
534  * Returns:     Pointer to the buffer data, or null.
535  *
536  * Use:         Gets a chunk of memory from a buffer.  The suffix is the
537  *              width and byte order of the length; @z@ means null-
538  *              terminated.
539  */
540
541 #define BUF_DECL_GETMEM_(n, W, w)                                       \
542   extern void *buf_getmem##w(buf */*b*/, size_t */*nn*/);               \
543   extern void *dbuf_getmem##w(dbuf */*db*/, size_t */*nn*/);
544 BUF_DOSUFFIXES(BUF_DECL_GETMEM_)
545 #define dbuf_getmem8(db, nn) (buf_getmem8(DBUF_BUF(db), (nn)))
546 #define dbuf_getmem16(db, nn) (buf_getmem16(DBUF_BUF(db), (nn)))
547 #define dbuf_getmem16l(db, nn) (buf_getmem16l(DBUF_BUF(db), (nn)))
548 #define dbuf_getmem16b(db, nn) (buf_getmem16b(DBUF_BUF(db), (nn)))
549 #define dbuf_getmem24(db, nn) (buf_getmem24(DBUF_BUF(db), (nn)))
550 #define dbuf_getmem24l(db, nn) (buf_getmem24l(DBUF_BUF(db), (nn)))
551 #define dbuf_getmem24b(db, nn) (buf_getmem24b(DBUF_BUF(db), (nn)))
552 #define dbuf_getmem32(db, nn) (buf_getmem32(DBUF_BUF(db), (nn)))
553 #define dbuf_getmem32l(db, nn) (buf_getmem32l(DBUF_BUF(db), (nn)))
554 #define dbuf_getmem32b(db, nn) (buf_getmem32b(DBUF_BUF(db), (nn)))
555 #define dbuf_getmem64(db, nn) (buf_getmem64(DBUF_BUF(db), (nn)))
556 #define dbuf_getmem64l(db, nn) (buf_getmem64l(DBUF_BUF(db), (nn)))
557 #define dbuf_getmem64b(db, nn) (buf_getmem64b(DBUF_BUF(db), (nn)))
558 #define dbuf_getmemz(db, nn) (buf_getmemz(DBUF_BUF(db), (nn)))
559
560 /* --- @{,d}buf_putmem{8,{16,24,32,64}{,l,b},z} --- *
561  *
562  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
563  *              @const void *p@ = pointer to data to write
564  *              @size_t n@ = length to write
565  *
566  * Returns:     Zero if OK, nonzero if there wasn't enough space.
567  *
568  * Use:         Writes a chunk of data to a buffer.  The suffix is the
569  *              width and byte order of the length; @z@ means null-
570  *              terminated.
571  */
572
573 #define BUF_DECL_PUTMEM_(n, W, w)                                       \
574   extern int buf_putmem##w(buf */*b*/, const void */*p*/, size_t /*nn*/); \
575   extern int dbuf_putmem##w(dbuf */*db*/, const void */*p*/, size_t /*nn*/);
576 BUF_DOSUFFIXES(BUF_DECL_PUTMEM_)
577 #define dbuf_putmem8(db, p, nn) (buf_putmem8(DBUF_BUF(db), (p), (nn)))
578 #define dbuf_putmem16(db, p, nn) (buf_putmem16(DBUF_BUF(db), (p), (nn)))
579 #define dbuf_putmem16l(db, p, nn) (buf_putmem16l(DBUF_BUF(db), (p), (nn)))
580 #define dbuf_putmem16b(db, p, nn) (buf_putmem16b(DBUF_BUF(db), (p), (nn)))
581 #define dbuf_putmem24(db, p, nn) (buf_putmem24(DBUF_BUF(db), (p), (nn)))
582 #define dbuf_putmem24l(db, p, nn) (buf_putmem24l(DBUF_BUF(db), (p), (nn)))
583 #define dbuf_putmem24b(db, p, nn) (buf_putmem24b(DBUF_BUF(db), (p), (nn)))
584 #define dbuf_putmem32(db, p, nn) (buf_putmem32(DBUF_BUF(db), (p), (nn)))
585 #define dbuf_putmem32l(db, p, nn) (buf_putmem32l(DBUF_BUF(db), (p), (nn)))
586 #define dbuf_putmem32b(db, p, nn) (buf_putmem32b(DBUF_BUF(db), (p), (nn)))
587 #define dbuf_putmem64(db, p, nn) (buf_putmem64(DBUF_BUF(db), (p), (nn)))
588 #define dbuf_putmem64l(db, p, nn) (buf_putmem64l(DBUF_BUF(db), (p), (nn)))
589 #define dbuf_putmem64b(db, p, nn) (buf_putmem64b(DBUF_BUF(db), (p), (nn)))
590 #define dbuf_putmemz(db, p, nn) (buf_putmemz(DBUF_BUF(db), (p), (nn)))
591
592 /* --- @{,d}buf_getbuf{8,{16,24,32,64}{,l,b},z} --- *
593  *
594  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
595  *              @buf *bb@ = where to put the result
596  *
597  * Returns:     Zero if it worked, nonzero if there wasn't enough space.
598  *
599  * Use:         Gets a block of data from a buffer, and writes its bounds to
600  *              another buffer.
601  */
602
603 #define BUF_DECL_GETBUF_(n, W, w)                                       \
604   extern int buf_getbuf##w(buf */*b*/, buf */*bb*/);                    \
605   extern int dbuf_getbuf##w(dbuf */*db*/, buf */*bb*/);
606 BUF_DOSUFFIXES(BUF_DECL_GETBUF_)
607 #define dbuf_getbuf8(db, bb) (buf_getbuf8(DBUF_BUF(db), (bb)))
608 #define dbuf_getbuf16(db, bb) (buf_getbuf16(DBUF_BUF(db), (bb)))
609 #define dbuf_getbuf16l(db, bb) (buf_getbuf16l(DBUF_BUF(db), (bb)))
610 #define dbuf_getbuf16b(db, bb) (buf_getbuf16b(DBUF_BUF(db), (bb)))
611 #define dbuf_getbuf24(db, bb) (buf_getbuf24(DBUF_BUF(db), (bb)))
612 #define dbuf_getbuf24l(db, bb) (buf_getbuf24l(DBUF_BUF(db), (bb)))
613 #define dbuf_getbuf24b(db, bb) (buf_getbuf24b(DBUF_BUF(db), (bb)))
614 #define dbuf_getbuf32(db, bb) (buf_getbuf32(DBUF_BUF(db), (bb)))
615 #define dbuf_getbuf32l(db, bb) (buf_getbuf32l(DBUF_BUF(db), (bb)))
616 #define dbuf_getbuf32b(db, bb) (buf_getbuf32b(DBUF_BUF(db), (bb)))
617 #define dbuf_getbuf64(db, bb) (buf_getbuf64(DBUF_BUF(db), (bb)))
618 #define dbuf_getbuf64l(db, bb) (buf_getbuf64l(DBUF_BUF(db), (bb)))
619 #define dbuf_getbuf64b(db, bb) (buf_getbuf64b(DBUF_BUF(db), (bb)))
620 #define dbuf_getbufz(db, bb) (buf_getbufz(DBUF_BUF(db), (bb)))
621
622 /* --- @{,d}buf_putbuf{8,{16,24,32,64}{,l,b},z} --- *
623  *
624  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
625  *              @buf *bb@ = buffer to write
626  *
627  * Returns:     Zero if it worked, nonzero if there wasn't enough space.
628  *
629  * Use:         Puts the contents of a buffer to a buffer.
630  */
631
632 #define BUF_DECL_PUTBUF_(n, W, w)                                       \
633   extern int buf_putbuf##w(buf */*b*/, buf */*bb*/);                    \
634   extern int dbuf_putbuf##w(dbuf */*db*/, buf */*bb*/);
635 BUF_DOSUFFIXES(BUF_DECL_PUTBUF_)
636 #define dbuf_putbuf8(db, bb) (buf_putbuf8(DBUF_BUF(db), (bb)))
637 #define dbuf_putbuf16(db, bb) (buf_putbuf16(DBUF_BUF(db), (bb)))
638 #define dbuf_putbuf16l(db, bb) (buf_putbuf16l(DBUF_BUF(db), (bb)))
639 #define dbuf_putbuf16b(db, bb) (buf_putbuf16b(DBUF_BUF(db), (bb)))
640 #define dbuf_putbuf24(db, bb) (buf_putbuf24(DBUF_BUF(db), (bb)))
641 #define dbuf_putbuf24l(db, bb) (buf_putbuf24l(DBUF_BUF(db), (bb)))
642 #define dbuf_putbuf24b(db, bb) (buf_putbuf24b(DBUF_BUF(db), (bb)))
643 #define dbuf_putbuf32(db, bb) (buf_putbuf32(DBUF_BUF(db), (bb)))
644 #define dbuf_putbuf32l(db, bb) (buf_putbuf32l(DBUF_BUF(db), (bb)))
645 #define dbuf_putbuf32b(db, bb) (buf_putbuf32b(DBUF_BUF(db), (bb)))
646 #define dbuf_putbuf64(db, bb) (buf_putbuf64(DBUF_BUF(db), (bb)))
647 #define dbuf_putbuf64l(db, bb) (buf_putbuf64l(DBUF_BUF(db), (bb)))
648 #define dbuf_putbuf64b(db, bb) (buf_putbuf64b(DBUF_BUF(db), (bb)))
649 #define dbuf_putbufz(db, bb) (buf_putbufz(DBUF_BUF(db), (bb)))
650
651 /* --- @{,d}buf_getdstr{8,{16,24,32,64}{,l,b},z} --- *
652  *
653  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
654  *              @dstr *d@ = where to put the result
655  *
656  * Returns:     Zero if it worked, nonzero if there wasn't enough space.
657  *
658  * Use:         Gets a block of data from a buffer, and writes its contents
659  *              to a string.
660  */
661
662 #define BUF_DECL_GETDSTR_(n, W, w)                                      \
663   extern int buf_getdstr##w(buf */*b*/, dstr */*d*/);                   \
664   extern int dbuf_getdstr##w(dbuf */*db*/, dstr */*d*/);
665 BUF_DOSUFFIXES(BUF_DECL_GETDSTR_)
666 #define dbuf_getdstr8(db, d) (buf_getdstr8(DBUF_BUF(db), (d)))
667 #define dbuf_getdstr16(db, d) (buf_getdstr16(DBUF_BUF(db), (d)))
668 #define dbuf_getdstr16l(db, d) (buf_getdstr16l(DBUF_BUF(db), (d)))
669 #define dbuf_getdstr16b(db, d) (buf_getdstr16b(DBUF_BUF(db), (d)))
670 #define dbuf_getdstr24(db, d) (buf_getdstr24(DBUF_BUF(db), (d)))
671 #define dbuf_getdstr24l(db, d) (buf_getdstr24l(DBUF_BUF(db), (d)))
672 #define dbuf_getdstr24b(db, d) (buf_getdstr24b(DBUF_BUF(db), (d)))
673 #define dbuf_getdstr32(db, d) (buf_getdstr32(DBUF_BUF(db), (d)))
674 #define dbuf_getdstr32l(db, d) (buf_getdstr32l(DBUF_BUF(db), (d)))
675 #define dbuf_getdstr32b(db, d) (buf_getdstr32b(DBUF_BUF(db), (d)))
676 #define dbuf_getdstr64(db, d) (buf_getdstr64(DBUF_BUF(db), (d)))
677 #define dbuf_getdstr64l(db, d) (buf_getdstr64l(DBUF_BUF(db), (d)))
678 #define dbuf_getdstr64b(db, d) (buf_getdstr64b(DBUF_BUF(db), (d)))
679 #define dbuf_getdstrz(db, d) (buf_getdstrz(DBUF_BUF(db), (d)))
680
681 /* --- @{,d}buf_putdstr{8,{16,24,32,64}{,l,b},z} --- *
682  *
683  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
684  *              @dstr *d@ = string to write
685  *
686  * Returns:     Zero if it worked, nonzero if there wasn't enough space.
687  *
688  * Use:         Puts a dynamic string to a buffer.
689  */
690
691 #define BUF_DECL_PUTDSTR_(n, W, w)                                      \
692   extern int buf_putdstr##w(buf */*b*/, dstr */*d*/);                   \
693   extern int dbuf_putdstr##w(dbuf */*db*/, dstr */*d*/);
694 BUF_DOSUFFIXES(BUF_DECL_PUTDSTR_)
695 #define dbuf_putdstr8(db, d) (buf_putdstr8(DBUF_BUF(db), (d)))
696 #define dbuf_putdstr16(db, d) (buf_putdstr16(DBUF_BUF(db), (d)))
697 #define dbuf_putdstr16l(db, d) (buf_putdstr16l(DBUF_BUF(db), (d)))
698 #define dbuf_putdstr16b(db, d) (buf_putdstr16b(DBUF_BUF(db), (d)))
699 #define dbuf_putdstr24(db, d) (buf_putdstr24(DBUF_BUF(db), (d)))
700 #define dbuf_putdstr24l(db, d) (buf_putdstr24l(DBUF_BUF(db), (d)))
701 #define dbuf_putdstr24b(db, d) (buf_putdstr24b(DBUF_BUF(db), (d)))
702 #define dbuf_putdstr32(db, d) (buf_putdstr32(DBUF_BUF(db), (d)))
703 #define dbuf_putdstr32l(db, d) (buf_putdstr32l(DBUF_BUF(db), (d)))
704 #define dbuf_putdstr32b(db, d) (buf_putdstr32b(DBUF_BUF(db), (d)))
705 #define dbuf_putdstr64(db, d) (buf_putdstr64(DBUF_BUF(db), (d)))
706 #define dbuf_putdstr64l(db, d) (buf_putdstr64l(DBUF_BUF(db), (d)))
707 #define dbuf_putdstr64b(db, d) (buf_putdstr64b(DBUF_BUF(db), (d)))
708 #define dbuf_putdstrz(db, d) (buf_putdstrz(DBUF_BUF(db), (d)))
709
710 /* --- @{,d}buf_putstr{8,{16,24,32,64}{,l,b},z} --- *
711  *
712  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
713  *              @const char *p@ = string to write
714  *
715  * Returns:     Zero if it worked, nonzero if there wasn't enough space.
716  *
717  * Use:         Puts a null-terminated string to a buffer.
718  */
719
720 #define BUF_DECL_PUTSTR_(n, W, w)                                       \
721   extern int buf_putstr##w(buf */*b*/, const char */*p*/);              \
722   extern int dbuf_putstr##w(dbuf */*db*/, const char */*p*/);
723 BUF_DOSUFFIXES(BUF_DECL_PUTSTR_)
724 #define dbuf_putstr8(db, p) (buf_putstr8(DBUF_BUF(db), (p)))
725 #define dbuf_putstr16(db, p) (buf_putstr16(DBUF_BUF(db), (p)))
726 #define dbuf_putstr16l(db, p) (buf_putstr16l(DBUF_BUF(db), (p)))
727 #define dbuf_putstr16b(db, p) (buf_putstr16b(DBUF_BUF(db), (p)))
728 #define dbuf_putstr24(db, p) (buf_putstr24(DBUF_BUF(db), (p)))
729 #define dbuf_putstr24l(db, p) (buf_putstr24l(DBUF_BUF(db), (p)))
730 #define dbuf_putstr24b(db, p) (buf_putstr24b(DBUF_BUF(db), (p)))
731 #define dbuf_putstr32(db, p) (buf_putstr32(DBUF_BUF(db), (p)))
732 #define dbuf_putstr32l(db, p) (buf_putstr32l(DBUF_BUF(db), (p)))
733 #define dbuf_putstr32b(db, p) (buf_putstr32b(DBUF_BUF(db), (p)))
734 #define dbuf_putstr64(db, p) (buf_putstr64(DBUF_BUF(db), (p)))
735 #define dbuf_putstr64l(db, p) (buf_putstr64l(DBUF_BUF(db), (p)))
736 #define dbuf_putstr64b(db, p) (buf_putstr64b(DBUF_BUF(db), (p)))
737 #define dbuf_putstrz(db, p) (buf_putstrz(DBUF_BUF(db), (p)))
738
739 /* --- @{,D}BUF_ENCLOSETAG@ --- *
740  *
741  * Arguments:   @tag@ = a control-structure macro tag
742  *              @buf *b@ or @dbuf *db@ = pointer to a buffer block
743  *              @size_t mk@ = temporary, used to stash starting offset
744  *              @check@ = expression which is true if the length @_delta@
745  *                      is representable
746  *              @poke@ = function or macro called as @poke(octet *, size_t)@
747  *                      to store the final size at the given address
748  *              @size_t lensz@ = space to leave for the length
749  *
750  * Use:         This is a statement head.  It ensures that there is enough
751  *              space in the buffer, saves the current output offset in @mk,
752  *              and reserves @lensz@ bytes for a length prefix.  It then
753  *              executes the @body@, which should contribute zero or more
754  *              further bytes to the buffer.  Finally, it invokes @poke@ to
755  *              store the length of the material written by @body@ in the
756  *              space reserved.
757  */
758
759 #define BUF_ENCLOSETAG(tag, b, mk, check, poke, lensz)                  \
760   MC_BEFORE(tag##__save, {                                              \
761     (mk) = BLEN(b);                                                     \
762     if (!BENSURE(b, lensz)) BSTEP(b, (lensz));                          \
763   })                                                                    \
764   MC_AFTER(tag##__poke, {                                               \
765     size_t _delta = BLEN(b) - (mk) - (lensz);                           \
766     if (!(check)) (b)->f |= BF_BROKEN;                                  \
767     else if (BOK(b)) poke(BBASE(b) + (mk), _delta);                     \
768   })
769
770 #define DBUF_ENCLOSETAG(tag, b, mk, check, poke, lensz)                 \
771   BUF_ENCLOSETAG(tag, DBUF_BUF(b), (mk), (check), poke, (lensz))
772
773 /* --- @{,D}BUF_ENCLOSE{I,K,Z}TAG@ --- *
774  *
775  * Arguments:   @tag@ = a control-structure macro tag
776  *              @buf *b@ or @dbuf *db@ = pointer to a buffer block
777  *              @size_t mk@ = temporary, used to stash starting offset
778  *              @W@ = word-size and -order suffix
779  *
780  * Use:         Specialized versions of @BUF_ENCLOSETAG@ above.
781  *
782  *              @BUF_ENCLOSEZTAG@ just writes a terminating zero byte.
783  *              @BUF_ENCLOSEITAG@ writes a word with the given size and
784  *              byte ordering.  @BUF_ENCLOSEKTAG@ does the same using the
785  *              @kludge64@ machinery.
786  */
787
788 #define MLIB__BUF_STORESZK64(p, sz)                                             \
789   do { kludge64 _k; ASSIGN64(_k, (sz)); STORE64_((p), _k); } while (0)
790 #define MLIB__BUF_STORESZK64_B(p, sz)                                           \
791   do { kludge64 _k; ASSIGN64(_k, (sz)); STORE64_B_((p), _k); } while (0)
792 #define MLIB__BUF_STORESZK64_L(p, sz)                                           \
793   do { kludge64 _k; ASSIGN64(_k, (sz)); STORE64_L_((p), _k); } while (0)
794
795 #define BUF_ENCLOSEITAG(tag, b, mk, W)                                  \
796   BUF_ENCLOSETAG(tag, (b), (mk), (_delta <= MASK##W), STORE##W, SZ_##W)
797 #define BUF_ENCLOSEKTAG(tag, b, mk, W)                                  \
798   BUF_ENCLOSETAG(tag, (b), (mk), 1, MLIB__BUF_STORESZK##W, 8)
799 #define BUF_ENCLOSEZTAG(tag, b)                                         \
800   MC_AFTER(tag##__zero, { buf_putbyte((b), 0); })
801
802 #define DBUF_ENCLOSEITAG(tag, b, mk, W)                                 \
803   BUF_ENCLOSEITAG(tag, DBUF_BUF(b), (mk), W)
804 #define DBUF_ENCLOSEKTAG(tag, b, mk, W)                                 \
805   BUF_ENCLOSEKTAG(tag, DBUF_BUF(b), (mk), W)
806 #define DBUF_ENCLOSEZTAG(tag, b)                                        \
807   BUF_ENCLOSEZTAG(tag, DBUF_BUF(b))
808
809 /* --- @{,D}BUF_ENCLOSE{8,{16,24,32,64}{,_L,_B},Z}@ --- *
810  *
811  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
812  *              @size_t mk@ = temporary, used to stash starting offset
813  *              @W@ = word-size and -order suffix
814  *
815  * Use:         User versions of @BUF_ENCLOSETAG@; see that macro for
816  *              details.
817  *
818  *              These are statement heads.  They reserve space for a length
819  *              prefix and execute the statement.  When the statement
820  *              completes, they patch the length of material written by the
821  *              statement into the reserved space.
822  */
823
824 #define BUF_ENCLOSE8(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 8)
825 #define BUF_ENCLOSE16(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 16)
826 #define BUF_ENCLOSE16_L(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 16_L)
827 #define BUF_ENCLOSE16_B(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 16_B)
828 #define BUF_ENCLOSE24(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 24)
829 #define BUF_ENCLOSE24_L(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 24_L)
830 #define BUF_ENCLOSE24_B(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 24_B)
831 #define BUF_ENCLOSE32(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 32)
832 #define BUF_ENCLOSE32_L(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 32_L)
833 #define BUF_ENCLOSE32_B(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 32_B)
834 #ifdef HAVE_UINT64
835 #  define BUF_ENCLOSE64(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 64)
836 #  define BUF_ENCLOSE64_L(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 64_L)
837 #  define BUF_ENCLOSE64_B(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 64_B)
838 #else
839 #  define BUF_ENCLOSE64(b, mk) BUF_ENCLOSEKTAG(encl, (b), (mk), 64)
840 #  define BUF_ENCLOSE64_L(b, mk) BUF_ENCLOSEKTAG(encl, (b), (mk), 64_L)
841 #  define BUF_ENCLOSE64_B(b, mk) BUF_ENCLOSEKTAG(encl, (b), (mk), 64_B)
842 #endif
843 #define BUF_ENCLOSEZ(b) BUF_ENCLOSEZTAG(encl, (b))
844
845 #define DBUF_ENCLOSE8(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 8)
846 #define DBUF_ENCLOSE16(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 16)
847 #define DBUF_ENCLOSE16_L(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 16_L)
848 #define DBUF_ENCLOSE16_B(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 16_B)
849 #define DBUF_ENCLOSE24(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 24)
850 #define DBUF_ENCLOSE24_L(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 24_L)
851 #define DBUF_ENCLOSE24_B(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 24_B)
852 #define DBUF_ENCLOSE32(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 32)
853 #define DBUF_ENCLOSE32_L(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 32_L)
854 #define DBUF_ENCLOSE32_B(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 32_B)
855 #ifdef HAVE_UINT64
856 #  define DBUF_ENCLOSE64(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 64)
857 #  define DBUF_ENCLOSE64_L(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 64_L)
858 #  define DBUF_ENCLOSE64_B(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 64_B)
859 #else
860 #  define DBUF_ENCLOSE64(db, mk) DBUF_ENCLOSEKTAG(encl, (db), (mk), 64)
861 #  define DBUF_ENCLOSE64_L(db, mk) DBUF_ENCLOSEKTAG(encl, (db), (mk), 64_L)
862 #  define DBUF_ENCLOSE64_B(db, mk) DBUF_ENCLOSEKTAG(encl, (db), (mk), 64_B)
863 #endif
864 #define DBUF_ENCLOSEZ(db) DBUF_ENCLOSEZTAG(encl, (db))
865
866 /* --- @{,d}buf_putstrf@, @{,d}buf_vputstrf@ --- *
867  *
868  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
869  *              @const char *p@ = pointer to @printf@-style format string
870  *              @va_list *ap@ = argument handle
871  *
872  * Returns:     The number of characters written to the string, or @-1@ on
873  *              failure.
874  *
875  * Use:         Format a string to a buffer.  The resulting output is not
876  *              null-terminated.
877  */
878
879 extern PRINTF_LIKE(2, 3)
880   int buf_putstrf(buf */*b*/, const char */*p*/, ...);
881 extern PRINTF_LIKE(2, 3)
882   int dbuf_putstrf(dbuf */*db*/, const char */*p*/, ...);
883 #if __STDC__ >= 199901
884 #  define dbuf_putstrf(db, /*p*/...) (buf_putstr(DBUF_BUF(db), __VA_ARGS__))
885 #endif
886 extern int buf_vputstrf(buf */*b*/, const char */*p*/, va_list */*ap*/);
887 extern int dbuf_vputstrf(dbuf */*db*/, const char */*p*/, va_list */*ap*/);
888 #define dbuf_vputstrf(db, p, ap) (buf_vputstrf(DBUF_BUF(db), (p), (ap)))
889
890 /* --- @{,d}buf_{,v}putstrf{8,{16,24,32,64}{,b,l},z}@ --- *
891  *
892  * Arguments:   @buf *b@ or @dbuf *db@ = pointer to a buffer block
893  *              @const char *p@ = pointer to @printf@-style format string
894  *              @va_list *ap@ = argument handle
895  *
896  * Returns:     The number of characters written to the string, or @-1@ on
897  *              failure.
898  *
899  * Use:         As for @buf_putstr@, but using a format string.
900  */
901
902 #define BUF_DECL_PUTSTRF_(n, W, w)                                      \
903   extern PRINTF_LIKE(2, 3)                                              \
904     int buf_putstrf##w(buf */*b*/, const char */*p*/, ...);             \
905   extern PRINTF_LIKE(2, 3)                                              \
906     int dbuf_putstrf##w(dbuf */*db*/, const char */*p*/, ...);          \
907   extern int buf_vputstrf##w(buf */*b*/,                                \
908                              const char */*p*/, va_list */*ap*/);       \
909   extern int dbuf_vputstrf##w(dbuf */*db*/,                             \
910                               const char */*p*/, va_list */*ap*/);
911 BUF_DOSUFFIXES(BUF_DECL_PUTSTRF_)
912 #if __STDC__ >= 199901
913 #  define dbuf_putstrf8(db, /*p*/...)                                   \
914      (buf_putstrf8(DBUF_BUF(db), __VA_ARGS__))
915 #  define dbuf_putstrf16(db, /*p*/...)                                  \
916      (buf_putstrf16(DBUF_BUF(db), __VA_ARGS__))
917 #  define dbuf_putstrf16l(db, /*p*/...)                                 \
918      (buf_putstrf16l(DBUF_BUF(db), __VA_ARGS__))
919 #  define dbuf_putstrf16b(db, /*p*/...)                                 \
920      (buf_putstrf16b(DBUF_BUF(db), __VA_ARGS__))
921 #  define dbuf_putstrf24(db, /*p*/...)                                  \
922      (buf_putstrf24(DBUF_BUF(db), __VA_ARGS__))
923 #  define dbuf_putstrf24l(db, /*p*/...)                                 \
924      (buf_putstrf24l(DBUF_BUF(db), __VA_ARGS__))
925 #  define dbuf_putstrf24b(db, /*p*/...)                                 \
926      (buf_putstrf24b(DBUF_BUF(db), __VA_ARGS__))
927 #  define dbuf_putstrf32(db, /*p*/...)                                  \
928      (buf_putstrf32(DBUF_BUF(db), __VA_ARGS__))
929 #  define dbuf_putstrf32l(db, /*p*/...)                                 \
930      (buf_putstrf32l(DBUF_BUF(db), __VA_ARGS__))
931 #  define dbuf_putstrf32b(db, /*p*/...)                                 \
932      (buf_putstrf32b(DBUF_BUF(db), __VA_ARGS__))
933 #  define dbuf_putstrf64(db, /*p*/...)                                  \
934      (buf_putstrf64(DBUF_BUF(db), __VA_ARGS__))
935 #  define dbuf_putstrf64l(db, /*p*/...)                                 \
936      (buf_putstrf64l(DBUF_BUF(db), __VA_ARGS__))
937 #  define dbuf_putstrf64b(db, /*p*/...)                                 \
938      (buf_putstrf64b(DBUF_BUF(db), __VA_ARGS__))
939 #  define dbuf_putstrfz(db, /*p*/...)                                   \
940      (buf_putstrfz(DBUF_BUF(db), __VA_ARGS__))
941 #endif
942 #define dbuf_vputstrf8(db, p, ap) (buf_vputstrf8(DBUF_BUF(db), (p), (ap)))
943 #define dbuf_vputstrf16(db, p, ap) (buf_vputstrf16(DBUF_BUF(db), (p), (ap)))
944 #define dbuf_vputstrf16l(db, p, ap) (buf_vputstrf16l(DBUF_BUF(db), (p), (ap)))
945 #define dbuf_vputstrf16b(db, p, ap) (buf_vputstrf16b(DBUF_BUF(db), (p), (ap)))
946 #define dbuf_vputstrf24(db, p, ap) (buf_vputstrf24(DBUF_BUF(db), (p), (ap)))
947 #define dbuf_vputstrf24l(db, p, ap) (buf_vputstrf24l(DBUF_BUF(db), (p), (ap)))
948 #define dbuf_vputstrf24b(db, p, ap) (buf_vputstrf24b(DBUF_BUF(db), (p), (ap)))
949 #define dbuf_vputstrf32(db, p, ap) (buf_vputstrf32(DBUF_BUF(db), (p), (ap)))
950 #define dbuf_vputstrf32l(db, p, ap) (buf_vputstrf32l(DBUF_BUF(db), (p), (ap)))
951 #define dbuf_vputstrf32b(db, p, ap) (buf_vputstrf32b(DBUF_BUF(db), (p), (ap)))
952 #define dbuf_vputstrf64(db, p, ap) (buf_vputstrf64(DBUF_BUF(db), (p), (ap)))
953 #define dbuf_vputstrf64l(db, p, ap) (buf_vputstrf64l(DBUF_BUF(db), (p), (ap)))
954 #define dbuf_vputstrf64b(db, p, ap) (buf_vputstrf64b(DBUF_BUF(db), (p), (ap)))
955 #define dbuf_vputstrfz(db, p, ap) (buf_vputstrfz(DBUF_BUF(db), (p), (ap)))
956
957 /*----- That's all, folks -------------------------------------------------*/
958
959 #ifdef __cplusplus
960   }
961 #endif
962
963 #endif