aboutsummaryrefslogtreecommitdiff
path: root/newlib/libc/stdio/vfprintf.c
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2009-03-06 09:55:52 +0000
committerCorinna Vinschen <corinna@vinschen.de>2009-03-06 09:55:52 +0000
commit6121968b198dcbb93427b0a11453563ebe462bb4 (patch)
tree1b612b73db2b4572c591bf8644021b2407a8f602 /newlib/libc/stdio/vfprintf.c
parent6e0e5a4fc20a1de8124c454a5c14c616c68e4653 (diff)
downloadnewlib-6121968b198dcbb93427b0a11453563ebe462bb4.zip
newlib-6121968b198dcbb93427b0a11453563ebe462bb4.tar.gz
newlib-6121968b198dcbb93427b0a11453563ebe462bb4.tar.bz2
* libc/include/stdio.h (__VALIST): Guard against multiple definition.
* libc/include/wchar.h: Include stdarg.h. (__VALIST): Define conditionally. (fwprintf, swprintf, vfwprintf, vswprintf, vwprintf, wprintf: Declare. (_fwprintf_r, _swprintf_r, _vfwprintf_r, _vswprintf_r, _vwprintf_r, _wprintf_r): Declare. * libc/stdio/Makefile.am: Add new files. * libc/stdio/Makefile.in: Regenerate. * libc/stdio/fwprintf.c: New file. * libc/stdio/local.h (_svfwprintf_r, _svfiwprintf_r): Declare. (__CH_CLASS, __STATE, __ACTION): Move definition from vfprintf.c here and move to the __ namespace. (__chclass, __state_table, __action_table): Declare. * libc/stdio/stdio.tex: Add new documentation references. * libc/stdio/swprintf.c: New file. * libc/stdio/vfprintf.c (__SPRINT): New macro to call the right __sprint_r function according to compilation unit. Use throughout. (__ssprint_r): Rename STRING_ONLY variant from __sprint_r. Make externaly available. Only define if INTEGER_ONLY is defined. (__sprint_r): Make externaly available. Only define if INTEGER_ONLY is defined. Handle stream orientation. (__sbprintf): Copy FILE's _flags2 member as well. (__chclass, __state_table, __action_table): Prepend __ to name and make externally available. * libc/stdio/vfwprintf.c: New file. * libc/stdio/vswprintf.c: New file. * libc/stdio/vwprintf.c: New file. * libc/stdio/wprintf.c: New file.
Diffstat (limited to 'newlib/libc/stdio/vfprintf.c')
-rw-r--r--newlib/libc/stdio/vfprintf.c113
1 files changed, 56 insertions, 57 deletions
diff --git a/newlib/libc/stdio/vfprintf.c b/newlib/libc/stdio/vfprintf.c
index ac1d919..e81b068 100644
--- a/newlib/libc/stdio/vfprintf.c
+++ b/newlib/libc/stdio/vfprintf.c
@@ -177,8 +177,18 @@ static char *rcsid = "$Id$";
#endif
#ifdef STRING_ONLY
-static int
-_DEFUN(__sprint_r, (ptr, fp, uio),
+#define __SPRINT __ssprint_r
+#else
+#define __SPRINT __sprint_r
+#endif
+
+/* The __sprint_r/__ssprint_r functions are shared between all versions of
+ vfprintf and vfwprintf. They must only be defined once, which we do in
+ the INTEGER_ONLY versions here. */
+#ifdef STRING_ONLY
+#ifdef INTEGER_ONLY
+int
+_DEFUN(__ssprint_r, (ptr, fp, uio),
struct _reent *ptr _AND
FILE *fp _AND
register struct __suio *uio)
@@ -268,29 +278,51 @@ err:
uio->uio_iovcnt = 0;
return EOF;
}
+#endif /* INTEGER_ONLY */
#else /* !STRING_ONLY */
+#ifdef INTEGER_ONLY
/*
* Flush out all the vectors defined by the given uio,
* then reset it so that it can be reused.
*/
-static int
+int
_DEFUN(__sprint_r, (ptr, fp, uio),
struct _reent *ptr _AND
FILE *fp _AND
register struct __suio *uio)
{
- register int err;
+ register int err = 0;
if (uio->uio_resid == 0) {
uio->uio_iovcnt = 0;
return (0);
}
- err = __sfvwrite_r(ptr, fp, uio);
+ if (fp->_flags2 & __SWID) {
+ struct __siov *iov;
+ wchar_t *p;
+ int i, len;
+
+ iov = uio->uio_iov;
+ for (; uio->uio_resid != 0;
+ uio->uio_resid -= len * sizeof (wchar_t), iov++) {
+ p = (wchar_t *) iov->iov_base;
+ len = iov->iov_len / sizeof (wchar_t);
+ for (i = 0; i < len; i++) {
+ if (_fputwc_r (ptr, p[i], fp) == WEOF) {
+ err = -1;
+ goto out;
+ }
+ }
+ }
+ } else
+ err = __sfvwrite_r(ptr, fp, uio);
+out:
uio->uio_resid = 0;
uio->uio_iovcnt = 0;
return (err);
}
+#endif /* INTEGER_ONLY */
/*
* Helper function for `fprintf to unbuffered unix file': creates a
@@ -310,6 +342,7 @@ _DEFUN(__sbprintf, (rptr, fp, fmt, ap),
/* copy the important variables */
fake._flags = fp->_flags & ~__SNBF;
+ fake._flags2 = fp->_flags2;
fake._file = fp->_file;
fake._cookie = fp->_cookie;
fake._write = fp->_write;
@@ -564,7 +597,7 @@ _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap),
uio.uio_resid += (len); \
iovp++; \
if (++uio.uio_iovcnt >= NIOV) { \
- if (__sprint_r(data, fp, &uio)) \
+ if (__SPRINT(data, fp, &uio)) \
goto error; \
iovp = iov; \
} \
@@ -579,7 +612,7 @@ _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap),
} \
}
#define FLUSH() { \
- if (uio.uio_resid && __sprint_r(data, fp, &uio)) \
+ if (uio.uio_resid && __SPRINT(data, fp, &uio)) \
goto error; \
uio.uio_iovcnt = 0; \
iovp = iov; \
@@ -1642,48 +1675,12 @@ exponent(char *p0, int exp, int fmtch)
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
-typedef enum {
- ZERO, /* '0' */
- DIGIT, /* '1-9' */
- DOLLAR, /* '$' */
- MODFR, /* spec modifier */
- SPEC, /* format specifier */
- DOT, /* '.' */
- STAR, /* '*' */
- FLAG, /* format flag */
- OTHER, /* all other chars */
- MAX_CH_CLASS /* place-holder */
-} CH_CLASS;
-
-typedef enum {
- START, /* start */
- SFLAG, /* seen a flag */
- WDIG, /* seen digits in width area */
- WIDTH, /* processed width */
- SMOD, /* seen spec modifier */
- SDOT, /* seen dot */
- VARW, /* have variable width specifier */
- VARP, /* have variable precision specifier */
- PREC, /* processed precision */
- VWDIG, /* have digits in variable width specification */
- VPDIG, /* have digits in variable precision specification */
- DONE, /* done */
- MAX_STATE, /* place-holder */
-} STATE;
-
-typedef enum {
- NOOP, /* do nothing */
- NUMBER, /* build a number from digits */
- SKIPNUM, /* skip over digits */
- GETMOD, /* get and process format modifier */
- GETARG, /* get and process argument */
- GETPW, /* get variable precision or width */
- GETPWB, /* get variable precision or width and pushback fmt char */
- GETPOS, /* get positional parameter value */
- PWPOS, /* get positional parameter value for variable width or precision */
-} ACTION;
-
-_CONST static CH_CLASS chclass[256] = {
+/* The below constant state tables are shared between all versions of
+ vfprintf and vfwprintf. They must only be defined once, which we do in
+ the STRING_ONLY/INTEGER_ONLY versions here. */
+#if defined (STRING_ONLY) && defined(INTEGER_ONLY)
+
+_CONST __CH_CLASS __chclass[256] = {
/* 00-07 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
/* 08-0f */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
/* 10-17 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
@@ -1718,7 +1715,7 @@ _CONST static CH_CLASS chclass[256] = {
/* f8-ff */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
};
-_CONST static STATE state_table[MAX_STATE][MAX_CH_CLASS] = {
+_CONST __STATE __state_table[MAX_STATE][MAX_CH_CLASS] = {
/* '0' '1-9' '$' MODFR SPEC '.' '*' FLAG OTHER */
/* START */ { SFLAG, WDIG, DONE, SMOD, DONE, SDOT, VARW, SFLAG, DONE },
/* SFLAG */ { SFLAG, WDIG, DONE, SMOD, DONE, SDOT, VARW, SFLAG, DONE },
@@ -1733,7 +1730,7 @@ _CONST static STATE state_table[MAX_STATE][MAX_CH_CLASS] = {
/* VPDIG */ { DONE, DONE, PREC, DONE, DONE, DONE, DONE, DONE, DONE },
};
-_CONST static ACTION action_table[MAX_STATE][MAX_CH_CLASS] = {
+_CONST __ACTION __action_table[MAX_STATE][MAX_CH_CLASS] = {
/* '0' '1-9' '$' MODFR SPEC '.' '*' FLAG OTHER */
/* START */ { NOOP, NUMBER, NOOP, GETMOD, GETARG, NOOP, NOOP, NOOP, NOOP },
/* SFLAG */ { NOOP, NUMBER, NOOP, GETMOD, GETARG, NOOP, NOOP, NOOP, NOOP },
@@ -1748,6 +1745,8 @@ _CONST static ACTION action_table[MAX_STATE][MAX_CH_CLASS] = {
/* VPDIG */ { NOOP, NOOP, PWPOS, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP },
};
+#endif /* STRING_ONLY && INTEGER_ONLY */
+
/* function to get positional parameter N where n = N - 1 */
static union arg_val *
_DEFUN(get_arg, (data, n, fmt, ap, numargs_p, args, arg_type, last_fmt),
@@ -1764,9 +1763,9 @@ _DEFUN(get_arg, (data, n, fmt, ap, numargs_p, args, arg_type, last_fmt),
int number, flags;
int spec_type;
int numargs = *numargs_p;
- CH_CLASS chtype;
- STATE state, next_state;
- ACTION action;
+ __CH_CLASS chtype;
+ __STATE state, next_state;
+ __ACTION action;
int pos, last_arg;
int max_pos_arg = n;
/* Only need types that can be reached via vararg promotions. */
@@ -1818,9 +1817,9 @@ _DEFUN(get_arg, (data, n, fmt, ap, numargs_p, args, arg_type, last_fmt),
while (state != DONE)
{
ch = *fmt++;
- chtype = chclass[ch];
- next_state = state_table[state][chtype];
- action = action_table[state][chtype];
+ chtype = __chclass[ch];
+ next_state = __state_table[state][chtype];
+ action = __action_table[state][chtype];
state = next_state;
switch (action)