summaryrefslogtreecommitdiff
path: root/lib/libc/stdio
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2006-01-13 17:56:19 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2006-01-13 17:56:19 +0000
commit1fc50f05e6c04f30ff6c36831df4af45777fadd9 (patch)
tree6d67da9d1edf5a823a95d4b732184a7eac9126be /lib/libc/stdio
parentf6b436a174305ff928248488ed2bb681ecd79d40 (diff)
Use long long and intmax_t instead of quad_t throughout. Adapted in
part from FreeBSD.
Diffstat (limited to 'lib/libc/stdio')
-rw-r--r--lib/libc/stdio/printf.3183
-rw-r--r--lib/libc/stdio/scanf.368
-rw-r--r--lib/libc/stdio/vfprintf.c189
-rw-r--r--lib/libc/stdio/vfscanf.c97
4 files changed, 268 insertions, 269 deletions
diff --git a/lib/libc/stdio/printf.3 b/lib/libc/stdio/printf.3
index 3fc265fe566..7a6cb1fd984 100644
--- a/lib/libc/stdio/printf.3
+++ b/lib/libc/stdio/printf.3
@@ -1,4 +1,4 @@
-.\" $OpenBSD: printf.3,v 1.51 2006/01/07 16:49:59 jmc Exp $
+.\" $OpenBSD: printf.3,v 1.52 2006/01/13 17:56:18 millert Exp $
.\"
.\" Copyright (c) 1990, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -33,7 +33,7 @@
.\"
.\" @(#)printf.3 8.1 (Berkeley) 6/4/93
.\"
-.Dd June 4, 1993
+.Dd December 27, 2005
.Dt PRINTF 3
.Os
.Sh NAME
@@ -256,6 +256,7 @@ produced by a signed conversion
.Cm e ,
.Cm E ,
.Cm f ,
+.Cm F ,
.Cm g ,
.Cm G ,
or
@@ -292,8 +293,9 @@ and
conversions, the number of digits to appear after the decimal-point for
.Cm e ,
.Cm E ,
+.Cm f ,
and
-.Cm f
+.Cm F
conversions, the maximum number of significant digits for
.Cm g
and
@@ -303,137 +305,74 @@ string for
.Cm s
conversions.
.It
-The optional character
-.Cm j ,
-specifying that a following
-.Cm d ,
-.Cm i ,
-.Cm o ,
-.Cm u ,
-.Cm x ,
-or
-.Cm X
-conversion corresponds to an
-.Li intmax_t
-or
-.Li uintmax_t
-argument.
-The optional character
-.Cm h ,
-specifying that a following
-.Cm d ,
-.Cm i ,
-.Cm o ,
-.Cm u ,
-.Cm x ,
-or
-.Cm X
-conversion corresponds to a
-.Li short int
-or
-.Li unsigned short int
-argument, or that a following
-.Cm n
-conversion corresponds to a pointer to a
-.Li short int
-argument.
-.It
-The optional character
-.Cm l
-(ell) specifying that a following
-.Cm d ,
-.Cm i ,
-.Cm o ,
-.Cm u ,
-.Cm x ,
-or
-.Cm X
-conversion corresponds to a
-.Li long int
-or
-.Li unsigned long int
-argument, or that a following
-.Cm n
-conversion corresponds to a pointer to a
-.Li long int
-argument.
-.It
-The optional character sequence
-.Cm \&ll ,
-specifying that a following
-.Cm d ,
-.Cm i ,
-.Cm o ,
-.Cm u ,
-.Cm x ,
-or
-.Cm X
-conversion corresponds to a
-.Li quad int
-or
-.Li unsigned quad int
-argument, or that a following
-.Cm n
-conversion corresponds to a pointer to a
-.Li quad int
-argument.
-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 ,
+An optional length modifier, that specifies the size of the argument.
+The following length modifiers are valid for the
+.Cm d , i , n ,
+.Cm o , u , 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 ,
+conversion:
+.Bl -column "(deprecated)" "signed char" "unsigned long long" "long long *"
+.It Sy Modifier Ta "d, i" Ta "o, u, x, X" Ta n
+.It hh Ta "signed char" Ta "unsigned char" Ta "signed char *"
+.It h Ta short Ta "unsigned short" Ta "short *"
+.It "l (ell)" Ta long Ta "unsigned long" Ta "long *"
+.It "ll (ell ell)" Ta "long long" Ta "unsigned long long" Ta "long long *"
+.It j Ta intmax_t Ta uintmax_t Ta "intmax_t *"
+.It t Ta ptrdiff_t Ta (see note) Ta "ptrdiff_t *"
+.It z Ta "(see note)" Ta size_t Ta "(see note)"
+.It "q (deprecated)" Ta quad_t Ta u_quad_t Ta "quad_t *"
+.El
+.Pp
+Note:
+the
+.Cm t
+modifier, when applied to an
+.Cm o , u , x ,
or
.Cm X
-conversion corresponds to a
-.Em size_t
+conversion, indicates that the argument is of an unsigned type
+equivalent in size to a
+.Vt ptrdiff_t .
+The
+.Cm z
+modifier, when applied to a
+.Cm d
or
-the corresponding signed integer type
-argument, or that a following
+.Cm i
+conversion, indicates that the argument is of a signed type equivalent in
+size to a
+.Vt size_t .
+Similarly, when applied to an
.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
+conversion, it indicates that the argument is a pointer to a signed type
+equivalent in size to a
+.Vt size_t .
+.Pp
+The following length modifier is valid for the
.Cm e ,
.Cm E ,
.Cm f ,
+.Cm F ,
.Cm g ,
or
.Cm G
-conversion corresponds to a
-.Li long double
-argument.
+conversion:
+.Bl -column "Modifier" "e, E, f, F, g, G"
+.It Sy Modifier Ta "e, E, f, F, g, G"
+.It "l (ell)" Ta double (ignored: same behavior as without it)
+.It L Ta "long double"
+.El
+.Pp
+The following length modifier is valid for the
+.Cm c
+or
+.Cm s
+conversion:
+.Bl -column "Modifier" "wint_t" "wchar_t *"
+.It Sy Modifier Ta c Ta s
+.It "l (ell)" Ta wint_t Ta "wchar_t *"
+.El
.It
A character that specifies the type of conversion to be applied.
.El
diff --git a/lib/libc/stdio/scanf.3 b/lib/libc/stdio/scanf.3
index 8e1e85942b6..393651c4ba5 100644
--- a/lib/libc/stdio/scanf.3
+++ b/lib/libc/stdio/scanf.3
@@ -1,4 +1,4 @@
-.\" $OpenBSD: scanf.3,v 1.14 2005/07/26 03:30:25 jaredy Exp $
+.\" $OpenBSD: scanf.3,v 1.15 2006/01/13 17:56:18 millert Exp $
.\"
.\" Copyright (c) 1990, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -31,7 +31,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd January 31, 1995
+.Dd December 27, 2005
.Dt SCANF 3
.Os
.Sh NAME
@@ -101,9 +101,9 @@ functions, respectively.
Each successive
.Em pointer
argument must correspond properly with each successive conversion specifier
-(but see
-.Dq suppression
-below).
+(but see the
+.Cm *
+conversion below).
All conversions are introduced by the
.Cm %
(percent sign) character.
@@ -122,11 +122,20 @@ Following the
character, introducing a conversion, there may be a number of
.Em flag
characters, as follows:
-.Bl -tag -width indent
+.Bl -tag -width "ll (ell ell)"
.It Cm *
Suppresses assignment.
The conversion that follows occurs as usual, but no pointer is used;
the result of the conversion is simply discarded.
+.It Cm hh
+Indicates that the conversion will be one of
+.Cm dioux
+or
+.Cm n
+and the next pointer is a pointer to a
+.Li char
+(rather than
+.Li int ) .
.It Cm h
Indicates that the conversion will be one of
.Cm dioux
@@ -136,7 +145,7 @@ and the next pointer is a pointer to a
.Li short int
(rather than
.Li int ) .
-.It Cm l
+.It Cm l No (ell)
Indicates either that the conversion will be one of
.Cm dioux
or
@@ -151,13 +160,13 @@ and the next pointer is a pointer to
.Li double
(rather than
.Li float ) .
-.It Cm q
+.It Cm \&ll No (ell ell)
Indicates that the conversion will be one of
.Cm dioux
or
.Cm n
and the next pointer is a pointer to a
-.Li quad_t
+.Li long long int
(rather than
.Li int ) .
.It Cm L
@@ -165,6 +174,43 @@ Indicates that the conversion will be
.Cm efg
and the next pointer is a pointer to
.Li long double .
+.It Cm j
+Indicates that the conversion will be one of
+.Cm dioux
+or
+.Cm n
+and the next pointer is a pointer to an
+.Li intmax_t
+(rather than
+.Li int ) .
+.It Cm t
+Indicates that the conversion will be one of
+.Cm dioux
+or
+.Cm n
+and the next pointer is a pointer to a
+.Li ptrdiff_t
+(rather than
+.Li int ) .
+.It Cm z
+Indicates that the conversion will be one of
+.Cm dioux
+or
+.Cm n
+and the next pointer is a pointer to a
+.Li size_t
+(rather than
+.Li int ) .
+.It Cm q
+(deprecated)
+Indicates that the conversion will be one of
+.Cm dioux
+or
+.Cm n
+and the next pointer is a pointer to a
+.Li "long long int"
+(rather than
+.Vt int ) .
.El
.Pp
In addition to these flags, there may be an optional maximum field width,
@@ -292,7 +338,9 @@ character
and a close bracket
.Cm \&]
character.
-The set excludes those characters
+The set
+.Em excludes
+those characters
if the first character after the open bracket is a circumflex
.Cm ^ .
To include a close bracket in the set,
diff --git a/lib/libc/stdio/vfprintf.c b/lib/libc/stdio/vfprintf.c
index 84e80889049..99a1c7534b6 100644
--- a/lib/libc/stdio/vfprintf.c
+++ b/lib/libc/stdio/vfprintf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfprintf.c,v 1.36 2006/01/06 18:53:04 millert Exp $ */
+/* $OpenBSD: vfprintf.c,v 1.37 2006/01/13 17:56:18 millert Exp $ */
/*-
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
@@ -40,12 +40,13 @@
#include <sys/types.h>
#include <sys/mman.h>
+#include <errno.h>
+#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
-#include <errno.h>
-#include <stdarg.h>
#include "local.h"
#include "fvwrite.h"
@@ -136,18 +137,19 @@ static int exponent(char *, int, int);
/*
* Flags used during conversion.
*/
-#define ALT 0x001 /* alternate form */
-#define HEXPREFIX 0x002 /* add 0x or 0X prefix */
-#define LADJUST 0x004 /* left adjustment */
-#define LONGDBL 0x008 /* long double; unimplemented */
-#define LONGINT 0x010 /* long integer */
-#define QUADINT 0x020 /* quad integer */
-#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 */
-#define CHARINT 0x800 /* 8 bit integer */
+#define ALT 0x0001 /* alternate form */
+#define HEXPREFIX 0x0002 /* add 0x or 0X prefix */
+#define LADJUST 0x0004 /* left adjustment */
+#define LONGDBL 0x0008 /* long double; unimplemented */
+#define LONGINT 0x0010 /* long integer */
+#define LLONGINT 0x0020 /* long long integer */
+#define SHORTINT 0x0040 /* short integer */
+#define ZEROPAD 0x0080 /* zero (as opposed to blank) pad */
+#define FPT 0x0100 /* Floating point number */
+#define PTRINT 0x0200 /* (unsigned) ptrdiff_t */
+#define SIZEINT 0x0400 /* (signed) size_t */
+#define CHARINT 0x0800 /* 8 bit integer */
+#define MAXINT 0x1000 /* largest integer size (intmax_t) */
int
vfprintf(FILE *fp, const char *fmt0, __va_list ap)
@@ -174,12 +176,7 @@ vfprintf(FILE *fp, const char *fmt0, __va_list ap)
char expstr[7]; /* buffer for exponent string */
#endif
-#ifdef __GNUC__ /* gcc has builtin quad type (long long) SOS */
-#define quad_t long long
-#define u_quad_t unsigned long long
-#endif
-
- u_quad_t _uquad; /* integer arguments %[diouxX] */
+ uintmax_t _umax; /* integer arguments %[diouxX] */
enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */
int dprec; /* a copy of prec if [diouxX], 0 otherwise */
int realsz; /* field size expanded by dprec */
@@ -242,21 +239,23 @@ vfprintf(FILE *fp, const char *fmt0, __va_list ap)
* argument extraction methods.
*/
#define SARG() \
- (flags&QUADINT ? GETARG(quad_t) : \
+ ((intmax_t)(flags&MAXINT ? GETARG(intmax_t) : \
+ flags&LLONGINT ? GETARG(long long) : \
flags&LONGINT ? GETARG(long) : \
flags&PTRINT ? GETARG(ptrdiff_t) : \
flags&SIZEINT ? GETARG(ssize_t) : \
- flags&SHORTINT ? (long)(short)GETARG(int) : \
- flags&CHARINT ? (long)(__signed char)GETARG(int) : \
- (long)GETARG(int))
+ flags&SHORTINT ? (short)GETARG(int) : \
+ flags&CHARINT ? (__signed char)GETARG(int) : \
+ GETARG(int)))
#define UARG() \
- (flags&QUADINT ? GETARG(u_quad_t) : \
- flags&LONGINT ? GETARG(u_long) : \
- flags&PTRINT ? GETARG(ptrdiff_t) : /* XXX */ \
+ ((uintmax_t)(flags&MAXINT ? GETARG(uintmax_t) : \
+ flags&LLONGINT ? GETARG(unsigned long long) : \
+ flags&LONGINT ? GETARG(unsigned long) : \
+ flags&PTRINT ? (uintptr_t)GETARG(ptrdiff_t) : /* XXX */ \
flags&SIZEINT ? GETARG(size_t) : \
- flags&SHORTINT ? (u_long)(u_short)GETARG(int) : \
- flags&CHARINT ? (u_long)(u_char)GETARG(int) : \
- (u_long)GETARG(u_int))
+ flags&SHORTINT ? (unsigned short)GETARG(int) : \
+ flags&CHARINT ? (unsigned char)GETARG(int) : \
+ GETARG(unsigned int)))
/*
* Get * arguments, including the form *nn$. Preserve the nextarg
@@ -429,18 +428,18 @@ reswitch: switch (ch) {
flags |= SHORTINT;
goto rflag;
case 'j':
- flags |= QUADINT;
+ flags |= MAXINT;
goto rflag;
case 'l':
if (*fmt == 'l') {
fmt++;
- flags |= QUADINT;
+ flags |= LLONGINT;
} else {
flags |= LONGINT;
}
goto rflag;
case 'q':
- flags |= QUADINT;
+ flags |= LLONGINT;
goto rflag;
case 't':
flags |= PTRINT;
@@ -458,9 +457,9 @@ reswitch: switch (ch) {
/*FALLTHROUGH*/
case 'd':
case 'i':
- _uquad = SARG();
- if ((quad_t)_uquad < 0) {
- _uquad = -_uquad;
+ _umax = SARG();
+ if ((intmax_t)_umax < 0) {
+ _umax = -_umax;
sign = '-';
}
base = DEC;
@@ -532,16 +531,20 @@ reswitch: switch (ch) {
break;
#endif /* FLOATING_POINT */
case 'n':
- if (flags & QUADINT)
- *GETARG(quad_t *) = ret;
+ if (flags & LLONGINT)
+ *GETARG(long long *) = ret;
else if (flags & LONGINT)
*GETARG(long *) = ret;
else if (flags & SHORTINT)
*GETARG(short *) = ret;
+ else if (flags & CHARINT)
+ *GETARG(__signed char *) = ret;
else if (flags & PTRINT)
*GETARG(ptrdiff_t *) = ret;
else if (flags & SIZEINT)
*GETARG(ssize_t *) = ret;
+ else if (flags & MAXINT)
+ *GETARG(intmax_t *) = ret;
else
*GETARG(int *) = ret;
continue; /* no output */
@@ -549,7 +552,7 @@ reswitch: switch (ch) {
flags |= LONGINT;
/*FALLTHROUGH*/
case 'o':
- _uquad = UARG();
+ _umax = UARG();
base = OCT;
goto nosign;
case 'p':
@@ -561,7 +564,7 @@ reswitch: switch (ch) {
* -- ANSI X3J11
*/
/* NOSTRICT */
- _uquad = (u_long)GETARG(void *);
+ _umax = (u_long)GETARG(void *);
base = HEX;
xdigs = "0123456789abcdef";
flags |= HEXPREFIX;
@@ -592,7 +595,7 @@ reswitch: switch (ch) {
flags |= LONGINT;
/*FALLTHROUGH*/
case 'u':
- _uquad = UARG();
+ _umax = UARG();
base = DEC;
goto nosign;
case 'X':
@@ -600,10 +603,10 @@ reswitch: switch (ch) {
goto hex;
case 'x':
xdigs = "0123456789abcdef";
-hex: _uquad = UARG();
+hex: _umax = UARG();
base = HEX;
/* leading 0x/X only if non-zero */
- if (flags & ALT && _uquad != 0)
+ if (flags & ALT && _umax != 0)
flags |= HEXPREFIX;
/* unsigned conversions */
@@ -622,7 +625,7 @@ number: if ((dprec = prec) >= 0)
* -- ANSI X3J11
*/
cp = buf + BUF;
- if (_uquad != 0 || prec != 0) {
+ if (_umax != 0 || prec != 0) {
/*
* Unsigned mod is hard, and unsigned mod
* by a constant is easier than that by
@@ -631,9 +634,9 @@ number: if ((dprec = prec) >= 0)
switch (base) {
case OCT:
do {
- *--cp = to_char(_uquad & 7);
- _uquad >>= 3;
- } while (_uquad);
+ *--cp = to_char(_umax & 7);
+ _umax >>= 3;
+ } while (_umax);
/* handle octal leading 0 */
if (flags & ALT && *cp != '0')
*--cp = '0';
@@ -641,18 +644,18 @@ number: if ((dprec = prec) >= 0)
case DEC:
/* many numbers are 1 digit */
- while (_uquad >= 10) {
- *--cp = to_char(_uquad % 10);
- _uquad /= 10;
+ while (_umax >= 10) {
+ *--cp = to_char(_umax % 10);
+ _umax /= 10;
}
- *--cp = to_char(_uquad);
+ *--cp = to_char(_umax);
break;
case HEX:
do {
- *--cp = xdigs[_uquad & 15];
- _uquad >>= 4;
- } while (_uquad);
+ *--cp = xdigs[_umax & 15];
+ _umax >>= 4;
+ } while (_umax);
break;
default:
@@ -795,9 +798,9 @@ error:
#define T_LONG 7
#define T_U_LONG 8
#define TP_LONG 9
-#define T_QUAD 10
-#define T_U_QUAD 11
-#define TP_QUAD 12
+#define T_LLONG 10
+#define T_U_LLONG 11
+#define TP_LLONG 12
#define T_DOUBLE 13
#define T_LONG_DOUBLE 14
#define TP_CHAR 15
@@ -807,6 +810,9 @@ error:
#define T_SIZEINT 19
#define T_SSIZEINT 20
#define TP_SSIZEINT 21
+#define T_MAXINT 22
+#define T_MAXUINT 23
+#define TP_MAXINT 24
/*
* Find all arguments when a positional parameter is encountered. Returns a
@@ -843,14 +849,20 @@ __find_arguments(const char *fmt0, va_list ap, va_list **argtable,
typetable[nextarg++] = type)
#define ADDSARG() \
- ((flags&QUADINT) ? ADDTYPE(T_QUAD) : \
+ ((flags&MAXINT) ? ADDTYPE(T_MAXINT) : \
+ ((flags&PTRINT) ? ADDTYPE(T_PTRINT) : \
+ ((flags&SIZEINT) ? ADDTYPE(T_SSIZEINT) : \
+ ((flags&LLONGINT) ? ADDTYPE(T_LLONG) : \
((flags&LONGINT) ? ADDTYPE(T_LONG) : \
- ((flags&SHORTINT) ? ADDTYPE(T_SHORT) : ADDTYPE(T_INT))))
+ ((flags&SHORTINT) ? ADDTYPE(T_SHORT) : ADDTYPE(T_INT)))))))
#define ADDUARG() \
- ((flags&QUADINT) ? ADDTYPE(T_U_QUAD) : \
+ ((flags&MAXINT) ? ADDTYPE(T_MAXUINT) : \
+ ((flags&PTRINT) ? ADDTYPE(T_PTRINT) : \
+ ((flags&SIZEINT) ? ADDTYPE(T_SIZEINT) : \
+ ((flags&LLONGINT) ? ADDTYPE(T_U_LLONG) : \
((flags&LONGINT) ? ADDTYPE(T_U_LONG) : \
- ((flags&SHORTINT) ? ADDTYPE(T_U_SHORT) : ADDTYPE(T_U_INT))))
+ ((flags&SHORTINT) ? ADDTYPE(T_U_SHORT) : ADDTYPE(T_U_INT)))))))
/*
* Add * arguments to the type array.
@@ -947,13 +959,13 @@ reswitch: switch (ch) {
case 'l':
if (*fmt == 'l') {
fmt++;
- flags |= QUADINT;
+ flags |= LLONGINT;
} else {
flags |= LONGINT;
}
goto rflag;
case 'q':
- flags |= QUADINT;
+ flags |= LLONGINT;
goto rflag;
case 't':
flags |= PTRINT;
@@ -969,14 +981,7 @@ reswitch: switch (ch) {
/*FALLTHROUGH*/
case 'd':
case 'i':
- if (flags & QUADINT)
- ADDTYPE(T_QUAD);
- else if (flags & PTRINT)
- ADDTYPE(T_PTRINT);
- else if (flags & SIZEINT)
- ADDTYPE(T_SSIZEINT);
- else
- ADDSARG();
+ ADDSARG();
break;
#ifdef FLOATING_POINT
case 'e':
@@ -991,8 +996,8 @@ reswitch: switch (ch) {
break;
#endif /* FLOATING_POINT */
case 'n':
- if (flags & QUADINT)
- ADDTYPE(TP_QUAD);
+ if (flags & LLONGINT)
+ ADDTYPE(TP_LLONG);
else if (flags & LONGINT)
ADDTYPE(TP_LONG);
else if (flags & SHORTINT)
@@ -1001,6 +1006,8 @@ reswitch: switch (ch) {
ADDTYPE(TP_PTRINT);
else if (flags & SIZEINT)
ADDTYPE(TP_SSIZEINT);
+ else if (flags & MAXINT)
+ ADDTYPE(TP_MAXINT);
else
ADDTYPE(TP_INT);
continue; /* no output */
@@ -1008,10 +1015,7 @@ reswitch: switch (ch) {
flags |= LONGINT;
/*FALLTHROUGH*/
case 'o':
- if (flags & QUADINT)
- ADDTYPE(T_U_QUAD);
- else
- ADDUARG();
+ ADDUARG();
break;
case 'p':
ADDTYPE(TP_VOID);
@@ -1023,21 +1027,9 @@ reswitch: switch (ch) {
flags |= LONGINT;
/*FALLTHROUGH*/
case 'u':
- if (flags & QUADINT)
- ADDTYPE(T_U_QUAD);
- else
- ADDUARG();
- break;
case 'X':
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();
+ ADDUARG();
break;
default: /* "%?" prints ?, unless ? is NUL */
if (ch == '\0')
@@ -1092,14 +1084,14 @@ done:
case TP_LONG:
(void) va_arg(ap, long *);
break;
- case T_QUAD:
- (void) va_arg(ap, quad_t);
+ case T_LLONG:
+ (void) va_arg(ap, long long);
break;
- case T_U_QUAD:
- (void) va_arg(ap, u_quad_t);
+ case T_U_LLONG:
+ (void) va_arg(ap, unsigned long long);
break;
- case TP_QUAD:
- (void) va_arg(ap, quad_t *);
+ case TP_LLONG:
+ (void) va_arg(ap, long long *);
break;
case T_DOUBLE:
(void) va_arg(ap, double);
@@ -1128,6 +1120,9 @@ done:
case TP_SSIZEINT:
(void) va_arg(ap, ssize_t *);
break;
+ case TP_MAXINT:
+ (void) va_arg(ap, intmax_t *);
+ break;
}
}
diff --git a/lib/libc/stdio/vfscanf.c b/lib/libc/stdio/vfscanf.c
index d7c51be2a76..543fd571334 100644
--- a/lib/libc/stdio/vfscanf.c
+++ b/lib/libc/stdio/vfscanf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfscanf.c,v 1.19 2006/01/08 02:13:28 millert Exp $ */
+/* $OpenBSD: vfscanf.c,v 1.20 2006/01/13 17:56:18 millert Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -31,6 +31,8 @@
* SUCH DAMAGE.
*/
+#include <stddef.h>
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
@@ -46,30 +48,33 @@
/*
* Flags used during conversion.
*/
-#define LONG 0x0001 /* l: long or double */
-#define LONGDBL 0x0002 /* L: long double; unimplemented */
-#define SHORT 0x0004 /* h: short */
-#define QUAD 0x0008 /* q: quad */
-#define SUPPRESS 0x0010 /* suppress assignment */
-#define POINTER 0x0020 /* weird %p pointer (`fake hex') */
-#define NOSKIP 0x0040 /* do not skip blanks */
-#define SHORTSHORT 0x0080 /* hh: 8 bit integer */
-#define SIZEINT 0x0100 /* z: (signed) size_t */
+#define LONG 0x00001 /* l: long or double */
+#define LONGDBL 0x00002 /* L: long double; unimplemented */
+#define SHORT 0x00004 /* h: short */
+#define SHORTSHORT 0x00008 /* hh: 8 bit integer */
+#define LLONG 0x00010 /* ll: long long (+ deprecated q: quad) */
+#define POINTER 0x00020 /* p: void * (as hex) */
+#define SIZEINT 0x00040 /* z: (signed) size_t */
+#define MAXINT 0x00080 /* j: intmax_t */
+#define PTRINT 0x00100 /* t: ptrdiff_t */
+#define NOSKIP 0x00200 /* [ or c: do not skip blanks */
+#define SUPPRESS 0x00400 /* *: suppress assignment */
+#define UNSIGNED 0x00800 /* %[oupxX] conversions */
/*
* The following are used in numeric conversions only:
* SIGNOK, HAVESIGN, NDIGITS, DPTOK, and EXPOK are for floating point;
* SIGNOK, HAVESIGN, NDIGITS, PFXOK, and NZDIGITS are for integral.
*/
-#define SIGNOK 0x0200 /* +/- is (still) legal */
-#define HAVESIGN 0x0400 /* sign detected */
-#define NDIGITS 0x0800 /* no digits detected */
+#define SIGNOK 0x01000 /* +/- is (still) legal */
+#define HAVESIGN 0x02000 /* sign detected */
+#define NDIGITS 0x04000 /* no digits detected */
-#define DPTOK 0x1000 /* (float) decimal point is still legal */
-#define EXPOK 0x2000 /* (float) exponent (e+3, etc) still legal */
+#define DPTOK 0x08000 /* (float) decimal point is still legal */
+#define EXPOK 0x10000 /* (float) exponent (e+3, etc) still legal */
-#define PFXOK 0x1000 /* 0x prefix is (still) legal */
-#define NZDIGITS 0x2000 /* no zero digits detected */
+#define PFXOK 0x08000 /* 0x prefix is (still) legal */
+#define NZDIGITS 0x10000 /* no zero digits detected */
/*
* Conversion types.
@@ -77,7 +82,7 @@
#define CT_CHAR 0 /* %c conversion */
#define CT_CCL 1 /* %[...] conversion */
#define CT_STRING 2 /* %s conversion */
-#define CT_INT 3 /* integer, i.e., strtoq or strtouq */
+#define CT_INT 3 /* integer, i.e., strtoimax or strtoumax */
#define CT_FLOAT 4 /* floating, i.e., strtod */
#define u_char unsigned char
@@ -104,8 +109,7 @@ VFSCANF(FILE *fp, const char *fmt0, __va_list ap)
char *p0; /* saves original value of p when necessary */
int nassigned; /* number of fields assigned */
int nread; /* number of characters consumed from fp */
- int base; /* base argument to strtoq/strtouq */
- u_quad_t (*ccfn)(); /* conversion function (strtoq/strtouq) */
+ int base; /* base argument to strtoimax/strtouimax */
char ccltab[256]; /* character class table for %[...] */
char buf[BUF]; /* buffer for numeric conversions */
@@ -118,7 +122,6 @@ VFSCANF(FILE *fp, const char *fmt0, __va_list ap)
nassigned = 0;
nread = 0;
base = 0; /* XXX just to keep gcc happy */
- ccfn = NULL; /* XXX just to keep gcc happy */
for (;;) {
c = *fmt++;
if (c == 0)
@@ -152,6 +155,9 @@ literal:
case '*':
flags |= SUPPRESS;
goto again;
+ case 'j':
+ flags |= MAXINT;
+ goto again;
case 'L':
flags |= LONGDBL;
goto again;
@@ -166,13 +172,16 @@ literal:
case 'l':
if (*fmt == 'l') {
fmt++;
- flags |= QUAD;
+ flags |= LLONG;
} else {
flags |= LONG;
}
goto again;
case 'q':
- flags |= QUAD;
+ flags |= LLONG; /* deprecated */
+ goto again;
+ case 't':
+ flags |= PTRINT;
goto again;
case 'z':
flags |= SIZEINT;
@@ -195,13 +204,11 @@ literal:
/* FALLTHROUGH */
case 'd':
c = CT_INT;
- ccfn = (u_quad_t (*)())strtoq;
base = 10;
break;
case 'i':
c = CT_INT;
- ccfn = (u_quad_t (*)())strtoq;
base = 0;
break;
@@ -210,13 +217,13 @@ literal:
/* FALLTHROUGH */
case 'o':
c = CT_INT;
- ccfn = strtouq;
+ flags |= UNSIGNED;
base = 8;
break;
case 'u':
c = CT_INT;
- ccfn = strtouq;
+ flags |= UNSIGNED;
base = 10;
break;
@@ -224,7 +231,7 @@ literal:
case 'x':
flags |= PFXOK; /* enable 0x prefixing */
c = CT_INT;
- ccfn = strtouq;
+ flags |= UNSIGNED;
base = 16;
break;
@@ -256,12 +263,12 @@ literal:
case 'p': /* pointer format is like hex */
flags |= POINTER | PFXOK;
c = CT_INT;
- ccfn = strtouq;
+ flags |= UNSIGNED;
base = 16;
break;
case 'n':
- if (flags & SUPPRESS) /* ??? */
+ if (flags & SUPPRESS)
continue;
if (flags & SHORTSHORT)
*va_arg(ap, __signed char *) = nread;
@@ -269,10 +276,14 @@ literal:
*va_arg(ap, short *) = nread;
else if (flags & LONG)
*va_arg(ap, long *) = nread;
- else if (flags & QUAD)
- *va_arg(ap, quad_t *) = nread;
else if (flags & SIZEINT)
*va_arg(ap, ssize_t *) = nread;
+ else if (flags & PTRINT)
+ *va_arg(ap, ptrdiff_t *) = nread;
+ else if (flags & LLONG)
+ *va_arg(ap, long long *) = nread;
+ else if (flags & MAXINT)
+ *va_arg(ap, intmax_t *) = nread;
else
*va_arg(ap, int *) = nread;
continue;
@@ -287,7 +298,6 @@ literal:
if (isupper(c))
flags |= LONG;
c = CT_INT;
- ccfn = (u_quad_t (*)())strtoq;
base = 10;
break;
}
@@ -429,7 +439,7 @@ literal:
continue;
case CT_INT:
- /* scan an integer as if by strtoq/strtouq */
+ /* scan an integer as if by strtoimax/strtoumax */
#ifdef hardway
if (width == 0 || width > sizeof(buf) - 1)
width = sizeof(buf) - 1;
@@ -511,7 +521,7 @@ literal:
* 3rd char if we have a sign).
*/
case 'x': case 'X':
- if (flags & PFXOK && p ==
+ if ((flags & PFXOK) && p ==
buf + 1 + !!(flags & HAVESIGN)) {
base = 16; /* if %i */
flags &= ~PFXOK;
@@ -552,17 +562,24 @@ literal:
(void) ungetc(c, fp);
}
if ((flags & SUPPRESS) == 0) {
- u_quad_t res;
+ uintmax_t res;
*p = '\0';
- res = (*ccfn)(buf, (char **)NULL, base);
+ if (flags & UNSIGNED)
+ res = strtoumax(buf, NULL, base);
+ else
+ res = strtoimax(buf, NULL, base);
if (flags & POINTER)
*va_arg(ap, void **) =
- (void *)(long)res;
+ (void *)(uintptr_t)res;
+ else if (flags & MAXINT)
+ *va_arg(ap, intmax_t *) = res;
+ else if (flags & LLONG)
+ *va_arg(ap, long long *) = res;
else if (flags & SIZEINT)
*va_arg(ap, ssize_t *) = res;
- else if (flags & QUAD)
- *va_arg(ap, quad_t *) = res;
+ else if (flags & PTRINT)
+ *va_arg(ap, ptrdiff_t *) = res;
else if (flags & LONG)
*va_arg(ap, long *) = res;
else if (flags & SHORT)