From 1c323788782c3a5d59153972e532cb079f14b120 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20M=C3=B6ller?= <nisse@lysator.liu.se>
Date: Wed, 4 Dec 2002 10:42:31 +0100
Subject: [PATCH] (format_length_string): Deleted function. (format_string):
 Deleted function. (sexp_vformat): New %t specifier, formatting an optional
 display type. Deleted %z specifier. Instead, introduced a new modifier "0"
 that can be used with %s, %l and %t, which says that the data is
 NUL-terminated.

Rev: src/nettle/sexp-format.c:1.5
Rev: src/nettle/sexp.h:1.11
---
 sexp-format.c | 304 +++++++++++++++++++++++++++++---------------------
 sexp.h        |  16 ++-
 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,
-- 
GitLab