Module Name:    src
Committed By:   tsutsui
Date:           Tue Jan 19 15:26:45 UTC 2010

Modified Files:
        src/sys/lib/libsa: subr_prf.c

Log Message:
Add long long (%lld etc.) support and width (%02x etc.) support
in libsa printf(3).  Disabled by default but enabled by
-DLIBSA_PRINTF_LONGLONG_SUPPORT and -DLIBSA_PRINTF_WIDTH_SUPPORT.
Provided by tnozaki@ for my libsa debugging. Thanks!


To generate a diff of this commit:
cvs rdiff -u -r1.16 -r1.17 src/sys/lib/libsa/subr_prf.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/lib/libsa/subr_prf.c
diff -u src/sys/lib/libsa/subr_prf.c:1.16 src/sys/lib/libsa/subr_prf.c:1.17
--- src/sys/lib/libsa/subr_prf.c:1.16	Sat Nov 24 13:20:57 2007
+++ src/sys/lib/libsa/subr_prf.c	Tue Jan 19 15:26:45 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: subr_prf.c,v 1.16 2007/11/24 13:20:57 isaki Exp $	*/
+/*	$NetBSD: subr_prf.c,v 1.17 2010/01/19 15:26:45 tsutsui Exp $	*/
 
 /*-
  * Copyright (c) 1993
@@ -42,7 +42,25 @@
 
 #include "stand.h"
 
-static void kprintn(void (*)(int), u_long, int);
+#ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
+#define INTMAX_T	longlong_t
+#define UINTMAX_T	u_longlong_t
+#else
+#define INTMAX_T	long
+#define UINTMAX_T	u_long
+#endif
+
+#if 0 /* XXX: abuse intptr_t until the situation with ptrdiff_t is clear */
+#define PTRDIFF_T	ptrdiff_t
+#else
+#define PTRDIFF_T	intptr_t
+#endif
+
+#ifdef LIBSA_PRINTF_WIDTH_SUPPORT
+static void kprintn(void (*)(int), UINTMAX_T, int, int, int);
+#else
+static void kprintn(void (*)(int), UINTMAX_T, int);
+#endif
 static void sputchar(int);
 static void kdoprnt(void (*)(int), const char *, va_list);
 
@@ -51,6 +69,65 @@
 const char HEXDIGITS[] = "0123456789ABCDEF";
 const char hexdigits[] = "0123456789abcdef";
 
