Minimize printf/scanf size on platforms that don't need C99.

* acconfig.h (_WANT_IO_C99_FORMATS): New macro.
* newlib.hin (_WANT_IO_C99_FORMATS): Likewise.
* configure.in (newlib-io-c99-formats): New configure option.
(_WANT_IO_C99_FORMATS): Define appropriately.
* configure.host (*-linux*, cygwin): Default c99-formats to yes.
* libc/stdio/vfprintf.c (_VFPRINTF_R) [!_WANT_IO_C99_FORMATS]:
Cripple ' flag; hh, z, j, t sizes; a, A, F, C, S specifiers.
* libc/stdio/vfscanf.c (_VFSCANF_R) [!_WANT_IO_C99_FORMATS]:
Likewise.
* configure: Regenerate.
This commit is contained in:
Eric Blake 2007-05-11 20:09:00 +00:00
parent b8a37af936
commit 0962fe9178
8 changed files with 187 additions and 63 deletions

View File

@ -1,5 +1,17 @@
2007-05-11 Eric Blake <ebb9@byu.net> 2007-05-11 Eric Blake <ebb9@byu.net>
Minimize printf/scanf size on platforms that don't need C99.
* acconfig.h (_WANT_IO_C99_FORMATS): New macro.
* newlib.hin (_WANT_IO_C99_FORMATS): Likewise.
* configure.in (newlib-io-c99-formats): New configure option.
(_WANT_IO_C99_FORMATS): Define appropriately.
* configure.host (*-linux*, cygwin): Default c99-formats to yes.
* libc/stdio/vfprintf.c (_VFPRINTF_R) [!_WANT_IO_C99_FORMATS]:
Cripple ' flag; hh, z, j, t sizes; a, A, F, C, S specifiers.
* libc/stdio/vfscanf.c (_VFSCANF_R) [!_WANT_IO_C99_FORMATS]:
Likewise.
* configure: Regenerate.
* libc/stdio/vfprintf.c (_VFPRINTF_R, cvt, exponent, chclass) * libc/stdio/vfprintf.c (_VFPRINTF_R, cvt, exponent, chclass)
(get_arg): Support '%a' and '%A'. (get_arg): Support '%a' and '%A'.

View File

@ -9,6 +9,10 @@
/* Newlib version */ /* Newlib version */
#undef _NEWLIB_VERSION #undef _NEWLIB_VERSION
/* C99 formats support (such as %a, %zu, ...) in IO functions like
* printf/scanf enabled */
#undef _WANT_IO_C99_FORMATS
/* long long type support in IO functions like printf/scanf enabled */ /* long long type support in IO functions like printf/scanf enabled */
#undef _WANT_IO_LONG_LONG #undef _WANT_IO_LONG_LONG
@ -154,4 +158,3 @@
#undef _ICONV_FROM_ENCODING_WIN_1258 #undef _ICONV_FROM_ENCODING_WIN_1258
#endif /* !__NEWLIB_H__ */ #endif /* !__NEWLIB_H__ */

29
newlib/configure vendored
View File

