diff --git a/newlib/ChangeLog b/newlib/ChangeLog index 83fa6bf98..6986e6e30 100644 --- a/newlib/ChangeLog +++ b/newlib/ChangeLog @@ -1,5 +1,17 @@ 2007-05-11 Eric Blake + 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) (get_arg): Support '%a' and '%A'. diff --git a/newlib/acconfig.h b/newlib/acconfig.h index d8b7dc774..2a138414c 100644 --- a/newlib/acconfig.h +++ b/newlib/acconfig.h @@ -9,6 +9,10 @@ /* 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 */ #undef _WANT_IO_LONG_LONG @@ -154,4 +158,3 @@ #undef _ICONV_FROM_ENCODING_WIN_1258 #endif /* !__NEWLIB_H__ */ - diff --git a/newlib/configure b/newlib/configure index c5009626c..03f6091de 100755 --- a/newlib/configure +++ b/newlib/configure @@ -823,6 +823,7 @@ Optional Features: --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --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-double enable long double type support in IO functions printf/scanf --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 newlib_io_pos_args= 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. if test "${enable_newlib_io_long_long+set}" = set; then 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 *-*-irix6*) # 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 (eval $ac_compile) 2>&5 ac_status=$? @@ -5197,6 +5211,13 @@ _ACEOF 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 cat >>confdefs.h <<_ACEOF #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 result=`echo "${available_encodings}" | grep -e "\(^\| \)${encoding}\( \|\$\)"` 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;} { (exit 1); exit 1; }; } fi @@ -5332,7 +5353,7 @@ _ACEOF for encoding in ${iconv_encodings1}; do result=`echo "${available_encodings}" | grep -e "\(^\| \)${encoding}\( \|\$\)"` 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;} { (exit 1); exit 1; }; } fi @@ -5352,7 +5373,7 @@ _ACEOF for encoding in ${iconv_encodings1}; do result=`echo "${available_encodings}" | grep -e "\(^\| \)${encoding}\( \|\$\)"` 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;} { (exit 1); exit 1; }; } fi diff --git a/newlib/configure.host b/newlib/configure.host index 3b6d996a7..67f7824ef 100644 --- a/newlib/configure.host +++ b/newlib/configure.host @@ -24,6 +24,7 @@ # target_optspace --enable-target-optspace ("yes", "no", "") # newlib_multithread --enable-newlib-multithread ("yes", "no", "yes") # 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_double --enable-newlib-io-long-double ("yes", "no", "") @@ -62,6 +63,7 @@ crt1_dir= have_crt0= use_libtool=no have_sys_mach_dir=no +default_newlib_io_c99_formats=no default_newlib_io_long_long=no default_newlib_io_long_double=no default_newlib_io_pos_args=no @@ -398,6 +400,7 @@ case "${host}" in crt1=crt1.o crt1_dir=libc/sys/${sys_dir} 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_long="yes" default_newlib_io_pos_args="yes" @@ -498,6 +501,7 @@ case "${host}" in *-*-cygwin*) test -z "$cygwin_srcdir" && cygwin_srcdir=`cd ${srcdir}/../winsup/cygwin; pwd` export cygwin_srcdir + default_newlib_io_c99_formats="yes" default_newlib_io_long_long="yes" default_newlib_io_long_double="yes" default_newlib_io_pos_args="yes" @@ -744,6 +748,13 @@ esac # 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. if [ "x${newlib_io_long_long}" = "x" ]; then if [ ${default_newlib_io_long_long} = "yes" ]; then diff --git a/newlib/configure.in b/newlib/configure.in index 378dd942c..c10a10671 100644 --- a/newlib/configure.in +++ b/newlib/configure.in @@ -20,6 +20,15 @@ AC_ARG_ENABLE(newlib-io-pos-args, *) AC_MSG_ERROR(bad value ${enableval} for newlib-io-pos-args option) ;; 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 AC_ARG_ENABLE(newlib-io-long-long, [ --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}) 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 AC_DEFINE_UNQUOTED(_WANT_IO_LONG_LONG) fi @@ -308,7 +321,7 @@ if test "x${iconv_encodings}" != "x" \ for encoding in ${iconv_encodings1}; do result=`echo "${available_encodings}" | grep -e "\(^\| \)${encoding}\( \|\$\)"` 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 encoding1=`echo "${result}" | sed -e 's/\(^[[^ ]]*\).*$/\1/'` iconv_encodings="${iconv_encodings} ${encoding1}" @@ -327,7 +340,7 @@ if test "x${iconv_encodings}" != "x" \ for encoding in ${iconv_encodings1}; do result=`echo "${available_encodings}" | grep -e "\(^\| \)${encoding}\( \|\$\)"` 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 encoding1=`echo "${result}" | sed -e 's/\(^[[^ ]]*\).*$/\1/'` iconv_to_encodings="${iconv_to_encodings} ${encoding1}" @@ -344,7 +357,7 @@ if test "x${iconv_encodings}" != "x" \ for encoding in ${iconv_encodings1}; do result=`echo "${available_encodings}" | grep -e "\(^\| \)${encoding}\( \|\$\)"` 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 encoding1=`echo "${result}" | sed -e 's/\(^[[^ ]]*\).*$/\1/'` iconv_from_encodings="${iconv_from_encodings} ${encoding1}" diff --git a/newlib/libc/stdio/vfprintf.c b/newlib/libc/stdio/vfprintf.c index 684b1e406..6175f0e09 100644 --- a/newlib/libc/stdio/vfprintf.c +++ b/newlib/libc/stdio/vfprintf.c @@ -319,16 +319,20 @@ _EXFUN(get_arg, (struct _reent *data, int n, char *fmt, #define LONGDBL 0x008 /* long double */ #define LONGINT 0x010 /* long integer */ #ifndef _NO_LONGLONG -#define QUADINT 0x020 /* quad integer */ +# define QUADINT 0x020 /* quad integer */ #else /* ifdef _NO_LONGLONG, make QUADINT equivalent to LONGINT, so that %lld behaves the same as %ld, not as %d, as expected if: sizeof (long long) = sizeof long > sizeof int */ -#define QUADINT LONGINT +# define QUADINT LONGINT #endif #define SHORTINT 0x040 /* short integer */ #define ZEROPAD 0x080 /* zero (as opposed to blank) pad */ #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)); @@ -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'}; #ifdef _MB_CAPABLE - memset (&state, '\0', sizeof (state)); + memset (&state, '\0', sizeof (state)); #endif /* * BEWARE, these `goto error' on error, and PAD uses `n'. @@ -565,12 +569,15 @@ _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap), rflag: ch = *fmt++; reswitch: switch (ch) { +#ifdef _WANT_IO_C99_FORMATS 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 no other locales are supported (yet), this flag is currently a no-op. */ goto rflag; +#endif case ' ': /* * ``If the space and + flags both appear, the space @@ -714,24 +721,27 @@ reswitch: switch (ch) { goto rflag; #endif case 'h': +#ifdef _WANT_IO_C99_FORMATS if (*fmt == 'h') { fmt++; flags |= CHARINT; - } else { + } else +#endif flags |= SHORTINT; - } goto rflag; case 'l': +#if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG if (*fmt == 'l') { fmt++; flags |= QUADINT; - } else { + } else +#endif flags |= LONGINT; - } goto rflag; - case 'q': + case 'q': /* extension */ flags |= QUADINT; goto rflag; +#ifdef _WANT_IO_C99_FORMATS case 'j': if (sizeof (intmax_t) == sizeof (long)) flags |= LONGINT; @@ -769,8 +779,9 @@ reswitch: switch (ch) { have ptrdiff_t as wide as long long. */ flags |= QUADINT; goto rflag; - case 'c': case 'C': +#endif /* _WANT_IO_C99_FORMATS */ + case 'c': cp = buf; #ifdef _MB_CAPABLE if (ch == 'C' || (flags & LONGINT)) { @@ -792,7 +803,7 @@ reswitch: switch (ch) { } sign = '\0'; break; - case 'D': + case 'D': /* extension */ flags |= LONGINT; /*FALLTHROUGH*/ case 'd': @@ -811,12 +822,14 @@ reswitch: switch (ch) { base = DEC; goto number; #ifdef FLOATING_POINT +# ifdef _WANT_IO_C99_FORMATS case 'a': case 'A': + case 'F': +# endif case 'e': case 'E': case 'f': - case 'F': case 'g': case 'G': # ifdef _NO_LONGDBL @@ -835,7 +848,7 @@ reswitch: switch (ch) { if (isinf (_fpvalue)) { if (_fpvalue < 0) sign = '-'; - if (ch <= 'G') /* 'E', 'F', or 'G' */ + if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */ cp = "INF"; else cp = "inf"; @@ -844,7 +857,7 @@ reswitch: switch (ch) { break; } if (isnan (_fpvalue)) { - if (ch <= 'G') /* 'E', 'F', or 'G' */ + if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */ cp = "NAN"; else cp = "nan"; @@ -866,7 +879,7 @@ reswitch: switch (ch) { if (tmp == 2) { if (_fpvalue < 0) sign = '-'; - if (ch <= 'G') /* 'E', 'F', or 'G' */ + if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */ cp = "INF"; else cp = "inf"; @@ -875,7 +888,7 @@ reswitch: switch (ch) { break; } if (tmp == 1) { - if (ch <= 'G') /* 'E', 'F', or 'G' */ + if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */ cp = "NAN"; else cp = "nan"; @@ -885,6 +898,7 @@ reswitch: switch (ch) { } # endif /* !_NO_LONGDBL */ +# ifdef _WANT_IO_C99_FORMATS if (ch == 'a' || ch == 'A') { ox[0] = '0'; ox[1] = ch == 'a' ? 'x' : 'X'; @@ -902,7 +916,9 @@ reswitch: switch (ch) { } else cp = buf; - } else if (prec == -1) { + } else +# endif /* _WANT_IO_C99_FORMATS */ + if (prec == -1) { prec = DEFPREC; } else if ((ch == 'g' || ch == 'G') && prec == 0) { prec = 1; @@ -919,8 +935,10 @@ reswitch: switch (ch) { else ch = 'g'; } +# ifdef _WANT_IO_C99_FORMATS else if (ch == 'F') ch = 'f'; +# endif if (ch <= 'e') { /* 'a', 'A', 'e', or 'E' fmt */ --expt; expsize = exponent (expstr, expt, ch); @@ -958,12 +976,14 @@ reswitch: switch (ch) { *GET_ARG (N, ap, long_ptr_t) = ret; else if (flags & SHORTINT) *GET_ARG (N, ap, short_ptr_t) = ret; +#ifdef _WANT_IO_C99_FORMATS else if (flags & CHARINT) *GET_ARG (N, ap, char_ptr_t) = ret; +#endif else *GET_ARG (N, ap, int_ptr_t) = ret; continue; /* no output */ - case 'O': + case 'O': /* extension */ flags |= LONGINT; /*FALLTHROUGH*/ case 'o': @@ -986,7 +1006,9 @@ reswitch: switch (ch) { ch = 'x'; goto nosign; case 's': +#ifdef _WANT_IO_C99_FORMATS case 'S': +#endif sign = '\0'; if ((cp = GET_ARG (N, ap, char_ptr_t)) == NULL) { cp = "(null)"; @@ -1068,7 +1090,7 @@ reswitch: switch (ch) { size = strlen (cp); break; - case 'U': + case 'U': /* extension */ flags |= LONGINT; /*FALLTHROUGH*/ case 'u': @@ -1357,6 +1379,7 @@ _DEFUN(cvt, (data, value, ndigits, flags, sign, decpt, ch, length, buf), *sign = '\000'; # endif /* !_NO_LONGDBL */ +# ifdef _WANT_IO_C99_FORMATS if (ch == 'a' || ch == 'A') { /* This code assumes FLT_RADIX is a power of 2. The initial 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; 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 */ } else { /* To obtain ndigits after the decimal point for the 'e' @@ -1426,7 +1451,11 @@ _DEFUN(exponent, (p0, exp, fmtch), { register char *p, *t; char expbuf[10]; +# ifdef _WANT_IO_C99_FORMATS int isa = fmtch == 'a' || fmtch == 'A'; +# else +# define isa 0 +# endif p = p0; *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; /* Only need types that can be reached via vararg promotions. */ enum types { INT, LONG_INT, QUAD_INT, CHAR_PTR, DOUBLE, LONG_DOUBLE, WIDE_CHAR }; -#ifdef _MB_CAPABLE +# ifdef _MB_CAPABLE wchar_t wc; mbstate_t wc_state; - int nbytes; -#endif - + int nbytes; +# endif + /* if this isn't the first call, pick up where we left off last time */ if (*last_fmt != NULL) fmt = *last_fmt; -#ifdef _MB_CAPABLE +# ifdef _MB_CAPABLE memset (&wc_state, '\0', sizeof (wc_state)); -#endif +# endif /* we need to process either to end of fmt string or until we have actually read the desired parameter from the vararg list. */ while (*fmt && n >= numargs) { -#ifdef _MB_CAPABLE +# ifdef _MB_CAPABLE while ((nbytes = _mbtowc_r (data, &wc, fmt, MB_CUR_MAX, &wc_state)) > 0) { fmt += nbytes; @@ -1644,13 +1673,13 @@ _DEFUN(get_arg, (data, n, fmt, ap, numargs_p, args, arg_type, last_fmt), if (nbytes <= 0) break; -#else +# else while (*fmt != '\0' && *fmt != '%') fmt += 1; if (*fmt == '\0') break; -#endif +# endif /* ! _MB_CAPABLE */ state = START; flags = 0; pos = -1; @@ -1667,14 +1696,14 @@ _DEFUN(get_arg, (data, n, fmt, ap, numargs_p, args, arg_type, last_fmt), next_state = state_table[state][chtype]; action = action_table[state][chtype]; state = next_state; - + switch (action) { case GETMOD: /* we have format modifier */ switch (ch) { case 'h': - /* No flag needed, since short and char promote to int. */ + /* No flag needed, since short and char promote to int. */ break; case 'L': flags |= LONGDBL; @@ -1682,6 +1711,7 @@ _DEFUN(get_arg, (data, n, fmt, ap, numargs_p, args, arg_type, last_fmt), case 'q': flags |= QUADINT; break; +# ifdef _WANT_IO_C99_FORMATS case 'j': if (sizeof (intmax_t) == sizeof (long)) 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. */ flags |= QUADINT; break; +# endif /* _WANT_IO_C99_FORMATS */ case 'l': default: +# if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG if (*fmt == 'l') { flags |= QUADINT; ++fmt; } else +# endif flags |= LONGINT; break; } @@ -1738,10 +1771,10 @@ _DEFUN(get_arg, (data, n, fmt, ap, numargs_p, args, arg_type, last_fmt), case 'u': if (flags & LONGINT) spec_type = LONG_INT; -#ifndef _NO_LONGLONG +# ifndef _NO_LONGLONG else if (flags & QUADINT) spec_type = QUAD_INT; -#endif +# endif else spec_type = INT; break; @@ -1750,36 +1783,44 @@ _DEFUN(get_arg, (data, n, fmt, ap, numargs_p, args, arg_type, last_fmt), case 'O': spec_type = LONG_INT; break; +# ifdef _WANT_IO_C99_FORMATS case 'a': case 'A': - case 'f': case 'F': +# endif + case 'f': case 'g': case 'G': case 'E': case 'e': -#ifndef _NO_LONGDBL +# ifndef _NO_LONGDBL if (flags & LONGDBL) spec_type = LONG_DOUBLE; else -#endif +# endif spec_type = DOUBLE; break; case 's': +# ifdef _WANT_IO_C99_FORMATS case 'S': +# endif case 'p': case 'n': spec_type = CHAR_PTR; break; case 'c': +# ifdef _WANT_IO_C99_FORMATS if (flags & LONGINT) spec_type = WIDE_CHAR; else +# endif spec_type = INT; break; +# ifdef _WANT_IO_C99_FORMATS case 'C': spec_type = WIDE_CHAR; break; +# endif } /* if we have a positional parameter, just store the type, otherwise diff --git a/newlib/libc/stdio/vfscanf.c b/newlib/libc/stdio/vfscanf.c index 3b3f63af8..9a7745e1a 100644 --- a/newlib/libc/stdio/vfscanf.c +++ b/newlib/libc/stdio/vfscanf.c @@ -361,33 +361,38 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap), flags |= SUPPRESS; goto again; case 'l': +#if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG if (*fmt == 'l') /* Check for 'll' = long long (SUSv3) */ { ++fmt; flags |= LONGDBL; } else +#endif flags |= LONG; goto again; case 'L': flags |= LONGDBL; goto again; case 'h': +#ifdef _WANT_IO_C99_FORMATS if (*fmt == 'h') /* Check for 'hh' = char int (SUSv3) */ { ++fmt; flags |= CHAR; } else +#endif flags |= SHORT; goto again; - case 'j': /* intmax_t */ +#ifdef _WANT_IO_C99_FORMATS + case 'j': /* intmax_t */ if (sizeof (intmax_t) == sizeof (long)) flags |= LONG; else flags |= LONGDBL; goto again; - case 't': /* ptrdiff_t */ + case 't': /* ptrdiff_t */ if (sizeof (ptrdiff_t) < sizeof (int)) /* POSIX states ptrdiff_t is 16 or more bits, as is short. */ @@ -403,7 +408,7 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap), have ptrdiff_t as wide as long long. */ flags |= LONGDBL; goto again; - case 'z': /* size_t */ + case 'z': /* size_t */ if (sizeof (size_t) < sizeof (int)) /* POSIX states size_t is 16 or more bits, as is short. */ flags |= SHORT; @@ -418,6 +423,7 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap), have size_t as wide as long long. */ flags |= LONGDBL; goto again; +#endif /* _WANT_IO_C99_FORMATS */ case '0': case '1': @@ -470,7 +476,7 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap), base = 10; break; - case 'X': /* compat XXX */ + case 'X': case 'x': flags |= PFXOK; /* enable 0x prefixing */ c = CT_INT; @@ -479,19 +485,25 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap), break; #ifdef FLOATING_POINT - case 'E': /* compat XXX */ - case 'G': /* compat XXX */ -/* ANSI says that E,G and X behave the same way as e,g,x */ - /* FALLTHROUGH */ +# ifdef _WANT_IO_C99_FORMATS + case 'a': + case 'A': + case 'F': +# endif + case 'E': + case 'G': case 'e': case 'f': case 'g': c = CT_FLOAT; break; #endif - case 'S': - flags |= LONG; - /* FALLTHROUGH */ + +#ifdef _WANT_IO_C99_FORMATS + case 'S': + flags |= LONG; + /* FALLTHROUGH */ +#endif case 's': c = CT_STRING; @@ -503,9 +515,11 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap), c = CT_CCL; break; - case 'C': - flags |= LONG; - /* FALLTHROUGH */ +#ifdef _WANT_IO_C99_FORMATS + case 'C': + flags |= LONG; + /* FALLTHROUGH */ +#endif case 'c': flags |= NOSKIP; @@ -522,12 +536,15 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap), case 'n': if (flags & SUPPRESS) /* ??? */ continue; +#ifdef _WANT_IO_C99_FORMATS if (flags & CHAR) { cp = va_arg (ap, char *); *cp = nread; } - else if (flags & SHORT) + else +#endif + if (flags & SHORT) { sp = va_arg (ap, short *); *sp = nread; @@ -976,11 +993,13 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap), res = (*ccfn) (rptr, buf, (char **) NULL, base); if (flags & POINTER) *(va_arg (ap, _PTR *)) = (_PTR) (unsigned _POINTER_INT) res; +#ifdef _WANT_IO_C99_FORMATS else if (flags & CHAR) { cp = va_arg (ap, char *); *cp = res; } +#endif else if (flags & SHORT) { sp = va_arg (ap, short *); @@ -1087,9 +1106,9 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap), break; case 'n': case 'N': - if (nancount == 0 + if (nancount == 0 && (flags & (SIGNOK | NDIGITS | DPTOK | EXPOK)) == - (SIGNOK | NDIGITS | DPTOK | EXPOK)) + (SIGNOK | NDIGITS | DPTOK | EXPOK)) { flags &= ~(SIGNOK | DPTOK | EXPOK | NDIGITS); nancount = 1; @@ -1230,7 +1249,7 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap), result. */ #ifndef _NO_LONGDBL /* !_NO_LONGDBL */ if (flags & LONGDBL) - qres = _strtold (buf, NULL); + qres = _strtold (buf, NULL); else #endif res = _strtod_r (rptr, buf, NULL); diff --git a/newlib/newlib.hin b/newlib/newlib.hin index bb09f9970..236c831ed 100644 --- a/newlib/newlib.hin +++ b/newlib/newlib.hin @@ -9,6 +9,10 @@ /* 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 */ #undef _WANT_IO_LONG_LONG