+#define dbuf_putstr8(db, p) (buf_putstr8(DBUF_BUF(db), (p)))
+#define dbuf_putstr16(db, p) (buf_putstr16(DBUF_BUF(db), (p)))
+#define dbuf_putstr16l(db, p) (buf_putstr16l(DBUF_BUF(db), (p)))
+#define dbuf_putstr16b(db, p) (buf_putstr16b(DBUF_BUF(db), (p)))
+#define dbuf_putstr24(db, p) (buf_putstr24(DBUF_BUF(db), (p)))
+#define dbuf_putstr24l(db, p) (buf_putstr24l(DBUF_BUF(db), (p)))
+#define dbuf_putstr24b(db, p) (buf_putstr24b(DBUF_BUF(db), (p)))
+#define dbuf_putstr32(db, p) (buf_putstr32(DBUF_BUF(db), (p)))
+#define dbuf_putstr32l(db, p) (buf_putstr32l(DBUF_BUF(db), (p)))
+#define dbuf_putstr32b(db, p) (buf_putstr32b(DBUF_BUF(db), (p)))
+#define dbuf_putstr64(db, p) (buf_putstr64(DBUF_BUF(db), (p)))
+#define dbuf_putstr64l(db, p) (buf_putstr64l(DBUF_BUF(db), (p)))
+#define dbuf_putstr64b(db, p) (buf_putstr64b(DBUF_BUF(db), (p)))
+#define dbuf_putstrz(db, p) (buf_putstrz(DBUF_BUF(db), (p)))
+
+/* --- @{,D}BUF_ENCLOSETAG@ --- *
+ *
+ * Arguments: @tag@ = a control-structure macro tag
+ * @buf *b@ or @dbuf *db@ = pointer to a buffer block
+ * @size_t mk@ = temporary, used to stash starting offset
+ * @check@ = expression which is true if the length @_delta@
+ * is representable
+ * @poke@ = function or macro called as @poke(octet *, size_t)@
+ * to store the final size at the given address
+ * @size_t lensz@ = space to leave for the length
+ *
+ * Use: This is a statement head. It ensures that there is enough
+ * space in the buffer, saves the current output offset in @mk,
+ * and reserves @lensz@ bytes for a length prefix. It then
+ * executes the @body@, which should contribute zero or more
+ * further bytes to the buffer. Finally, it invokes @poke@ to
+ * store the length of the material written by @body@ in the
+ * space reserved.
+ */
+
+#define BUF_ENCLOSETAG(tag, b, mk, check, poke, lensz) \
+ MC_BEFORE(tag##__save, { \
+ (mk) = BLEN(b); \
+ if (!BENSURE(b, lensz)) BSTEP(b, (lensz)); \
+ }) \
+ MC_AFTER(tag##__poke, { \
+ size_t _delta = BLEN(b) - (mk) - (lensz); \
+ if (!(check)) (b)->f |= BF_BROKEN; \
+ else if (BOK(b)) poke(BBASE(b) + (mk), _delta); \
+ })
+
+#define DBUF_ENCLOSETAG(tag, b, mk, check, poke, lensz) \
+ BUF_ENCLOSETAG(tag, DBUF_BUF(b), (mk), (check), poke, (lensz))
+
+/* --- @{,D}BUF_ENCLOSE{I,K,Z}TAG@ --- *
+ *
+ * Arguments: @tag@ = a control-structure macro tag
+ * @buf *b@ or @dbuf *db@ = pointer to a buffer block
+ * @size_t mk@ = temporary, used to stash starting offset
+ * @W@ = word-size and -order suffix
+ *
+ * Use: Specialized versions of @BUF_ENCLOSETAG@ above.
+ *
+ * @BUF_ENCLOSEZTAG@ just writes a terminating zero byte.
+ * @BUF_ENCLOSEITAG@ writes a word with the given size and
+ * byte ordering. @BUF_ENCLOSEKTAG@ does the same using the
+ * @kludge64@ machinery.
+ */
+
+#define MLIB__BUF_STORESZK64(p, sz) \
+ do { kludge64 _k; ASSIGN64(_k, (sz)); STORE64_((p), _k); } while (0)
+#define MLIB__BUF_STORESZK64_B(p, sz) \
+ do { kludge64 _k; ASSIGN64(_k, (sz)); STORE64_B_((p), _k); } while (0)
+#define MLIB__BUF_STORESZK64_L(p, sz) \
+ do { kludge64 _k; ASSIGN64(_k, (sz)); STORE64_L_((p), _k); } while (0)
+
+#define BUF_ENCLOSEITAG(tag, b, mk, W) \
+ BUF_ENCLOSETAG(tag, (b), (mk), (_delta <= MASK##W), STORE##W, SZ_##W)
+#define BUF_ENCLOSEKTAG(tag, b, mk, W) \
+ BUF_ENCLOSETAG(tag, (b), (mk), 1, MLIB__BUF_STORESZK##W, 8)
+#define BUF_ENCLOSEZTAG(tag, b) \
+ MC_AFTER(tag##__zero, { buf_putbyte((b), 0); })
+
+#define DBUF_ENCLOSEITAG(tag, b, mk, W) \
+ BUF_ENCLOSEITAG(tag, DBUF_BUF(b), (mk), W)
+#define DBUF_ENCLOSEKTAG(tag, b, mk, W) \
+ BUF_ENCLOSEKTAG(tag, DBUF_BUF(b), (mk), W)
+#define DBUF_ENCLOSEZTAG(tag, b) \
+ BUF_ENCLOSEZTAG(tag, DBUF_BUF(b))
+
+/* --- @{,D}BUF_ENCLOSE{8,{16,24,32,64}{,_L,_B},Z}@ --- *
+ *
+ * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
+ * @size_t mk@ = temporary, used to stash starting offset
+ * @W@ = word-size and -order suffix
+ *
+ * Use: User versions of @BUF_ENCLOSETAG@; see that macro for
+ * details.
+ *
+ * These are statement heads. They reserve space for a length
+ * prefix and execute the statement. When the statement
+ * completes, they patch the length of material written by the
+ * statement into the reserved space.
+ */
+
+#define BUF_ENCLOSE8(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 8)
+#define BUF_ENCLOSE16(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 16)
+#define BUF_ENCLOSE16_L(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 16_L)
+#define BUF_ENCLOSE16_B(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 16_B)
+#define BUF_ENCLOSE24(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 24)
+#define BUF_ENCLOSE24_L(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 24_L)
+#define BUF_ENCLOSE24_B(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 24_B)
+#define BUF_ENCLOSE32(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 32)
+#define BUF_ENCLOSE32_L(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 32_L)
+#define BUF_ENCLOSE32_B(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 32_B)
+#ifdef HAVE_UINT64
+# define BUF_ENCLOSE64(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 64)
+# define BUF_ENCLOSE64_L(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 64_L)
+# define BUF_ENCLOSE64_B(b, mk) BUF_ENCLOSEITAG(encl, (b), (mk), 64_B)
+#else
+# define BUF_ENCLOSE64(b, mk) BUF_ENCLOSEKTAG(encl, (b), (mk), 64)
+# define BUF_ENCLOSE64_L(b, mk) BUF_ENCLOSEKTAG(encl, (b), (mk), 64_L)
+# define BUF_ENCLOSE64_B(b, mk) BUF_ENCLOSEKTAG(encl, (b), (mk), 64_B)
+#endif
+#define BUF_ENCLOSEZ(b) BUF_ENCLOSEZTAG(encl, (b))
+
+#define DBUF_ENCLOSE8(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 8)
+#define DBUF_ENCLOSE16(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 16)
+#define DBUF_ENCLOSE16_L(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 16_L)
+#define DBUF_ENCLOSE16_B(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 16_B)
+#define DBUF_ENCLOSE24(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 24)
+#define DBUF_ENCLOSE24_L(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 24_L)
+#define DBUF_ENCLOSE24_B(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 24_B)
+#define DBUF_ENCLOSE32(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 32)
+#define DBUF_ENCLOSE32_L(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 32_L)
+#define DBUF_ENCLOSE32_B(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 32_B)
+#ifdef HAVE_UINT64
+# define DBUF_ENCLOSE64(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 64)
+# define DBUF_ENCLOSE64_L(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 64_L)
+# define DBUF_ENCLOSE64_B(db, mk) DBUF_ENCLOSEITAG(encl, (db), (mk), 64_B)
+#else
+# define DBUF_ENCLOSE64(db, mk) DBUF_ENCLOSEKTAG(encl, (db), (mk), 64)
+# define DBUF_ENCLOSE64_L(db, mk) DBUF_ENCLOSEKTAG(encl, (db), (mk), 64_L)
+# define DBUF_ENCLOSE64_B(db, mk) DBUF_ENCLOSEKTAG(encl, (db), (mk), 64_B)
+#endif
+#define DBUF_ENCLOSEZ(db) DBUF_ENCLOSEZTAG(encl, (db))
+
+/* --- @{,d}buf_putstrf@, @{,d}buf_vputstrf@ --- *
+ *
+ * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
+ * @const char *p@ = pointer to @printf@-style format string
+ * @va_list *ap@ = argument handle
+ *
+ * Returns: The number of characters written to the string, or @-1@ on
+ * failure.
+ *
+ * Use: Format a string to a buffer. The resulting output is not
+ * null-terminated.
+ */
+
+extern PRINTF_LIKE(2, 3)
+ int buf_putstrf(buf */*b*/, const char */*p*/, ...);
+extern PRINTF_LIKE(2, 3)
+ int dbuf_putstrf(dbuf */*db*/, const char */*p*/, ...);
+#if __STDC__ >= 199901
+# define dbuf_putstrf(db, /*p*/...) (buf_putstr(DBUF_BUF(db), __VA_ARGS__))
+#endif
+extern int buf_vputstrf(buf */*b*/, const char */*p*/, va_list */*ap*/);
+extern int dbuf_vputstrf(dbuf */*db*/, const char */*p*/, va_list */*ap*/);
+#define dbuf_vputstrf(db, p, ap) (buf_vputstrf(DBUF_BUF(db), (p), (ap)))
+
+/* --- @{,d}buf_{,v}putstrf{8,{16,24,32,64}{,b,l},z}@ --- *
+ *
+ * Arguments: @buf *b@ or @dbuf *db@ = pointer to a buffer block
+ * @const char *p@ = pointer to @printf@-style format string
+ * @va_list *ap@ = argument handle
+ *
+ * Returns: The number of characters written to the string, or @-1@ on
+ * failure.
+ *
+ * Use: As for @buf_putstr@, but using a format string.
+ */
+
+#define BUF_DECL_PUTSTRF_(n, W, w) \
+ extern PRINTF_LIKE(2, 3) \
+ int buf_putstrf##w(buf */*b*/, const char */*p*/, ...); \
+ extern PRINTF_LIKE(2, 3) \
+ int dbuf_putstrf##w(dbuf */*db*/, const char */*p*/, ...); \
+ extern int buf_vputstrf##w(buf */*b*/, \
+ const char */*p*/, va_list */*ap*/); \
+ extern int dbuf_vputstrf##w(dbuf */*db*/, \
+ const char */*p*/, va_list */*ap*/);
+BUF_DOSUFFIXES(BUF_DECL_PUTSTRF_)
+#if __STDC__ >= 199901
+# define dbuf_putstrf8(db, /*p*/...) \
+ (buf_putstrf8(DBUF_BUF(db), __VA_ARGS__))
+# define dbuf_putstrf16(db, /*p*/...) \
+ (buf_putstrf16(DBUF_BUF(db), __VA_ARGS__))
+# define dbuf_putstrf16l(db, /*p*/...) \
+ (buf_putstrf16l(DBUF_BUF(db), __VA_ARGS__))
+# define dbuf_putstrf16b(db, /*p*/...) \
+ (buf_putstrf16b(DBUF_BUF(db), __VA_ARGS__))
+# define dbuf_putstrf24(db, /*p*/...) \
+ (buf_putstrf24(DBUF_BUF(db), __VA_ARGS__))
+# define dbuf_putstrf24l(db, /*p*/...) \
+ (buf_putstrf24l(DBUF_BUF(db), __VA_ARGS__))
+# define dbuf_putstrf24b(db, /*p*/...) \
+ (buf_putstrf24b(DBUF_BUF(db), __VA_ARGS__))
+# define dbuf_putstrf32(db, /*p*/...) \
+ (buf_putstrf32(DBUF_BUF(db), __VA_ARGS__))
+# define dbuf_putstrf32l(db, /*p*/...) \
+ (buf_putstrf32l(DBUF_BUF(db), __VA_ARGS__))
+# define dbuf_putstrf32b(db, /*p*/...) \
+ (buf_putstrf32b(DBUF_BUF(db), __VA_ARGS__))
+# define dbuf_putstrf64(db, /*p*/...) \
+ (buf_putstrf64(DBUF_BUF(db), __VA_ARGS__))
+# define dbuf_putstrf64l(db, /*p*/...) \
+ (buf_putstrf64l(DBUF_BUF(db), __VA_ARGS__))
+# define dbuf_putstrf64b(db, /*p*/...) \
+ (buf_putstrf64b(DBUF_BUF(db), __VA_ARGS__))
+# define dbuf_putstrfz(db, /*p*/...) \
+ (buf_putstrfz(DBUF_BUF(db), __VA_ARGS__))
+#endif
+#define dbuf_vputstrf8(db, p, ap) (buf_vputstrf8(DBUF_BUF(db), (p), (ap)))
+#define dbuf_vputstrf16(db, p, ap) (buf_vputstrf16(DBUF_BUF(db), (p), (ap)))
+#define dbuf_vputstrf16l(db, p, ap) (buf_vputstrf16l(DBUF_BUF(db), (p), (ap)))
+#define dbuf_vputstrf16b(db, p, ap) (buf_vputstrf16b(DBUF_BUF(db), (p), (ap)))
+#define dbuf_vputstrf24(db, p, ap) (buf_vputstrf24(DBUF_BUF(db), (p), (ap)))
+#define dbuf_vputstrf24l(db, p, ap) (buf_vputstrf24l(DBUF_BUF(db), (p), (ap)))
+#define dbuf_vputstrf24b(db, p, ap) (buf_vputstrf24b(DBUF_BUF(db), (p), (ap)))
+#define dbuf_vputstrf32(db, p, ap) (buf_vputstrf32(DBUF_BUF(db), (p), (ap)))
+#define dbuf_vputstrf32l(db, p, ap) (buf_vputstrf32l(DBUF_BUF(db), (p), (ap)))
+#define dbuf_vputstrf32b(db, p, ap) (buf_vputstrf32b(DBUF_BUF(db), (p), (ap)))
+#define dbuf_vputstrf64(db, p, ap) (buf_vputstrf64(DBUF_BUF(db), (p), (ap)))
+#define dbuf_vputstrf64l(db, p, ap) (buf_vputstrf64l(DBUF_BUF(db), (p), (ap)))
+#define dbuf_vputstrf64b(db, p, ap) (buf_vputstrf64b(DBUF_BUF(db), (p), (ap)))
+#define dbuf_vputstrfz(db, p, ap) (buf_vputstrfz(DBUF_BUF(db), (p), (ap)))