@ -823,6 +823,7 @@ Optional Features:
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
--enable-newlib-io-pos-args enable printf-family positional arg support --enable-newlib-io-pos-args enable printf-family positional arg support
--enable-newlib-io-c99-formats enable C99 support in IO functions like printf/scanf
--enable-newlib-io-long-long enable long long type support in IO functions like printf/scanf --enable-newlib-io-long-long enable long long type support in IO functions like printf/scanf
--enable-newlib-io-long-double enable long double type support in IO functions printf/scanf --enable-newlib-io-long-double enable long double type support in IO functions printf/scanf
--enable-newlib-mb enable multibyte support --enable-newlib-mb enable multibyte support
@ -1357,6 +1358,19 @@ echo "$as_me: error: bad value ${enableval} for newlib-io-pos-args option" >&2;}
else else
newlib_io_pos_args= newlib_io_pos_args=
fi; fi;
# Check whether --enable-newlib-io-c99-formats or --disable-newlib-io-c99-formats was given.
if test "${enable_newlib_io_c99_formats+set}" = set; then
enableval="$enable_newlib_io_c99_formats"
case "${enableval}" in
yes) newlib_io_c99_formats=yes;;
no) newlib_io_c99_formats=no ;;
*) { { echo "$as_me:$LINENO: error: bad value ${enableval} for newlib-io-c99-formats option" >&5
echo "$as_me: error: bad value ${enableval} for newlib-io-c99-formats option" >&2;}
{ (exit 1); exit 1; }; } ;;
esac
else
newlib_io_c99_formats=
fi;
# Check whether --enable-newlib-io-long-long or --disable-newlib-io-long-long was given. # Check whether --enable-newlib-io-long-long or --disable-newlib-io-long-long was given.
if test "${enable_newlib_io_long_long+set}" = set; then if test "${enable_newlib_io_long_long+set}" = set; then
enableval="$enable_newlib_io_long_long" enableval="$enable_newlib_io_long_long"
@ -4778,7 +4792,7 @@ test x"$pic_mode" = xno && libtool_flags="$libtool_flags --prefer-non-pic"
case $host in case $host in
*-*-irix6*) *-*-irix6*)
# Find out which ABI we are using. # Find out which ABI we are using.
echo '#line 4781 "configure"' > conftest.$ac_ext echo '#line 4795 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5 (eval $ac_compile) 2>&5
ac_status=$? ac_status=$?
@ -5197,6 +5211,13 @@ _ACEOF
fi fi
if test "${newlib_io_c99_formats}" = "yes"; then
cat >>confdefs.h <<_ACEOF
#define _WANT_IO_C99_FORMATS 1
_ACEOF
fi
if test "${newlib_io_long_long}" = "yes"; then if test "${newlib_io_long_long}" = "yes"; then
cat >>confdefs.h <<_ACEOF cat >>confdefs.h <<_ACEOF
#define _WANT_IO_LONG_LONG 1 #define _WANT_IO_LONG_LONG 1
@ -5307,7 +5328,7 @@ echo "$as_me: error: --enable-newlib-iconv-encodings, --enable-newlib-iconv-from
for encoding in ${iconv_encodings1}; do for encoding in ${iconv_encodings1}; do
result=`echo "${available_encodings}" | grep -e "\(^\| \)${encoding}\( \|\$\)"` result=`echo "${available_encodings}" | grep -e "\(^\| \)${encoding}\( \|\$\)"`
if test $? != "0"; then if test $? != "0"; then
{ { echo "$as_me:$LINENO: error: ${encoding} is not supported - see ${srcdir}/libc/iconv/encoding.aliases file for the list of available encodings" >&5 { { echo "$as_me:$LINENO: error: ${encoding} is not supported - see ${srcdir}/libc/iconv/encoding.aliases file for the list of available encodings" >&5
echo "$as_me: error: ${encoding} is not supported - see ${srcdir}/libc/iconv/encoding.aliases file for the list of available encodings" >&2;} echo "$as_me: error: ${encoding} is not supported - see ${srcdir}/libc/iconv/encoding.aliases file for the list of available encodings" >&2;}
{ (exit 1); exit 1; }; } { (exit 1); exit 1; }; }
fi fi
@ -5332,7 +5353,7 @@ _ACEOF
for encoding in ${iconv_encodings1}; do for encoding in ${iconv_encodings1}; do
result=`echo "${available_encodings}" | grep -e "\(^\| \)${encoding}\( \|\$\)"` result=`echo "${available_encodings}" | grep -e "\(^\| \)${encoding}\( \|\$\)"`
if test $? != "0"; then if test $? != "0"; then
{ { echo "$as_me:$LINENO: error: ${encoding} is not supported - see ${srcdir}/libc/iconv/encoding.aliases file for the list of available encodings" >&5 { { echo "$as_me:$LINENO: error: ${encoding} is not supported - see ${srcdir}/libc/iconv/encoding.aliases file for the list of available encodings" >&5
echo "$as_me: error: ${encoding} is not supported - see ${srcdir}/libc/iconv/encoding.aliases file for the list of available encodings" >&2;} echo "$as_me: error: ${encoding} is not supported - see ${srcdir}/libc/iconv/encoding.aliases file for the list of available encodings" >&2;}
{ (exit 1); exit 1; }; } { (exit 1); exit 1; }; }
fi fi
@ -5352,7 +5373,7 @@ _ACEOF
for encoding in ${iconv_encodings1}; do for encoding in ${iconv_encodings1}; do
result=`echo "${available_encodings}" | grep -e "\(^\| \)${encoding}\( \|\$\)"` result=`echo "${available_encodings}" | grep -e "\(^\| \)${encoding}\( \|\$\)"`
if test $? != "0"; then if test $? != "0"; then
{ { echo "$as_me:$LINENO: error: ${encoding} is not supported - see ${srcdir}/libc/iconv/encoding.aliases file for the list of available encodings" >&5 { { echo "$as_me:$LINENO: error: ${encoding} is not supported - see ${srcdir}/libc/iconv/encoding.aliases file for the list of available encodings" >&5
echo "$as_me: error: ${encoding} is not supported - see ${srcdir}/libc/iconv/encoding.aliases file for the list of available encodings" >&2;} echo "$as_me: error: ${encoding} is not supported - see ${srcdir}/libc/iconv/encoding.aliases file for the list of available encodings" >&2;}
{ (exit 1); exit 1; }; } { (exit 1); exit 1; }; }
fi fi

View File

