+void priomsg_new(struct priomsg *pm, int32_t maxlen); /* UF -> Z */
+void priomsg_destroy(struct priomsg *pm, int32_t maxlen); /* FZM -> F */
+void priomsg_reset(struct priomsg *pm); /* FZM -> Z */
+bool_t priomsg_update_p(struct priomsg *pm, int prio); /* ZM -> M */
+ /* returns true iff message of priority prio ought to be added,
+ * caller should then call truncmsg_add_*.
+ * pm may be NULL, in which case it just returns false */
+const char *priomsg_getmessage(const struct priomsg *pm, const char *defmsg);
+ /* return value is null-terminated, valid until next call
+ * or until defmsg is no longer valid ZM */
+
+bool_t priomsg_update_fixed(struct priomsg *pm, int prio, const char *m);
+ /* convenience combination of _update_p and truncmsg_add_string */
+
+/*
+ * void BUF_ADD_BYTES(append, struct buffer_if*, const void*, int32_t size);
+ * void BUF_ADD_BYTES(prepend, struct buffer_if*, const void*, int32_t size);
+ * void BUF_GET_BYTES(unappend, struct buffer_if*, void*, int32_t size);
+ * void BUF_GET_BYTES(unprepend, struct buffer_if*, void*, int32_t size);
+ * // all of these evaluate size twice
+ *
+ * void BUF_ADD_OBJ(append, struct_buffer_if*, const OBJECT& something);
+ * void BUF_ADD_OBJ(prepend, struct_buffer_if*, const OBJECT& something);
+ * void BUF_GET_OBJ(unappend, struct_buffer_if*, OBJECT& something);
+ * void BUF_GET_OBJ(unprepend, struct_buffer_if*, OBJECT& something);
+ */
+#define BUF_ADD_BYTES(appendprepend, bufp, datap, size) \
+ (buf_un##appendprepend /* ensures we have correct direction */, \
+ memcpy(buf_##appendprepend((bufp),(size)),(datap),(size)))
+#define BUF_ADD_OBJ(appendprepend, bufp, obj) \
+ BUF_ADD_BYTES(appendprepend,(bufp),&(obj),sizeof((obj)))
+#define BUF_GET_BYTES(unappendunprepend, bufp, datap, size) \
+ (BUF_GET__DOESNOTEXIST__buf_un##unappendunprepend, \
+ memcpy((datap),buf_##unappendunprepend((bufp),(size)),(size)))
+#define BUF_GET_OBJ(unappendunprepend, bufp, obj) \
+ BUF_ADD_BYTES(unappendunprepend,&(obj),(bufp),sizeof((obj)))
+#define BUF_GET__DOESNOTEXIST__buf_ununappend 0
+#define BUF_GET__DOESNOTEXIST__buf_ununprepend 0
+
+static inline int32_t buf_remaining_space(const struct buffer_if *buf)
+{
+ return (buf->base + buf->alloclen) - (buf->start + buf->size);
+}
+
+extern void buffer_readonly_view(struct buffer_if *n, const void*, int32_t len);
+extern void buffer_readonly_clone(struct buffer_if *n, const struct buffer_if*);
+ /* Caller must only use unappend, unprepend et al. on n.
+ * New buffer state (in n) before this can be undefined. After use,
+ * it must NOT be freed. */
+
+extern void buf_append_string(struct buffer_if *buf, cstring_t s);
+ /* Append a two-byte length and the string to the buffer. Length is in
+ * network byte order. */
+
+static inline int hex_encode_size(int binsize) { return binsize*2 + 1; }
+extern void hex_encode(const uint8_t *bin, int binsize, char *buf);
+ /* Convert a byte array to hex into a supplied buffer. */
+extern string_t hex_encode_alloc(const uint8_t *bin, int binsize);
+ /* Returns the result in a freshly allocated string. */
+
+extern bool_t hex_decode(uint8_t *buffer, int32_t buflen, int32_t *outlen,
+ cstring_t hb, bool_t allow_odd_nibble);
+ /* Convert a hex string to binary, storing the result in buffer. If
+ * allow_odd_nibble then it is acceptable if the input is an odd number of
+ * digits, and an additional leading zero digit is assumed; otherwise, this
+ * is not acceptable and the conversion fails.
+ *
+ * The input is processed left to right until it is consumed, the buffer is
+ * full, or an error is encountered in the input. The length of output
+ * produced is stored in *outlen. Returns true if the entire input was
+ * processed without error; otherwise false. */