- /* --- Structured information encoding --- *
- *
- * The format for structured key data is `[NAME=KEY,...]', where the
- * brackets are part of the syntax. Structured keys have no flags apart
- * from the encoding.
- *
- * The binary encoding only allows names up to 255 bytes long. Check for
- * this here.
- */
-
- case KENC_STRUCT: {
- dstr d = DSTR_INIT;
- char *q;
-
- /* --- Read the opening bracket --- */
-
- k->e &= KF_ENCMASK;
- if (*p != '[')
- return (-1);
- p++;
- sym_create(&k->u.s);
-
- /* --- Read named key subparts --- */
-
- for (;;) {
- size_t sz;
- key_struct *ks;
-
- /* --- Stop if there's a close-bracket --- *
- *
- * This allows `[]' to be an empty structured key, which is good. It
- * also makes `[foo=enc:bar,]' legal, and that's less good but I can
- * live with it.
- */
-
- if (*p == ']')
- break;
-
- /* --- Read the name out and check the length --- */
-
- if ((q = strchr(p, '=')) == 0)
- goto fail;
- sz = q - p;
- if (sz >= 256)
- goto fail;
- DRESET(&d);
- DPUTM(&d, p, sz);
- DPUTZ(&d);
-
- /* --- Add an appropriate block to the key table --- *
- *
- * Simply destroy old data if there's already a match.
- */
-
- {
- unsigned f;
- ks = sym_find(&k->u.s, d.buf, d.len + 1, sizeof(*ks), &f);
- if (f)
- key_destroy(&ks->k);
- }
-
- /* --- Read the key data for the subkey --- */
-
- if (key_read(q + 1, &ks->k, &q)) {
- sym_remove(&k->u.s, ks);
- goto fail;
- }
- p = q;
-
- /* --- Read the comma or close-bracket --- */
-
- if (*p == ']')
- break;
- else if (*p == ',')
- p++;
- else
- goto fail;
- }
-
- /* --- Step past the close bracket --- */
-
- p++;
- dstr_destroy(&d);
- break;
-
- /* --- Tidy up after a failure --- */
-
- fail:
- dstr_destroy(&d);
- key_destroy(k);
- return (-1);
- } break;
-
- /* --- Anything else is unknown --- */
-
- default:
- return (-1);
- }
-
- /* --- Return the end pointer --- */
-
- if (pp)
- *pp = (char *)p;
- return (0);
-}
-
-/* --- @key_write@ --- *
- *
- * Arguments: @key_data *k@ = pointer to key data
- * @dstr *d@ = destination string to write on
- * @const key_filter *kf@ = pointer to key selection block
- *
- * Returns: Nonzero if an item was actually written.
- *
- * Use: Writes a key in a textual encoding.
- */
-
-int key_write(key_data *k, dstr *d, const key_filter *kf)
-{
- int rc = 0;