diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2006-01-13 17:56:19 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2006-01-13 17:56:19 +0000 |
commit | 1fc50f05e6c04f30ff6c36831df4af45777fadd9 (patch) | |
tree | 6d67da9d1edf5a823a95d4b732184a7eac9126be /lib/libc/stdio | |
parent | f6b436a174305ff928248488ed2bb681ecd79d40 (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.3 | 183 | ||||
-rw-r--r-- | lib/libc/stdio/scanf.3 | 68 | ||||
-rw-r--r-- | lib/libc/stdio/vfprintf.c | 189 | ||||
-rw-r--r-- | lib/libc/stdio/vfscanf.c | 97 |
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) |