[U-Boot] [PATCH v3 4/6] vsprintf: Introduce ugly macros to reduce code size

Simon Glass sjg at chromium.org
Tue Oct 18 03:54:16 CEST 2011


Even with CONFIG_SYS_VSNPRINT not defined, the code size is a little larger
(12 bytes on ARM). This ugly change could be used to fix that. I am very
doubtful that we want to go this far.

Even if we do, perhaps we would be better defining the functions as normal
(with an end parameter) and then using macros to optionally remove that
parameter. But neither option is great so I am sending this as is for
comment. Hopefully there is a better way, or we can just drop this patch.

This generates a checkpatch warning:
error: lib/vsprintf.c,309: Macros with complex values should be enclosed in
parenthesis

Signed-off-by: Simon Glass <sjg at chromium.org>
---
Changes in v3:
- Add ugly macros to reduce code size

 lib/vsprintf.c |   59 +++++++++++++++++++++++++++++++------------------------
 1 files changed, 33 insertions(+), 26 deletions(-)

diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 5eaf87c..65c0984 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -300,11 +300,20 @@ static noinline char* put_dec(char *buf, unsigned NUM_TYPE num)
 		*(str) = (ch); \
 	++str; \
 	} while (0)
+
+/*
+ * Macros to declare and use the end pointer, depending on whether we are
+ * using one or not.
+ */
+#define DECLARE_END char *end,
+#define USE_END end,
 #else
 #define ADDCH(str, ch)	(*(str)++ = (ch))
+#define DECLARE_END
+#define USE_END
 #endif
 
