aboutsummaryrefslogtreecommitdiff
path: root/newlib/libc
diff options
context:
space:
mode:
authorEric Blake <eblake@redhat.com>2007-05-11 20:09:00 +0000
committerEric Blake <eblake@redhat.com>2007-05-11 20:09:00 +0000
commit0962fe9178a40c8410d5f1497bb1966f0db66d6d (patch)
tree96b95530f13f58319534a60386c6c523d97a9e6a /newlib/libc
parentb8a37af936acca73d6f6814d89d422b34e342790 (diff)
downloadnewlib-0962fe9178a40c8410d5f1497bb1966f0db66d6d.zip
newlib-0962fe9178a40c8410d5f1497bb1966f0db66d6d.tar.gz
newlib-0962fe9178a40c8410d5f1497bb1966f0db66d6d.tar.bz2
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.
Diffstat (limited to 'newlib/libc')
-rw-r--r--newlib/libc/stdio/vfprintf.c115
-rw-r--r--newlib/libc/stdio/vfscanf.c55
2 files changed, 115 insertions, 55 deletions
diff --git a/newlib/libc/stdio/vfprintf.c b/newlib/libc/stdio/vfprintf.c
index 684b1e4..6175f0e 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 3b3f63a..9a7745e 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);