summaryrefslogtreecommitdiff
path: root/src/sexp.c
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2020-04-14 14:25:18 +0200
committerWerner Koch <wk@gnupg.org>2020-04-14 14:27:21 +0200
commit32b08e38628b3ed409054db05a7f73b1ab86464a (patch)
tree3cd39b55af46f22d92e68e9651556b6c7dce19a6 /src/sexp.c
parent0ff36e04f7cdef961610e7bc674a9c9ef0fd4853 (diff)
downloadlibgcrypt-32b08e38628b3ed409054db05a7f73b1ab86464a.tar.gz
sexp: Extend gcry_sexp_extract_param with a multi-string extractor.
* src/sexp.c (_gcry_sexp_vextract_param): Implement "%#s" control sequence. -- This comes handy to extract a list of flags. Signed-off-by: Werner Koch <wk@gnupg.org>
Diffstat (limited to 'src/sexp.c')
-rw-r--r--src/sexp.c54
1 files changed, 52 insertions, 2 deletions
diff --git a/src/sexp.c b/src/sexp.c
index 4697f77e..72c12d7f 100644
--- a/src/sexp.c
+++ b/src/sexp.c
@@ -2251,6 +2251,7 @@ _gcry_sexp_canon_len (const unsigned char *buffer, size_t length,
* / :: Switch to opaque format
* & :: Switch to buffer descriptor mode - see below.
* %s :: Switch to allocated string arguments.
+ * %#s :: Switch to allocated string arguments for a list of string flags.
* %u :: Switch to unsigned integer arguments.
* %lu :: Switch to unsigned long integer arguments.
* %zu :: Switch to size_t arguments.
@@ -2283,6 +2284,9 @@ _gcry_sexp_canon_len (const unsigned char *buffer, size_t length,
* is too small, the function immediately returns with an error code
* (and LEN set to 0).
*
+ * For a flag list ("%#s") which has other lists as elements these
+ * sub-lists are skipped and a indicated by "()" in the output.
+ *
* PATH is an optional string used to locate a token. The exclamation
* mark separated tokens are used to via gcry_sexp_find_token to find
* a start point inside SEXP.
@@ -2301,7 +2305,7 @@ _gcry_sexp_vextract_param (gcry_sexp_t sexp, const char *path,
const char *s, *s2;
void **array[20];
char arrayisdesc[20];
- int idx;
+ int idx, i;
gcry_sexp_t l1 = NULL;
int mode = '+'; /* Default to GCRYMPI_FMT_USG. */
int submode = 0;
@@ -2331,6 +2335,8 @@ _gcry_sexp_vextract_param (gcry_sexp_t sexp, const char *path,
s++;
else if (*s == 'z' && s[1] == 'u')
s++;
+ else if (*s == '#' && s[1] == 's')
+ s++;
continue;
}
else if (whitespacep (s))
@@ -2414,6 +2420,12 @@ _gcry_sexp_vextract_param (gcry_sexp_t sexp, const char *path,
submode = 'z';
s++;
}
+ else if (*s == '#' && s[1] == 's')
+ {
+ mode = s[1];
+ submode = '#';
+ s++;
+ }
continue;
}
else if (whitespacep (s))
@@ -2524,7 +2536,45 @@ _gcry_sexp_vextract_param (gcry_sexp_t sexp, const char *path,
}
else if (mode == 's')
{
- *array[idx] = _gcry_sexp_nth_string (l1, 1);
+ if (submode == '#')
+ {
+ size_t needed = 0;
+ size_t n;
+ int l1len;
+ char *p;
+
+ l1len = l1? sexp_length (l1) : 0;
+ for (i = 1; i < l1len; i++)
+ {
+ s2 = sexp_nth_data (l1, i, &n);
+ if (!s2)
+ n = 2; /* Not a data element; we use "()". */
+ needed += n + 1;
+ }
+ if (!needed)
+ {
+ *array[idx] = p = xtrymalloc (1);
+ if (p)
+ *p = 0;
+ }
+ else if ((*array[idx] = p = xtrymalloc (needed)))
+ {
+ for (i = 1; i < l1len; i++)
+ {
+ s2 = sexp_nth_data (l1, i, &n);
+ if (!s2)
+ memcpy (p, "()", (n=2));
+ else
+ memcpy (p, s2, n);
+ p[n] = ' ';
+ p += n + 1;
+ }
+ if (p != *array[idx])
+ p[-1] = 0;
+ }
+ }
+ else
+ *array[idx] = _gcry_sexp_nth_string (l1, 1);
if (!*array[idx])
{
rc = gpg_err_code_from_syserror ();