mirror of
https://github.com/opnsense/src.git
synced 2026-06-09 00:32:25 -04:00
libc: Implement N2630.
This adds formatted input/output of binary integer numbers to the printf(), scanf(), and strtol() families, including their wide-character counterparts. Reviewed by: imp, emaste Differential Revision: https://reviews.freebsd.org/D41511 (cherry picked from commitd9dc1603d6) libc: Add unit tests for N2630 and possible collateral damage. Reviewed by: imp, emaste Differential Revision: https://reviews.freebsd.org/D41512 (cherry picked from commitb9385720f3) libc: Document support for binary integers. Reviewed by: debdrup, emaste Differential Revision: https://reviews.freebsd.org/D41522 (cherry picked from commit76edfabbec) libc: Fix fixed-width case in the new integer parser. Fixes:d9dc1603d6Differential Revision: https://reviews.freebsd.org/D41622 (cherry picked from commitaca3bd1602) libc: Add a wide version of snprintf_test. Reviewed by: imp, emaste Differential Revision: https://reviews.freebsd.org/D41726 (cherry picked from commit4ec9ee9912) libc: Suppress format checks on printf() / scanf() tests. Reviewed by: jrtc27, markj, emaste Differential Revision: https://reviews.freebsd.org/D41727 (cherry picked from commit294bd2827e) Approved by: re (gjb)
This commit is contained in:
parent
70fbe797c0
commit
bae932999e
29 changed files with 1315 additions and 259 deletions
|
|
@ -94,6 +94,12 @@ ATF_TC_BODY(strtol_base, tc)
|
|||
{ "01234567", 342391, 0, NULL },
|
||||
{ "0123456789", 123456789, 10, NULL },
|
||||
{ "0x75bcd15", 123456789, 0, NULL },
|
||||
#ifdef __FreeBSD__
|
||||
{ "0x", 0, 0, "x" },
|
||||
{ "0b111010110111100110100010101", 123456789, 0, NULL },
|
||||
{ "0b0123", 1, 0, "23" },
|
||||
{ "0b", 0, 0, "b" },
|
||||
#endif
|
||||
};
|
||||
|
||||
long long int lli;
|
||||
|
|
|
|||
|
|
@ -91,6 +91,13 @@ _FUNCNAME(const char *nptr, char **endptr, int base)
|
|||
s += 2;
|
||||
base = 16;
|
||||
}
|
||||
if ((base == 0 || base == 2) &&
|
||||
c == '0' && (*s == 'b' || *s == 'B') &&
|
||||
(s[1] >= '0' && s[1] <= '1')) {
|
||||
c = s[1];
|
||||
s += 2;
|
||||
base = 2;
|
||||
}
|
||||
if (base == 0)
|
||||
base = (c == '0' ? 8 : 10);
|
||||
|
||||
|
|
|
|||
|
|
@ -87,6 +87,13 @@ _FUNCNAME(const char *nptr, char **endptr, int base)
|
|||
s += 2;
|
||||
base = 16;
|
||||
}
|
||||
if ((base == 0 || base == 2) &&
|
||||
c == '0' && (*s == 'b' || *s == 'B') &&
|
||||
(s[1] >= '0' && s[1] <= '1')) {
|
||||
c = s[1];
|
||||
s += 2;
|
||||
base = 2;
|
||||
}
|
||||
if (base == 0)
|
||||
base = (c == '0' ? 8 : 10);
|
||||
|
||||
|
|
|
|||
|
|
@ -86,6 +86,13 @@ wcstoimax_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
|
|||
s += 2;
|
||||
base = 16;
|
||||
}
|
||||
if ((base == 0 || base == 2) &&
|
||||
c == L'0' && (*s == L'b' || *s == L'B') &&
|
||||
(s[1] >= L'0' && s[1] <= L'1')) {
|
||||
c = s[1];
|
||||
s += 2;
|
||||
base = 2;
|
||||
}
|
||||
if (base == 0)
|
||||
base = c == L'0' ? 8 : 10;
|
||||
acc = any = 0;
|
||||
|
|
|
|||
|
|
@ -80,6 +80,13 @@ wcstol_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int
|
|||
s += 2;
|
||||
base = 16;
|
||||
}
|
||||
if ((base == 0 || base == 2) &&
|
||||
c == L'0' && (*s == L'b' || *s == L'B') &&
|
||||
(s[1] >= L'0' && s[1] <= L'1')) {
|
||||
c = s[1];
|
||||
s += 2;
|
||||
base = 2;
|
||||
}
|
||||
if (base == 0)
|
||||
base = c == L'0' ? 8 : 10;
|
||||
acc = any = 0;
|
||||
|
|
|
|||
|
|
@ -86,6 +86,13 @@ wcstoll_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
|
|||
s += 2;
|
||||
base = 16;
|
||||
}
|
||||
if ((base == 0 || base == 2) &&
|
||||
c == L'0' && (*s == L'b' || *s == L'B') &&
|
||||
(s[1] >= L'0' && s[1] <= L'1')) {
|
||||
c = s[1];
|
||||
s += 2;
|
||||
base = 2;
|
||||
}
|
||||
if (base == 0)
|
||||
base = c == L'0' ? 8 : 10;
|
||||
acc = any = 0;
|
||||
|
|
|
|||
|
|
@ -80,6 +80,13 @@ wcstoul_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
|
|||
s += 2;
|
||||
base = 16;
|
||||
}
|
||||
if ((base == 0 || base == 2) &&
|
||||
c == L'0' && (*s == L'b' || *s == L'B') &&
|
||||
(s[1] >= L'0' && s[1] <= L'1')) {
|
||||
c = s[1];
|
||||
s += 2;
|
||||
base = 2;
|
||||
}
|
||||
if (base == 0)
|
||||
base = c == L'0' ? 8 : 10;
|
||||
acc = any = 0;
|
||||
|
|
|
|||
|
|
@ -86,6 +86,13 @@ wcstoull_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
|
|||
s += 2;
|
||||
base = 16;
|
||||
}
|
||||
if ((base == 0 || base == 2) &&
|
||||
c == L'0' && (*s == L'b' || *s == L'B') &&
|
||||
(s[1] >= L'0' && s[1] <= L'1')) {
|
||||
c = s[1];
|
||||
s += 2;
|
||||
base = 2;
|
||||
}
|
||||
if (base == 0)
|
||||
base = c == L'0' ? 8 : 10;
|
||||
acc = any = 0;
|
||||
|
|
|
|||
|
|
@ -86,6 +86,13 @@ wcstoumax_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
|
|||
s += 2;
|
||||
base = 16;
|
||||
}
|
||||
if ((base == 0 || base == 2) &&
|
||||
c == L'0' && (*s == L'b' || *s == L'B') &&
|
||||
(s[1] >= L'0' && s[1] <= L'1')) {
|
||||
c = s[1];
|
||||
s += 2;
|
||||
base = 2;
|
||||
}
|
||||
if (base == 0)
|
||||
base = c == L'0' ? 8 : 10;
|
||||
acc = any = 0;
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
.\"
|
||||
.\" @(#)printf.3 8.1 (Berkeley) 6/4/93
|
||||
.\"
|
||||
.Dd May 22, 2018
|
||||
.Dd August 21, 2023
|
||||
.Dt PRINTF 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
|
@ -212,6 +212,17 @@ and
|
|||
.Cm u
|
||||
conversions, this option has no effect.
|
||||
For
|
||||
.Cm b
|
||||
and
|
||||
.Cm B
|
||||
conversions, a non-zero result has the string
|
||||
.Ql 0b
|
||||
(or
|
||||
.Ql 0B
|
||||
for
|
||||
.Cm B
|
||||
conversions) prepended to it.
|
||||
For
|
||||
.Cm o
|
||||
conversions, the precision of the number is increased to force the first
|
||||
character of the output string to a zero.
|
||||
|
|
@ -245,7 +256,7 @@ For all conversions except
|
|||
.Cm n ,
|
||||
the converted value is padded on the left with zeros rather than blanks.
|
||||
If a precision is given with a numeric conversion
|
||||
.Cm ( d , i , o , u , i , x ,
|
||||
.Cm ( b , B , d , i , o , u , i , x ,
|
||||
and
|
||||
.Cm X ) ,
|
||||
the
|
||||
|
|
@ -301,7 +312,7 @@ followed by an
|
|||
optional digit string.
|
||||
If the digit string is omitted, the precision is taken as zero.
|
||||
This gives the minimum number of digits to appear for
|
||||
.Cm d , i , o , u , x ,
|
||||
.Cm b , B , d , i , o , u , x ,
|
||||
and
|
||||
.Cm X
|
||||
conversions, the number of digits to appear after the decimal-point for
|
||||
|
|
@ -319,12 +330,12 @@ conversions.
|
|||
.It
|
||||
An optional length modifier, that specifies the size of the argument.
|
||||
The following length modifiers are valid for the
|
||||
.Cm d , i , n , o , u , x ,
|
||||
.Cm b , B , d , i , n , o , u , x ,
|
||||
or
|
||||
.Cm X
|
||||
conversion:
|
||||
.Bl -column ".Cm q Em (deprecated)" ".Vt signed char" ".Vt unsigned long long" ".Vt long long *"
|
||||
.It Sy Modifier Ta Cm d , i Ta Cm o , u , x , X Ta Cm n
|
||||
.It Sy Modifier Ta Cm d , i Ta Cm b , B , o , u , x , X Ta Cm n
|
||||
.It Cm hh Ta Vt "signed char" Ta Vt "unsigned char" Ta Vt "signed char *"
|
||||
.It Cm h Ta Vt short Ta Vt "unsigned short" Ta Vt "short *"
|
||||
.It Cm l No (ell) Ta Vt long Ta Vt "unsigned long" Ta Vt "long *"
|
||||
|
|
@ -339,7 +350,7 @@ Note:
|
|||
the
|
||||
.Cm t
|
||||
modifier, when applied to a
|
||||
.Cm o , u , x ,
|
||||
.Cm b , B , o , u , x ,
|
||||
or
|
||||
.Cm X
|
||||
conversion, indicates that the argument is of an unsigned type
|
||||
|
|
@ -403,11 +414,16 @@ If a single format directive mixes positional
|
|||
and non-positional arguments, the results are undefined.
|
||||
.Pp
|
||||
The conversion specifiers and their meanings are:
|
||||
.Bl -tag -width ".Cm diouxX"
|
||||
.It Cm diouxX
|
||||
.Bl -tag -width ".Cm bBdiouxX"
|
||||
.It Cm bBdiouxX
|
||||
The
|
||||
.Vt int
|
||||
(or appropriate variant) argument is converted to signed decimal
|
||||
(or appropriate variant) argument is converted to
|
||||
unsigned binary
|
||||
.Cm ( b
|
||||
and
|
||||
.Cm B ) ,
|
||||
signed decimal
|
||||
.Cm ( d
|
||||
and
|
||||
.Cm i ) ,
|
||||
|
|
|
|||
|
|
@ -194,6 +194,13 @@ __ultoa(u_long val, CHAR *endp, int base, int octzero, const char *xdigs)
|
|||
} while (sval != 0);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
do {
|
||||
*--cp = to_char(val & 1);
|
||||
val >>= 1;
|
||||
} while (val);
|
||||
break;
|
||||
|
||||
case 8:
|
||||
do {
|
||||
*--cp = to_char(val & 7);
|
||||
|
|
@ -244,6 +251,13 @@ __ujtoa(uintmax_t val, CHAR *endp, int base, int octzero, const char *xdigs)
|
|||
} while (sval != 0);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
do {
|
||||
*--cp = to_char(val & 1);
|
||||
val >>= 1;
|
||||
} while (val);
|
||||
break;
|
||||
|
||||
case 8:
|
||||
do {
|
||||
*--cp = to_char(val & 7);
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
.\"
|
||||
.\" @(#)scanf.3 8.2 (Berkeley) 12/11/93
|
||||
.\"
|
||||
.Dd April 2, 2022
|
||||
.Dd August 21, 2023
|
||||
.Dt SCANF 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
|
@ -141,7 +141,7 @@ 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
|
||||
.Cm bdioux
|
||||
or
|
||||
.Cm n
|
||||
and the next pointer is a pointer to a
|
||||
|
|
@ -150,7 +150,7 @@ and the next pointer is a pointer to a
|
|||
.Vt int ) .
|
||||
.It Cm h
|
||||
Indicates that the conversion will be one of
|
||||
.Cm dioux
|
||||
.Cm bdioux
|
||||
or
|
||||
.Cm n
|
||||
and the next pointer is a pointer to a
|
||||
|
|
@ -159,7 +159,7 @@ and the next pointer is a pointer to a
|
|||
.Vt int ) .
|
||||
.It Cm l No (ell)
|
||||
Indicates that the conversion will be one of
|
||||
.Cm dioux
|
||||
.Cm bdioux
|
||||
or
|
||||
.Cm n
|
||||
and the next pointer is a pointer to a
|
||||
|
|
@ -185,7 +185,7 @@ and the next pointer is a pointer to an array of
|
|||
.Vt char ) .
|
||||
.It Cm ll No (ell ell)
|
||||
Indicates that the conversion will be one of
|
||||
.Cm dioux
|
||||
.Cm bdioux
|
||||
or
|
||||
.Cm n
|
||||
and the next pointer is a pointer to a
|
||||
|
|
@ -201,7 +201,7 @@ and the next pointer is a pointer to
|
|||
.Vt "long double" .
|
||||
.It Cm j
|
||||
Indicates that the conversion will be one of
|
||||
.Cm dioux
|
||||
.Cm bdioux
|
||||
or
|
||||
.Cm n
|
||||
and the next pointer is a pointer to a
|
||||
|
|
@ -210,7 +210,7 @@ and the next pointer is a pointer to a
|
|||
.Vt int ) .
|
||||
.It Cm t
|
||||
Indicates that the conversion will be one of
|
||||
.Cm dioux
|
||||
.Cm bdioux
|
||||
or
|
||||
.Cm n
|
||||
and the next pointer is a pointer to a
|
||||
|
|
@ -219,7 +219,7 @@ and the next pointer is a pointer to a
|
|||
.Vt int ) .
|
||||
.It Cm z
|
||||
Indicates that the conversion will be one of
|
||||
.Cm dioux
|
||||
.Cm bdioux
|
||||
or
|
||||
.Cm n
|
||||
and the next pointer is a pointer to a
|
||||
|
|
@ -229,7 +229,7 @@ and the next pointer is a pointer to a
|
|||
.It Cm q
|
||||
(deprecated.)
|
||||
Indicates that the conversion will be one of
|
||||
.Cm dioux
|
||||
.Cm bdioux
|
||||
or
|
||||
.Cm n
|
||||
and the next pointer is a pointer to a
|
||||
|
|
@ -273,6 +273,10 @@ matches a single input
|
|||
.Ql %
|
||||
character.
|
||||
No conversion is done, and assignment does not occur.
|
||||
.It Cm b , B
|
||||
Matches an optionally signed binary integer;
|
||||
the next pointer must be a pointer to
|
||||
.Vt "unsigned int" .
|
||||
.It Cm d
|
||||
Matches an optionally signed decimal integer;
|
||||
the next pointer must be a pointer to
|
||||
|
|
@ -281,7 +285,12 @@ the next pointer must be a pointer to
|
|||
Matches an optionally signed integer;
|
||||
the next pointer must be a pointer to
|
||||
.Vt int .
|
||||
The integer is read in base 16 if it begins
|
||||
The integer is read
|
||||
in base 2 if it begins with
|
||||
.Ql 0b
|
||||
or
|
||||
.Ql 0B ,
|
||||
in base 16 if it begins
|
||||
with
|
||||
.Ql 0x
|
||||
or
|
||||
|
|
|
|||
|
|
@ -613,6 +613,19 @@ reswitch: switch (ch) {
|
|||
case 'z':
|
||||
flags |= SIZET;
|
||||
goto rflag;
|
||||
case 'B':
|
||||
case 'b':
|
||||
if (flags & INTMAX_SIZE)
|
||||
ujval = UJARG();
|
||||
else
|
||||
ulval = UARG();
|
||||
base = 2;
|
||||
/* leading 0b/B only if non-zero */
|
||||
if (flags & ALT &&
|
||||
(flags & INTMAX_SIZE ? ujval != 0 : ulval != 0))
|
||||
ox[1] = ch;
|
||||
goto nosign;
|
||||
break;
|
||||
case 'C':
|
||||
flags |= LONGINT;
|
||||
/*FALLTHROUGH*/
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
*
|
||||
* Copyright (c) 2011 The FreeBSD Foundation
|
||||
*
|
||||
* Copyright (c) 2023 Dag-Erling Smørgrav
|
||||
*
|
||||
* Portions of this software were developed by David Chisnall
|
||||
* under sponsorship from the FreeBSD Foundation.
|
||||
*
|
||||
|
|
@ -80,16 +82,6 @@ static char sccsid[] = "@(#)vfscanf.c 8.1 (Berkeley) 6/4/93";
|
|||
#define SHORTSHORT 0x4000 /* hh: char */
|
||||
#define UNSIGNED 0x8000 /* %[oupxX] conversions */
|
||||
|
||||
/*
|
||||
* The following are used in integral conversions only:
|
||||
* SIGNOK, NDIGITS, PFXOK, and NZDIGITS
|
||||
*/
|
||||
#define SIGNOK 0x40 /* +/- is (still) legal */
|
||||
#define NDIGITS 0x80 /* no digits detected */
|
||||
#define PFXOK 0x100 /* 0x prefix is (still) legal */
|
||||
#define NZDIGITS 0x200 /* no zero digits detected */
|
||||
#define HAVESIGN 0x10000 /* sign detected */
|
||||
|
||||
/*
|
||||
* Conversion types.
|
||||
*/
|
||||
|
|
@ -307,129 +299,160 @@ convert_wstring(FILE *fp, wchar_t *wcp, int width, locale_t locale)
|
|||
return (n);
|
||||
}
|
||||
|
||||
enum parseint_state {
|
||||
begin,
|
||||
havesign,
|
||||
havezero,
|
||||
haveprefix,
|
||||
any,
|
||||
};
|
||||
|
||||
static __inline int
|
||||
parseint_fsm(int c, enum parseint_state *state, int *base)
|
||||
{
|
||||
switch (c) {
|
||||
case '+':
|
||||
case '-':
|
||||
if (*state == begin) {
|
||||
*state = havesign;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case '0':
|
||||
if (*state == begin || *state == havesign) {
|
||||
*state = havezero;
|
||||
} else {
|
||||
*state = any;
|
||||
}
|
||||
return 1;
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
if (*state == havezero && *base == 0) {
|
||||
*base = 8;
|
||||
}
|
||||
/* FALL THROUGH */
|
||||
case '8':
|
||||
case '9':
|
||||
if (*state == begin ||
|
||||
*state == havesign) {
|
||||
if (*base == 0) {
|
||||
*base = 10;
|
||||
}
|
||||
}
|
||||
if (*state == begin ||
|
||||
*state == havesign ||
|
||||
*state == havezero ||
|
||||
*state == haveprefix ||
|
||||
*state == any) {
|
||||
if (*base > c - '0') {
|
||||
*state = any;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
if (*state == havezero) {
|
||||
if (*base == 0 || *base == 2) {
|
||||
*state = haveprefix;
|
||||
*base = 2;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
/* FALL THROUGH */
|
||||
case 'a':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
if (*state == begin ||
|
||||
*state == havesign ||
|
||||
*state == havezero ||
|
||||
*state == haveprefix ||
|
||||
*state == any) {
|
||||
if (*base > c - 'a' + 10) {
|
||||
*state = any;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'B':
|
||||
if (*state == havezero) {
|
||||
if (*base == 0 || *base == 2) {
|
||||
*state = haveprefix;
|
||||
*base = 2;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
/* FALL THROUGH */
|
||||
case 'A':
|
||||
case 'C':
|
||||
case 'D':
|
||||
case 'E':
|
||||
case 'F':
|
||||
if (*state == begin ||
|
||||
*state == havesign ||
|
||||
*state == havezero ||
|
||||
*state == haveprefix ||
|
||||
*state == any) {
|
||||
if (*base > c - 'A' + 10) {
|
||||
*state = any;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'x':
|
||||
case 'X':
|
||||
if (*state == havezero) {
|
||||
if (*base == 0 || *base == 16) {
|
||||
*state = haveprefix;
|
||||
*base = 16;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read an integer, storing it in buf. The only relevant bit in the
|
||||
* flags argument is PFXOK.
|
||||
* Read an integer, storing it in buf.
|
||||
*
|
||||
* Return 0 on a match failure, and the number of characters read
|
||||
* otherwise.
|
||||
*/
|
||||
static __inline int
|
||||
parseint(FILE *fp, char * __restrict buf, int width, int base, int flags)
|
||||
parseint(FILE *fp, char * __restrict buf, int width, int base)
|
||||
{
|
||||
/* `basefix' is used to avoid `if' tests */
|
||||
static const short basefix[17] =
|
||||
{ 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
|
||||
enum parseint_state state = begin;
|
||||
char *p;
|
||||
int c;
|
||||
|
||||
flags |= SIGNOK | NDIGITS | NZDIGITS;
|
||||
for (p = buf; width; width--) {
|
||||
c = *fp->_p;
|
||||
/*
|
||||
* Switch on the character; `goto ok' if we accept it
|
||||
* as a part of number.
|
||||
*/
|
||||
switch (c) {
|
||||
|
||||
/*
|
||||
* The digit 0 is always legal, but is special. For
|
||||
* %i conversions, if no digits (zero or nonzero) have
|
||||
* been scanned (only signs), we will have base==0.
|
||||
* In that case, we should set it to 8 and enable 0x
|
||||
* prefixing. Also, if we have not scanned zero
|
||||
* digits before this, do not turn off prefixing
|
||||
* (someone else will turn it off if we have scanned
|
||||
* any nonzero digits).
|
||||
*/
|
||||
case '0':
|
||||
if (base == 0) {
|
||||
base = 8;
|
||||
flags |= PFXOK;
|
||||
}
|
||||
if (flags & NZDIGITS)
|
||||
flags &= ~(SIGNOK|NZDIGITS|NDIGITS);
|
||||
else
|
||||
flags &= ~(SIGNOK|PFXOK|NDIGITS);
|
||||
goto ok;
|
||||
|
||||
/* 1 through 7 always legal */
|
||||
case '1': case '2': case '3':
|
||||
case '4': case '5': case '6': case '7':
|
||||
base = basefix[base];
|
||||
flags &= ~(SIGNOK | PFXOK | NDIGITS);
|
||||
goto ok;
|
||||
|
||||
/* digits 8 and 9 ok iff decimal or hex */
|
||||
case '8': case '9':
|
||||
base = basefix[base];
|
||||
if (base <= 8)
|
||||
break; /* not legal here */
|
||||
flags &= ~(SIGNOK | PFXOK | NDIGITS);
|
||||
goto ok;
|
||||
|
||||
/* letters ok iff hex */
|
||||
case 'A': case 'B': case 'C':
|
||||
case 'D': case 'E': case 'F':
|
||||
case 'a': case 'b': case 'c':
|
||||
case 'd': case 'e': case 'f':
|
||||
/* no need to fix base here */
|
||||
if (base <= 10)
|
||||
break; /* not legal here */
|
||||
flags &= ~(SIGNOK | PFXOK | NDIGITS);
|
||||
goto ok;
|
||||
|
||||
/* sign ok only as first character */
|
||||
case '+': case '-':
|
||||
if (flags & SIGNOK) {
|
||||
flags &= ~SIGNOK;
|
||||
flags |= HAVESIGN;
|
||||
goto ok;
|
||||
}
|
||||
c = __sgetc(fp);
|
||||
if (c == EOF)
|
||||
break;
|
||||
|
||||
/*
|
||||
* x ok iff flag still set & 2nd char (or 3rd char if
|
||||
* we have a sign).
|
||||
*/
|
||||
case 'x': case 'X':
|
||||
if (flags & PFXOK && p ==
|
||||
buf + 1 + !!(flags & HAVESIGN)) {
|
||||
base = 16; /* if %i */
|
||||
flags &= ~PFXOK;
|
||||
goto ok;
|
||||
}
|
||||
if (!parseint_fsm(c, &state, &base))
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we got here, c is not a legal character for a
|
||||
* number. Stop accumulating digits.
|
||||
*/
|
||||
break;
|
||||
ok:
|
||||
/*
|
||||
* c is legal: store it and look at the next.
|
||||
*/
|
||||
*p++ = c;
|
||||
if (--fp->_r > 0)
|
||||
fp->_p++;
|
||||
else if (__srefill(fp))
|
||||
break; /* EOF */
|
||||
}
|
||||
/*
|
||||
* If we had only a sign, it is no good; push back the sign.
|
||||
* If the number ends in `x', it was [sign] '0' 'x', so push
|
||||
* back the x and treat it as [sign] '0'.
|
||||
* If we only had a sign, push it back. If we only had a 0b or 0x
|
||||
* prefix (possibly preceded by a sign), we view it as "0" and
|
||||
* push back the letter. In all other cases, if we stopped
|
||||
* because we read a non-number character, push it back.
|
||||
*/
|
||||
if (flags & NDIGITS) {
|
||||
if (p > buf)
|
||||
(void) __ungetc(*(u_char *)--p, fp);
|
||||
return (0);
|
||||
}
|
||||
c = ((u_char *)p)[-1];
|
||||
if (c == 'x' || c == 'X') {
|
||||
--p;
|
||||
if (state == havesign) {
|
||||
p--;
|
||||
(void) __ungetc(*(u_char *)p, fp);
|
||||
} else if (state == haveprefix) {
|
||||
p--;
|
||||
(void) __ungetc(c, fp);
|
||||
} else if (width && c != EOF) {
|
||||
(void) __ungetc(c, fp);
|
||||
}
|
||||
return (p - buf);
|
||||
|
|
@ -554,6 +577,13 @@ literal:
|
|||
/*
|
||||
* Conversions.
|
||||
*/
|
||||
case 'B':
|
||||
case 'b':
|
||||
c = CT_INT;
|
||||
flags |= UNSIGNED;
|
||||
base = 2;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
c = CT_INT;
|
||||
base = 10;
|
||||
|
|
@ -578,7 +608,6 @@ literal:
|
|||
|
||||
case 'X':
|
||||
case 'x':
|
||||
flags |= PFXOK; /* enable 0x prefixing */
|
||||
c = CT_INT;
|
||||
flags |= UNSIGNED;
|
||||
base = 16;
|
||||
|
|
@ -613,7 +642,7 @@ literal:
|
|||
break;
|
||||
|
||||
case 'p': /* pointer format is like hex */
|
||||
flags |= POINTER | PFXOK;
|
||||
flags |= POINTER;
|
||||
c = CT_INT; /* assumes sizeof(uintmax_t) */
|
||||
flags |= UNSIGNED; /* >= sizeof(uintptr_t) */
|
||||
base = 16;
|
||||
|
|
@ -738,7 +767,7 @@ literal:
|
|||
width = sizeof(buf) - 2;
|
||||
width++;
|
||||
#endif
|
||||
nr = parseint(fp, buf, width, base, flags);
|
||||
nr = parseint(fp, buf, width, base);
|
||||
if (nr == 0)
|
||||
goto match_failure;
|
||||
if ((flags & SUPPRESS) == 0) {
|
||||
|
|
|
|||
|
|
@ -684,6 +684,19 @@ reswitch: switch (ch) {
|
|||
case 'z':
|
||||
flags |= SIZET;
|
||||
goto rflag;
|
||||
case 'B':
|
||||
case 'b':
|
||||
if (flags & INTMAX_SIZE)
|
||||
ujval = UJARG();
|
||||
else
|
||||
ulval = UARG();
|
||||
base = 2;
|
||||
/* leading 0b/B only if non-zero */
|
||||
if (flags & ALT &&
|
||||
(flags & INTMAX_SIZE ? ujval != 0 : ulval != 0))
|
||||
ox[1] = ch;
|
||||
goto nosign;
|
||||
break;
|
||||
case 'C':
|
||||
flags |= LONGINT;
|
||||
/*FALLTHROUGH*/
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@
|
|||
*
|
||||
* Copyright (c) 2011 The FreeBSD Foundation
|
||||
*
|
||||
* Copyright (c) 2023 Dag-Erling Smørgrav
|
||||
*
|
||||
* Portions of this software were developed by David Chisnall
|
||||
* under sponsorship from the FreeBSD Foundation.
|
||||
*
|
||||
|
|
@ -78,16 +80,6 @@ static char sccsid[] = "@(#)vfscanf.c 8.1 (Berkeley) 6/4/93";
|
|||
#define SHORTSHORT 0x4000 /* hh: char */
|
||||
#define UNSIGNED 0x8000 /* %[oupxX] conversions */
|
||||
|
||||
/*
|
||||
* The following are used in integral conversions only:
|
||||
* SIGNOK, NDIGITS, PFXOK, and NZDIGITS
|
||||
*/
|
||||
#define SIGNOK 0x40 /* +/- is (still) legal */
|
||||
#define NDIGITS 0x80 /* no digits detected */
|
||||
#define PFXOK 0x100 /* 0x prefix is (still) legal */
|
||||
#define NZDIGITS 0x200 /* no zero digits detected */
|
||||
#define HAVESIGN 0x10000 /* sign detected */
|
||||
|
||||
/*
|
||||
* Conversion types.
|
||||
*/
|
||||
|
|
@ -289,128 +281,161 @@ convert_wstring(FILE *fp, wchar_t *wcp, int width, locale_t locale)
|
|||
return (nread);
|
||||
}
|
||||
|
||||
enum parseint_state {
|
||||
begin,
|
||||
havesign,
|
||||
havezero,
|
||||
haveprefix,
|
||||
any,
|
||||
};
|
||||
|
||||
static __inline int
|
||||
parseint_fsm(wchar_t c, enum parseint_state *state, int *base)
|
||||
{
|
||||
switch (c) {
|
||||
case '+':
|
||||
case '-':
|
||||
if (*state == begin) {
|
||||
*state = havesign;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case '0':
|
||||
if (*state == begin || *state == havesign) {
|
||||
*state = havezero;
|
||||
} else {
|
||||
*state = any;
|
||||
}
|
||||
return 1;
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
if (*state == havezero && *base == 0) {
|
||||
*base = 8;
|
||||
}
|
||||
/* FALL THROUGH */
|
||||
case '8':
|
||||
case '9':
|
||||
if (*state == begin ||
|
||||
*state == havesign) {
|
||||
if (*base == 0) {
|
||||
*base = 10;
|
||||
}
|
||||
}
|
||||
if (*state == begin ||
|
||||
*state == havesign ||
|
||||
*state == havezero ||
|
||||
*state == haveprefix ||
|
||||
*state == any) {
|
||||
if (*base > c - '0') {
|
||||
*state = any;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
if (*state == havezero) {
|
||||
if (*base == 0 || *base == 2) {
|
||||
*state = haveprefix;
|
||||
*base = 2;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
/* FALL THROUGH */
|
||||
case 'a':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
if (*state == begin ||
|
||||
*state == havesign ||
|
||||
*state == havezero ||
|
||||
*state == haveprefix ||
|
||||
*state == any) {
|
||||
if (*base > c - 'a' + 10) {
|
||||
*state = any;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'B':
|
||||
if (*state == havezero) {
|
||||
if (*base == 0 || *base == 2) {
|
||||
*state = haveprefix;
|
||||
*base = 2;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
/* FALL THROUGH */
|
||||
case 'A':
|
||||
case 'C':
|
||||
case 'D':
|
||||
case 'E':
|
||||
case 'F':
|
||||
if (*state == begin ||
|
||||
*state == havesign ||
|
||||
*state == havezero ||
|
||||
*state == haveprefix ||
|
||||
*state == any) {
|
||||
if (*base > c - 'A' + 10) {
|
||||
*state = any;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'x':
|
||||
case 'X':
|
||||
if (*state == havezero) {
|
||||
if (*base == 0 || *base == 16) {
|
||||
*state = haveprefix;
|
||||
*base = 16;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read an integer, storing it in buf. The only relevant bit in the
|
||||
* flags argument is PFXOK.
|
||||
* Read an integer, storing it in buf.
|
||||
*
|
||||
* Return 0 on a match failure, and the number of characters read
|
||||
* otherwise.
|
||||
*/
|
||||
static __inline int
|
||||
parseint(FILE *fp, wchar_t *buf, int width, int base, int flags,
|
||||
parseint(FILE *fp, wchar_t * __restrict buf, int width, int base,
|
||||
locale_t locale)
|
||||
{
|
||||
/* `basefix' is used to avoid `if' tests */
|
||||
static const short basefix[17] =
|
||||
{ 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
|
||||
enum parseint_state state = begin;
|
||||
wchar_t *wcp;
|
||||
int c;
|
||||
|
||||
flags |= SIGNOK | NDIGITS | NZDIGITS;
|
||||
for (wcp = buf; width; width--) {
|
||||
c = __fgetwc(fp, locale);
|
||||
/*
|
||||
* Switch on the character; `goto ok' if we accept it
|
||||
* as a part of number.
|
||||
*/
|
||||
switch (c) {
|
||||
|
||||
/*
|
||||
* The digit 0 is always legal, but is special. For
|
||||
* %i conversions, if no digits (zero or nonzero) have
|
||||
* been scanned (only signs), we will have base==0.
|
||||
* In that case, we should set it to 8 and enable 0x
|
||||
* prefixing. Also, if we have not scanned zero
|
||||
* digits before this, do not turn off prefixing
|
||||
* (someone else will turn it off if we have scanned
|
||||
* any nonzero digits).
|
||||
*/
|
||||
case '0':
|
||||
if (base == 0) {
|
||||
base = 8;
|
||||
flags |= PFXOK;
|
||||
}
|
||||
if (flags & NZDIGITS)
|
||||
flags &= ~(SIGNOK|NZDIGITS|NDIGITS);
|
||||
else
|
||||
flags &= ~(SIGNOK|PFXOK|NDIGITS);
|
||||
goto ok;
|
||||
|
||||
/* 1 through 7 always legal */
|
||||
case '1': case '2': case '3':
|
||||
case '4': case '5': case '6': case '7':
|
||||
base = basefix[base];
|
||||
flags &= ~(SIGNOK | PFXOK | NDIGITS);
|
||||
goto ok;
|
||||
|
||||
/* digits 8 and 9 ok iff decimal or hex */
|
||||
case '8': case '9':
|
||||
base = basefix[base];
|
||||
if (base <= 8)
|
||||
break; /* not legal here */
|
||||
flags &= ~(SIGNOK | PFXOK | NDIGITS);
|
||||
goto ok;
|
||||
|
||||
/* letters ok iff hex */
|
||||
case 'A': case 'B': case 'C':
|
||||
case 'D': case 'E': case 'F':
|
||||
case 'a': case 'b': case 'c':
|
||||
case 'd': case 'e': case 'f':
|
||||
/* no need to fix base here */
|
||||
if (base <= 10)
|
||||
break; /* not legal here */
|
||||
flags &= ~(SIGNOK | PFXOK | NDIGITS);
|
||||
goto ok;
|
||||
|
||||
/* sign ok only as first character */
|
||||
case '+': case '-':
|
||||
if (flags & SIGNOK) {
|
||||
flags &= ~SIGNOK;
|
||||
flags |= HAVESIGN;
|
||||
goto ok;
|
||||
}
|
||||
if (c == WEOF)
|
||||
break;
|
||||
|
||||
/*
|
||||
* x ok iff flag still set & 2nd char (or 3rd char if
|
||||
* we have a sign).
|
||||
*/
|
||||
case 'x': case 'X':
|
||||
if (flags & PFXOK && wcp ==
|
||||
buf + 1 + !!(flags & HAVESIGN)) {
|
||||
base = 16; /* if %i */
|
||||
flags &= ~PFXOK;
|
||||
goto ok;
|
||||
}
|
||||
if (!parseint_fsm(c, &state, &base))
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we got here, c is not a legal character for a
|
||||
* number. Stop accumulating digits.
|
||||
*/
|
||||
if (c != WEOF)
|
||||
__ungetwc(c, fp, locale);
|
||||
break;
|
||||
ok:
|
||||
/*
|
||||
* c is legal: store it and look at the next.
|
||||
*/
|
||||
*wcp++ = (wchar_t)c;
|
||||
}
|
||||
/*
|
||||
* If we had only a sign, it is no good; push back the sign.
|
||||
* If the number ends in `x', it was [sign] '0' 'x', so push
|
||||
* back the x and treat it as [sign] '0'.
|
||||
* If we only had a sign, push it back. If we only had a 0b or 0x
|
||||
* prefix (possibly preceded by a sign), we view it as "0" and
|
||||
* push back the letter. In all other cases, if we stopped
|
||||
* because we read a non-number character, push it back.
|
||||
*/
|
||||
if (flags & NDIGITS) {
|
||||
if (wcp > buf)
|
||||
__ungetwc(*--wcp, fp, locale);
|
||||
return (0);
|
||||
}
|
||||
c = wcp[-1];
|
||||
if (c == 'x' || c == 'X') {
|
||||
--wcp;
|
||||
if (state == havesign) {
|
||||
wcp--;
|
||||
__ungetwc(*wcp, fp, locale);
|
||||
} else if (state == haveprefix) {
|
||||
wcp--;
|
||||
__ungetwc(c, fp, locale);
|
||||
} else if (width && c != WEOF) {
|
||||
__ungetwc(c, fp, locale);
|
||||
}
|
||||
return (wcp - buf);
|
||||
|
|
@ -536,6 +561,13 @@ literal:
|
|||
/*
|
||||
* Conversions.
|
||||
*/
|
||||
case 'B':
|
||||
case 'b':
|
||||
c = CT_INT;
|
||||
flags |= UNSIGNED;
|
||||
base = 2;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
c = CT_INT;
|
||||
base = 10;
|
||||
|
|
@ -560,7 +592,6 @@ literal:
|
|||
|
||||
case 'X':
|
||||
case 'x':
|
||||
flags |= PFXOK; /* enable 0x prefixing */
|
||||
c = CT_INT;
|
||||
flags |= UNSIGNED;
|
||||
base = 16;
|
||||
|
|
@ -606,7 +637,7 @@ literal:
|
|||
break;
|
||||
|
||||
case 'p': /* pointer format is like hex */
|
||||
flags |= POINTER | PFXOK;
|
||||
flags |= POINTER;
|
||||
c = CT_INT; /* assumes sizeof(uintmax_t) */
|
||||
flags |= UNSIGNED; /* >= sizeof(uintptr_t) */
|
||||
base = 16;
|
||||
|
|
@ -716,7 +747,7 @@ literal:
|
|||
sizeof(*buf) - 1)
|
||||
width = sizeof(buf) / sizeof(*buf) - 1;
|
||||
|
||||
nr = parseint(fp, buf, width, base, flags, locale);
|
||||
nr = parseint(fp, buf, width, base, locale);
|
||||
if (nr == 0)
|
||||
goto match_failure;
|
||||
if ((flags & SUPPRESS) == 0) {
|
||||
|
|
|
|||
|
|
@ -87,6 +87,13 @@ strtoimax_l(const char * __restrict nptr, char ** __restrict endptr, int base,
|
|||
s += 2;
|
||||
base = 16;
|
||||
}
|
||||
if ((base == 0 || base == 2) &&
|
||||
c == '0' && (*s == 'b' || *s == 'B') &&
|
||||
(s[1] >= '0' && s[1] <= '1')) {
|
||||
c = s[1];
|
||||
s += 2;
|
||||
base = 2;
|
||||
}
|
||||
if (base == 0)
|
||||
base = c == '0' ? 8 : 10;
|
||||
acc = any = 0;
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
.\"
|
||||
.\" @(#)strtol.3 8.1 (Berkeley) 6/4/93
|
||||
.\"
|
||||
.Dd November 28, 2001
|
||||
.Dd August 21, 2023
|
||||
.Dt STRTOL 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
|
@ -108,6 +108,8 @@ If
|
|||
.Fa base
|
||||
is zero or 16,
|
||||
the string may then include a
|
||||
.Dq Li 0b
|
||||
prefix, and the number will be read in base 2; or it may include a
|
||||
.Dq Li 0x
|
||||
prefix,
|
||||
and the number will be read in base 16; otherwise, a zero
|
||||
|
|
|
|||
|
|
@ -87,6 +87,13 @@ strtol_l(const char * __restrict nptr, char ** __restrict endptr, int base,
|
|||
s += 2;
|
||||
base = 16;
|
||||
}
|
||||
if ((base == 0 || base == 2) &&
|
||||
c == '0' && (*s == 'b' || *s == 'B') &&
|
||||
(s[1] >= '0' && s[1] <= '1')) {
|
||||
c = s[1];
|
||||
s += 2;
|
||||
base = 2;
|
||||
}
|
||||
if (base == 0)
|
||||
base = c == '0' ? 8 : 10;
|
||||
acc = any = 0;
|
||||
|
|
|
|||
|
|
@ -63,8 +63,9 @@ strtoll_l(const char * __restrict nptr, char ** __restrict endptr, int base,
|
|||
|
||||
/*
|
||||
* Skip white space and pick up leading +/- sign if any.
|
||||
* If base is 0, allow 0x for hex and 0 for octal, else
|
||||
* assume decimal; if base is already 16, allow 0x.
|
||||
* If base is 0, allow 0b for binary, 0x for hex, and 0 for
|
||||
* octal, else assume decimal; if base is already 2, allow
|
||||
* 0b; if base is already 16, allow 0x.
|
||||
*/
|
||||
s = nptr;
|
||||
do {
|
||||
|
|
@ -87,6 +88,13 @@ strtoll_l(const char * __restrict nptr, char ** __restrict endptr, int base,
|
|||
s += 2;
|
||||
base = 16;
|
||||
}
|
||||
if ((base == 0 || base == 2) &&
|
||||
c == '0' && (*s == 'b' || *s == 'B') &&
|
||||
(s[1] >= '0' && s[1] <= '1')) {
|
||||
c = s[1];
|
||||
s += 2;
|
||||
base = 2;
|
||||
}
|
||||
if (base == 0)
|
||||
base = c == '0' ? 8 : 10;
|
||||
acc = any = 0;
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
.\"
|
||||
.\" @(#)strtoul.3 8.1 (Berkeley) 6/4/93
|
||||
.\"
|
||||
.Dd November 28, 2001
|
||||
.Dd August 21, 2023
|
||||
.Dt STRTOUL 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
|
@ -108,6 +108,8 @@ If
|
|||
.Fa base
|
||||
is zero or 16,
|
||||
the string may then include a
|
||||
.Dq Li 0b
|
||||
prefix, and the number will be read in base 2; or it may include a
|
||||
.Dq Li 0x
|
||||
prefix,
|
||||
and the number will be read in base 16; otherwise, a zero
|
||||
|
|
|
|||
|
|
@ -84,6 +84,13 @@ strtoul_l(const char * __restrict nptr, char ** __restrict endptr, int base, loc
|
|||
s += 2;
|
||||
base = 16;
|
||||
}
|
||||
if ((base == 0 || base == 2) &&
|
||||
c == '0' && (*s == 'b' || *s == 'B') &&
|
||||
(s[1] >= '0' && s[1] <= '1')) {
|
||||
c = s[1];
|
||||
s += 2;
|
||||
base = 2;
|
||||
}
|
||||
if (base == 0)
|
||||
base = c == '0' ? 8 : 10;
|
||||
acc = any = 0;
|
||||
|
|
|
|||
|
|
@ -85,6 +85,13 @@ strtoull_l(const char * __restrict nptr, char ** __restrict endptr, int base,
|
|||
s += 2;
|
||||
base = 16;
|
||||
}
|
||||
if ((base == 0 || base == 2) &&
|
||||
c == '0' && (*s == 'b' || *s == 'B') &&
|
||||
(s[1] >= '0' && s[1] <= '1')) {
|
||||
c = s[1];
|
||||
s += 2;
|
||||
base = 2;
|
||||
}
|
||||
if (base == 0)
|
||||
base = c == '0' ? 8 : 10;
|
||||
acc = any = 0;
|
||||
|
|
|
|||
|
|
@ -85,6 +85,13 @@ strtoumax_l(const char * __restrict nptr, char ** __restrict endptr, int base,
|
|||
s += 2;
|
||||
base = 16;
|
||||
}
|
||||
if ((base == 0 || base == 2) &&
|
||||
c == '0' && (*s == 'b' || *s == 'B') &&
|
||||
(s[1] >= '0' && s[1] <= '1')) {
|
||||
c = s[1];
|
||||
s += 2;
|
||||
base = 2;
|
||||
}
|
||||
if (base == 0)
|
||||
base = c == '0' ? 8 : 10;
|
||||
acc = any = 0;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,10 @@ ATF_TESTS_C+= print_positional_test
|
|||
ATF_TESTS_C+= printbasic_test
|
||||
ATF_TESTS_C+= printfloat_test
|
||||
ATF_TESTS_C+= scanfloat_test
|
||||
ATF_TESTS_C+= snprintf_test
|
||||
ATF_TESTS_C+= sscanf_test
|
||||
ATF_TESTS_C+= swprintf_test
|
||||
ATF_TESTS_C+= swscanf_test
|
||||
|
||||
SRCS.fopen2_test= fopen_test.c
|
||||
|
||||
|
|
@ -34,9 +38,15 @@ LIBADD.eintr_test+= md
|
|||
LIBADD.printfloat_test+= m
|
||||
LIBADD.scanfloat_test+= m
|
||||
|
||||
# Older toolchains won't understand C23 %b, %wN, %wfN
|
||||
PROG_OVERRIDE_VARS+= NO_WFORMAT
|
||||
NO_WFORMAT.snprintf_test=
|
||||
NO_WFORMAT.sscanf_test=
|
||||
NO_WFORMAT.swprintf_test=
|
||||
NO_WFORMAT.swscanf_test=
|
||||
|
||||
.if ${COMPILER_TYPE} == "gcc"
|
||||
# 90: use of assignment suppression and length modifier together in scanf format
|
||||
PROG_OVERRIDE_VARS+= NO_WFORMAT
|
||||
NO_WFORMAT.scanfloat_test=
|
||||
.endif
|
||||
|
||||
|
|
|
|||
139
lib/libc/tests/stdio/snprintf_test.c
Normal file
139
lib/libc/tests/stdio/snprintf_test.c
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
/*-
|
||||
* Copyright (c) 2023 Dag-Erling Smørgrav
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <locale.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <atf-c.h>
|
||||
|
||||
#ifndef nitems
|
||||
#define nitems(a) (sizeof(a) / sizeof(a[0]))
|
||||
#endif
|
||||
|
||||
#define SNPRINTF_TEST(output, format, ...) \
|
||||
do { \
|
||||
char buf[256]; \
|
||||
assert(strlen(output) < nitems(buf)); \
|
||||
int ret = snprintf(buf, nitems(buf), format, \
|
||||
__VA_ARGS__); \
|
||||
ATF_CHECK_EQ(strlen(output), ret); \
|
||||
if (ret > 0) { \
|
||||
ATF_CHECK_EQ(0, strcmp(output, buf)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
ATF_TC_WITHOUT_HEAD(snprintf_b);
|
||||
ATF_TC_BODY(snprintf_b, tc)
|
||||
{
|
||||
SNPRINTF_TEST("0", "%b", 0);
|
||||
SNPRINTF_TEST(" 0", "%12b", 0);
|
||||
SNPRINTF_TEST("000000000000", "%012b", 0);
|
||||
SNPRINTF_TEST("1", "%b", 1);
|
||||
SNPRINTF_TEST(" 1", "%12b", 1);
|
||||
SNPRINTF_TEST("000000000001", "%012b", 1);
|
||||
SNPRINTF_TEST("1111111111111111111111111111111", "%b", INT_MAX);
|
||||
SNPRINTF_TEST("0", "%#b", 0);
|
||||
SNPRINTF_TEST(" 0", "%#12b", 0);
|
||||
SNPRINTF_TEST("000000000000", "%#012b", 0);
|
||||
SNPRINTF_TEST("0b1", "%#b", 1);
|
||||
SNPRINTF_TEST(" 0b1", "%#12b", 1);
|
||||
SNPRINTF_TEST("0b0000000001", "%#012b", 1);
|
||||
SNPRINTF_TEST("0b1111111111111111111111111111111", "%#b", INT_MAX);
|
||||
}
|
||||
|
||||
ATF_TC_WITHOUT_HEAD(snprintf_B);
|
||||
ATF_TC_BODY(snprintf_B, tc)
|
||||
{
|
||||
SNPRINTF_TEST("0", "%B", 0);
|
||||
SNPRINTF_TEST(" 0", "%12B", 0);
|
||||
SNPRINTF_TEST("000000000000", "%012B", 0);
|
||||
SNPRINTF_TEST("1", "%B", 1);
|
||||
SNPRINTF_TEST(" 1", "%12B", 1);
|
||||
SNPRINTF_TEST("000000000001", "%012B", 1);
|
||||
SNPRINTF_TEST("1111111111111111111111111111111", "%B", INT_MAX);
|
||||
SNPRINTF_TEST("0", "%#B", 0);
|
||||
SNPRINTF_TEST(" 0", "%#12B", 0);
|
||||
SNPRINTF_TEST("000000000000", "%#012B", 0);
|
||||
SNPRINTF_TEST("0B1", "%#B", 1);
|
||||
SNPRINTF_TEST(" 0B1", "%#12B", 1);
|
||||
SNPRINTF_TEST("0B0000000001", "%#012B", 1);
|
||||
SNPRINTF_TEST("0B1111111111111111111111111111111", "%#B", INT_MAX);
|
||||
}
|
||||
|
||||
ATF_TC_WITHOUT_HEAD(snprintf_d);
|
||||
ATF_TC_BODY(snprintf_d, tc)
|
||||
{
|
||||
SNPRINTF_TEST("0", "%d", 0);
|
||||
SNPRINTF_TEST(" 0", "%12d", 0);
|
||||
SNPRINTF_TEST("000000000000", "%012d", 0);
|
||||
SNPRINTF_TEST("1", "%d", 1);
|
||||
SNPRINTF_TEST(" 1", "%12d", 1);
|
||||
SNPRINTF_TEST("000000000001", "%012d", 1);
|
||||
SNPRINTF_TEST("2147483647", "%d", INT_MAX);
|
||||
SNPRINTF_TEST(" 2147483647", "%12d", INT_MAX);
|
||||
SNPRINTF_TEST("002147483647", "%012d", INT_MAX);
|
||||
SNPRINTF_TEST("2,147,483,647", "%'d", INT_MAX);
|
||||
}
|
||||
|
||||
ATF_TC_WITHOUT_HEAD(snprintf_x);
|
||||
ATF_TC_BODY(snprintf_x, tc)
|
||||
{
|
||||
SNPRINTF_TEST("0", "%x", 0);
|
||||
SNPRINTF_TEST(" 0", "%12x", 0);
|
||||
SNPRINTF_TEST("000000000000", "%012x", 0);
|
||||
SNPRINTF_TEST("1", "%x", 1);
|
||||
SNPRINTF_TEST(" 1", "%12x", 1);
|
||||
SNPRINTF_TEST("000000000001", "%012x", 1);
|
||||
SNPRINTF_TEST("7fffffff", "%x", INT_MAX);
|
||||
SNPRINTF_TEST(" 7fffffff", "%12x", INT_MAX);
|
||||
SNPRINTF_TEST("00007fffffff", "%012x", INT_MAX);
|
||||
SNPRINTF_TEST("0", "%#x", 0);
|
||||
SNPRINTF_TEST(" 0", "%#12x", 0);
|
||||
SNPRINTF_TEST("000000000000", "%#012x", 0);
|
||||
SNPRINTF_TEST("0x1", "%#x", 1);
|
||||
SNPRINTF_TEST(" 0x1", "%#12x", 1);
|
||||
SNPRINTF_TEST("0x0000000001", "%#012x", 1);
|
||||
SNPRINTF_TEST("0x7fffffff", "%#x", INT_MAX);
|
||||
SNPRINTF_TEST(" 0x7fffffff", "%#12x", INT_MAX);
|
||||
SNPRINTF_TEST("0x007fffffff", "%#012x", INT_MAX);
|
||||
}
|
||||
|
||||
ATF_TC_WITHOUT_HEAD(snprintf_X);
|
||||
ATF_TC_BODY(snprintf_X, tc)
|
||||
{
|
||||
SNPRINTF_TEST("0", "%X", 0);
|
||||
SNPRINTF_TEST(" 0", "%12X", 0);
|
||||
SNPRINTF_TEST("000000000000", "%012X", 0);
|
||||
SNPRINTF_TEST("1", "%X", 1);
|
||||
SNPRINTF_TEST(" 1", "%12X", 1);
|
||||
SNPRINTF_TEST("000000000001", "%012X", 1);
|
||||
SNPRINTF_TEST("7FFFFFFF", "%X", INT_MAX);
|
||||
SNPRINTF_TEST(" 7FFFFFFF", "%12X", INT_MAX);
|
||||
SNPRINTF_TEST("00007FFFFFFF", "%012X", INT_MAX);
|
||||
SNPRINTF_TEST("0", "%#X", 0);
|
||||
SNPRINTF_TEST(" 0", "%#12X", 0);
|
||||
SNPRINTF_TEST("000000000000", "%#012X", 0);
|
||||
SNPRINTF_TEST("0X1", "%#X", 1);
|
||||
SNPRINTF_TEST(" 0X1", "%#12X", 1);
|
||||
SNPRINTF_TEST("0X0000000001", "%#012X", 1);
|
||||
SNPRINTF_TEST("0X7FFFFFFF", "%#X", INT_MAX);
|
||||
SNPRINTF_TEST(" 0X7FFFFFFF", "%#12X", INT_MAX);
|
||||
SNPRINTF_TEST("0X007FFFFFFF", "%#012X", INT_MAX);
|
||||
}
|
||||
|
||||
ATF_TP_ADD_TCS(tp)
|
||||
{
|
||||
setlocale(LC_NUMERIC, "en_US.UTF-8");
|
||||
ATF_TP_ADD_TC(tp, snprintf_b);
|
||||
ATF_TP_ADD_TC(tp, snprintf_B);
|
||||
ATF_TP_ADD_TC(tp, snprintf_d);
|
||||
ATF_TP_ADD_TC(tp, snprintf_x);
|
||||
ATF_TP_ADD_TC(tp, snprintf_X);
|
||||
return (atf_no_error());
|
||||
}
|
||||
266
lib/libc/tests/stdio/sscanf_test.c
Normal file
266
lib/libc/tests/stdio/sscanf_test.c
Normal file
|
|
@ -0,0 +1,266 @@
|
|||
/*-
|
||||
* Copyright (c) 2023 Dag-Erling Smørgrav
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <locale.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <atf-c.h>
|
||||
|
||||
static const struct sscanf_test_case {
|
||||
char input[8];
|
||||
struct {
|
||||
int ret, val, len;
|
||||
} b, o, d, x, i;
|
||||
} sscanf_test_cases[] = {
|
||||
// input binary octal decimal hexadecimal automatic
|
||||
// all digits
|
||||
{ "0", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, },
|
||||
{ "1", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, },
|
||||
{ "2", { 0, 0, 0 }, { 1, 2, 1 }, { 1, 2, 1 }, { 1, 2, 1 }, { 1, 2, 1 }, },
|
||||
{ "3", { 0, 0, 0 }, { 1, 3, 1 }, { 1, 3, 1 }, { 1, 3, 1 }, { 1, 3, 1 }, },
|
||||
{ "4", { 0, 0, 0 }, { 1, 4, 1 }, { 1, 4, 1 }, { 1, 4, 1 }, { 1, 4, 1 }, },
|
||||
{ "5", { 0, 0, 0 }, { 1, 5, 1 }, { 1, 5, 1 }, { 1, 5, 1 }, { 1, 5, 1 }, },
|
||||
{ "6", { 0, 0, 0 }, { 1, 6, 1 }, { 1, 6, 1 }, { 1, 6, 1 }, { 1, 6, 1 }, },
|
||||
{ "7", { 0, 0, 0 }, { 1, 7, 1 }, { 1, 7, 1 }, { 1, 7, 1 }, { 1, 7, 1 }, },
|
||||
{ "8", { 0, 0, 0 }, { 0, 0, 0 }, { 1, 8, 1 }, { 1, 8, 1 }, { 1, 8, 1 }, },
|
||||
{ "9", { 0, 0, 0 }, { 0, 0, 0 }, { 1, 9, 1 }, { 1, 9, 1 }, { 1, 9, 1 }, },
|
||||
{ "A", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 10, 1 }, { 0, 0, 0 }, },
|
||||
{ "B", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 11, 1 }, { 0, 0, 0 }, },
|
||||
{ "C", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 12, 1 }, { 0, 0, 0 }, },
|
||||
{ "D", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 13, 1 }, { 0, 0, 0 }, },
|
||||
{ "E", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 14, 1 }, { 0, 0, 0 }, },
|
||||
{ "F", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 15, 1 }, { 0, 0, 0 }, },
|
||||
{ "X", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, },
|
||||
{ "a", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 10, 1 }, { 0, 0, 0 }, },
|
||||
{ "b", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 11, 1 }, { 0, 0, 0 }, },
|
||||
{ "c", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 12, 1 }, { 0, 0, 0 }, },
|
||||
{ "d", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 13, 1 }, { 0, 0, 0 }, },
|
||||
{ "e", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 14, 1 }, { 0, 0, 0 }, },
|
||||
{ "f", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 15, 1 }, { 0, 0, 0 }, },
|
||||
{ "x", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, },
|
||||
// all digits with leading zero
|
||||
{ "00", { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, },
|
||||
{ "01", { 1, 1, 2 }, { 1, 1, 2 }, { 1, 1, 2 }, { 1, 1, 2 }, { 1, 1, 2 }, },
|
||||
{ "02", { 1, 0, 1 }, { 1, 2, 2 }, { 1, 2, 2 }, { 1, 2, 2 }, { 1, 2, 2 }, },
|
||||
{ "03", { 1, 0, 1 }, { 1, 3, 2 }, { 1, 3, 2 }, { 1, 3, 2 }, { 1, 3, 2 }, },
|
||||
{ "04", { 1, 0, 1 }, { 1, 4, 2 }, { 1, 4, 2 }, { 1, 4, 2 }, { 1, 4, 2 }, },
|
||||
{ "05", { 1, 0, 1 }, { 1, 5, 2 }, { 1, 5, 2 }, { 1, 5, 2 }, { 1, 5, 2 }, },
|
||||
{ "06", { 1, 0, 1 }, { 1, 6, 2 }, { 1, 6, 2 }, { 1, 6, 2 }, { 1, 6, 2 }, },
|
||||
{ "07", { 1, 0, 1 }, { 1, 7, 2 }, { 1, 7, 2 }, { 1, 7, 2 }, { 1, 7, 2 }, },
|
||||
{ "08", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 8, 2 }, { 1, 8, 2 }, { 1, 0, 1 }, },
|
||||
{ "09", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 9, 2 }, { 1, 9, 2 }, { 1, 0, 1 }, },
|
||||
{ "0A", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 10, 2 }, { 1, 0, 1 }, },
|
||||
{ "0B", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 11, 2 }, { 1, 0, 1 }, },
|
||||
{ "0C", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 12, 2 }, { 1, 0, 1 }, },
|
||||
{ "0D", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 13, 2 }, { 1, 0, 1 }, },
|
||||
{ "0E", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 14, 2 }, { 1, 0, 1 }, },
|
||||
{ "0F", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 15, 2 }, { 1, 0, 1 }, },
|
||||
{ "0X", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, },
|
||||
{ "0a", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 10, 2 }, { 1, 0, 1 }, },
|
||||
{ "0b", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 11, 2 }, { 1, 0, 1 }, },
|
||||
{ "0c", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 12, 2 }, { 1, 0, 1 }, },
|
||||
{ "0d", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 13, 2 }, { 1, 0, 1 }, },
|
||||
{ "0e", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 14, 2 }, { 1, 0, 1 }, },
|
||||
{ "0f", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 15, 2 }, { 1, 0, 1 }, },
|
||||
{ "0x", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, },
|
||||
// all digits with leading one
|
||||
{ "10", { 1, 2, 2 }, { 1, 8, 2 }, { 1, 10, 2 }, { 1, 16, 2 }, { 1, 10, 2 }, },
|
||||
{ "11", { 1, 3, 2 }, { 1, 9, 2 }, { 1, 11, 2 }, { 1, 17, 2 }, { 1, 11, 2 }, },
|
||||
{ "12", { 1, 1, 1 }, { 1, 10, 2 }, { 1, 12, 2 }, { 1, 18, 2 }, { 1, 12, 2 }, },
|
||||
{ "13", { 1, 1, 1 }, { 1, 11, 2 }, { 1, 13, 2 }, { 1, 19, 2 }, { 1, 13, 2 }, },
|
||||
{ "14", { 1, 1, 1 }, { 1, 12, 2 }, { 1, 14, 2 }, { 1, 20, 2 }, { 1, 14, 2 }, },
|
||||
{ "15", { 1, 1, 1 }, { 1, 13, 2 }, { 1, 15, 2 }, { 1, 21, 2 }, { 1, 15, 2 }, },
|
||||
{ "16", { 1, 1, 1 }, { 1, 14, 2 }, { 1, 16, 2 }, { 1, 22, 2 }, { 1, 16, 2 }, },
|
||||
{ "17", { 1, 1, 1 }, { 1, 15, 2 }, { 1, 17, 2 }, { 1, 23, 2 }, { 1, 17, 2 }, },
|
||||
{ "18", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 18, 2 }, { 1, 24, 2 }, { 1, 18, 2 }, },
|
||||
{ "19", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 19, 2 }, { 1, 25, 2 }, { 1, 19, 2 }, },
|
||||
{ "1A", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 26, 2 }, { 1, 1, 1 }, },
|
||||
{ "1B", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 27, 2 }, { 1, 1, 1 }, },
|
||||
{ "1C", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 28, 2 }, { 1, 1, 1 }, },
|
||||
{ "1D", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 29, 2 }, { 1, 1, 1 }, },
|
||||
{ "1E", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 30, 2 }, { 1, 1, 1 }, },
|
||||
{ "1F", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 31, 2 }, { 1, 1, 1 }, },
|
||||
{ "1X", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, },
|
||||
{ "1a", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 26, 2 }, { 1, 1, 1 }, },
|
||||
{ "1b", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 27, 2 }, { 1, 1, 1 }, },
|
||||
{ "1c", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 28, 2 }, { 1, 1, 1 }, },
|
||||
{ "1d", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 29, 2 }, { 1, 1, 1 }, },
|
||||
{ "1e", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 30, 2 }, { 1, 1, 1 }, },
|
||||
{ "1f", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 31, 2 }, { 1, 1, 1 }, },
|
||||
{ "1x", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, },
|
||||
// all digits with leading binary prefix
|
||||
{ "0b0", { 1, 0, 3 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 176, 3 }, { 1, 0, 3 }, },
|
||||
{ "0b1", { 1, 1, 3 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 177, 3 }, { 1, 1, 3 }, },
|
||||
{ "0b2", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 178, 3 }, { 1, 0, 1 }, },
|
||||
{ "0b3", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 179, 3 }, { 1, 0, 1 }, },
|
||||
{ "0b4", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 180, 3 }, { 1, 0, 1 }, },
|
||||
{ "0b5", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 181, 3 }, { 1, 0, 1 }, },
|
||||
{ "0b6", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 182, 3 }, { 1, 0, 1 }, },
|
||||
{ "0b7", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 183, 3 }, { 1, 0, 1 }, },
|
||||
{ "0b8", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 184, 3 }, { 1, 0, 1 }, },
|
||||
{ "0b9", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 185, 3 }, { 1, 0, 1 }, },
|
||||
{ "0bA", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 186, 3 }, { 1, 0, 1 }, },
|
||||
{ "0bB", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 187, 3 }, { 1, 0, 1 }, },
|
||||
{ "0bC", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 188, 3 }, { 1, 0, 1 }, },
|
||||
{ "0bD", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 189, 3 }, { 1, 0, 1 }, },
|
||||
{ "0bE", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 190, 3 }, { 1, 0, 1 }, },
|
||||
{ "0bF", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 191, 3 }, { 1, 0, 1 }, },
|
||||
{ "0bX", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 11, 2 }, { 1, 0, 1 }, },
|
||||
{ "0ba", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 186, 3 }, { 1, 0, 1 }, },
|
||||
{ "0bb", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 187, 3 }, { 1, 0, 1 }, },
|
||||
{ "0bc", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 188, 3 }, { 1, 0, 1 }, },
|
||||
{ "0bd", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 189, 3 }, { 1, 0, 1 }, },
|
||||
{ "0be", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 190, 3 }, { 1, 0, 1 }, },
|
||||
{ "0bf", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 191, 3 }, { 1, 0, 1 }, },
|
||||
{ "0bx", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 11, 2 }, { 1, 0, 1 }, },
|
||||
// all digits with leading hexadecimal prefix
|
||||
{ "0x0", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 3 }, { 1, 0, 3 }, },
|
||||
{ "0x1", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 1, 3 }, { 1, 1, 3 }, },
|
||||
{ "0x2", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 2, 3 }, { 1, 2, 3 }, },
|
||||
{ "0x3", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 3, 3 }, { 1, 3, 3 }, },
|
||||
{ "0x4", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 4, 3 }, { 1, 4, 3 }, },
|
||||
{ "0x5", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 5, 3 }, { 1, 5, 3 }, },
|
||||
{ "0x6", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 6, 3 }, { 1, 6, 3 }, },
|
||||
{ "0x7", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 7, 3 }, { 1, 7, 3 }, },
|
||||
{ "0x8", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 8, 3 }, { 1, 8, 3 }, },
|
||||
{ "0x9", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 9, 3 }, { 1, 9, 3 }, },
|
||||
{ "0xA", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 10, 3 }, { 1, 10, 3 }, },
|
||||
{ "0xB", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 11, 3 }, { 1, 11, 3 }, },
|
||||
{ "0xC", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 12, 3 }, { 1, 12, 3 }, },
|
||||
{ "0xD", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 13, 3 }, { 1, 13, 3 }, },
|
||||
{ "0xE", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 14, 3 }, { 1, 14, 3 }, },
|
||||
{ "0xF", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 15, 3 }, { 1, 15, 3 }, },
|
||||
{ "0xX", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, },
|
||||
{ "0xa", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 10, 3 }, { 1, 10, 3 }, },
|
||||
{ "0xb", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 11, 3 }, { 1, 11, 3 }, },
|
||||
{ "0xc", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 12, 3 }, { 1, 12, 3 }, },
|
||||
{ "0xd", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 13, 3 }, { 1, 13, 3 }, },
|
||||
{ "0xe", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 14, 3 }, { 1, 14, 3 }, },
|
||||
{ "0xf", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 15, 3 }, { 1, 15, 3 }, },
|
||||
{ "0xX", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, },
|
||||
// terminator
|
||||
{ "" }
|
||||
};
|
||||
|
||||
#define SSCANF_TEST(string, format, expret, expval, explen) \
|
||||
do { \
|
||||
int ret = 0, val = 0, len = 0; \
|
||||
ret = sscanf(string, format "%n", &val, &len); \
|
||||
ATF_CHECK_EQ(expret, ret); \
|
||||
if (expret && ret) { \
|
||||
ATF_CHECK_EQ(expval, val); \
|
||||
ATF_CHECK_EQ(explen, len); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
ATF_TC_WITHOUT_HEAD(sscanf_b);
|
||||
ATF_TC_BODY(sscanf_b, tc)
|
||||
{
|
||||
const struct sscanf_test_case *stc;
|
||||
char input[16];
|
||||
|
||||
for (stc = sscanf_test_cases; *stc->input; stc++) {
|
||||
strcpy(input + 1, stc->input);
|
||||
SSCANF_TEST(input + 1, "%b", stc->b.ret, stc->b.val, stc->b.len);
|
||||
input[0] = '+';
|
||||
SSCANF_TEST(input, "%b", stc->b.ret, stc->b.val, stc->b.len ? stc->b.len + 1 : 0);
|
||||
input[0] = '-';
|
||||
SSCANF_TEST(input, "%b", stc->b.ret, -stc->b.val, stc->b.len ? stc->b.len + 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
ATF_TC_WITHOUT_HEAD(sscanf_o);
|
||||
ATF_TC_BODY(sscanf_o, tc)
|
||||
{
|
||||
const struct sscanf_test_case *stc;
|
||||
char input[16];
|
||||
|
||||
for (stc = sscanf_test_cases; *stc->input; stc++) {
|
||||
strcpy(input + 1, stc->input);
|
||||
SSCANF_TEST(input + 1, "%o", stc->o.ret, stc->o.val, stc->o.len);
|
||||
input[0] = '+';
|
||||
SSCANF_TEST(input, "%o", stc->o.ret, stc->o.val, stc->o.len ? stc->o.len + 1 : 0);
|
||||
input[0] = '-';
|
||||
SSCANF_TEST(input, "%o", stc->o.ret, -stc->o.val, stc->o.len ? stc->o.len + 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
ATF_TC_WITHOUT_HEAD(sscanf_d);
|
||||
ATF_TC_BODY(sscanf_d, tc)
|
||||
{
|
||||
const struct sscanf_test_case *stc;
|
||||
char input[16];
|
||||
|
||||
for (stc = sscanf_test_cases; *stc->input; stc++) {
|
||||
strcpy(input + 1, stc->input);
|
||||
SSCANF_TEST(input + 1, "%d", stc->d.ret, stc->d.val, stc->d.len);
|
||||
input[0] = '+';
|
||||
SSCANF_TEST(input, "%d", stc->d.ret, stc->d.val, stc->d.len ? stc->d.len + 1 : 0);
|
||||
input[0] = '-';
|
||||
SSCANF_TEST(input, "%d", stc->d.ret, -stc->d.val, stc->d.len ? stc->d.len + 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
ATF_TC_WITHOUT_HEAD(sscanf_x);
|
||||
ATF_TC_BODY(sscanf_x, tc)
|
||||
{
|
||||
const struct sscanf_test_case *stc;
|
||||
char input[16];
|
||||
|
||||
for (stc = sscanf_test_cases; *stc->input; stc++) {
|
||||
strcpy(input + 1, stc->input);
|
||||
SSCANF_TEST(input + 1, "%x", stc->x.ret, stc->x.val, stc->x.len);
|
||||
input[0] = '+';
|
||||
SSCANF_TEST(input, "%x", stc->x.ret, stc->x.val, stc->x.len ? stc->x.len + 1 : 0);
|
||||
input[0] = '-';
|
||||
SSCANF_TEST(input, "%x", stc->x.ret, -stc->x.val, stc->x.len ? stc->x.len + 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
ATF_TC_WITHOUT_HEAD(sscanf_i);
|
||||
ATF_TC_BODY(sscanf_i, tc)
|
||||
{
|
||||
const struct sscanf_test_case *stc;
|
||||
char input[16];
|
||||
|
||||
for (stc = sscanf_test_cases; *stc->input; stc++) {
|
||||
strcpy(input + 1, stc->input);
|
||||
SSCANF_TEST(input + 1, "%i", stc->i.ret, stc->i.val, stc->i.len);
|
||||
input[0] = '+';
|
||||
SSCANF_TEST(input, "%i", stc->i.ret, stc->i.val, stc->i.len ? stc->i.len + 1 : 0);
|
||||
input[0] = '-';
|
||||
SSCANF_TEST(input, "%i", stc->i.ret, -stc->i.val, stc->i.len ? stc->i.len + 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Test termination cases: non-numeric character, fixed width, EOF
|
||||
*/
|
||||
ATF_TC_WITHOUT_HEAD(sscanf_termination);
|
||||
ATF_TC_BODY(sscanf_termination, tc)
|
||||
{
|
||||
int a = 0, b = 0, c = 0;
|
||||
char d = 0;
|
||||
|
||||
ATF_CHECK_EQ(4, sscanf("3.1415", "%d%c%2d%d", &a, &d, &b, &c));
|
||||
ATF_CHECK_EQ(3, a);
|
||||
ATF_CHECK_EQ(14, b);
|
||||
ATF_CHECK_EQ(15, c);
|
||||
ATF_CHECK_EQ('.', d);
|
||||
}
|
||||
|
||||
ATF_TP_ADD_TCS(tp)
|
||||
{
|
||||
setlocale(LC_NUMERIC, "en_US.UTF-8");
|
||||
ATF_TP_ADD_TC(tp, sscanf_b);
|
||||
ATF_TP_ADD_TC(tp, sscanf_o);
|
||||
ATF_TP_ADD_TC(tp, sscanf_d);
|
||||
ATF_TP_ADD_TC(tp, sscanf_x);
|
||||
ATF_TP_ADD_TC(tp, sscanf_i);
|
||||
ATF_TP_ADD_TC(tp, sscanf_termination);
|
||||
return (atf_no_error());
|
||||
}
|
||||
140
lib/libc/tests/stdio/swprintf_test.c
Normal file
140
lib/libc/tests/stdio/swprintf_test.c
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
/*-
|
||||
* Copyright (c) 2023 Dag-Erling Smørgrav
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <locale.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include <atf-c.h>
|
||||
|
||||
#ifndef nitems
|
||||
#define nitems(a) (sizeof(a) / sizeof(a[0]))
|
||||
#endif
|
||||
|
||||
#define SWPRINTF_TEST(output, format, ...) \
|
||||
do { \
|
||||
wchar_t buf[256]; \
|
||||
assert(wcslen(L##output) < nitems(buf)); \
|
||||
int ret = swprintf(buf, nitems(buf), L##format, \
|
||||
__VA_ARGS__); \
|
||||
ATF_CHECK_EQ(wcslen(L##output), ret); \
|
||||
if (ret > 0) { \
|
||||
ATF_CHECK_EQ(0, wcscmp(L##output, buf)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
ATF_TC_WITHOUT_HEAD(swprintf_b);
|
||||
ATF_TC_BODY(swprintf_b, tc)
|
||||
{
|
||||
SWPRINTF_TEST("0", "%b", 0);
|
||||
SWPRINTF_TEST(" 0", "%12b", 0);
|
||||
SWPRINTF_TEST("000000000000", "%012b", 0);
|
||||
SWPRINTF_TEST("1", "%b", 1);
|
||||
SWPRINTF_TEST(" 1", "%12b", 1);
|
||||
SWPRINTF_TEST("000000000001", "%012b", 1);
|
||||
SWPRINTF_TEST("1111111111111111111111111111111", "%b", INT_MAX);
|
||||
SWPRINTF_TEST("0", "%#b", 0);
|
||||
SWPRINTF_TEST(" 0", "%#12b", 0);
|
||||
SWPRINTF_TEST("000000000000", "%#012b", 0);
|
||||
SWPRINTF_TEST("0b1", "%#b", 1);
|
||||
SWPRINTF_TEST(" 0b1", "%#12b", 1);
|
||||
SWPRINTF_TEST("0b0000000001", "%#012b", 1);
|
||||
SWPRINTF_TEST("0b1111111111111111111111111111111", "%#b", INT_MAX);
|
||||
}
|
||||
|
||||
ATF_TC_WITHOUT_HEAD(swprintf_B);
|
||||
ATF_TC_BODY(swprintf_B, tc)
|
||||
{
|
||||
SWPRINTF_TEST("0", "%B", 0);
|
||||
SWPRINTF_TEST(" 0", "%12B", 0);
|
||||
SWPRINTF_TEST("000000000000", "%012B", 0);
|
||||
SWPRINTF_TEST("1", "%B", 1);
|
||||
SWPRINTF_TEST(" 1", "%12B", 1);
|
||||
SWPRINTF_TEST("000000000001", "%012B", 1);
|
||||
SWPRINTF_TEST("1111111111111111111111111111111", "%B", INT_MAX);
|
||||
SWPRINTF_TEST("0", "%#B", 0);
|
||||
SWPRINTF_TEST(" 0", "%#12B", 0);
|
||||
SWPRINTF_TEST("000000000000", "%#012B", 0);
|
||||
SWPRINTF_TEST("0B1", "%#B", 1);
|
||||
SWPRINTF_TEST(" 0B1", "%#12B", 1);
|
||||
SWPRINTF_TEST("0B0000000001", "%#012B", 1);
|
||||
SWPRINTF_TEST("0B1111111111111111111111111111111", "%#B", INT_MAX);
|
||||
}
|
||||
|
||||
ATF_TC_WITHOUT_HEAD(swprintf_d);
|
||||
ATF_TC_BODY(swprintf_d, tc)
|
||||
{
|
||||
SWPRINTF_TEST("0", "%d", 0);
|
||||
SWPRINTF_TEST(" 0", "%12d", 0);
|
||||
SWPRINTF_TEST("000000000000", "%012d", 0);
|
||||
SWPRINTF_TEST("1", "%d", 1);
|
||||
SWPRINTF_TEST(" 1", "%12d", 1);
|
||||
SWPRINTF_TEST("000000000001", "%012d", 1);
|
||||
SWPRINTF_TEST("2147483647", "%d", INT_MAX);
|
||||
SWPRINTF_TEST(" 2147483647", "%12d", INT_MAX);
|
||||
SWPRINTF_TEST("002147483647", "%012d", INT_MAX);
|
||||
SWPRINTF_TEST("2,147,483,647", "%'d", INT_MAX);
|
||||
}
|
||||
|
||||
ATF_TC_WITHOUT_HEAD(swprintf_x);
|
||||
ATF_TC_BODY(swprintf_x, tc)
|
||||
{
|
||||
SWPRINTF_TEST("0", "%x", 0);
|
||||
SWPRINTF_TEST(" 0", "%12x", 0);
|
||||
SWPRINTF_TEST("000000000000", "%012x", 0);
|
||||
SWPRINTF_TEST("1", "%x", 1);
|
||||
SWPRINTF_TEST(" 1", "%12x", 1);
|
||||
SWPRINTF_TEST("000000000001", "%012x", 1);
|
||||
SWPRINTF_TEST("7fffffff", "%x", INT_MAX);
|
||||
SWPRINTF_TEST(" 7fffffff", "%12x", INT_MAX);
|
||||
SWPRINTF_TEST("00007fffffff", "%012x", INT_MAX);
|
||||
SWPRINTF_TEST("0", "%#x", 0);
|
||||
SWPRINTF_TEST(" 0", "%#12x", 0);
|
||||
SWPRINTF_TEST("000000000000", "%#012x", 0);
|
||||
SWPRINTF_TEST("0x1", "%#x", 1);
|
||||
SWPRINTF_TEST(" 0x1", "%#12x", 1);
|
||||
SWPRINTF_TEST("0x0000000001", "%#012x", 1);
|
||||
SWPRINTF_TEST("0x7fffffff", "%#x", INT_MAX);
|
||||
SWPRINTF_TEST(" 0x7fffffff", "%#12x", INT_MAX);
|
||||
SWPRINTF_TEST("0x007fffffff", "%#012x", INT_MAX);
|
||||
}
|
||||
|
||||
ATF_TC_WITHOUT_HEAD(swprintf_X);
|
||||
ATF_TC_BODY(swprintf_X, tc)
|
||||
{
|
||||
SWPRINTF_TEST("0", "%X", 0);
|
||||
SWPRINTF_TEST(" 0", "%12X", 0);
|
||||
SWPRINTF_TEST("000000000000", "%012X", 0);
|
||||
SWPRINTF_TEST("1", "%X", 1);
|
||||
SWPRINTF_TEST(" 1", "%12X", 1);
|
||||
SWPRINTF_TEST("000000000001", "%012X", 1);
|
||||
SWPRINTF_TEST("7FFFFFFF", "%X", INT_MAX);
|
||||
SWPRINTF_TEST(" 7FFFFFFF", "%12X", INT_MAX);
|
||||
SWPRINTF_TEST("00007FFFFFFF", "%012X", INT_MAX);
|
||||
SWPRINTF_TEST("0", "%#X", 0);
|
||||
SWPRINTF_TEST(" 0", "%#12X", 0);
|
||||
SWPRINTF_TEST("000000000000", "%#012X", 0);
|
||||
SWPRINTF_TEST("0X1", "%#X", 1);
|
||||
SWPRINTF_TEST(" 0X1", "%#12X", 1);
|
||||
SWPRINTF_TEST("0X0000000001", "%#012X", 1);
|
||||
SWPRINTF_TEST("0X7FFFFFFF", "%#X", INT_MAX);
|
||||
SWPRINTF_TEST(" 0X7FFFFFFF", "%#12X", INT_MAX);
|
||||
SWPRINTF_TEST("0X007FFFFFFF", "%#012X", INT_MAX);
|
||||
}
|
||||
|
||||
ATF_TP_ADD_TCS(tp)
|
||||
{
|
||||
setlocale(LC_NUMERIC, "en_US.UTF-8");
|
||||
ATF_TP_ADD_TC(tp, swprintf_b);
|
||||
ATF_TP_ADD_TC(tp, swprintf_B);
|
||||
ATF_TP_ADD_TC(tp, swprintf_d);
|
||||
ATF_TP_ADD_TC(tp, swprintf_x);
|
||||
ATF_TP_ADD_TC(tp, swprintf_X);
|
||||
return (atf_no_error());
|
||||
}
|
||||
267
lib/libc/tests/stdio/swscanf_test.c
Normal file
267
lib/libc/tests/stdio/swscanf_test.c
Normal file
|
|
@ -0,0 +1,267 @@
|
|||
/*-
|
||||
* Copyright (c) 2023 Dag-Erling Smørgrav
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <locale.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include <atf-c.h>
|
||||
|
||||
static const struct swscanf_test_case {
|
||||
wchar_t input[8];
|
||||
struct {
|
||||
int ret, val, len;
|
||||
} b, o, d, x, i;
|
||||
} swscanf_test_cases[] = {
|
||||
// input binary octal decimal hexadecimal automatic
|
||||
// all digits
|
||||
{ L"0", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, },
|
||||
{ L"1", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, },
|
||||
{ L"2", { 0, 0, 0 }, { 1, 2, 1 }, { 1, 2, 1 }, { 1, 2, 1 }, { 1, 2, 1 }, },
|
||||
{ L"3", { 0, 0, 0 }, { 1, 3, 1 }, { 1, 3, 1 }, { 1, 3, 1 }, { 1, 3, 1 }, },
|
||||
{ L"4", { 0, 0, 0 }, { 1, 4, 1 }, { 1, 4, 1 }, { 1, 4, 1 }, { 1, 4, 1 }, },
|
||||
{ L"5", { 0, 0, 0 }, { 1, 5, 1 }, { 1, 5, 1 }, { 1, 5, 1 }, { 1, 5, 1 }, },
|
||||
{ L"6", { 0, 0, 0 }, { 1, 6, 1 }, { 1, 6, 1 }, { 1, 6, 1 }, { 1, 6, 1 }, },
|
||||
{ L"7", { 0, 0, 0 }, { 1, 7, 1 }, { 1, 7, 1 }, { 1, 7, 1 }, { 1, 7, 1 }, },
|
||||
{ L"8", { 0, 0, 0 }, { 0, 0, 0 }, { 1, 8, 1 }, { 1, 8, 1 }, { 1, 8, 1 }, },
|
||||
{ L"9", { 0, 0, 0 }, { 0, 0, 0 }, { 1, 9, 1 }, { 1, 9, 1 }, { 1, 9, 1 }, },
|
||||
{ L"A", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 10, 1 }, { 0, 0, 0 }, },
|
||||
{ L"B", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 11, 1 }, { 0, 0, 0 }, },
|
||||
{ L"C", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 12, 1 }, { 0, 0, 0 }, },
|
||||
{ L"D", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 13, 1 }, { 0, 0, 0 }, },
|
||||
{ L"E", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 14, 1 }, { 0, 0, 0 }, },
|
||||
{ L"F", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 15, 1 }, { 0, 0, 0 }, },
|
||||
{ L"X", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, },
|
||||
{ L"a", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 10, 1 }, { 0, 0, 0 }, },
|
||||
{ L"b", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 11, 1 }, { 0, 0, 0 }, },
|
||||
{ L"c", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 12, 1 }, { 0, 0, 0 }, },
|
||||
{ L"d", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 13, 1 }, { 0, 0, 0 }, },
|
||||
{ L"e", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 14, 1 }, { 0, 0, 0 }, },
|
||||
{ L"f", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 15, 1 }, { 0, 0, 0 }, },
|
||||
{ L"x", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, },
|
||||
// all digits with leading zero
|
||||
{ L"00", { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, },
|
||||
{ L"01", { 1, 1, 2 }, { 1, 1, 2 }, { 1, 1, 2 }, { 1, 1, 2 }, { 1, 1, 2 }, },
|
||||
{ L"02", { 1, 0, 1 }, { 1, 2, 2 }, { 1, 2, 2 }, { 1, 2, 2 }, { 1, 2, 2 }, },
|
||||
{ L"03", { 1, 0, 1 }, { 1, 3, 2 }, { 1, 3, 2 }, { 1, 3, 2 }, { 1, 3, 2 }, },
|
||||
{ L"04", { 1, 0, 1 }, { 1, 4, 2 }, { 1, 4, 2 }, { 1, 4, 2 }, { 1, 4, 2 }, },
|
||||
{ L"05", { 1, 0, 1 }, { 1, 5, 2 }, { 1, 5, 2 }, { 1, 5, 2 }, { 1, 5, 2 }, },
|
||||
{ L"06", { 1, 0, 1 }, { 1, 6, 2 }, { 1, 6, 2 }, { 1, 6, 2 }, { 1, 6, 2 }, },
|
||||
{ L"07", { 1, 0, 1 }, { 1, 7, 2 }, { 1, 7, 2 }, { 1, 7, 2 }, { 1, 7, 2 }, },
|
||||
{ L"08", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 8, 2 }, { 1, 8, 2 }, { 1, 0, 1 }, },
|
||||
{ L"09", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 9, 2 }, { 1, 9, 2 }, { 1, 0, 1 }, },
|
||||
{ L"0A", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 10, 2 }, { 1, 0, 1 }, },
|
||||
{ L"0B", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 11, 2 }, { 1, 0, 1 }, },
|
||||
{ L"0C", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 12, 2 }, { 1, 0, 1 }, },
|
||||
{ L"0D", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 13, 2 }, { 1, 0, 1 }, },
|
||||
{ L"0E", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 14, 2 }, { 1, 0, 1 }, },
|
||||
{ L"0F", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 15, 2 }, { 1, 0, 1 }, },
|
||||
{ L"0X", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, },
|
||||
{ L"0a", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 10, 2 }, { 1, 0, 1 }, },
|
||||
{ L"0b", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 11, 2 }, { 1, 0, 1 }, },
|
||||
{ L"0c", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 12, 2 }, { 1, 0, 1 }, },
|
||||
{ L"0d", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 13, 2 }, { 1, 0, 1 }, },
|
||||
{ L"0e", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 14, 2 }, { 1, 0, 1 }, },
|
||||
{ L"0f", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 15, 2 }, { 1, 0, 1 }, },
|
||||
{ L"0x", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, },
|
||||
// all digits with leading one
|
||||
{ L"10", { 1, 2, 2 }, { 1, 8, 2 }, { 1, 10, 2 }, { 1, 16, 2 }, { 1, 10, 2 }, },
|
||||
{ L"11", { 1, 3, 2 }, { 1, 9, 2 }, { 1, 11, 2 }, { 1, 17, 2 }, { 1, 11, 2 }, },
|
||||
{ L"12", { 1, 1, 1 }, { 1, 10, 2 }, { 1, 12, 2 }, { 1, 18, 2 }, { 1, 12, 2 }, },
|
||||
{ L"13", { 1, 1, 1 }, { 1, 11, 2 }, { 1, 13, 2 }, { 1, 19, 2 }, { 1, 13, 2 }, },
|
||||
{ L"14", { 1, 1, 1 }, { 1, 12, 2 }, { 1, 14, 2 }, { 1, 20, 2 }, { 1, 14, 2 }, },
|
||||
{ L"15", { 1, 1, 1 }, { 1, 13, 2 }, { 1, 15, 2 }, { 1, 21, 2 }, { 1, 15, 2 }, },
|
||||
{ L"16", { 1, 1, 1 }, { 1, 14, 2 }, { 1, 16, 2 }, { 1, 22, 2 }, { 1, 16, 2 }, },
|
||||
{ L"17", { 1, 1, 1 }, { 1, 15, 2 }, { 1, 17, 2 }, { 1, 23, 2 }, { 1, 17, 2 }, },
|
||||
{ L"18", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 18, 2 }, { 1, 24, 2 }, { 1, 18, 2 }, },
|
||||
{ L"19", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 19, 2 }, { 1, 25, 2 }, { 1, 19, 2 }, },
|
||||
{ L"1A", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 26, 2 }, { 1, 1, 1 }, },
|
||||
{ L"1B", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 27, 2 }, { 1, 1, 1 }, },
|
||||
{ L"1C", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 28, 2 }, { 1, 1, 1 }, },
|
||||
{ L"1D", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 29, 2 }, { 1, 1, 1 }, },
|
||||
{ L"1E", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 30, 2 }, { 1, 1, 1 }, },
|
||||
{ L"1F", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 31, 2 }, { 1, 1, 1 }, },
|
||||
{ L"1X", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, },
|
||||
{ L"1a", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 26, 2 }, { 1, 1, 1 }, },
|
||||
{ L"1b", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 27, 2 }, { 1, 1, 1 }, },
|
||||
{ L"1c", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 28, 2 }, { 1, 1, 1 }, },
|
||||
{ L"1d", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 29, 2 }, { 1, 1, 1 }, },
|
||||
{ L"1e", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 30, 2 }, { 1, 1, 1 }, },
|
||||
{ L"1f", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 31, 2 }, { 1, 1, 1 }, },
|
||||
{ L"1x", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, },
|
||||
// all digits with leading binary prefix
|
||||
{ L"0b0", { 1, 0, 3 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 176, 3 }, { 1, 0, 3 }, },
|
||||
{ L"0b1", { 1, 1, 3 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 177, 3 }, { 1, 1, 3 }, },
|
||||
{ L"0b2", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 178, 3 }, { 1, 0, 1 }, },
|
||||
{ L"0b3", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 179, 3 }, { 1, 0, 1 }, },
|
||||
{ L"0b4", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 180, 3 }, { 1, 0, 1 }, },
|
||||
{ L"0b5", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 181, 3 }, { 1, 0, 1 }, },
|
||||
{ L"0b6", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 182, 3 }, { 1, 0, 1 }, },
|
||||
{ L"0b7", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 183, 3 }, { 1, 0, 1 }, },
|
||||
{ L"0b8", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 184, 3 }, { 1, 0, 1 }, },
|
||||
{ L"0b9", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 185, 3 }, { 1, 0, 1 }, },
|
||||
{ L"0bA", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 186, 3 }, { 1, 0, 1 }, },
|
||||
{ L"0bB", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 187, 3 }, { 1, 0, 1 }, },
|
||||
{ L"0bC", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 188, 3 }, { 1, 0, 1 }, },
|
||||
{ L"0bD", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 189, 3 }, { 1, 0, 1 }, },
|
||||
{ L"0bE", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 190, 3 }, { 1, 0, 1 }, },
|
||||
{ L"0bF", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 191, 3 }, { 1, 0, 1 }, },
|
||||
{ L"0bX", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 11, 2 }, { 1, 0, 1 }, },
|
||||
{ L"0ba", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 186, 3 }, { 1, 0, 1 }, },
|
||||
{ L"0bb", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 187, 3 }, { 1, 0, 1 }, },
|
||||
{ L"0bc", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 188, 3 }, { 1, 0, 1 }, },
|
||||
{ L"0bd", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 189, 3 }, { 1, 0, 1 }, },
|
||||
{ L"0be", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 190, 3 }, { 1, 0, 1 }, },
|
||||
{ L"0bf", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 191, 3 }, { 1, 0, 1 }, },
|
||||
{ L"0bx", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 11, 2 }, { 1, 0, 1 }, },
|
||||
// all digits with leading hexadecimal prefix
|
||||
{ L"0x0", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 3 }, { 1, 0, 3 }, },
|
||||
{ L"0x1", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 1, 3 }, { 1, 1, 3 }, },
|
||||
{ L"0x2", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 2, 3 }, { 1, 2, 3 }, },
|
||||
{ L"0x3", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 3, 3 }, { 1, 3, 3 }, },
|
||||
{ L"0x4", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 4, 3 }, { 1, 4, 3 }, },
|
||||
{ L"0x5", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 5, 3 }, { 1, 5, 3 }, },
|
||||
{ L"0x6", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 6, 3 }, { 1, 6, 3 }, },
|
||||
{ L"0x7", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 7, 3 }, { 1, 7, 3 }, },
|
||||
{ L"0x8", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 8, 3 }, { 1, 8, 3 }, },
|
||||
{ L"0x9", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 9, 3 }, { 1, 9, 3 }, },
|
||||
{ L"0xA", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 10, 3 }, { 1, 10, 3 }, },
|
||||
{ L"0xB", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 11, 3 }, { 1, 11, 3 }, },
|
||||
{ L"0xC", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 12, 3 }, { 1, 12, 3 }, },
|
||||
{ L"0xD", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 13, 3 }, { 1, 13, 3 }, },
|
||||
{ L"0xE", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 14, 3 }, { 1, 14, 3 }, },
|
||||
{ L"0xF", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 15, 3 }, { 1, 15, 3 }, },
|
||||
{ L"0xX", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, },
|
||||
{ L"0xa", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 10, 3 }, { 1, 10, 3 }, },
|
||||
{ L"0xb", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 11, 3 }, { 1, 11, 3 }, },
|
||||
{ L"0xc", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 12, 3 }, { 1, 12, 3 }, },
|
||||
{ L"0xd", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 13, 3 }, { 1, 13, 3 }, },
|
||||
{ L"0xe", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 14, 3 }, { 1, 14, 3 }, },
|
||||
{ L"0xf", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 15, 3 }, { 1, 15, 3 }, },
|
||||
{ L"0xX", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, },
|
||||
// terminator
|
||||
{ L"" }
|
||||
};
|
||||
|
||||
#define SWSCANF_TEST(string, format, expret, expval, explen) \
|
||||
do { \
|
||||
int ret = 0, val = 0, len = 0; \
|
||||
ret = swscanf(string, format "%n", &val, &len); \
|
||||
ATF_CHECK_EQ(expret, ret); \
|
||||
if (expret && ret) { \
|
||||
ATF_CHECK_EQ(expval, val); \
|
||||
ATF_CHECK_EQ(explen, len); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
ATF_TC_WITHOUT_HEAD(swscanf_b);
|
||||
ATF_TC_BODY(swscanf_b, tc)
|
||||
{
|
||||
const struct swscanf_test_case *stc;
|
||||
wchar_t input[16];
|
||||
|
||||
for (stc = swscanf_test_cases; *stc->input; stc++) {
|
||||
wcscpy(input + 1, stc->input);
|
||||
SWSCANF_TEST(input + 1, L"%b", stc->b.ret, stc->b.val, stc->b.len);
|
||||
input[0] = L'+';
|
||||
SWSCANF_TEST(input, L"%b", stc->b.ret, stc->b.val, stc->b.len ? stc->b.len + 1 : 0);
|
||||
input[0] = L'-';
|
||||
SWSCANF_TEST(input, L"%b", stc->b.ret, -stc->b.val, stc->b.len ? stc->b.len + 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
ATF_TC_WITHOUT_HEAD(swscanf_o);
|
||||
ATF_TC_BODY(swscanf_o, tc)
|
||||
{
|
||||
const struct swscanf_test_case *stc;
|
||||
wchar_t input[16];
|
||||
|
||||
for (stc = swscanf_test_cases; *stc->input; stc++) {
|
||||
wcscpy(input + 1, stc->input);
|
||||
SWSCANF_TEST(input + 1, L"%o", stc->o.ret, stc->o.val, stc->o.len);
|
||||
input[0] = L'+';
|
||||
SWSCANF_TEST(input, L"%o", stc->o.ret, stc->o.val, stc->o.len ? stc->o.len + 1 : 0);
|
||||
input[0] = L'-';
|
||||
SWSCANF_TEST(input, L"%o", stc->o.ret, -stc->o.val, stc->o.len ? stc->o.len + 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
ATF_TC_WITHOUT_HEAD(swscanf_d);
|
||||
ATF_TC_BODY(swscanf_d, tc)
|
||||
{
|
||||
const struct swscanf_test_case *stc;
|
||||
wchar_t input[16];
|
||||
|
||||
for (stc = swscanf_test_cases; *stc->input; stc++) {
|
||||
wcscpy(input + 1, stc->input);
|
||||
SWSCANF_TEST(input + 1, L"%d", stc->d.ret, stc->d.val, stc->d.len);
|
||||
input[0] = L'+';
|
||||
SWSCANF_TEST(input, L"%d", stc->d.ret, stc->d.val, stc->d.len ? stc->d.len + 1 : 0);
|
||||
input[0] = L'-';
|
||||
SWSCANF_TEST(input, L"%d", stc->d.ret, -stc->d.val, stc->d.len ? stc->d.len + 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
ATF_TC_WITHOUT_HEAD(swscanf_x);
|
||||
ATF_TC_BODY(swscanf_x, tc)
|
||||
{
|
||||
const struct swscanf_test_case *stc;
|
||||
wchar_t input[16];
|
||||
|
||||
for (stc = swscanf_test_cases; *stc->input; stc++) {
|
||||
wcscpy(input + 1, stc->input);
|
||||
SWSCANF_TEST(input + 1, L"%x", stc->x.ret, stc->x.val, stc->x.len);
|
||||
input[0] = L'+';
|
||||
SWSCANF_TEST(input, L"%x", stc->x.ret, stc->x.val, stc->x.len ? stc->x.len + 1 : 0);
|
||||
input[0] = L'-';
|
||||
SWSCANF_TEST(input, L"%x", stc->x.ret, -stc->x.val, stc->x.len ? stc->x.len + 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
ATF_TC_WITHOUT_HEAD(swscanf_i);
|
||||
ATF_TC_BODY(swscanf_i, tc)
|
||||
{
|
||||
const struct swscanf_test_case *stc;
|
||||
wchar_t input[16];
|
||||
|
||||
for (stc = swscanf_test_cases; *stc->input; stc++) {
|
||||
wcscpy(input + 1, stc->input);
|
||||
SWSCANF_TEST(input + 1, L"%i", stc->i.ret, stc->i.val, stc->i.len);
|
||||
input[0] = L'+';
|
||||
SWSCANF_TEST(input, L"%i", stc->i.ret, stc->i.val, stc->i.len ? stc->i.len + 1 : 0);
|
||||
input[0] = L'-';
|
||||
SWSCANF_TEST(input, L"%i", stc->i.ret, -stc->i.val, stc->i.len ? stc->i.len + 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Test termination cases: non-numeric character, fixed width, EOF
|
||||
*/
|
||||
ATF_TC_WITHOUT_HEAD(swscanf_termination);
|
||||
ATF_TC_BODY(swscanf_termination, tc)
|
||||
{
|
||||
int a = 0, b = 0, c = 0;
|
||||
char d = 0;
|
||||
|
||||
ATF_CHECK_EQ(4, swscanf(L"3.1415", L"%d%c%2d%d", &a, &d, &b, &c));
|
||||
ATF_CHECK_EQ(3, a);
|
||||
ATF_CHECK_EQ(14, b);
|
||||
ATF_CHECK_EQ(15, c);
|
||||
ATF_CHECK_EQ(L'.', d);
|
||||
}
|
||||
|
||||
ATF_TP_ADD_TCS(tp)
|
||||
{
|
||||
setlocale(LC_NUMERIC, "en_US.UTF-8");
|
||||
ATF_TP_ADD_TC(tp, swscanf_b);
|
||||
ATF_TP_ADD_TC(tp, swscanf_o);
|
||||
ATF_TP_ADD_TC(tp, swscanf_d);
|
||||
ATF_TP_ADD_TC(tp, swscanf_x);
|
||||
ATF_TP_ADD_TC(tp, swscanf_i);
|
||||
ATF_TP_ADD_TC(tp, swscanf_termination);
|
||||
return (atf_no_error());
|
||||
}
|
||||
Loading…
Reference in a new issue