summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sexp-format.c304
-rw-r--r--sexp.h16
2 files changed, 188 insertions, 132 deletions
diff --git a/sexp-format.c b/sexp-format.c
index 217ead31..5c98f7a7 100644
--- a/sexp-format.c
+++ b/sexp-format.c
@@ -71,27 +71,6 @@ format_prefix(struct nettle_buffer *buffer,
return prefix_length + 1;
}
-static unsigned
-format_length_string(struct nettle_buffer *buffer,
- unsigned length, const char *s)
-{
- unsigned done = format_prefix(buffer, length);
- if (!done)
- return 0;
-
- if (buffer && !nettle_buffer_write(buffer, length, s))
- return 0;
-
- return done + length;
-}
-
-static unsigned
-format_string(struct nettle_buffer *buffer,
- const char *s)
-{
- return format_length_string(buffer, strlen(s), s);
-}
-
unsigned
sexp_vformat(struct nettle_buffer *buffer, const char *format, va_list args)
{
@@ -127,133 +106,200 @@ sexp_vformat(struct nettle_buffer *buffer, const char *format, va_list args)
break;
case '%':
- switch (*format++)
- {
- default:
- abort();
-
- case 'z':
- {
- const char *s = va_arg(args, const char *);
- unsigned length = format_string(buffer, s);
-
- if (!length)
- return 0;
+ {
+ int nul_flag = 0;
- done += length;
- break;
+ if (*format == '0')
+ {
+ format++;
+ nul_flag = 1;
}
- case 's':
+ switch (*format++)
{
- unsigned length = va_arg(args, unsigned);
- const char *s = va_arg(args, const char *);
- unsigned prefix_length = format_prefix(buffer, length);
-
- if (!prefix_length)
- return 0;
+ default:
+ abort();
- done += prefix_length;
+ case 's':
+ {
+ const char *s;
+ unsigned length;
+ unsigned prefix_length;
+
+ if (nul_flag)
+ {
+ s = va_arg(args, const char *);
+ length = strlen(s);
+ }
+ else
+ {
+ length = va_arg(args, unsigned);
+ s = va_arg(args, const char *);
+ }
+
+ prefix_length = format_prefix(buffer, length);
+
+ if (!prefix_length)
+ return 0;
+
+ done += prefix_length;
+
+ if (buffer && !nettle_buffer_write(buffer, length, s))
+ return 0;
+
+ done += length;
+
+ break;
+ }
+ case 't':
+ {
+ const char *s;
+ unsigned length;
+ unsigned prefix_length;
+
+ if (nul_flag)
+ {
+ s = va_arg(args, const char *);
+ if (!s)
+ break;
+
+ length = strlen(s);
+ }
+ else
+ {
+ length = va_arg(args, unsigned);
+ s = va_arg(args, const char *);
+ if (!s)
+ break;
+ }
+
+ if (buffer && !NETTLE_BUFFER_PUTC(buffer, '['))
+ return 0;
+ done++;
+
+ prefix_length = format_prefix(buffer, length);
+
+ if (!prefix_length)
+ return 0;
- if (buffer && !nettle_buffer_write(buffer, length, s))
- return 0;
+ done += prefix_length;
- done += length;
+ if (buffer && !nettle_buffer_write(buffer, length, s))
+ return 0;
- break;
- }
- case 'l':
- {
- unsigned length = va_arg(args, unsigned);
- const char *s = va_arg(args, const char *);
+ done += length;
- if (buffer && !nettle_buffer_write(buffer, length, s))
- return 0;
+ if (buffer && !NETTLE_BUFFER_PUTC(buffer, ']'))
+ return 0;
+ done++;
+
+ break;
+ }
- done += length;
- break;
- }
- case 'i':
- {
- uint32_t x = va_arg(args, uint32_t);
- unsigned length;
+ case 'l':
+ {
+ const char *s;
+ unsigned length;
+
+ if (nul_flag)
+ {
+ s = va_arg(args, const char *);
+ length = strlen(s);
+ }
+ else
+ {
+ length = va_arg(args, unsigned);
+ s = va_arg(args, const char *);
+ }
+
+ if (buffer && !nettle_buffer_write(buffer, length, s))
+ return 0;
- if (x < 0x80)
- length = 1;
- else if (x < 0x8000L)
- length = 2;
- else if (x < 0x800000L)
- length = 3;
- else if (x < 0x80000000L)
- length = 4;
- else
- length = 5;
+ done += length;
+ break;
+ }
+ case 'i':
+ {
+ uint32_t x = va_arg(args, uint32_t);
+ unsigned length;
- if (buffer && !(NETTLE_BUFFER_PUTC(buffer, '0' + length)
- && NETTLE_BUFFER_PUTC(buffer, ':')))
- return 0;
-
- done += (2 + length);
-
- if (buffer)
- switch(length)
- {
- case 5:
- /* Leading byte needed for the sign. */
- if (!NETTLE_BUFFER_PUTC(buffer, 0))
- return 0;
- /* Fall through */
- case 4:
- if (!NETTLE_BUFFER_PUTC(buffer, x >> 24))
- return 0;
- /* Fall through */
- case 3:
- if (!NETTLE_BUFFER_PUTC(buffer, (x >> 16) & 0xff))
- return 0;
- /* Fall through */
- case 2:
- if (!NETTLE_BUFFER_PUTC(buffer, (x >> 8) & 0xff))
- return 0;
- /* Fall through */
- case 1:
- if (!NETTLE_BUFFER_PUTC(buffer, x & 0xff))
- return 0;
- break;
- default:
- abort();
- }
- break;
- }
- case 'b':
- {
+ if (x < 0x80)
+ length = 1;
+ else if (x < 0x8000L)
+ length = 2;
+ else if (x < 0x800000L)
+ length = 3;
+ else if (x < 0x80000000L)
+ length = 4;
+ else
+ length = 5;
+
+ if (buffer && !(NETTLE_BUFFER_PUTC(buffer, '0' + length)
+ && NETTLE_BUFFER_PUTC(buffer, ':')))
+ return 0;
+
+ done += (2 + length);
+
+ if (buffer)
+ switch(length)
+ {
+ case 5:
+ /* Leading byte needed for the sign. */
+ if (!NETTLE_BUFFER_PUTC(buffer, 0))
+ return 0;
+ /* Fall through */
+ case 4:
+ if (!NETTLE_BUFFER_PUTC(buffer, x >> 24))
+ return 0;
+ /* Fall through */
+ case 3:
+ if (!NETTLE_BUFFER_PUTC(buffer, (x >> 16) & 0xff))
+ return 0;
+ /* Fall through */
+ case 2:
+ if (!NETTLE_BUFFER_PUTC(buffer, (x >> 8) & 0xff))
+ return 0;
+ /* Fall through */
+ case 1:
+ if (!NETTLE_BUFFER_PUTC(buffer, x & 0xff))
+ return 0;
+ break;
+ default:
+ abort();
+ }
+ break;
+ }
+ case 'b':
+ {
#if HAVE_LIBGMP
- const MP_INT *n = va_arg(args, const MP_INT *);
- unsigned length;
- unsigned prefix_length;
+ const MP_INT *n = va_arg(args, const MP_INT *);
+ unsigned length;
+ unsigned prefix_length;
- length = nettle_mpz_sizeinbase_256_s(n);
- prefix_length = format_prefix(buffer, length);
- if (!prefix_length)
- return 0;
-
- done += prefix_length;
-
- if (buffer)
- {
- uint8_t *space = nettle_buffer_space(buffer, length);
- if (!space)
- return 0;
+ length = nettle_mpz_sizeinbase_256_s(n);
+ prefix_length = format_prefix(buffer, length);
+ if (!prefix_length)
+ return 0;
+
+ done += prefix_length;
+
+ if (buffer)
+ {
+ uint8_t *space = nettle_buffer_space(buffer, length);
+ if (!space)
+ return 0;
- nettle_mpz_get_str_256(length, space, n);
- }
+ nettle_mpz_get_str_256(length, space, n);
+ }
- done += length;
+ done += length;
#else /* ! HAVE_LIBGMP */
- abort();
+ abort();
#endif /* ! HAVE_LIBGMP */
- break;
+ break;
+ }
}
- }
+ }
}
}
diff --git a/sexp.h b/sexp.h
index 7baee5b8..aa86db24 100644
--- a/sexp.h
+++ b/sexp.h
@@ -137,10 +137,12 @@ struct nettle_buffer;
* Format strings can contained matched parentheses, and the following
* formatting specifiers:
*
- * %z NUL-terminated string, const uint8_t *.
- *
* %s String represented as unsigned length, const uint8_t *data.
*
+ * %t Optional display type, represented as
+ * unsigned display_length, const uint8_t *display,
+ * display == NULL means no display type.
+ *
* %i Non-negative small integer, uint32_t.
*
* %b Non-negative bignum, mpz_t.
@@ -148,7 +150,15 @@ struct nettle_buffer;
* %l Literal string (no length added), typically a balanced
* subexpression. Represented as unsigned length, const uint8_t
* *data.
- */
+ *
+ * Modifiers:
+ *
+ * %0 For %s, %t and %l, says that there's no length argument,
+ * instead the string is NUL-terminated, and there's only one
+ * const uint8_t * argument.
+ *
+ * FIXME: Allow literals, like "(x%b)". Allow "%(" for unbalanced
+ * parenthesis. */
unsigned
sexp_format(struct nettle_buffer *buffer,