+#define LONG		0x01
+#ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
+#define LLONG		0x02
+#endif
+#ifdef LIBSA_PRINTF_WIDTH_SUPPORT
+#define ALT		0x04
+#define SPACE		0x08
+#define LADJUST		0x10
+#define SIGN		0x20
+#define ZEROPAD		0x40
+#define NEGATIVE	0x80
+#define KPRINTN(base)	kprintn(put, ul, base, lflag, width)
+#define RZERO()							\
+do {								\
+	if ((lflag & (ZEROPAD|LADJUST)) == ZEROPAD) {		\
+		while (width-- > 0)				\
+			put('0');				\
+	}							\
+} while (/*CONSTCOND*/0)
+#define RPAD()							\
+do {								\
+	if (lflag & LADJUST) {					\
+		while (width-- > 0)				\
+			put(' ');				\
+	}							\
+} while (/*CONSTCOND*/0)
+#define LPAD()							\
+do {								\
+	if ((lflag & (ZEROPAD|LADJUST)) == 0) {			\
+		while (width-- > 0)				\
+			put(' ');				\
+	}							\
+} while (/*CONSTCOND*/0)
+#else	/* LIBSA_PRINTF_WIDTH_SUPPORT */
+#define KPRINTN(base)	kprintn(put, ul, base)
+#define RZERO()		/**/
+#define RPAD()		/**/
+#define LPAD()		/**/
+#endif	/* LIBSA_PRINTF_WIDTH_SUPPORT */
+
+#ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
+#define KPRINT(base)						\
+do {								\
+	ul = (lflag & LLONG)					\
+	    ? va_arg(ap, u_longlong_t)				\
+	    : (lflag & LONG)					\
+		? va_arg(ap, u_long)				\
+		: va_arg(ap, u_int);				\
+	KPRINTN(base);						\
+} while (/*CONSTCOND*/0)
+#else	/* LIBSA_PRINTF_LONGLONG_SUPPORT */
+#define KPRINT(base)						\
+do {								\
+	ul = (lflag & LONG)					\
+	    ? va_arg(ap, u_long) : va_arg(ap, u_int);		\
+	KPRINTN(base);						\
+} while (/*CONSTCOND*/0)
+#endif	/* LIBSA_PRINTF_LONGLONG_SUPPORT */
+
 static void
 sputchar(int c)
 {
@@ -82,8 +159,12 @@
 {
 	char *p;
 	int ch;
-	unsigned long ul;
+	UINTMAX_T ul;
 	int lflag;
+#ifdef LIBSA_PRINTF_WIDTH_SUPPORT
+	int width;
+	char *q;
+#endif
 
 	for (;;) {
 		while ((ch = *fmt++) != '%') {
@@ -92,63 +173,110 @@
 			put(ch);
 		}
 		lflag = 0;
+#ifdef LIBSA_PRINTF_WIDTH_SUPPORT
+		width = 0;
+#endif
 reswitch:
 		switch (ch = *fmt++) {
+#ifdef LIBSA_PRINTF_WIDTH_SUPPORT
+		case '#':
+			lflag |= ALT;
+			goto reswitch;
+		case ' ':
+			lflag |= SPACE;
+			goto reswitch;
+		case '-':
+			lflag |= LADJUST;
+			goto reswitch;
+		case '+':
+			lflag |= SIGN;
+			goto reswitch;
+		case '0':
+			lflag |= ZEROPAD;
+			goto reswitch;
+		case '1': case '2': case '3': case '4': case '5':
+		case '6': case '7': case '8': case '9':
+			for (;;) {
+				width *= 10;
+				width += ch - '0';
+				ch = *fmt;
+				if ((unsigned)ch - '0' > 9)
+					break;
+				++fmt;
+			}
+#endif
+			goto reswitch;
 		case 'l':
-			lflag = 1;
+#ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
+			if (*fmt == 'l') {
+				++fmt;
+				lflag |= LLONG;
+			} else
+#endif
+				lflag |= LONG;
 			goto reswitch;
 		case 't':
-#if 0 /* XXX: abuse intptr_t until the situation with ptrdiff_t is clear */
-			lflag = (sizeof(ptrdiff_t) == sizeof(long));
-#else
-			lflag = (sizeof(intptr_t) == sizeof(long));
-#endif
+			if (sizeof(PTRDIFF_T) == sizeof(long))
+				lflag |= LONG;
 			goto reswitch;
 		case 'z':
-			lflag = (sizeof(size_t) == sizeof(unsigned long));
+			if (sizeof(ssize_t) == sizeof(long))
+				lflag |= LONG;
 			goto reswitch;
 		case 'c':
 			ch = va_arg(ap, int);
-				put(ch & 0x7f);
+#ifdef LIBSA_PRINTF_WIDTH_SUPPORT
+			--width;
+#endif
+			RPAD();
+			put(ch & 0xFF);
+			LPAD();
 			break;
 		case 's':
 			p = va_arg(ap, char *);
-			while ((ch = *p++))
+#ifdef LIBSA_PRINTF_WIDTH_SUPPORT
+			for (q = p; *q; ++q);
+			width -= q - p;
+#endif
+			RPAD();
+			while ((ch = (unsigned char)*p++))
 				put(ch);
+			LPAD();
 			break;
 		case 'd':
-			ul = lflag ?
-			    va_arg(ap, long) : va_arg(ap, int);
-			if ((long)ul < 0) {
+			ul =
+#ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
+			(lflag & LLONG) ? va_arg(ap, longlong_t) :
+#endif
+			(lflag & LONG) ? va_arg(ap, long) : va_arg(ap, int);
+			if ((INTMAX_T)ul < 0) {
+				ul = -(INTMAX_T)ul;
+#ifdef LIBSA_PRINTF_WIDTH_SUPPORT
+				lflag |= NEGATIVE;
+#else
 				put('-');
-				ul = -(long)ul;
+#endif
 			}
-			kprintn(put, ul, 10);
+			KPRINTN(10);
 			break;
 		case 'o':
-			ul = lflag ?
-			    va_arg(ap, u_long) : va_arg(ap, u_int);
-			kprintn(put, ul, 8);
+			KPRINT(8);
 			break;
 		case 'u':
-			ul = lflag ?
-			    va_arg(ap, u_long) : va_arg(ap, u_int);
-			kprintn(put, ul, 10);
+			KPRINT(10);
 			break;
 		case 'p':
+#ifdef LIBSA_PRINTF_WIDTH_SUPPORT
+			lflag |= (LONG|ALT);
+#else
 			put('0');
 			put('x');
-			lflag = 1;
+#endif
 			/* FALLTHROUGH */
 		case 'x':
-			ul = lflag ?
-			    va_arg(ap, u_long) : va_arg(ap, u_int);
-			kprintn(put, ul, 16);
+			KPRINT(16);
 			break;
 		default:
-			put('%');
-			if (lflag)
-				put('l');
 			if (ch == '\0')
 				return;
 			put(ch);
@@ -158,16 +286,48 @@
 }
 
 static void
-kprintn(void (*put)(int), unsigned long ul, int base)
+#ifdef LIBSA_PRINTF_WIDTH_SUPPORT
+kprintn(void (*put)(int), UINTMAX_T ul, int base, int lflag, int width)
+#else
+kprintn(void (*put)(int), UINTMAX_T ul, int base)
+#endif
 {
-					/* hold a long in base 8 */
-	char *p, buf[(sizeof(long) * NBBY / 3) + 1];
+					/* hold a INTMAX_T in base 8 */
+	char *p, buf[(sizeof(INTMAX_T) * NBBY / 3) + 1 + 2 /* ALT + SIGN */];
+#ifdef LIBSA_PRINTF_WIDTH_SUPPORT
+	char *q;
+#endif
 
 	p = buf;
 	do {
 		*p++ = hexdigits[ul % base];
 	} while (ul /= base);
+#ifdef LIBSA_PRINTF_WIDTH_SUPPORT
+	q = p;
+	if (lflag & ALT && *(p - 1) != '0') {
+		if (base == 8) {
+			*p++ = '0';
+		} else if (base == 16) {
+			*p++ = 'x';
+			*p++ = '0';
+		}
+	}
+	if (lflag & NEGATIVE)
+		*p++ = '-';
+	else if (lflag & SIGN)
+		*p++ = '+';
+	else if (lflag & SPACE)
+		*p++ = ' ';
+	width -= p - buf;
+	if ((lflag & LADJUST) == 0) {
+		while (p > q)
+			put(*--p);
+	}
+#endif
+	RPAD();
+	RZERO();
 	do {
 		put(*--p);
 	} while (p > buf);
+	LPAD();
 }

Reply via email to