return prefix_length + 1;
}
+static unsigned
+format_string(struct nettle_buffer *buffer,
+ unsigned length, const uint8_t *s)
+{
+ unsigned prefix_length = format_prefix(buffer, length);
+ if (!prefix_length)
+ return 0;
+
+ if (buffer && !nettle_buffer_write(buffer, length, s))
+ return 0;
+
+ return prefix_length + length;
+}
+
unsigned
sexp_vformat(struct nettle_buffer *buffer, const char *format, va_list args)
{
switch (*format++)
{
default:
- abort();
-
+ {
+ const char *start = format - 1;
+ unsigned length = 1 + strcspn(format, "()%");
+ unsigned output_length = format_string(buffer, length, start);
+ if (!output_length)
+ return 0;
+
+ done += output_length;
+ format = start + length;
+
+ break;
+ }
case '\0':
assert(!nesting);
{
const char *s;
unsigned length;
- unsigned prefix_length;
+ unsigned output_length;
if (nul_flag)
{
s = va_arg(args, const char *);
}
- prefix_length = format_prefix(buffer, length);
-
- if (!prefix_length)
+ output_length = format_string(buffer, length, s);
+ if (!output_length)
return 0;
- done += prefix_length;
-
- if (buffer && !nettle_buffer_write(buffer, length, s))
- return 0;
-
- done += length;
-
+ done += output_length;
break;
}
case 't':
{
const char *s;
unsigned length;
- unsigned prefix_length;
+ unsigned output_length;
if (nul_flag)
{
return 0;
done++;
- prefix_length = format_prefix(buffer, length);
+ output_length = format_string(buffer, length, s);
- if (!prefix_length)
+ if (!output_length)
return 0;
- done += prefix_length;
-
- if (buffer && !nettle_buffer_write(buffer, length, s))
- return 0;
-
- done += length;
-
+ done += output_length;
+
if (buffer && !NETTLE_BUFFER_PUTC(buffer, ']'))
return 0;
done++;
/* Returns the number of output characters, or 0 on out of memory. If
* buffer == NULL, just compute length.
*
- * Format strings can contained matched parentheses, and the following
+ * Format strings can contained matched parentheses, tokens ("foo" in
+ * the format string is formatted as "3:foo"), and the following
* formatting specifiers:
*
* %s String represented as unsigned length, const uint8_t *data.
* 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. */
+ * FIXME: Allow "%(" for unbalanced parenthesis. */
unsigned
sexp_format(struct nettle_buffer *buffer,
sexp_transport_vformat(struct nettle_buffer *buffer,
const char *format, va_list args);
+/* Classification for advanced syntax. */
+extern const char
+sexp_token_chars[0x80];
+
+#define TOKEN_CHAR(c) ((c) < 0x80 && sexp_token_chars[(c)])
+
#endif /* NETTLE_SEXP_H_INCLUDED */