diff options
author | Werner Koch <wk@gnupg.org> | 2020-04-14 14:25:18 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2020-04-14 14:27:21 +0200 |
commit | 32b08e38628b3ed409054db05a7f73b1ab86464a (patch) | |
tree | 3cd39b55af46f22d92e68e9651556b6c7dce19a6 /src | |
parent | 0ff36e04f7cdef961610e7bc674a9c9ef0fd4853 (diff) | |
download | libgcrypt-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')
-rw-r--r-- | src/sexp.c | 54 |
1 files changed, 52 insertions, 2 deletions
@@ -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 (); |