-static char *number(char *buf, char *end, unsigned NUM_TYPE num,
+static char *number(char *buf, DECLARE_END unsigned NUM_TYPE num,
 		int base, int size, int precision, int type)
 {
 	/* we are called with base 8, 10 or 16, only, thus don't need "G..."  */
@@ -399,7 +408,7 @@ static char *number(char *buf, char *end, unsigned NUM_TYPE num,
 	return buf;
 }
 
-static char *string(char *buf, char *end, char *s, int field_width,
+static char *string(char *buf, DECLARE_END char *s, int field_width,
 		int precision, int flags)
 {
 	int len, i;
@@ -420,8 +429,8 @@ static char *string(char *buf, char *end, char *s, int field_width,
 }
 
 #ifdef CONFIG_CMD_NET
-static char *mac_address_string(char *buf, char *end, u8 *addr, int field_width,
-				int precision, int flags)
+static char *mac_address_string(char *buf, DECLARE_END u8 *addr,
+				int field_width, int precision, int flags)
 {
 	char mac_addr[6 * 3]; /* (6 * 2 hex digits), 5 colons and trailing zero */
 	char *p = mac_addr;
@@ -438,7 +447,7 @@ static char *mac_address_string(char *buf, char *end, u8 *addr, int field_width,
 		      flags & ~SPECIAL);
 }
 
-static char *ip6_addr_string(char *buf, char *end, u8 *addr, int field_width,
+static char *ip6_addr_string(char *buf, DECLARE_END u8 *addr, int field_width,
 			 int precision, int flags)
 {
 	char ip6_addr[8 * 5]; /* (8 * 4 hex digits), 7 colons and trailing zero */
@@ -457,7 +466,7 @@ static char *ip6_addr_string(char *buf, char *end, u8 *addr, int field_width,
 		      flags & ~SPECIAL);
 }
 
-static char *ip4_addr_string(char *buf, char *end, u8 *addr, int field_width,
+static char *ip4_addr_string(char *buf, DECLARE_END u8 *addr, int field_width,
 			 int precision, int flags)
 {
 	char ip4_addr[4 * 4]; /* (4 * 3 decimal digits), 3 dots and trailing zero */
@@ -498,11 +507,11 @@ static char *ip4_addr_string(char *buf, char *end, u8 *addr, int field_width,
  * function pointers are really function descriptors, which contain a
  * pointer to the real address.
  */
-static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
+static char *pointer(const char *fmt, char *buf, DECLARE_END void *ptr,
 		int field_width, int precision, int flags)
 {
 	if (!ptr)
-		return string(buf, end, "(null)", field_width, precision,
+		return string(buf, USE_END "(null)", field_width, precision,
 			      flags);
 
 #ifdef CONFIG_CMD_NET
@@ -511,17 +520,17 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
 		flags |= SPECIAL;
 		/* Fallthrough */
 	case 'M':
-		return mac_address_string(buf, end, ptr, field_width,
+		return mac_address_string(buf, USE_END ptr, field_width,
 					  precision, flags);
 	case 'i':
 		flags |= SPECIAL;
 		/* Fallthrough */
 	case 'I':
 		if (fmt[1] == '6')
-			return ip6_addr_string(buf, end, ptr, field_width,
+			return ip6_addr_string(buf, USE_END ptr, field_width,
 					       precision, flags);
 		if (fmt[1] == '4')
-			return ip4_addr_string(buf, end, ptr, field_width,
+			return ip4_addr_string(buf, USE_END ptr, field_width,
 					       precision, flags);
 		flags &= ~SPECIAL;
 		break;
@@ -532,7 +541,7 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
 		field_width = 2*sizeof(void *);
 		flags |= ZEROPAD;
 	}
-	return number(buf, end, (unsigned long)ptr, 16, field_width,
+	return number(buf, USE_END(unsigned long)ptr, 16, field_width,
 		      precision, flags);
 }
 
@@ -555,8 +564,11 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
  * Call this function if you are already dealing with a va_list.
  * You probably want snprintf() instead.
  */
-static int vsnprintf_internal(char *buf, size_t size, const char *fmt,
-			      va_list args)
+#ifdef CONFIG_SYS_VSNPRINT
+int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
+#else
+int vsprintf(char *buf, const char *fmt, va_list args)
+#endif
 {
 	unsigned NUM_TYPE num;
 	int base;
@@ -571,6 +583,7 @@ static int vsnprintf_internal(char *buf, size_t size, const char *fmt,
 				/* 'z' support added 23/7/1999 S.H.    */
 				/* 'z' changed to 'Z' --davidm 1/25/99 */
 				/* 't' added for ptrdiff_t */
+#ifdef CONFIG_SYS_VSNPRINT
 	char *end = buf + size;
 
 	/* Make sure end is always >= buf - do we want this in U-Boot? */
@@ -578,7 +591,7 @@ static int vsnprintf_internal(char *buf, size_t size, const char *fmt,
 		end = ((void *)-1);
 		size = end - buf;
 	}
-
+#endif
 	str = buf;
 
 	for (; *fmt ; ++fmt) {
@@ -655,12 +668,12 @@ static int vsnprintf_internal(char *buf, size_t size, const char *fmt,
 			continue;
 
 		case 's':
-			str = string(str, end, va_arg(args, char *),
+			str = string(str, USE_END va_arg(args, char *),
 				     field_width, precision, flags);
 			continue;
 
 		case 'p':
-			str = pointer(fmt+1, str, end,
+			str = pointer(fmt+1, str, USE_END
 					va_arg(args, void *),
 					field_width, precision, flags);
 			/* Skip all alphanumeric pointer suffixes */
@@ -726,7 +739,7 @@ static int vsnprintf_internal(char *buf, size_t size, const char *fmt,
 			if (flags & SIGN)
 				num = (signed int) num;
 		}
-		str = number(str, end, num, base, field_width, precision,
+		str = number(str, USE_END num, base, field_width, precision,
 			     flags);
 	}
 
@@ -744,12 +757,6 @@ static int vsnprintf_internal(char *buf, size_t size, const char *fmt,
 }
 
 #ifdef CONFIG_SYS_VSNPRINT
-int vsnprintf(char *buf, size_t size, const char *fmt,
-			      va_list args)
-{
-	return vsnprintf_internal(buf, size, fmt, args);
-}
-
 /**
  * Format a string and place it in a buffer (va_list version)
  *
@@ -829,7 +836,6 @@ int scnprintf(char *buf, size_t size, const char *fmt, ...)
 
 	return i;
 }
-#endif /* CONFIG_SYS_VSNPRINT */
 
 /**
  * Format a string and place it in a buffer (va_list version)
@@ -846,8 +852,9 @@ int scnprintf(char *buf, size_t size, const char *fmt, ...)
  */
 int vsprintf(char *buf, const char *fmt, va_list args)
 {
-	return vsnprintf_internal(buf, INT_MAX, fmt, args);
+	return vsnprintf(buf, INT_MAX, fmt, args);
 }
+#endif /* CONFIG_SYS_VSNPRINT */
 
 /**
  * Format a string and place it in a buffer
-- 
1.7.3.1



More information about the U-Boot mailing list