@ -24,6 +24,7 @@
# target_optspace --enable-target-optspace ("yes", "no", "") # target_optspace --enable-target-optspace ("yes", "no", "")
# newlib_multithread --enable-newlib-multithread ("yes", "no", "yes") # newlib_multithread --enable-newlib-multithread ("yes", "no", "yes")
# newlib_elix_level --enable-newlib-elix-level ("1","2","3","4") ("4") # newlib_elix_level --enable-newlib-elix-level ("1","2","3","4") ("4")
# newlib_io_c99_formats --enable-newlib-io-c99-formats ("yes", "no", "")
# newlib_io_long_long --enable-newlib-io-long-long ("yes", "no", "") # newlib_io_long_long --enable-newlib-io-long-long ("yes", "no", "")
# newlib_io_long_double --enable-newlib-io-long-double ("yes", "no", "") # newlib_io_long_double --enable-newlib-io-long-double ("yes", "no", "")
@ -62,6 +63,7 @@ crt1_dir=
have_crt0= have_crt0=
use_libtool=no use_libtool=no
have_sys_mach_dir=no have_sys_mach_dir=no
default_newlib_io_c99_formats=no
default_newlib_io_long_long=no default_newlib_io_long_long=no
default_newlib_io_long_double=no default_newlib_io_long_double=no
default_newlib_io_pos_args=no default_newlib_io_pos_args=no
@ -398,6 +400,7 @@ case "${host}" in
crt1=crt1.o crt1=crt1.o
crt1_dir=libc/sys/${sys_dir} crt1_dir=libc/sys/${sys_dir}
gcc_dir=`gcc -print-search-dirs | awk '/^install:/{print $2}'` gcc_dir=`gcc -print-search-dirs | awk '/^install:/{print $2}'`
default_newlib_io_c99_formats="yes"
default_newlib_io_long_double="yes" default_newlib_io_long_double="yes"
default_newlib_io_long_long="yes" default_newlib_io_long_long="yes"
default_newlib_io_pos_args="yes" default_newlib_io_pos_args="yes"
@ -498,6 +501,7 @@ case "${host}" in
*-*-cygwin*) *-*-cygwin*)
test -z "$cygwin_srcdir" && cygwin_srcdir=`cd ${srcdir}/../winsup/cygwin; pwd` test -z "$cygwin_srcdir" && cygwin_srcdir=`cd ${srcdir}/../winsup/cygwin; pwd`
export cygwin_srcdir export cygwin_srcdir
default_newlib_io_c99_formats="yes"
default_newlib_io_long_long="yes" default_newlib_io_long_long="yes"
default_newlib_io_long_double="yes" default_newlib_io_long_double="yes"
default_newlib_io_pos_args="yes" default_newlib_io_pos_args="yes"
@ -744,6 +748,13 @@ esac
# Use defaults for certain settings if not specified by user # Use defaults for certain settings if not specified by user
# Enable C99 format support in I/O routines if requested.
if [ "x${newlib_io_c99_formats}" = "x" ]; then
if [ ${default_newlib_io_c99_formats} = "yes" ]; then
newlib_io_c99_formats="yes";
fi
fi
# Enable long long support in I/O routines if requested. # Enable long long support in I/O routines if requested.
if [ "x${newlib_io_long_long}" = "x" ]; then if [ "x${newlib_io_long_long}" = "x" ]; then
if [ ${default_newlib_io_long_long} = "yes" ]; then if [ ${default_newlib_io_long_long} = "yes" ]; then

View File

