+/* --- @buf_putf64{,b,l} --- *
+ *
+ * Arguments: @buf *b@ = a buffer to write to
+ * @double x@ = a number to write
+ *
+ * Returns: Zero on success, @-1@ on failure (and the buffer is broken).
+ *
+ * On C89, this function can't detect negative zero so these
+ * will be silently written as positive zero.
+ *
+ * This function doesn't distinguish NaNs. Any NaN is written
+ * as a quiet NaN with all payload bits zero.
+ *
+ * A finite value with too large a magnitude to be represented
+ * is rounded to the appropriate infinity. Other finite values
+ * are rounded as necessary, in the usual IEEE 754 round-to-
+ * nearest-or-even way.
+ */
+
+extern int buf_putf64(buf */*b*/, double /*x*/);
+extern int buf_putf64b(buf */*b*/, double /*x*/);
+extern int buf_putf64l(buf */*b*/, double /*x*/);
+
+/* --- @buf_getf64{,b,l} --- *
+ *
+ * Arguments: @buf *b@ = a buffer to read from
+ * @double *x_out@ = where to put the result
+ *
+ * Returns: Zero on success, @-1@ on failure (and the buffer is broken).
+ *
+ * If the system supports NaNs, then any encoded NaN is returned
+ * as the value of @NAN@ in @<math.h>@; otherwise, this function
+ * reports failure.
+ *
+ * In general, values are rounded to the nearest available
+ * value, in the way that the system usually rounds. If the
+ * system doesn't support infinities, then any encoded infinity
+ * is reported as the largest-possible-magnitude finite value
+ * instead.
+ */
+
+extern int buf_getf64(buf */*b*/, double *x_/*out*/);
+extern int buf_getf64b(buf */*b*/, double *x_/*out*/);
+extern int buf_getf64l(buf */*b*/, double *x_/*out*/);
+
+#define BUF_ENCLOSETAG(tag, buf, mk, check, poke, lensz) \
+ MC_BEFORE(tag##__save, \
+ { (mk) = BLEN(buf); \
+ if (!BENSURE(buf, lensz)) (buf)->p += (lensz); }) \
+ MC_AFTER(tag##__poke, \
+ { size_t _delta = BLEN(buf) - (mk) + (lensz); \
+ assert(check); \
+ if (BOK(buf)) poke((buf)->base + (mk), _delta); })
+
+#define BUF_ENCLOSEZTAG(tag, buf) \
+ MC_AFTER(tag##__zero, { buf_putbyte(buf, 0); })
+
+#define BUF_ENCLOSENATIVETAG(tag, buf, mk, W) \
+ BUF_ENCLOSETAG(tag, buf, mk, (_delta <= MASK##W), STORE##W, SZ_##W)
+
+#define BUF_STORESZK64(p, sz) \
+ do { kludge64 _k; ASSIGN64(_k, (sz)); STORE64_((p), _k); } while (0)
+#define BUF_STORESZK64_B(p, sz) \
+ do { kludge64 _k; ASSIGN64(_k, (sz)); STORE64_B_((p), _k); } while (0)
+#define BUF_STORESZK64_L(p, sz) \
+ do { kludge64 _k; ASSIGN64(_k, (sz)); STORE64_L_((p), _k); } while (0)
+#define BUF_ENCLOSEK64TAG(tag, buf, mk, W) \
+ BUF_ENCLOSE(tag, buf, mk, 1, BUF_STORESZK##W, 8)
+
+#define BUF_ENCLOSE8(buf, mk) BUF_ENCLOSENATIVETAG(encl, buf, mk, 8)
+#define BUF_ENCLOSE16(buf, mk) BUF_ENCLOSENATIVETAG(encl, buf, mk, 16)
+#define BUF_ENCLOSE16_B(buf, mk) BUF_ENCLOSENATIVETAG(encl, buf, mk, 16_B)
+#define BUF_ENCLOSE16_L(buf, mk) BUF_ENCLOSENATIVETAG(encl, buf, mk, 16_L)
+#define BUF_ENCLOSE24(buf, mk) BUF_ENCLOSENATIVETAG(encl, buf, mk, 24)
+#define BUF_ENCLOSE24_B(buf, mk) BUF_ENCLOSENATIVETAG(encl, buf, mk, 24_B)
+#define BUF_ENCLOSE24_L(buf, mk) BUF_ENCLOSENATIVETAG(encl, buf, mk, 24_L)
+#define BUF_ENCLOSE32(buf, mk) BUF_ENCLOSENATIVETAG(encl, buf, mk, 32)
+#define BUF_ENCLOSE32_B(buf, mk) BUF_ENCLOSENATIVETAG(encl, buf, mk, 32_B)
+#define BUF_ENCLOSE32_L(buf, mk) BUF_ENCLOSENATIVETAG(encl, buf, mk, 32_L)
+#ifdef HAVE_UINT64
+# define BUF_ENCLOSE64(buf, mk) BUF_ENCLOSENATIVETAG(encl, buf, mk, 64)
+# define BUF_ENCLOSE64_B(buf, mk) BUF_ENCLOSENATIVETAG(encl, buf, mk, 64_B)
+# define BUF_ENCLOSE64_L(buf, mk) BUF_ENCLOSENATIVETAG(encl, buf, mk, 64_L)
+#else
+# define BUF_ENCLOSE64(buf, mk) BUF_ENCLOSEK64TAG(encl, buf, mk, 64)
+# define BUF_ENCLOSE64_B(buf, mk) BUF_ENCLOSEK64TAG(encl, buf, mk, 64_B)
+# define BUF_ENCLOSE64_L(buf, mk) BUF_ENCLOSEK64TAG(encl, buf, mk, 64_L)
+#endif
+#define BUF_ENCLOSEZ(buf) BUF_ENCLOSEZTAG(encl, buf)
+
+/* --- @buf_vputstrf@ --- *
+ *
+ * Arguments: @buf *b@ = pointer to a buffer
+ * @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_putstrf@, but may be used as a back-end to user-
+ * supplied functions with @printf@-style interfaces.
+ */
+
+extern int buf_vputstrf(buf */*b*/, const char */*p*/, va_list */*ap*/);
+
+/* --- @buf_putstrf@ --- *
+ *
+ * Arguments: @buf *b@ = pointer to a buffer
+ * @const char *p@ = pointer to @printf@-style format string
+ * @...@ = 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*/, ...);
+
+/* --- @buf_{,v}putstrf{8,{16,24,32,64}{,b,l},z}@ --- *
+ *
+ * Arguments: @buf *b@ = pointer to a buffer
+ * @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 int buf_vputstrf##w(buf */*b*/, \
+ const char */*p*/, va_list */*ap*/); \
+ extern PRINTF_LIKE(2, 3) \
+ int buf_putstrf##w(buf */*b*/, const char */*p*/, ...);
+BUF_DOSUFFIXES(BUF_DECL_PUTSTRF_)
+#undef BUF_DECL_PUTSTRF_
+