[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
printf(3): add support for z and t modifiers
- To: tech_(_at_)_openbsd_(_dot_)_org
- Subject: printf(3): add support for z and t modifiers
- From: Otto Moerbeek <otto_(_at_)_drijf_(_dot_)_net>
- Date: Sat, 18 Sep 2004 21:11:44 +0200 (CEST)
Hi,
this adds support for the C99 z and t modifiers to printf(3).
Currently, the only safe way to print a size_t v is:
printf("%llu", (unsigned long long) v);
Since the size of size_t can be 32 or 64 bits, depending on arch.
With this diff you can just do:
printf("%zu", v);
'%td' can be used in the same way for ptrdiff_t.
Please review and test this diff; it promises to make lives of C
programmers easier.
Thanks,
-Otto
Index: lib/libc/stdio/printf.3
===================================================================
RCS file: /cvs/src/lib/libc/stdio/printf.3,v
retrieving revision 1.43
diff -u -p -r1.43 printf.3
--- lib/libc/stdio/printf.3 17 Aug 2003 17:08:09 -0000 1.43
+++ lib/libc/stdio/printf.3 18 Sep 2004 18:56:16 -0000
@@ -394,6 +394,47 @@ The use of
.Cm q
has been deprecated as conversion character.
.It
+The optional character
+.Cm t ,
+specifying that a following
+.Cm d ,
+.Cm i ,
+.Cm o ,
+.Cm u ,
+.Cm x ,
+or
+.Cm X
+conversion corresponds to a
+.Em ptrdiff_t
+or
+the corresponding unsigned integer type
+argument, or that a following
+.Cm n
+conversion corresponds to a pointer to a
+.Em ptrdiff_t
+argument.
+.It
+The optional character
+.Cm z ,
+specifying that a following
+.Cm d ,
+.Cm i ,
+.Cm o ,
+.Cm u ,
+.Cm x ,
+or
+.Cm X
+conversion corresponds to a
+.Em size_t
+or
+the corresponding signed integer type
+argument, or that a following
+.Cm n
+conversion corresponds to a pointer to a
+signed integer type corresponding to
+.Em size_t
+argument.
+.It
The character
.Cm L
specifying that a following
Index: lib/libc/stdio/vfprintf.c
===================================================================
RCS file: /cvs/src/lib/libc/stdio/vfprintf.c,v
retrieving revision 1.22
diff -u -p -r1.22 vfprintf.c
--- lib/libc/stdio/vfprintf.c 16 Sep 2004 20:21:03 -0000 1.22
+++ lib/libc/stdio/vfprintf.c 18 Sep 2004 18:56:16 -0000
@@ -43,6 +43,7 @@ static char *rcsid = "$OpenBSD: vfprintf
#include <sys/types.h>
#include <sys/mman.h>
+#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -150,6 +151,9 @@ static int exponent(char *, int, int);
#define SHORTINT 0x040 /* short integer */
#define ZEROPAD 0x080 /* zero (as opposed to blank) pad */
#define FPT 0x100 /* Floating point number */
+#define PTRINT 0x200 /* (unsigned) ptrdiff_t */
+#define SIZEINT 0x400 /* (signed) size_t */
+
int
vfprintf(fp, fmt0, ap)
FILE *fp;
@@ -247,11 +251,15 @@ vfprintf(fp, fmt0, ap)
#define SARG() \
(flags&QUADINT ? va_arg(ap, quad_t) : \
flags&LONGINT ? GETARG(long) : \
+ flags&PTRINT ? GETARG(ptrdiff_t) : \
+ flags&SIZEINT ? GETARG(ssize_t) : \
flags&SHORTINT ? (long)(short)GETARG(int) : \
(long)GETARG(int))
#define UARG() \
(flags&QUADINT ? va_arg(ap, u_quad_t) : \
flags&LONGINT ? GETARG(u_long) : \
+ flags&PTRINT ? GETARG(ptrdiff_t) : /* XXX */ \
+ flags&SIZEINT ? GETARG(size_t) : \
flags&SHORTINT ? (u_long)(u_short)GETARG(int) : \
(u_long)GETARG(u_int))
@@ -434,6 +442,12 @@ reswitch: switch (ch) {
case 'q':
flags |= QUADINT;
goto rflag;
+ case 't':
+ flags |= PTRINT;
+ goto rflag;
+ case 'z':
+ flags |= SIZEINT;
+ goto rflag;
case 'c':
*(cp = buf) = GETARG(int);
size = 1;
@@ -524,6 +538,10 @@ reswitch: switch (ch) {
*GETARG(long *) = ret;
else if (flags & SHORTINT)
*GETARG(short *) = ret;
+ else if (flags & PTRINT)
+ *GETARG(ptrdiff_t *) = ret;
+ else if (flags & SIZEINT)
+ *GETARG(ssize_t *) = ret;
else
*GETARG(int *) = ret;
continue; /* no output */
@@ -784,6 +802,11 @@ error:
#define T_LONG_DOUBLE 14
#define TP_CHAR 15
#define TP_VOID 16
+#define T_PTRINT 17
+#define TP_PTRINT 18
+#define T_SIZEINT 19
+#define T_SSIZEINT 20
+#define TP_SSIZEINT 21
/*
* Find all arguments when a positional parameter is encountered. Returns a
@@ -917,6 +940,12 @@ reswitch: switch (ch) {
case 'q':
flags |= QUADINT;
goto rflag;
+ case 't':
+ flags |= PTRINT;
+ goto rflag;
+ case 'z':
+ flags |= SIZEINT;
+ goto rflag;
case 'c':
ADDTYPE(T_INT);
break;
@@ -925,11 +954,14 @@ reswitch: switch (ch) {
/*FALLTHROUGH*/
case 'd':
case 'i':
- if (flags & QUADINT) {
+ if (flags & QUADINT)
ADDTYPE(T_QUAD);
- } else {
+ else if (flags & PTRINT)
+ ADDTYPE(T_PTRINT);
+ else if (flags & SIZEINT)
+ ADDTYPE(T_SSIZEINT);
+ else
ADDSARG();
- }
break;
#ifdef FLOATING_POINT
case 'e':
@@ -950,6 +982,10 @@ reswitch: switch (ch) {
ADDTYPE(TP_LONG);
else if (flags & SHORTINT)
ADDTYPE(TP_SHORT);
+ else if (flags & PTRINT)
+ ADDTYPE(TP_PTRINT);
+ else if (flags & SIZEINT)
+ ADDTYPE(TP_SSIZEINT);
else
ADDTYPE(TP_INT);
continue; /* no output */
@@ -981,6 +1017,10 @@ reswitch: switch (ch) {
case 'x':
if (flags & QUADINT)
ADDTYPE(T_U_QUAD);
+ else if (flags & PTRINT)
+ ADDTYPE(T_PTRINT);
+ else if (flags & SIZEINT)
+ ADDTYPE(T_SIZEINT);
else
ADDUARG();
break;
@@ -1057,6 +1097,21 @@ done:
break;
case TP_VOID:
(void) va_arg(ap, void *);
+ break;
+ case T_PTRINT:
+ (void) va_arg(ap, ptrdiff_t);
+ break;
+ case TP_PTRINT:
+ (void) va_arg(ap, ptrdiff_t *);
+ break;
+ case T_SIZEINT:
+ (void) va_arg(ap, size_t);
+ break;
+ case T_SSIZEINT:
+ (void) va_arg(ap, ssize_t);
+ break;
+ case TP_SSIZEINT:
+ (void) va_arg(ap, ssize_t *);
break;
}
}
Index: regress/lib/libc/sprintf/sprintf_test.c
===================================================================
RCS file: /cvs/src/regress/lib/libc/sprintf/sprintf_test.c,v
retrieving revision 1.3
diff -u -p -r1.3 sprintf_test.c
--- regress/lib/libc/sprintf/sprintf_test.c 16 Sep 2004 20:22:26 -0000 1.3
+++ regress/lib/libc/sprintf/sprintf_test.c 18 Sep 2004 18:56:22 -0000
@@ -29,6 +29,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -48,10 +49,16 @@ char correct[] =
"|xx 41 42 43 44\n"
"|xx 45 -1 1 -1 1\n";
+char correct2[] =
+ "1 0 -1 1 1 2 1 3 -1 4 1 \n"
+ "1 -1 1 1 -1 1 \n";
+
int
main(int argc, char *argv[])
{
char buf[1024];
+ size_t sz1, sz2, sz3, sz4;
+ ptrdiff_t p1, p2, p3, p4;
/* Test positional arguments */
snprintf(buf, sizeof buf,
@@ -77,8 +84,19 @@ main(int argc, char *argv[])
"43", "44", 45, -1L, 1LL, -1, 1LL
);
- printf(buf);
- if (strcmp(buf, correct) == 0)
- exit(0);
- exit(1);
+ if (strcmp(buf, correct) != 0)
+ exit(1);
+
+ sz1 = (size_t)1;
+ sz2 = (size_t)-1;
+ p1 = (ptrdiff_t)1;
+ p2 = (ptrdiff_t)-1;
+ snprintf(buf, sizeof buf,
+ "%zx %d %zd %d %zu %d %tx %d %td %d %tu %zn %tn\n"
+ "%1$zx %3$zd %5$zu %7$tx %9$td %11$tu %14$zn %15$tn\n",
+ sz1, 0, sz2, 1, sz1, 2, p1, 3, p2, 4, p1, &sz3, &p3, &sz4, &p4);
+ if (strcmp(buf, correct2) != 0 || sz3 != 24 || p3 != 25 ||
+ sz4 != 40 || p4 != 41)
+ exit(1);
+ exit(0);
}
Visit your host, monkey.org