@ -20,6 +20,15 @@ AC_ARG_ENABLE(newlib-io-pos-args,
*) AC_MSG_ERROR(bad value ${enableval} for newlib-io-pos-args option) ;; *) AC_MSG_ERROR(bad value ${enableval} for newlib-io-pos-args option) ;;
esac], [newlib_io_pos_args=])dnl esac], [newlib_io_pos_args=])dnl
dnl Support --enable-newlib-io-c99-formats
AC_ARG_ENABLE(newlib-io-c99-formats,
[ --enable-newlib-io-c99-formats enable C99 support in IO functions like printf/scanf],
[case "${enableval}" in
yes) newlib_io_c99_formats=yes;;
no) newlib_io_c99_formats=no ;;
*) AC_MSG_ERROR(bad value ${enableval} for newlib-io-c99-formats option) ;;
esac], [newlib_io_c99_formats=])dnl
dnl Support --enable-newlib-io-long-long dnl Support --enable-newlib-io-long-long
AC_ARG_ENABLE(newlib-io-long-long, AC_ARG_ENABLE(newlib-io-long-long,
[ --enable-newlib-io-long-long enable long long type support in IO functions like printf/scanf], [ --enable-newlib-io-long-long enable long long type support in IO functions like printf/scanf],
@ -229,6 +238,10 @@ if test "${newlib_elix_level}" -gt "0"; then
AC_DEFINE_UNQUOTED(_ELIX_LEVEL,${newlib_elix_level}) AC_DEFINE_UNQUOTED(_ELIX_LEVEL,${newlib_elix_level})
fi fi
if test "${newlib_io_c99_formats}" = "yes"; then
AC_DEFINE_UNQUOTED(_WANT_IO_C99_FORMATS)
fi
if test "${newlib_io_long_long}" = "yes"; then if test "${newlib_io_long_long}" = "yes"; then
AC_DEFINE_UNQUOTED(_WANT_IO_LONG_LONG) AC_DEFINE_UNQUOTED(_WANT_IO_LONG_LONG)
fi fi
@ -308,7 +321,7 @@ if test "x${iconv_encodings}" != "x" \
for encoding in ${iconv_encodings1}; do for encoding in ${iconv_encodings1}; do
result=`echo "${available_encodings}" | grep -e "\(^\| \)${encoding}\( \|\$\)"` result=`echo "${available_encodings}" | grep -e "\(^\| \)${encoding}\( \|\$\)"`
if test $? != "0"; then if test $? != "0"; then
AC_MSG_ERROR(${encoding} is not supported - see ${srcdir}/libc/iconv/encoding.aliases file for the list of available encodings) AC_MSG_ERROR(${encoding} is not supported - see ${srcdir}/libc/iconv/encoding.aliases file for the list of available encodings)
fi fi
encoding1=`echo "${result}" | sed -e 's/\(^[[^ ]]*\).*$/\1/'` encoding1=`echo "${result}" | sed -e 's/\(^[[^ ]]*\).*$/\1/'`
iconv_encodings="${iconv_encodings} ${encoding1}" iconv_encodings="${iconv_encodings} ${encoding1}"
@ -327,7 +340,7 @@ if test "x${iconv_encodings}" != "x" \
for encoding in ${iconv_encodings1}; do for encoding in ${iconv_encodings1}; do
result=`echo "${available_encodings}" | grep -e "\(^\| \)${encoding}\( \|\$\)"` result=`echo "${available_encodings}" | grep -e "\(^\| \)${encoding}\( \|\$\)"`
if test $? != "0"; then if test $? != "0"; then
AC_MSG_ERROR(${encoding} is not supported - see ${srcdir}/libc/iconv/encoding.aliases file for the list of available encodings) AC_MSG_ERROR(${encoding} is not supported - see ${srcdir}/libc/iconv/encoding.aliases file for the list of available encodings)
fi fi
encoding1=`echo "${result}" | sed -e 's/\(^[[^ ]]*\).*$/\1/'` encoding1=`echo "${result}" | sed -e 's/\(^[[^ ]]*\).*$/\1/'`
iconv_to_encodings="${iconv_to_encodings} ${encoding1}" iconv_to_encodings="${iconv_to_encodings} ${encoding1}"
@ -344,7 +357,7 @@ if test "x${iconv_encodings}" != "x" \
for encoding in ${iconv_encodings1}; do for encoding in ${iconv_encodings1}; do
result=`echo "${available_encodings}" | grep -e "\(^\| \)${encoding}\( \|\$\)"` result=`echo "${available_encodings}" | grep -e "\(^\| \)${encoding}\( \|\$\)"`
if test $? != "0"; then if test $? != "0"; then
AC_MSG_ERROR(${encoding} is not supported - see ${srcdir}/libc/iconv/encoding.aliases file for the list of available encodings) AC_MSG_ERROR(${encoding} is not supported - see ${srcdir}/libc/iconv/encoding.aliases file for the list of available encodings)
fi fi
encoding1=`echo "${result}" | sed -e 's/\(^[[^ ]]*\).*$/\1/'` encoding1=`echo "${result}" | sed -e 's/\(^[[^ ]]*\).*$/\1/'`
iconv_from_encodings="${iconv_from_encodings} ${encoding1}" iconv_from_encodings="${iconv_from_encodings} ${encoding1}"

View File

@ -319,16 +319,20 @@ _EXFUN(get_arg, (struct _reent *data, int n, char *fmt,
#define LONGDBL 0x008 /* long double */ #define LONGDBL 0x008 /* long double */
#define LONGINT 0x010 /* long integer */ #define LONGINT 0x010 /* long integer */
#ifndef _NO_LONGLONG #ifndef _NO_LONGLONG
#define QUADINT 0x020 /* quad integer */ # define QUADINT 0x020 /* quad integer */
#else /* ifdef _NO_LONGLONG, make QUADINT equivalent to LONGINT, so #else /* ifdef _NO_LONGLONG, make QUADINT equivalent to LONGINT, so
that %lld behaves the same as %ld, not as %d, as expected if: that %lld behaves the same as %ld, not as %d, as expected if:
sizeof (long long) = sizeof long > sizeof int */ sizeof (long long) = sizeof long > sizeof int */
#define QUADINT LONGINT # define QUADINT LONGINT
#endif #endif
#define SHORTINT 0x040 /* short integer */ #define SHORTINT 0x040 /* short integer */
#define ZEROPAD 0x080 /* zero (as opposed to blank) pad */ #define ZEROPAD 0x080 /* zero (as opposed to blank) pad */
#define FPT 0x100 /* Floating point number */ #define FPT 0x100 /* Floating point number */
#define CHARINT 0x200 /* char as integer */ #ifdef _WANT_IO_C99_FORMATS
# define CHARINT 0x200 /* char as integer */
#else /* define as 0, to make SARG and UARG occupy fewer instructions */
# define CHARINT 0
#endif
int _EXFUN(_VFPRINTF_R, (struct _reent *, FILE *, _CONST char *, va_list)); int _EXFUN(_VFPRINTF_R, (struct _reent *, FILE *, _CONST char *, va_list));
@ -416,7 +420,7 @@ _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap),
{'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'}; {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
#ifdef _MB_CAPABLE #ifdef _MB_CAPABLE
memset (&state, '\0', sizeof (state)); memset (&state, '\0', sizeof (state));
#endif #endif
/* /*
* BEWARE, these `goto error' on error, and PAD uses `n'. * BEWARE, these `goto error' on error, and PAD uses `n'.
@ -565,12 +569,15 @@ _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap),
rflag: ch = *fmt++; rflag: ch = *fmt++;
reswitch: switch (ch) { reswitch: switch (ch) {
#ifdef _WANT_IO_C99_FORMATS
case '\'': case '\'':
/* In the C locale, LC_NUMERIC requires /* The ' flag is required by POSIX, but not C99.
In the C locale, LC_NUMERIC requires
thousands_sep to be the empty string. And since thousands_sep to be the empty string. And since
no other locales are supported (yet), this flag no other locales are supported (yet), this flag
is currently a no-op. */ is currently a no-op. */
goto rflag; goto rflag;
#endif
case ' ': case ' ':
/* /*
* ``If the space and + flags both appear, the space * ``If the space and + flags both appear, the space
@ -714,24 +721,27 @@ reswitch: switch (ch) {
goto rflag; goto rflag;
#endif #endif
case 'h': case 'h':
#ifdef _WANT_IO_C99_FORMATS
if (*fmt == 'h') { if (*fmt == 'h') {
fmt++; fmt++;
flags |= CHARINT; flags |= CHARINT;
} else { } else
#endif
flags |= SHORTINT; flags |= SHORTINT;
}
goto rflag; goto rflag;
case 'l': case 'l':
#if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
if (*fmt == 'l') { if (*fmt == 'l') {
fmt++; fmt++;
flags |= QUADINT; flags |= QUADINT;
} else { } else
#endif
flags |= LONGINT; flags |= LONGINT;
}
goto rflag; goto rflag;
case 'q': case 'q': /* extension */
flags |= QUADINT; flags |= QUADINT;
goto rflag; goto rflag;
#ifdef _WANT_IO_C99_FORMATS
case 'j': case 'j':
if (sizeof (intmax_t) == sizeof (long)) if (sizeof (intmax_t) == sizeof (long))
flags |= LONGINT; flags |= LONGINT;
@ -769,8 +779,9 @@ reswitch: switch (ch) {
have ptrdiff_t as wide as long long. */ have ptrdiff_t as wide as long long. */
flags |= QUADINT; flags |= QUADINT;
goto rflag; goto rflag;
case 'c':
case 'C': case 'C':
#endif /* _WANT_IO_C99_FORMATS */
case 'c':
cp = buf; cp = buf;
#ifdef _MB_CAPABLE #ifdef _MB_CAPABLE
if (ch == 'C' || (flags & LONGINT)) { if (ch == 'C' || (flags & LONGINT)) {
@ -792,7 +803,7 @@ reswitch: switch (ch) {
} }
sign = '\0'; sign = '\0';
break; break;
case 'D': case 'D': /* extension */
flags |= LONGINT; flags |= LONGINT;
/*FALLTHROUGH*/ /*FALLTHROUGH*/
case 'd': case 'd':
@ -811,12 +822,14 @@ reswitch: switch (ch) {
base = DEC; base = DEC;
goto number; goto number;
#ifdef FLOATING_POINT #ifdef FLOATING_POINT
# ifdef _WANT_IO_C99_FORMATS
case 'a': case 'a':
case 'A': case 'A':
case 'F':
# endif
case 'e': case 'e':
case 'E': case 'E':
case 'f': case 'f':
case 'F':
case 'g': case 'g':
case 'G': case 'G':
# ifdef _NO_LONGDBL # ifdef _NO_LONGDBL
@ -835,7 +848,7 @@ reswitch: switch (ch) {
if (isinf (_fpvalue)) { if (isinf (_fpvalue)) {
if (_fpvalue < 0) if (_fpvalue < 0)
sign = '-'; sign = '-';
if (ch <= 'G') /* 'E', 'F', or 'G' */ if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */
cp = "INF"; cp = "INF";
else else
cp = "inf"; cp = "inf";
@ -844,7 +857,7 @@ reswitch: switch (ch) {
break; break;
} }
if (isnan (_fpvalue)) { if (isnan (_fpvalue)) {
if (ch <= 'G') /* 'E', 'F', or 'G' */ if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */
cp = "NAN"; cp = "NAN";
else else
cp = "nan"; cp = "nan";
@ -866,7 +879,7 @@ reswitch: switch (ch) {
if (tmp == 2) { if (tmp == 2) {
if (_fpvalue < 0) if (_fpvalue < 0)
sign = '-'; sign = '-';
if (ch <= 'G') /* 'E', 'F', or 'G' */ if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */
cp = "INF"; cp = "INF";
else else
cp = "inf"; cp = "inf";
@ -875,7 +888,7 @@ reswitch: switch (ch) {
break; break;
} }
if (tmp == 1) { if (tmp == 1) {
if (ch <= 'G') /* 'E', 'F', or 'G' */ if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */
cp = "NAN"; cp = "NAN";
else else
cp = "nan"; cp = "nan";
@ -885,6 +898,7 @@ reswitch: switch (ch) {
} }
# endif /* !_NO_LONGDBL */ # endif /* !_NO_LONGDBL */
# ifdef _WANT_IO_C99_FORMATS
if (ch == 'a' || ch == 'A') { if (ch == 'a' || ch == 'A') {
ox[0] = '0'; ox[0] = '0';
ox[1] = ch == 'a' ? 'x' : 'X'; ox[1] = ch == 'a' ? 'x' : 'X';
@ -902,7 +916,9 @@ reswitch: switch (ch) {
} }
else else
cp = buf; cp = buf;
} else if (prec == -1) { } else
# endif /* _WANT_IO_C99_FORMATS */
if (prec == -1) {
prec = DEFPREC; prec = DEFPREC;
} else if ((ch == 'g' || ch == 'G') && prec == 0) { } else if ((ch == 'g' || ch == 'G') && prec == 0) {
prec = 1; prec = 1;
@ -919,8 +935,10 @@ reswitch: switch (ch) {
else else
ch = 'g'; ch = 'g';
} }
# ifdef _WANT_IO_C99_FORMATS
else if (ch == 'F') else if (ch == 'F')
ch = 'f'; ch = 'f';
# endif
if (ch <= 'e') { /* 'a', 'A', 'e', or 'E' fmt */ if (ch <= 'e') { /* 'a', 'A', 'e', or 'E' fmt */
--expt; --expt;
expsize = exponent (expstr, expt, ch); expsize = exponent (expstr, expt, ch);
@ -958,12 +976,14 @@ reswitch: switch (ch) {
*GET_ARG (N, ap, long_ptr_t) = ret; *GET_ARG (N, ap, long_ptr_t) = ret;
else if (flags & SHORTINT) else if (flags & SHORTINT)
*GET_ARG (N, ap, short_ptr_t) = ret; *GET_ARG (N, ap, short_ptr_t) = ret;
#ifdef _WANT_IO_C99_FORMATS
else if (flags & CHARINT) else if (flags & CHARINT)
*GET_ARG (N, ap, char_ptr_t) = ret; *GET_ARG (N, ap, char_ptr_t) = ret;
#endif
else else
*GET_ARG (N, ap, int_ptr_t) = ret; *GET_ARG (N, ap, int_ptr_t) = ret;
continue; /* no output */ continue; /* no output */
case 'O': case 'O': /* extension */
flags |= LONGINT; flags |= LONGINT;
/*FALLTHROUGH*/ /*FALLTHROUGH*/
case 'o': case 'o':
@ -986,7 +1006,9 @@ reswitch: switch (ch) {
ch = 'x'; ch = 'x';
goto nosign; goto nosign;
case 's': case 's':
#ifdef _WANT_IO_C99_FORMATS
case 'S': case 'S':
#endif
sign = '\0'; sign = '\0';
if ((cp = GET_ARG (N, ap, char_ptr_t)) == NULL) { if ((cp = GET_ARG (N, ap, char_ptr_t)) == NULL) {
cp = "(null)"; cp = "(null)";
@ -1068,7 +1090,7 @@ reswitch: switch (ch) {
size = strlen (cp); size = strlen (cp);
break; break;
case 'U': case 'U': /* extension */
flags |= LONGINT; flags |= LONGINT;
/*FALLTHROUGH*/ /*FALLTHROUGH*/
case 'u': case 'u':
@ -1357,6 +1379,7 @@ _DEFUN(cvt, (data, value, ndigits, flags, sign, decpt, ch, length, buf),
*sign = '\000'; *sign = '\000';
# endif /* !_NO_LONGDBL */ # endif /* !_NO_LONGDBL */
# ifdef _WANT_IO_C99_FORMATS
if (ch == 'a' || ch == 'A') { if (ch == 'a' || ch == 'A') {
/* This code assumes FLT_RADIX is a power of 2. The initial /* This code assumes FLT_RADIX is a power of 2. The initial
division ensures the digit before the decimal will be less division ensures the digit before the decimal will be less
@ -1387,7 +1410,9 @@ _DEFUN(cvt, (data, value, ndigits, flags, sign, decpt, ch, length, buf),
} }
*length = bp - buf; *length = bp - buf;
return buf; return buf;
} else if (ch == 'f' || ch == 'F') { }
# endif /* _WANT_IO_C99_FORMATS */
if (ch == 'f' || ch == 'F') {
mode = 3; /* ndigits after the decimal point */ mode = 3; /* ndigits after the decimal point */
} else { } else {
/* To obtain ndigits after the decimal point for the 'e' /* To obtain ndigits after the decimal point for the 'e'
@ -1426,7 +1451,11 @@ _DEFUN(exponent, (p0, exp, fmtch),
{ {
register char *p, *t; register char *p, *t;
char expbuf[10]; char expbuf[10];
# ifdef _WANT_IO_C99_FORMATS
int isa = fmtch == 'a' || fmtch == 'A'; int isa = fmtch == 'a' || fmtch == 'A';
# else
# define isa 0
# endif
p = p0; p = p0;
*p++ = isa ? 'p' - 'a' + fmtch : fmtch; *p++ = isa ? 'p' - 'a' + fmtch : fmtch;
@ -1616,25 +1645,25 @@ _DEFUN(get_arg, (data, n, fmt, ap, numargs_p, args, arg_type, last_fmt),
int max_pos_arg = n; int max_pos_arg = n;
/* Only need types that can be reached via vararg promotions. */ /* Only need types that can be reached via vararg promotions. */
enum types { INT, LONG_INT, QUAD_INT, CHAR_PTR, DOUBLE, LONG_DOUBLE, WIDE_CHAR }; enum types { INT, LONG_INT, QUAD_INT, CHAR_PTR, DOUBLE, LONG_DOUBLE, WIDE_CHAR };
#ifdef _MB_CAPABLE # ifdef _MB_CAPABLE
wchar_t wc; wchar_t wc;
mbstate_t wc_state; mbstate_t wc_state;
int nbytes; int nbytes;
#endif # endif
/* if this isn't the first call, pick up where we left off last time */ /* if this isn't the first call, pick up where we left off last time */
if (*last_fmt != NULL) if (*last_fmt != NULL)
fmt = *last_fmt; fmt = *last_fmt;
#ifdef _MB_CAPABLE # ifdef _MB_CAPABLE
memset (&wc_state, '\0', sizeof (wc_state)); memset (&wc_state, '\0', sizeof (wc_state));
#endif # endif
/* we need to process either to end of fmt string or until we have actually /* we need to process either to end of fmt string or until we have actually
read the desired parameter from the vararg list. */ read the desired parameter from the vararg list. */
while (*fmt && n >= numargs) while (*fmt && n >= numargs)
{ {
#ifdef _MB_CAPABLE # ifdef _MB_CAPABLE
while ((nbytes = _mbtowc_r (data, &wc, fmt, MB_CUR_MAX, &wc_state)) > 0) while ((nbytes = _mbtowc_r (data, &wc, fmt, MB_CUR_MAX, &wc_state)) > 0)
{ {
fmt += nbytes; fmt += nbytes;
@ -1644,13 +1673,13 @@ _DEFUN(get_arg, (data, n, fmt, ap, numargs_p, args, arg_type, last_fmt),
if (nbytes <= 0) if (nbytes <= 0)
break; break;
#else # else
while (*fmt != '\0' && *fmt != '%') while (*fmt != '\0' && *fmt != '%')
fmt += 1; fmt += 1;
if (*fmt == '\0') if (*fmt == '\0')
break; break;
#endif # endif /* ! _MB_CAPABLE */
state = START; state = START;
flags = 0; flags = 0;
pos = -1; pos = -1;
@ -1674,7 +1703,7 @@ _DEFUN(get_arg, (data, n, fmt, ap, numargs_p, args, arg_type, last_fmt),
switch (ch) switch (ch)
{ {
case 'h': case 'h':
/* No flag needed, since short and char promote to int. */ /* No flag needed, since short and char promote to int. */
break; break;
case 'L': case 'L':
flags |= LONGDBL; flags |= LONGDBL;
@ -1682,6 +1711,7 @@ _DEFUN(get_arg, (data, n, fmt, ap, numargs_p, args, arg_type, last_fmt),
case 'q': case 'q':
flags |= QUADINT; flags |= QUADINT;
break; break;
# ifdef _WANT_IO_C99_FORMATS
case 'j': case 'j':
if (sizeof (intmax_t) == sizeof (long)) if (sizeof (intmax_t) == sizeof (long))
flags |= LONGINT; flags |= LONGINT;
@ -1712,14 +1742,17 @@ _DEFUN(get_arg, (data, n, fmt, ap, numargs_p, args, arg_type, last_fmt),
have ptrdiff_t as wide as long long. */ have ptrdiff_t as wide as long long. */
flags |= QUADINT; flags |= QUADINT;
break; break;
# endif /* _WANT_IO_C99_FORMATS */
case 'l': case 'l':
default: default:
# if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
if (*fmt == 'l') if (*fmt == 'l')
{ {
flags |= QUADINT; flags |= QUADINT;
++fmt; ++fmt;
} }
else else
# endif
flags |= LONGINT; flags |= LONGINT;
break; break;
} }
@ -1738,10 +1771,10 @@ _DEFUN(get_arg, (data, n, fmt, ap, numargs_p, args, arg_type, last_fmt),
case 'u': case 'u':
if (flags & LONGINT) if (flags & LONGINT)
spec_type = LONG_INT; spec_type = LONG_INT;
#ifndef _NO_LONGLONG # ifndef _NO_LONGLONG
else if (flags & QUADINT) else if (flags & QUADINT)
spec_type = QUAD_INT; spec_type = QUAD_INT;
#endif # endif
else else
spec_type = INT; spec_type = INT;
break; break;
@ -1750,36 +1783,44 @@ _DEFUN(get_arg, (data, n, fmt, ap, numargs_p, args, arg_type, last_fmt),
case 'O': case 'O':
spec_type = LONG_INT; spec_type = LONG_INT;
break; break;
# ifdef _WANT_IO_C99_FORMATS
case 'a': case 'a':
case 'A': case 'A':
case 'f':
case 'F': case 'F':
# endif
case 'f':
case 'g': case 'g':
case 'G': case 'G':
case 'E': case 'E':
case 'e': case 'e':
#ifndef _NO_LONGDBL # ifndef _NO_LONGDBL
if (flags & LONGDBL) if (flags & LONGDBL)
spec_type = LONG_DOUBLE; spec_type = LONG_DOUBLE;
else else
#endif # endif
spec_type = DOUBLE; spec_type = DOUBLE;
break; break;
case 's': case 's':
# ifdef _WANT_IO_C99_FORMATS
case 'S': case 'S':
# endif
case 'p': case 'p':
case 'n': case 'n':
spec_type = CHAR_PTR; spec_type = CHAR_PTR;
break; break;
case 'c': case 'c':
# ifdef _WANT_IO_C99_FORMATS
if (flags & LONGINT) if (flags & LONGINT)
spec_type = WIDE_CHAR; spec_type = WIDE_CHAR;
else else
# endif
spec_type = INT; spec_type = INT;
break; break;
# ifdef _WANT_IO_C99_FORMATS
case 'C': case 'C':
spec_type = WIDE_CHAR; spec_type = WIDE_CHAR;
break; break;
# endif
} }
/* if we have a positional parameter, just store the type, otherwise /* if we have a positional parameter, just store the type, otherwise

View File

@ -361,33 +361,38 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
flags |= SUPPRESS; flags |= SUPPRESS;
goto again; goto again;
case 'l': case 'l':
#if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
if (*fmt == 'l') /* Check for 'll' = long long (SUSv3) */ if (*fmt == 'l') /* Check for 'll' = long long (SUSv3) */
{ {
++fmt; ++fmt;
flags |= LONGDBL; flags |= LONGDBL;
} }
else else
#endif
flags |= LONG; flags |= LONG;
goto again; goto again;
case 'L': case 'L':
flags |= LONGDBL; flags |= LONGDBL;
goto again; goto again;
case 'h': case 'h':
#ifdef _WANT_IO_C99_FORMATS
if (*fmt == 'h') /* Check for 'hh' = char int (SUSv3) */ if (*fmt == 'h') /* Check for 'hh' = char int (SUSv3) */
{ {
++fmt; ++fmt;
flags |= CHAR; flags |= CHAR;
} }
else else
#endif
flags |= SHORT; flags |= SHORT;
goto again; goto again;
case 'j': /* intmax_t */ #ifdef _WANT_IO_C99_FORMATS
case 'j': /* intmax_t */
if (sizeof (intmax_t) == sizeof (long)) if (sizeof (intmax_t) == sizeof (long))
flags |= LONG; flags |= LONG;
else else
flags |= LONGDBL; flags |= LONGDBL;
goto again; goto again;
case 't': /* ptrdiff_t */ case 't': /* ptrdiff_t */
if (sizeof (ptrdiff_t) < sizeof (int)) if (sizeof (ptrdiff_t) < sizeof (int))
/* POSIX states ptrdiff_t is 16 or more bits, as /* POSIX states ptrdiff_t is 16 or more bits, as
is short. */ is short. */
@ -403,7 +408,7 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
have ptrdiff_t as wide as long long. */ have ptrdiff_t as wide as long long. */
flags |= LONGDBL; flags |= LONGDBL;
goto again; goto again;
case 'z': /* size_t */ case 'z': /* size_t */
if (sizeof (size_t) < sizeof (int)) if (sizeof (size_t) < sizeof (int))
/* POSIX states size_t is 16 or more bits, as is short. */ /* POSIX states size_t is 16 or more bits, as is short. */
flags |= SHORT; flags |= SHORT;
@ -418,6 +423,7 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
have size_t as wide as long long. */ have size_t as wide as long long. */
flags |= LONGDBL; flags |= LONGDBL;
goto again; goto again;
#endif /* _WANT_IO_C99_FORMATS */
case '0': case '0':
case '1': case '1':
@ -470,7 +476,7 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
base = 10; base = 10;
break; break;
case 'X': /* compat XXX */ case 'X':
case 'x': case 'x':
flags |= PFXOK; /* enable 0x prefixing */ flags |= PFXOK; /* enable 0x prefixing */
c = CT_INT; c = CT_INT;
@ -479,19 +485,25 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
break; break;
#ifdef FLOATING_POINT #ifdef FLOATING_POINT
case 'E': /* compat XXX */ # ifdef _WANT_IO_C99_FORMATS
case 'G': /* compat XXX */ case 'a':
/* ANSI says that E,G and X behave the same way as e,g,x */ case 'A':
/* FALLTHROUGH */ case 'F':
# endif
case 'E':
case 'G':
case 'e': case 'e':
case 'f': case 'f':
case 'g': case 'g':
c = CT_FLOAT; c = CT_FLOAT;
break; break;
#endif #endif
case 'S':
flags |= LONG; #ifdef _WANT_IO_C99_FORMATS
/* FALLTHROUGH */ case 'S':
flags |= LONG;
/* FALLTHROUGH */
#endif
case 's': case 's':
c = CT_STRING; c = CT_STRING;
@ -503,9 +515,11 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
c = CT_CCL; c = CT_CCL;
break; break;
case 'C': #ifdef _WANT_IO_C99_FORMATS
flags |= LONG; case 'C':
/* FALLTHROUGH */ flags |= LONG;
/* FALLTHROUGH */
#endif
case 'c': case 'c':
flags |= NOSKIP; flags |= NOSKIP;
@ -522,12 +536,15 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
case 'n': case 'n':
if (flags & SUPPRESS) /* ??? */ if (flags & SUPPRESS) /* ??? */
continue; continue;
#ifdef _WANT_IO_C99_FORMATS
if (flags & CHAR) if (flags & CHAR)
{ {
cp = va_arg (ap, char *); cp = va_arg (ap, char *);
*cp = nread; *cp = nread;
} }
else if (flags & SHORT) else
#endif
if (flags & SHORT)
{ {
sp = va_arg (ap, short *); sp = va_arg (ap, short *);
*sp = nread; *sp = nread;
@ -976,11 +993,13 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
res = (*ccfn) (rptr, buf, (char **) NULL, base); res = (*ccfn) (rptr, buf, (char **) NULL, base);
if (flags & POINTER) if (flags & POINTER)
*(va_arg (ap, _PTR *)) = (_PTR) (unsigned _POINTER_INT) res; *(va_arg (ap, _PTR *)) = (_PTR) (unsigned _POINTER_INT) res;
#ifdef _WANT_IO_C99_FORMATS
else if (flags & CHAR) else if (flags & CHAR)
{ {
cp = va_arg (ap, char *); cp = va_arg (ap, char *);
*cp = res; *cp = res;
} }
#endif
else if (flags & SHORT) else if (flags & SHORT)
{ {
sp = va_arg (ap, short *); sp = va_arg (ap, short *);
@ -1087,9 +1106,9 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
break; break;
case 'n': case 'n':
case 'N': case 'N':
if (nancount == 0 if (nancount == 0
&& (flags & (SIGNOK | NDIGITS | DPTOK | EXPOK)) == && (flags & (SIGNOK | NDIGITS | DPTOK | EXPOK)) ==
(SIGNOK | NDIGITS | DPTOK | EXPOK)) (SIGNOK | NDIGITS | DPTOK | EXPOK))
{ {
flags &= ~(SIGNOK | DPTOK | EXPOK | NDIGITS); flags &= ~(SIGNOK | DPTOK | EXPOK | NDIGITS);
nancount = 1; nancount = 1;
@ -1230,7 +1249,7 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
result. */ result. */
#ifndef _NO_LONGDBL /* !_NO_LONGDBL */ #ifndef _NO_LONGDBL /* !_NO_LONGDBL */
if (flags & LONGDBL) if (flags & LONGDBL)
qres = _strtold (buf, NULL); qres = _strtold (buf, NULL);
else else
#endif #endif
res = _strtod_r (rptr, buf, NULL); res = _strtod_r (rptr, buf, NULL);

View File

@ -9,6 +9,10 @@
/* Newlib version */ /* Newlib version */
#undef _NEWLIB_VERSION #undef _NEWLIB_VERSION
/* C99 formats support (such as %a, %zu, ...) in IO functions like
* printf/scanf enabled */
#undef _WANT_IO_C99_FORMATS
/* long long type support in IO functions like printf/scanf enabled */ /* long long type support in IO functions like printf/scanf enabled */
#undef _WANT_IO_LONG_LONG #undef _WANT_IO_LONG_LONG