mirror of
https://sourceware.org/git/glibc.git
synced 2025-08-08 17:42:12 +03:00
Update.
* Versions.def: Add GLIBC_2.2 for libc. * iconv/gconv.h: Make header suitable for inclusion in public header by protecting all names with __. * iconv/gconv.c: Adapt for symbol name changes. * iconv/gconv.h: Likewise. * iconv/gconv_builtin.c: Likewise. * iconv/gconv_close.c: Likewise. * iconv/gconv_db.c: Likewise. * iconv/gconv_dl.c: Likewise. * iconv/gconv_int.h: Likewise. * iconv/gconv_open.c: Likewise. * iconv/gconv_simple.c: Likewise. * iconv/iconv.c: Likewise. * iconv/iconv_close.c: Likewise. * iconv/iconv_open.c: Likewise. * iconv/loop.c: Likewise. * iconv/skeleton.c: Likewise. * iconvdata/8bit-gap.c: Likewise. * iconvdata/8bit-generic.c: Likewise. * iconvdata/ansi_x3.110.c: Likewise. * iconvdata/big5.c: Likewise. * iconvdata/cns11643.h: Likewise. * iconvdata/cns11643l1.h: Likewise. * iconvdata/euc-cn.c: Likewise. * iconvdata/euc-jp.c: Likewise. * iconvdata/euc-kr.c: Likewise. * iconvdata/euc-tw.c: Likewise. * iconvdata/gb2312.h: Likewise. * iconvdata/iso-2022-jp.c: Likewise. * iconvdata/iso-2022-kr.c: Likewise. * iconvdata/iso646.c: Likewise. * iconvdata/iso8859-1.c: Likewise. * iconvdata/iso_6937-2.c: Likewise. * iconvdata/iso_6937.c: Likewise. * iconvdata/jis0201.h: Likewise. * iconvdata/jis0208.h: Likewise. * iconvdata/jis0212.h: Likewise. * iconvdata/johab.c: Likewise. * iconvdata/ksc5601.h: Likewise. * iconvdata/sjis.c: Likewise. * iconvdata/t.61.c: Likewise. * iconvdata/uhc.c: Likewise. * stdlib/mblen.c: Likewise. * stdlib/mbtowc.c: Likewise. * stdlib/wctomb.c: Likewise. * wcsmbs/btowc.c: Likewise. * wcsmbs/mbrtowc.c: Likewise. * wcsmbs/mbsnrtowcs.c: Likewise. * wcsmbs/mbsrtowcs.c: Likewise. * wcsmbs/wchar.h: Likewise. * wcsmbs/wcrtomb.c: Likewise. * wcsmbs/wcsmbsload.c: Likewise. * wcsmbs/wcsmbsload.h: Likewise. * wcsmbs/wcsnrtombs.c: Likewise. * wcsmbs/wcsrtombs.c: Likewise. * wcsmbs/wctob.c: Likewise. * include/limits.h (MB_LEN_MAX): Increase to 16. * sysdeps/generic/_G_config.h: Define _G_fpos_t as struct. Define _G_iconv_t. * sysdeps/unix/sysv/linux/_G_config.h: Likewise. * include/wchar.h: Change mbstate_t to __mbstate_t. * libio/Makefile (routines): Add wfiledoalloc, oldiofgetpos, oldiofgetpos64, oldiofsetpos, oldiofsetpos64, fputwc, fputwc_u, getwc, getwc_u, getwchar, getwchar_u, iofgetws, iofgetws_u, iofputws, iofputws_u, iogetwline, iowpadn, ioungetwc, putwc, putwc_u, putchar, putchar_u, swprintf, vwprintf, wprintf, wscanf, fwscanf, vwscanf, vswprintf, iovswscanf, swscanf, wgenops, wstrops, wfileops, and iofwide. (tests): Add tst_swprintf, tst_wprintf, tst_swscanf, and tst_wscanf. * libio/Versions: Add _IO_fgetpos, _IO_fgetpos64, _IO_fsetpos, _IO_fsetpos64, fgetpos, fgetpos64, fgetwc, fgetwc_unlocked, fgetws, fgetws_unlocked, fputwc, fputwc_unlocked, fputws, fputws_unlocked, fsetpos, fsetpos64, fwide, fwprintf, fwscanf, getwc, getwc_unlocked, getwchar, getwchar_unlocked, putwc, putwc_unlocked, putwchar, putwchar_unlocked, swprintf, swscanf, ungetwc, vfwprintf, vswprintf, vwprintf, vfwscanf, vswscanf, vwscanf, wprintf, and wscanf to GLIBC_2.2 for libc. * libio/libio.h: Define codecvt struct. Define _IO_wide_data. Extend _IO_file contain pointer to codecvt, widedata and mode. (_IO_getwc_unlocked): New macro. (_IO_putwc_unlocked): New macro. (_IO_fwide): New macro. * libio/libioP.h: Add new prototypes and adjust existing declarations. * libio/fileops.c (_IO_new_file_close_it): Reset normal or widedata buffers based on mode. (new_do_write): Set _IO_write_end to _IO_buf_end if stream is wide oriented. (_IO_new_file_overflow): Don't depend only on _IO_CURRENTLY_PUTTING flag to be enough to signal unallocated buffer. For wide oriented stream don't make it linebuffered. Don't use _IO_do_flush, use _IO_new_do_write directly. (_IO_new_file_seekoff): Change return value type to _IO_off64_t. (_IO_file_seek): Likewise. * libio/genops.c (_IO_least_marker): Make global. (__underflow): Orient stream if not already done. (__uflow): Likewise. (_IO_default_seekpos): Change to type _IO_off64_t. (_IO_default_seekoff): Likewise. (_IO_default_seek): Likewise. (_IO_no_init): New function. Similar to _IO_init but allows to orient in initialization. * libio/iolibio.h: Add prototype for _IO_vswprintf. Change _IO_pos_BAD to use _IO_off64_t. * libio/ftello.c: Use _IO_off_t. For now abort when use with wide char stream. * libio/ftello64.c: Likewise. * libio/ioftell.c: Likewise. * libio/iofopncook.c: Likewise. * libio/ioseekoff.c: Likewise. * libio/ioseekpos.c: Likewise. * libio/oldfileops.c: Likewise. * libio/iofgetpos.c: Store state of conversion if necessary. * libio/iofgetpos64.c: Likewise. * libio/iofsetpos.c: Restore conversion state if necessary. * libio/iofsetpos64.c: Likewise. * libio/iofdopen.c: Initialize so that stream can be wide oriented. * libio/iofopen.c: Likewise. * libio/iofopen64.c: Likewise. * libio/iopopen.c: Likewise. * libio/iovdprintf.c: Likewise. * libio/iovsprintf.c: Likewise. * libio/iovsscanf.c: Likewise. * libio/memstream.c: Likewise. * libio/obprintf.c: Likewise. * libio/iofputs.c: Orient stream if not already happened. * libio/iofputs_u.c: Likewise. * libio/iofwrite.c: Likewise. * libio/iofwrite_u.c: Likewise. * libio/ioputs.c: Likewise. * libio/iosetbuffer.c: Handle not yet oriented stream. * libio/iosetvbuf.c: Likewise. * libio/oldstdfiles.c: Adjust FILEBUF_LITERAL call. * libio/stdfiles.c: Likewise. * libio/strops.c (_IO_str_overflow): Correctly free buffer after failed allocation. (_IO_str_seekoff): Use _IO_off64_t. * libio/vasprintf.c: Pre-orient stream. * libio/vsnprintf.c: Likewise. * libio/fputwc.c: New file. * libio/fputwc_u.c: New file. * libio/fwprintf.c: New file. * libio/fwscanf.c: New file. * libio/getwc.c: New file. * libio/getwc_u.c: New file. * libio/getwchar.c: New file. * libio/getwchar_u.c: New file. * libio/iofgetws.c: New file. * libio/iofgetws_u.c: New file. * libio/iofputws.c: New file. * libio/iofputws_u.c: New file. * libio/iofwide.c: New file. * libio/iogetwline.c: New file. * libio/ioungetwc.c: New file. * libio/iovswscanf.c: New file. * libio/iowpadn.c: New file. * libio/oldiofgetpos.c: New file. * libio/oldiofgetpos64.c: New file. * libio/oldiofsetpos.c: New file. * libio/oldiofsetpos64.c: New file. * libio/putwc.c: New file. * libio/putwc_u.c: New file. * libio/putwchar.c: New file. * libio/putwchar_u.c: New file. * libio/swprintf.c: New file. * libio/swscanf.c: New file. * libio/tst_swprintf.c: New file. * libio/tst_swscanf.c: New file. * libio/tst_wprintf.c: New file. * libio/tst_wscanf.c: New file. * libio/tst_wscanf.input: New file. * libio/vswprintf.c: New file. * libio/vwprintf.c: New file. * libio/vwscanf.c: New file. * libio/wfiledoalloc.c: New file. * libio/wfileops.c: New file. * libio/wgenops.c: New file. * libio/wprintf.c: New file. * libio/wscanf.c: New file. * libio/wstrops.c: New file. * stdio-common/Makefile (routines): Add _itowa, itowa-digits, vfwprintf, and vfwscanf. * stdio-common/_itoa.c (base_table): Rename to _IO_base_table and make global. * stdio-common/_itowa.c: New file. * stdio-common/_itowa.h: New file. * stdio-common/itoa-digits.c: Minimal optimization. * stdio-common/itowa-digits.c: New file. * stdio-common/printf-parse.h: Allow use in wide character context. * stdio-common/printf-prs.c: Define ISASCII and MBRLEN. * stdio-common/printf.h (printf_info): Add wide bit. * stdio-common/printf_fp.c: Determine from wide bit whether stream is wide oriented or not. * stdio-common/printf_size.c: Likewise. * sysdeps/generic/printf_fphex.c: Likewise. * stdlib/strfmon.c: Call __printf_fp with wide bit cleared. * stdio-common/vfprintf.c: Rewrite to allow use in wide character context. * stdio-common/vfscand.c: Likewise. * stdio-common/vfwprintf.c: New file. * stdio-common/vfwscanf.c: New file. * time/Makefile (routines): Add wcsftime. (tests): Add tst_wcsftime. * time/Versions: Add wcsftime to GLIBC_2.2 for libc. * time/strftime.c: Make usable as wcsftime. * time/wcsftime.c: New file. * time/tst_wcsftime.c: New file. * wcsmbs/Makefile (routines): Add wmempcpy and wcschrnul. * wcsmbs/Versions: Add wmempcpy and wcschrnul to GLIBC_2.2 for libc. * wcsmbs/wcschrnul.c: New file. * wcsmbs/wmemcpy.c: New file. * wcsmbs/wmemcpy.c: Rename to __wmemcpy and make wmemcpy weak alias. * wcsmbs/wmemmove.c: Likewise for wmemmove. * manual/stdio.texi: Document is_char and wide element if printf_info. * manual/time.texi: Document wcsftime. * include/wchar.h: Add prototypes for __wmemcpy, __wmempcpy, __wmemmove, __wcschrnul, and __vfwscanf. * locale/langinfo.h: Add new LC_TIME entries for wchar_t data. * locale/C-time.c: Adapt for above change. * locale/categories.def: Likewise. * locale/localeinfo.h: Likewise. * localedata/Makefile: Don't run tests for now.
This commit is contained in:
@@ -25,11 +25,12 @@ headers := printf.h
|
||||
|
||||
routines := \
|
||||
ctermid cuserid \
|
||||
_itoa itoa-digits \
|
||||
_itoa _itowa itoa-digits itowa-digits \
|
||||
vfprintf vprintf printf_fp reg-printf printf-prs printf_fphex \
|
||||
printf_size fprintf printf snprintf sprintf asprintf dprintf \
|
||||
vfscanf \
|
||||
fscanf scanf sscanf \
|
||||
vfwprintf vfwscanf \
|
||||
perror psignal \
|
||||
tmpfile tmpfile64 tmpnam tmpnam_r tempnam tempname \
|
||||
getline getw putw \
|
||||
|
@@ -78,7 +78,7 @@ struct base_table_t
|
||||
|
||||
|
||||
/* Local variables. */
|
||||
static const struct base_table_t base_table[] =
|
||||
const struct base_table_t _itoa_base_table[] =
|
||||
{
|
||||
#if BITS_PER_MP_LIMB == 64
|
||||
/* 2 */ {SEL1(0ul) 1, 1},
|
||||
@@ -171,7 +171,7 @@ _itoa (value, buflim, base, upper_case)
|
||||
{
|
||||
const char *digits = upper_case ? _itoa_upper_digits : _itoa_lower_digits;
|
||||
char *bp = buflim;
|
||||
const struct base_table_t *brec = &base_table[base - 2];
|
||||
const struct base_table_t *brec = &_itoa_base_table[base - 2];
|
||||
|
||||
switch (base)
|
||||
{
|
||||
|
346
stdio-common/_itowa.c
Normal file
346
stdio-common/_itowa.c
Normal file
@@ -0,0 +1,346 @@
|
||||
/* Internal function for converting integers to ASCII.
|
||||
Copyright (C) 1994, 1995, 1996, 1999 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Torbjorn Granlund <tege@matematik.su.se>
|
||||
and Ulrich Drepper <drepper@gnu.org>.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include <gmp-mparam.h>
|
||||
#include <stdlib/gmp.h>
|
||||
#include <stdlib/gmp-impl.h>
|
||||
#include <stdlib/longlong.h>
|
||||
|
||||
#include "_itowa.h"
|
||||
|
||||
|
||||
/* Canonize environment. For some architectures not all values might
|
||||
be defined in the GMP header files. */
|
||||
#ifndef UMUL_TIME
|
||||
# define UMUL_TIME 1
|
||||
#endif
|
||||
#ifndef UDIV_TIME
|
||||
# define UDIV_TIME 3
|
||||
#endif
|
||||
|
||||
/* Control memory layout. */
|
||||
#ifdef PACK
|
||||
# undef PACK
|
||||
# define PACK __attribute__ ((packed))
|
||||
#else
|
||||
# define PACK
|
||||
#endif
|
||||
|
||||
|
||||
/* Declare local types. */
|
||||
struct base_table_t
|
||||
{
|
||||
#if (UDIV_TIME > 2 * UMUL_TIME)
|
||||
mp_limb_t base_multiplier;
|
||||
#endif
|
||||
char flag;
|
||||
char post_shift;
|
||||
#if BITS_PER_MP_LIMB == 32
|
||||
struct
|
||||
{
|
||||
char normalization_steps;
|
||||
char ndigits;
|
||||
mp_limb_t base PACK;
|
||||
#if UDIV_TIME > 2 * UMUL_TIME
|
||||
mp_limb_t base_ninv PACK;
|
||||
#endif
|
||||
} big;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* To reduce the memory needed we include some fields of the tables
|
||||
only conditionally. */
|
||||
#if UDIV_TIME > 2 * UMUL_TIME
|
||||
# define SEL1(X) X,
|
||||
# define SEL2(X) ,X
|
||||
#else
|
||||
# define SEL1(X)
|
||||
# define SEL2(X)
|
||||
#endif
|
||||
|
||||
/* Factor table for the different bases. */
|
||||
extern const struct base_table_t _itoa_base_table[];
|
||||
|
||||
/* Lower-case digits. */
|
||||
extern const wchar_t _itowa_lower_digits[];
|
||||
/* Upper-case digits. */
|
||||
extern const wchar_t _itowa_upper_digits[];
|
||||
|
||||
|
||||
wchar_t *
|
||||
_itowa (value, buflim, base, upper_case)
|
||||
unsigned long long int value;
|
||||
wchar_t *buflim;
|
||||
unsigned int base;
|
||||
int upper_case;
|
||||
{
|
||||
const wchar_t *digits = (upper_case
|
||||
? _itowa_upper_digits : _itowa_lower_digits);
|
||||
wchar_t *bp = buflim;
|
||||
const struct base_table_t *brec = &_itoa_base_table[base - 2];
|
||||
|
||||
switch (base)
|
||||
{
|
||||
#define RUN_2N(BITS) \
|
||||
do \
|
||||
{ \
|
||||
/* `unsigned long long int' always has 64 bits. */ \
|
||||
mp_limb_t work_hi = value >> (64 - BITS_PER_MP_LIMB); \
|
||||
\
|
||||
if (BITS_PER_MP_LIMB == 32) \
|
||||
{ \
|
||||
if (work_hi != 0) \
|
||||
{ \
|
||||
mp_limb_t work_lo; \
|
||||
int cnt; \
|
||||
\
|
||||
work_lo = value & 0xfffffffful; \
|
||||
for (cnt = BITS_PER_MP_LIMB / BITS; cnt > 0; --cnt) \
|
||||
{ \
|
||||
*--bp = digits[work_lo & ((1ul << BITS) - 1)]; \
|
||||
work_lo >>= BITS; \
|
||||
} \
|
||||
if (BITS_PER_MP_LIMB % BITS != 0) \
|
||||
{ \
|
||||
work_lo \
|
||||
|= ((work_hi \
|
||||
& ((1 << (BITS - BITS_PER_MP_LIMB%BITS)) \
|
||||
- 1)) \
|
||||
<< BITS_PER_MP_LIMB % BITS); \
|
||||
work_hi >>= BITS - BITS_PER_MP_LIMB % BITS; \
|
||||
if (work_hi == 0) \
|
||||
work_hi = work_lo; \
|
||||
else \
|
||||
*--bp = digits[work_lo]; \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
work_hi = value & 0xfffffffful; \
|
||||
} \
|
||||
do \
|
||||
{ \
|
||||
*--bp = digits[work_hi & ((1 << BITS) - 1)]; \
|
||||
work_hi >>= BITS; \
|
||||
} \
|
||||
while (work_hi != 0); \
|
||||
} \
|
||||
while (0)
|
||||
case 8:
|
||||
RUN_2N (3);
|
||||
break;
|
||||
|
||||
case 16:
|
||||
RUN_2N (4);
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
#if BITS_PER_MP_LIMB == 64
|
||||
mp_limb_t base_multiplier = brec->base_multiplier;
|
||||
if (brec->flag)
|
||||
while (value != 0)
|
||||
{
|
||||
mp_limb_t quo, rem, x, dummy;
|
||||
|
||||
umul_ppmm (x, dummy, value, base_multiplier);
|
||||
quo = (x + ((value - x) >> 1)) >> (brec->post_shift - 1);
|
||||
rem = value - quo * base;
|
||||
*--bp = digits[rem];
|
||||
value = quo;
|
||||
}
|
||||
else
|
||||
while (value != 0)
|
||||
{
|
||||
mp_limb_t quo, rem, x, dummy;
|
||||
|
||||
umul_ppmm (x, dummy, value, base_multiplier);
|
||||
quo = x >> brec->post_shift;
|
||||
rem = value - quo * base;
|
||||
*--bp = digits[rem];
|
||||
value = quo;
|
||||
}
|
||||
#endif
|
||||
#if BITS_PER_MP_LIMB == 32
|
||||
mp_limb_t t[3];
|
||||
int n;
|
||||
|
||||
/* First convert x0 to 1-3 words in base s->big.base.
|
||||
Optimize for frequent cases of 32 bit numbers. */
|
||||
if ((mp_limb_t) (value >> 32) >= 1)
|
||||
{
|
||||
#if UDIV_TIME > 2 * UMUL_TIME || UDIV_NEEDS_NORMALIZATION
|
||||
int big_normalization_steps = brec->big.normalization_steps;
|
||||
mp_limb_t big_base_norm
|
||||
= brec->big.base << big_normalization_steps;
|
||||
#endif
|
||||
if ((mp_limb_t) (value >> 32) >= brec->big.base)
|
||||
{
|
||||
mp_limb_t x1hi, x1lo, r;
|
||||
/* If you want to optimize this, take advantage of
|
||||
that the quotient in the first udiv_qrnnd will
|
||||
always be very small. It might be faster just to
|
||||
subtract in a tight loop. */
|
||||
|
||||
#if UDIV_TIME > 2 * UMUL_TIME
|
||||
mp_limb_t x, xh, xl;
|
||||
|
||||
if (big_normalization_steps == 0)
|
||||
xh = 0;
|
||||
else
|
||||
xh = (mp_limb_t) (value >> (64 - big_normalization_steps));
|
||||
xl = (mp_limb_t) (value >> (32 - big_normalization_steps));
|
||||
udiv_qrnnd_preinv (x1hi, r, xh, xl, big_base_norm,
|
||||
brec->big.base_ninv);
|
||||
|
||||
xl = ((mp_limb_t) value) << big_normalization_steps;
|
||||
udiv_qrnnd_preinv (x1lo, x, r, xl, big_base_norm,
|
||||
brec->big.base_ninv);
|
||||
t[2] = x >> big_normalization_steps;
|
||||
|
||||
if (big_normalization_steps == 0)
|
||||
xh = x1hi;
|
||||
else
|
||||
xh = ((x1hi << big_normalization_steps)
|
||||
| (x1lo >> (32 - big_normalization_steps)));
|
||||
xl = x1lo << big_normalization_steps;
|
||||
udiv_qrnnd_preinv (t[0], x, xh, xl, big_base_norm,
|
||||
brec->big.base_ninv);
|
||||
t[1] = x >> big_normalization_steps;
|
||||
#elif UDIV_NEEDS_NORMALIZATION
|
||||
mp_limb_t x, xh, xl;
|
||||
|
||||
if (big_normalization_steps == 0)
|
||||
xh = 0;
|
||||
else
|
||||
xh = (mp_limb_t) (value >> 64 - big_normalization_steps);
|
||||
xl = (mp_limb_t) (value >> 32 - big_normalization_steps);
|
||||
udiv_qrnnd (x1hi, r, xh, xl, big_base_norm);
|
||||
|
||||
xl = ((mp_limb_t) value) << big_normalization_steps;
|
||||
udiv_qrnnd (x1lo, x, r, xl, big_base_norm);
|
||||
t[2] = x >> big_normalization_steps;
|
||||
|
||||
if (big_normalization_steps == 0)
|
||||
xh = x1hi;
|
||||
else
|
||||
xh = ((x1hi << big_normalization_steps)
|
||||
| (x1lo >> 32 - big_normalization_steps));
|
||||
xl = x1lo << big_normalization_steps;
|
||||
udiv_qrnnd (t[0], x, xh, xl, big_base_norm);
|
||||
t[1] = x >> big_normalization_steps;
|
||||
#else
|
||||
udiv_qrnnd (x1hi, r, 0, (mp_limb_t) (value >> 32),
|
||||
brec->big.base);
|
||||
udiv_qrnnd (x1lo, t[2], r, (mp_limb_t) value, brec->big.base);
|
||||
udiv_qrnnd (t[0], t[1], x1hi, x1lo, brec->big.base);
|
||||
#endif
|
||||
n = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if (UDIV_TIME > 2 * UMUL_TIME)
|
||||
mp_limb_t x;
|
||||
|
||||
value <<= brec->big.normalization_steps;
|
||||
udiv_qrnnd_preinv (t[0], x, (mp_limb_t) (value >> 32),
|
||||
(mp_limb_t) value, big_base_norm,
|
||||
brec->big.base_ninv);
|
||||
t[1] = x >> brec->big.normalization_steps;
|
||||
#elif UDIV_NEEDS_NORMALIZATION
|
||||
mp_limb_t x;
|
||||
|
||||
value <<= big_normalization_steps;
|
||||
udiv_qrnnd (t[0], x, (mp_limb_t) (value >> 32),
|
||||
(mp_limb_t) value, big_base_norm);
|
||||
t[1] = x >> big_normalization_steps;
|
||||
#else
|
||||
udiv_qrnnd (t[0], t[1], (mp_limb_t) (value >> 32),
|
||||
(mp_limb_t) value, brec->big.base);
|
||||
#endif
|
||||
n = 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
t[0] = value;
|
||||
n = 1;
|
||||
}
|
||||
|
||||
/* Convert the 1-3 words in t[], word by word, to ASCII. */
|
||||
do
|
||||
{
|
||||
mp_limb_t ti = t[--n];
|
||||
int ndig_for_this_limb = 0;
|
||||
|
||||
#if UDIV_TIME > 2 * UMUL_TIME
|
||||
mp_limb_t base_multiplier = brec->base_multiplier;
|
||||
if (brec->flag)
|
||||
while (ti != 0)
|
||||
{
|
||||
mp_limb_t quo, rem, x, dummy;
|
||||
|
||||
umul_ppmm (x, dummy, ti, base_multiplier);
|
||||
quo = (x + ((ti - x) >> 1)) >> (brec->post_shift - 1);
|
||||
rem = ti - quo * base;
|
||||
*--bp = digits[rem];
|
||||
ti = quo;
|
||||
++ndig_for_this_limb;
|
||||
}
|
||||
else
|
||||
while (ti != 0)
|
||||
{
|
||||
mp_limb_t quo, rem, x, dummy;
|
||||
|
||||
umul_ppmm (x, dummy, ti, base_multiplier);
|
||||
quo = x >> brec->post_shift;
|
||||
rem = ti - quo * base;
|
||||
*--bp = digits[rem];
|
||||
ti = quo;
|
||||
++ndig_for_this_limb;
|
||||
}
|
||||
#else
|
||||
while (ti != 0)
|
||||
{
|
||||
mp_limb_t quo, rem;
|
||||
|
||||
quo = ti / base;
|
||||
rem = ti % base;
|
||||
*--bp = digits[rem];
|
||||
ti = quo;
|
||||
++ndig_for_this_limb;
|
||||
}
|
||||
#endif
|
||||
/* If this wasn't the most significant word, pad with zeros. */
|
||||
if (n != 0)
|
||||
while (ndig_for_this_limb < brec->big.ndigits)
|
||||
{
|
||||
*--bp = '0';
|
||||
++ndig_for_this_limb;
|
||||
}
|
||||
}
|
||||
while (n != 0);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return bp;
|
||||
}
|
63
stdio-common/_itowa.h
Normal file
63
stdio-common/_itowa.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/* Internal function for converting integers to ASCII.
|
||||
Copyright (C) 1994, 95, 96, 97, 98, 99 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef _ITOWA_H
|
||||
#define _ITOWA_H 1
|
||||
#include <features.h>
|
||||
#include <wchar.h>
|
||||
|
||||
/* Convert VALUE into ASCII in base BASE (2..36).
|
||||
Write backwards starting the character just before BUFLIM.
|
||||
Return the address of the first (left-to-right) character in the number.
|
||||
Use upper case letters iff UPPER_CASE is nonzero. */
|
||||
|
||||
extern wchar_t *_itowa __P ((unsigned long long int value, wchar_t *buflim,
|
||||
unsigned int base, int upper_case));
|
||||
|
||||
static inline wchar_t *
|
||||
__attribute__ ((unused))
|
||||
_itowa_word (unsigned long value, wchar_t *buflim,
|
||||
unsigned int base, int upper_case)
|
||||
{
|
||||
extern const wchar_t _itowa_upper_digits[], _itowa_lower_digits[];
|
||||
const wchar_t *digits = (upper_case
|
||||
? _itowa_upper_digits : _itowa_lower_digits);
|
||||
wchar_t *bp = buflim;
|
||||
|
||||
switch (base)
|
||||
{
|
||||
#define SPECIAL(Base) \
|
||||
case Base: \
|
||||
do \
|
||||
*--bp = digits[value % Base]; \
|
||||
while ((value /= Base) != 0); \
|
||||
break
|
||||
|
||||
SPECIAL (10);
|
||||
SPECIAL (16);
|
||||
SPECIAL (8);
|
||||
default:
|
||||
do
|
||||
*--bp = digits[value % base];
|
||||
while ((value /= base) != 0);
|
||||
}
|
||||
return bp;
|
||||
}
|
||||
|
||||
#endif /* itowa.h */
|
@@ -1,5 +1,5 @@
|
||||
/* Digits.
|
||||
Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
Copyright (C) 1994, 1995, 1996, 1999 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
@@ -18,9 +18,8 @@
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Lower-case digits. */
|
||||
const char _itoa_lower_digits[]
|
||||
const char _itoa_lower_digits[36]
|
||||
= "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
/* Upper-case digits. */
|
||||
const char _itoa_upper_digits[]
|
||||
const char _itoa_upper_digits[36]
|
||||
= "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
||||
|
27
stdio-common/itowa-digits.c
Normal file
27
stdio-common/itowa-digits.c
Normal file
@@ -0,0 +1,27 @@
|
||||
/* Digits.
|
||||
Copyright (C) 1994, 1995, 1996, 1999 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include <wchar.h>
|
||||
|
||||
/* Lower-case digits. */
|
||||
const wchar_t _itowa_lower_digits[36]
|
||||
= L"0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
/* Upper-case digits. */
|
||||
const wchar_t _itowa_upper_digits[36]
|
||||
= L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
@@ -35,7 +35,7 @@ struct printf_spec
|
||||
|
||||
/* Pointers into the format string for the end of this format
|
||||
spec and the next (or to the end of the string if no more). */
|
||||
const char *end_of_fmt, *next_fmt;
|
||||
const UCHAR_T *end_of_fmt, *next_fmt;
|
||||
|
||||
/* Position of arguments for precision and width, or -1 if `info' has
|
||||
the constant value. */
|
||||
@@ -90,21 +90,29 @@ read_int (const UCHAR_T * *pstr)
|
||||
|
||||
/* Find the next spec in FORMAT, or the end of the string. Returns
|
||||
a pointer into FORMAT, to a '%' or a '\0'. */
|
||||
static inline const char *
|
||||
find_spec (const char *format, mbstate_t *ps)
|
||||
static inline const UCHAR_T *
|
||||
#ifdef COMPILE_WPRINTF
|
||||
find_spec (const UCHAR_T *format)
|
||||
#else
|
||||
find_spec (const UCHAR_T *format, mbstate_t *ps)
|
||||
#endif
|
||||
{
|
||||
while (*format != '\0' && *format != '%')
|
||||
#ifdef COMPILE_WPRINTF
|
||||
return (const UCHAR_T *) __wcschrnul ((const CHAR_T *) format, L'%');
|
||||
#else
|
||||
while (*format != L_('\0') && *format != L_('%'))
|
||||
{
|
||||
int len;
|
||||
|
||||
/* Remove any hints of a wrong encoding. */
|
||||
ps->count = 0;
|
||||
if (isascii (*format) || (len = mbrlen (format, MB_CUR_MAX, ps)) <= 0)
|
||||
++format;
|
||||
else
|
||||
if (! ISASCII (*format) && (len = MBRLEN (format, MB_CUR_MAX, ps)) > 0)
|
||||
format += len;
|
||||
else
|
||||
++format;
|
||||
}
|
||||
return format;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -119,8 +127,13 @@ extern printf_function **__printf_function_table;
|
||||
the number of args consumed by this spec; *MAX_REF_ARG is updated so it
|
||||
remains the highest argument index used. */
|
||||
static inline size_t
|
||||
#ifdef COMPILE_WPRINTF
|
||||
parse_one_spec (const UCHAR_T *format, size_t posn, struct printf_spec *spec,
|
||||
size_t *max_ref_arg)
|
||||
#else
|
||||
parse_one_spec (const UCHAR_T *format, size_t posn, struct printf_spec *spec,
|
||||
size_t *max_ref_arg, mbstate_t *ps)
|
||||
#endif
|
||||
{
|
||||
unsigned int n;
|
||||
size_t nargs = 0;
|
||||
@@ -342,12 +355,12 @@ parse_one_spec (const UCHAR_T *format, size_t posn, struct printf_spec *spec,
|
||||
|
||||
switch (spec->info.spec)
|
||||
{
|
||||
case L'i':
|
||||
case L'd':
|
||||
case L'u':
|
||||
case L'o':
|
||||
case L'X':
|
||||
case L'x':
|
||||
case L_('i'):
|
||||
case L_('d'):
|
||||
case L_('u'):
|
||||
case L_('o'):
|
||||
case L_('X'):
|
||||
case L_('x'):
|
||||
#if LONG_MAX != LONG_LONG_MAX
|
||||
if (spec->info.is_long_double)
|
||||
spec->data_arg_type = PA_INT|PA_FLAG_LONG_LONG;
|
||||
@@ -362,38 +375,38 @@ parse_one_spec (const UCHAR_T *format, size_t posn, struct printf_spec *spec,
|
||||
else
|
||||
spec->data_arg_type = PA_INT;
|
||||
break;
|
||||
case L'e':
|
||||
case L'E':
|
||||
case L'f':
|
||||
case L'g':
|
||||
case L'G':
|
||||
case L'a':
|
||||
case L'A':
|
||||
case L_('e'):
|
||||
case L_('E'):
|
||||
case L_('f'):
|
||||
case L_('g'):
|
||||
case L_('G'):
|
||||
case L_('a'):
|
||||
case L_('A'):
|
||||
if (spec->info.is_long_double)
|
||||
spec->data_arg_type = PA_DOUBLE|PA_FLAG_LONG_DOUBLE;
|
||||
else
|
||||
spec->data_arg_type = PA_DOUBLE;
|
||||
break;
|
||||
case L'c':
|
||||
case L_('c'):
|
||||
spec->data_arg_type = PA_CHAR;
|
||||
break;
|
||||
case L'C':
|
||||
case L_('C'):
|
||||
spec->data_arg_type = PA_WCHAR;
|
||||
break;
|
||||
case L's':
|
||||
case L_('s'):
|
||||
spec->data_arg_type = PA_STRING;
|
||||
break;
|
||||
case L'S':
|
||||
case L_('S'):
|
||||
spec->data_arg_type = PA_WSTRING;
|
||||
break;
|
||||
case L'p':
|
||||
case L_('p'):
|
||||
spec->data_arg_type = PA_POINTER;
|
||||
break;
|
||||
case L'n':
|
||||
case L_('n'):
|
||||
spec->data_arg_type = PA_INT|PA_FLAG_PTR;
|
||||
break;
|
||||
|
||||
case L'm':
|
||||
case L_('m'):
|
||||
default:
|
||||
/* An unknown spec will consume no args. */
|
||||
spec->ndata_args = 0;
|
||||
@@ -416,7 +429,11 @@ parse_one_spec (const UCHAR_T *format, size_t posn, struct printf_spec *spec,
|
||||
{
|
||||
/* Find the next format spec. */
|
||||
spec->end_of_fmt = format;
|
||||
#ifdef COMPILE_WPRINTF
|
||||
spec->next_fmt = find_spec (format);
|
||||
#else
|
||||
spec->next_fmt = find_spec (format, ps);
|
||||
#endif
|
||||
}
|
||||
|
||||
return nargs;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1991, 1992, 1995, 1996 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1991, 1992, 1995, 1996, 1999 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
@@ -29,6 +29,8 @@
|
||||
# define INT_T int
|
||||
# define L_(Str) Str
|
||||
# define ISDIGIT(Ch) isdigit (Ch)
|
||||
# define ISASCII(Ch) isascii (Ch)
|
||||
# define MBRLEN(Cp, L, St) mbrlen (Cp, L, St)
|
||||
|
||||
# ifdef USE_IN_LIBIO
|
||||
# define PUT(F, S, N) _IO_sputn (F, S, N)
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1991, 92, 93, 95, 96, 97, 98 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1991,92,93,95,96,97,98,99 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
@@ -45,6 +45,7 @@ struct printf_info
|
||||
unsigned int group:1; /* ' flag. */
|
||||
unsigned int extra:1; /* For special use. */
|
||||
unsigned int is_char:1; /* hh flag. */
|
||||
unsigned int wide:1; /* Nonzero for wide character streams. */
|
||||
wchar_t pad; /* Padding character. */
|
||||
};
|
||||
|
||||
|
@@ -52,11 +52,12 @@
|
||||
the GNU I/O library. */
|
||||
#ifdef USE_IN_LIBIO
|
||||
# define PUT(f, s, n) _IO_sputn (f, s, n)
|
||||
# define PAD(f, c, n) _IO_padn (f, c, n)
|
||||
# define PAD(f, c, n) (wide ? _IO_wpadn (f, c, n) : _IO_padn (f, c, n))
|
||||
/* We use this file GNU C library and GNU I/O library. So make
|
||||
names equal. */
|
||||
# undef putc
|
||||
# define putc(c, f) _IO_putc_unlocked (c, f)
|
||||
# define putc(c, f) (wide \
|
||||
? _IO_putwc_unlocked (c, f) : _IO_putc_unlocked (c, f))
|
||||
# define size_t _IO_size_t
|
||||
# define FILE _IO_FILE
|
||||
#else /* ! USE_IN_LIBIO */
|
||||
@@ -188,6 +189,9 @@ __printf_fp (FILE *fp,
|
||||
/* General helper (carry limb). */
|
||||
mp_limb_t cy;
|
||||
|
||||
/* Nonzero if this is output on a wide character stream. */
|
||||
int wide = info->wide;
|
||||
|
||||
char hack_digit (void)
|
||||
{
|
||||
mp_limb_t hi;
|
||||
@@ -765,7 +769,10 @@ __printf_fp (FILE *fp,
|
||||
if ((expsign == 0 && exponent >= dig_max)
|
||||
|| (expsign != 0 && exponent > 4))
|
||||
{
|
||||
type = isupper (info->spec) ? 'E' : 'e';
|
||||
if ('g' - 'G' == 'e' - 'E')
|
||||
type = 'E' + (info->spec - 'G');
|
||||
else
|
||||
type = isupper (info->spec) ? 'E' : 'e';
|
||||
fracdig_max = dig_max - 1;
|
||||
intdig_max = 1;
|
||||
chars_needed = 1 + 1 + fracdig_max + 1 + 1 + 4;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/* Print size value using units for orders of magnitude.
|
||||
Copyright (C) 1997, 1998 Free Software Foundation, Inc.
|
||||
Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
|
||||
Based on a proposal by Larry McVoy <lm@sgi.com>.
|
||||
@@ -212,6 +212,7 @@ printf_size (FILE *fp, const struct printf_info *info, const void *const *args)
|
||||
fp_info.group = info->group;
|
||||
fp_info.extra = info->extra;
|
||||
fp_info.pad = info->pad;
|
||||
fp_info.wide = 0;
|
||||
|
||||
if (fp_info.left && fp_info.pad == L' ')
|
||||
{
|
||||
|
@@ -36,74 +36,16 @@
|
||||
Beside this it is also shared between the normal and wide character
|
||||
implementation as defined in ISO/IEC 9899:1990/Amendment 1:1995. */
|
||||
|
||||
#ifndef COMPILE_WPRINTF
|
||||
# define CHAR_T char
|
||||
# define UCHAR_T unsigned char
|
||||
# define INT_T int
|
||||
# define L_(Str) Str
|
||||
# define ISDIGIT(Ch) isdigit (Ch)
|
||||
|
||||
# ifdef USE_IN_LIBIO
|
||||
# define PUT(F, S, N) _IO_sputn ((F), (S), (N))
|
||||
# define PAD(Padchar) \
|
||||
if (width > 0) \
|
||||
done += _IO_padn (s, (Padchar), width)
|
||||
# else
|
||||
# define PUTC(C, F) putc (C, F)
|
||||
ssize_t __printf_pad __P ((FILE *, char pad, size_t n));
|
||||
# define PAD(Padchar) \
|
||||
if (width > 0) \
|
||||
{ ssize_t __res = __printf_pad (s, (Padchar), width); \
|
||||
if (__res == -1) \
|
||||
{ \
|
||||
done = -1; \
|
||||
goto all_done; \
|
||||
} \
|
||||
done += __res; }
|
||||
# endif
|
||||
#else
|
||||
# define vfprintf vfwprintf
|
||||
# define CHAR_T wchar_t
|
||||
# define UCHAR_T uwchar_t
|
||||
# define INT_T wint_t
|
||||
# define L_(Str) L##Str
|
||||
# define ISDIGIT(Ch) iswdigit (Ch)
|
||||
|
||||
# ifdef USE_IN_LIBIO
|
||||
# define PUT(F, S, N) _IO_sputn ((F), (S), (N))
|
||||
# define PAD(Padchar) \
|
||||
if (width > 0) \
|
||||
done += _IO_wpadn (s, (Padchar), width)
|
||||
# else
|
||||
# define PUTC(C, F) wputc (C, F)
|
||||
ssize_t __wprintf_pad __P ((FILE *, wchar_t pad, size_t n));
|
||||
# define PAD(Padchar) \
|
||||
if (width > 0) \
|
||||
{ ssize_t __res = __wprintf_pad (s, (Padchar), width); \
|
||||
if (__res == -1) \
|
||||
{ \
|
||||
done = -1; \
|
||||
goto all_done; \
|
||||
} \
|
||||
done += __res; }
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Include the shared code for parsing the format string. */
|
||||
#include "printf-parse.h"
|
||||
|
||||
|
||||
#ifdef USE_IN_LIBIO
|
||||
/* This code is for use in libio. */
|
||||
# include <libioP.h>
|
||||
# define PUTC(C, F) _IO_putc_unlocked (C, F)
|
||||
# define vfprintf _IO_vfprintf
|
||||
# define FILE _IO_FILE
|
||||
# undef va_list
|
||||
# define va_list _IO_va_list
|
||||
# undef BUFSIZ
|
||||
# undef BUFSIZ
|
||||
# define BUFSIZ _IO_BUFSIZ
|
||||
# define ARGCHECK(S, Format) \
|
||||
# define ARGCHECK(S, Format) \
|
||||
do \
|
||||
{ \
|
||||
/* Check file argument for consistence. */ \
|
||||
@@ -120,11 +62,54 @@ ssize_t __wprintf_pad __P ((FILE *, wchar_t pad, size_t n));
|
||||
} \
|
||||
} while (0)
|
||||
# define UNBUFFERED_P(S) ((S)->_IO_file_flags & _IO_UNBUFFERED)
|
||||
|
||||
# ifndef COMPILE_WPRINTF
|
||||
# define vfprintf _IO_vfprintf
|
||||
# define CHAR_T char
|
||||
# define UCHAR_T unsigned char
|
||||
# define INT_T int
|
||||
# define L_(Str) Str
|
||||
# define ISDIGIT(Ch) isdigit (Ch)
|
||||
# define ISASCII(Ch) isascii (Ch)
|
||||
# define MBRLEN(Cp, L, St) mbrlen (Cp, L, St)
|
||||
|
||||
# define PUT(F, S, N) _IO_sputn ((F), (S), (N))
|
||||
# define PAD(Padchar) \
|
||||
if (width > 0) \
|
||||
done += _IO_padn (s, (Padchar), width)
|
||||
# define PUTC(C, F) _IO_putc_unlocked (C, F)
|
||||
# define ORIENT if (_IO_fwide (s, -1) != -1) return -1
|
||||
# else
|
||||
# include "_itowa.h"
|
||||
|
||||
# define vfprintf _IO_vfwprintf
|
||||
# define CHAR_T wchar_t
|
||||
/* This is a hack!!! There should be a type uwchar_t. */
|
||||
# define UCHAR_T unsigned int /* uwchar_t */
|
||||
# define INT_T wint_t
|
||||
# define L_(Str) L##Str
|
||||
# define ISDIGIT(Ch) iswdigit (Ch)
|
||||
# define ISASCII(Ch) (((unsigned int) (Ch) & ~0x7f) == 0)
|
||||
# define MBRLEN(Cp, L, St) wcslen ((const wchar_t *) (Cp))
|
||||
|
||||
# define PUT(F, S, N) _IO_sputn ((F), (S), (N))
|
||||
# define PAD(Padchar) \
|
||||
if (width > 0) \
|
||||
done += _IO_wpadn (s, (Padchar), width)
|
||||
# define PUTC(C, F) _IO_putwc_unlocked (C, F)
|
||||
# define ORIENT if (_IO_fwide (s, 1) != 1) return -1
|
||||
|
||||
# define _itoa(Val, Buf, Base, Case) _itowa (Val, (wchar_t *) Buf, Base, Case)
|
||||
# define _itoa_word(Val, Buf, Base, Case) _itowa_word (Val, (wchar_t *) Buf, \
|
||||
Base, Case)
|
||||
# undef EOF
|
||||
# define EOF WEOF
|
||||
# endif
|
||||
#else /* ! USE_IN_LIBIO */
|
||||
/* This code is for use in the GNU C library. */
|
||||
# include <stdio.h>
|
||||
# define PUT(F, S, N) fwrite (S, 1, N, F)
|
||||
# define ARGCHECK(S, Format) \
|
||||
# define ARGCHECK(S, Format) \
|
||||
do \
|
||||
{ \
|
||||
/* Check file argument for consistence. */ \
|
||||
@@ -153,11 +138,14 @@ extern void __flockfile (FILE *);
|
||||
extern void __funlockfile (FILE *);
|
||||
#endif /* USE_IN_LIBIO */
|
||||
|
||||
/* Include the shared code for parsing the format string. */
|
||||
#include "printf-parse.h"
|
||||
|
||||
|
||||
#define outchar(Ch) \
|
||||
do \
|
||||
{ \
|
||||
register const int outc = (Ch); \
|
||||
register const INT_T outc = (Ch); \
|
||||
if (PUTC (outc, s) == EOF) \
|
||||
{ \
|
||||
done = -1; \
|
||||
@@ -199,7 +187,7 @@ extern void __funlockfile (FILE *);
|
||||
|
||||
|
||||
/* Global variables. */
|
||||
static const char null[] = "(null)";
|
||||
static const CHAR_T null[] = L_("(null)");
|
||||
|
||||
|
||||
/* Helper function to provide temporary buffering for unbuffered streams. */
|
||||
@@ -211,7 +199,8 @@ static int printf_unknown __P ((FILE *, const struct printf_info *,
|
||||
const void *const *));
|
||||
|
||||
/* Group digits of number string. */
|
||||
static char *group_number __P ((CHAR_T *, CHAR_T *, const CHAR_T *, wchar_t))
|
||||
static UCHAR_T *group_number __P ((UCHAR_T *, UCHAR_T *, const char *,
|
||||
wchar_t))
|
||||
internal_function;
|
||||
|
||||
|
||||
@@ -238,11 +227,13 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
const UCHAR_T *end_of_spec;
|
||||
|
||||
/* Buffer intermediate results. */
|
||||
char work_buffer[1000];
|
||||
char *workend;
|
||||
UCHAR_T work_buffer[1000];
|
||||
UCHAR_T *workend;
|
||||
|
||||
/* State for restartable multibyte character handling functions. */
|
||||
#ifndef COMPILE_WPRINTF
|
||||
mbstate_t mbstate;
|
||||
#endif
|
||||
|
||||
/* We have to save the original argument pointer. */
|
||||
va_list ap_save;
|
||||
@@ -505,7 +496,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
now process the wanted format specifier. */ \
|
||||
LABEL (form_percent): \
|
||||
/* Write a literal "%". */ \
|
||||
outchar ('%'); \
|
||||
outchar (L_('%')); \
|
||||
break; \
|
||||
\
|
||||
LABEL (form_integer): \
|
||||
@@ -588,7 +579,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
else \
|
||||
/* We have to take care for the '0' flag. If a precision \
|
||||
is given it must be ignored. */ \
|
||||
pad = ' '; \
|
||||
pad = L_(' '); \
|
||||
\
|
||||
/* If the precision is 0 and the number is 0 nothing has to \
|
||||
be written for the number, except for the 'o' format in \
|
||||
@@ -597,13 +588,13 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
{ \
|
||||
string = workend; \
|
||||
if (base == 8 && alt) \
|
||||
*string-- = '0'; \
|
||||
*string-- = L_('0'); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
/* Put the number in WORK. */ \
|
||||
string = _itoa (number.longlong, workend + 1, base, \
|
||||
spec == 'X'); \
|
||||
string = (UCHAR_T *) _itoa (number.longlong, workend + 1, base, \
|
||||
spec == L_('X')); \
|
||||
string -= 1; \
|
||||
if (group && grouping) \
|
||||
string = group_number (string, workend, grouping, \
|
||||
@@ -642,7 +633,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
else \
|
||||
/* We have to take care for the '0' flag. If a precision \
|
||||
is given it must be ignored. */ \
|
||||
pad = ' '; \
|
||||
pad = L_(' '); \
|
||||
\
|
||||
/* If the precision is 0 and the number is 0 nothing has to \
|
||||
be written for the number, except for the 'o' format in \
|
||||
@@ -651,13 +642,13 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
{ \
|
||||
string = workend; \
|
||||
if (base == 8 && alt) \
|
||||
*string-- = '0'; \
|
||||
*string-- = L_('0'); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
/* Put the number in WORK. */ \
|
||||
string = _itoa_word (number.word, workend + 1, base, \
|
||||
spec == 'X'); \
|
||||
string = (UCHAR_T *) _itoa_word (number.word, workend + 1, \
|
||||
base, spec == L_('X')); \
|
||||
string -= 1; \
|
||||
if (group && grouping) \
|
||||
string = group_number (string, workend, grouping, \
|
||||
@@ -670,10 +661,10 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
if (prec > 0) \
|
||||
/* Add zeros to the precision. */ \
|
||||
while (prec-- > 0) \
|
||||
*string-- = '0'; \
|
||||
*string-- = L_('0'); \
|
||||
else if (number.word != 0 && alt && base == 8) \
|
||||
/* Add octal marker. */ \
|
||||
*string-- = '0'; \
|
||||
*string-- = L_('0'); \
|
||||
\
|
||||
if (!left) \
|
||||
{ \
|
||||
@@ -686,41 +677,41 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
if (is_negative || showsign || space) \
|
||||
--width; \
|
||||
\
|
||||
if (pad == '0') \
|
||||
if (pad == L_('0')) \
|
||||
{ \
|
||||
while (width-- > 0) \
|
||||
*string-- = '0'; \
|
||||
*string-- = L_('0'); \
|
||||
\
|
||||
if (number.word != 0 && alt && base == 16) \
|
||||
{ \
|
||||
*string-- = spec; \
|
||||
*string-- = '0'; \
|
||||
*string-- = L_('0'); \
|
||||
} \
|
||||
\
|
||||
if (is_negative) \
|
||||
*string-- = '-'; \
|
||||
*string-- = L_('-'); \
|
||||
else if (showsign) \
|
||||
*string-- = '+'; \
|
||||
*string-- = L_('+'); \
|
||||
else if (space) \
|
||||
*string-- = ' '; \
|
||||
*string-- = L_(' '); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if (number.word != 0 && alt && base == 16) \
|
||||
{ \
|
||||
*string-- = spec; \
|
||||
*string-- = '0'; \
|
||||
*string-- = L_('0'); \
|
||||
} \
|
||||
\
|
||||
if (is_negative) \
|
||||
*string-- = '-'; \
|
||||
*string-- = L_('-'); \
|
||||
else if (showsign) \
|
||||
*string-- = '+'; \
|
||||
*string-- = L_('+'); \
|
||||
else if (space) \
|
||||
*string-- = ' '; \
|
||||
*string-- = L_(' '); \
|
||||
\
|
||||
while (width-- > 0) \
|
||||
*string-- = ' '; \
|
||||
*string-- = L_(' '); \
|
||||
} \
|
||||
\
|
||||
outstring (string + 1, workend - string); \
|
||||
@@ -732,20 +723,20 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
if (number.word != 0 && alt && base == 16) \
|
||||
{ \
|
||||
*string-- = spec; \
|
||||
*string-- = '0'; \
|
||||
*string-- = L_('0'); \
|
||||
} \
|
||||
\
|
||||
if (is_negative) \
|
||||
*string-- = '-'; \
|
||||
*string-- = L_('-'); \
|
||||
else if (showsign) \
|
||||
*string-- = '+'; \
|
||||
*string-- = L_('+'); \
|
||||
else if (space) \
|
||||
*string-- = ' '; \
|
||||
*string-- = L_(' '); \
|
||||
\
|
||||
width -= workend - string; \
|
||||
outstring (string + 1, workend - string); \
|
||||
\
|
||||
PAD (' '); \
|
||||
PAD (L_(' ')); \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
@@ -771,7 +762,8 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
showsign: showsign, \
|
||||
group: group, \
|
||||
pad: pad, \
|
||||
extra: 0 }; \
|
||||
extra: 0, \
|
||||
wide: sizeof (CHAR_T) != 1 }; \
|
||||
\
|
||||
if (is_long_double) \
|
||||
the_arg.pa_long_double = va_arg (ap, long double); \
|
||||
@@ -821,7 +813,8 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
showsign: showsign, \
|
||||
group: group, \
|
||||
pad: pad, \
|
||||
extra: 0 }; \
|
||||
extra: 0, \
|
||||
wide: sizeof (CHAR_T) != 1 }; \
|
||||
\
|
||||
if (is_long_double) \
|
||||
the_arg.pa_long_double = va_arg (ap, long double); \
|
||||
@@ -849,6 +842,178 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
} \
|
||||
break; \
|
||||
\
|
||||
LABEL (form_pointer): \
|
||||
/* Generic pointer. */ \
|
||||
{ \
|
||||
const void *ptr; \
|
||||
if (fspec == NULL) \
|
||||
ptr = va_arg (ap, void *); \
|
||||
else \
|
||||
ptr = args_value[fspec->data_arg].pa_pointer; \
|
||||
if (ptr != NULL) \
|
||||
{ \
|
||||
/* If the pointer is not NULL, write it as a %#x spec. */ \
|
||||
base = 16; \
|
||||
number.word = (unsigned long int) ptr; \
|
||||
is_negative = 0; \
|
||||
alt = 1; \
|
||||
group = 0; \
|
||||
spec = 'x'; \
|
||||
goto LABEL (number); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
/* Write "(nil)" for a nil pointer. */ \
|
||||
string = (UCHAR_T *) L_("(nil)"); \
|
||||
/* Make sure the full string "(nil)" is printed. */ \
|
||||
if (prec < 5) \
|
||||
prec = 5; \
|
||||
is_long = 0; /* This is no wide-char string. */ \
|
||||
goto LABEL (print_string); \
|
||||
} \
|
||||
} \
|
||||
/* NOTREACHED */ \
|
||||
\
|
||||
LABEL (form_number): \
|
||||
/* Answer the count of characters written. */ \
|
||||
if (fspec == NULL) \
|
||||
{ \
|
||||
if (is_longlong) \
|
||||
*(long long int *) va_arg (ap, void *) = done; \
|
||||
else if (is_long_num) \
|
||||
*(long int *) va_arg (ap, void *) = done; \
|
||||
else if (!is_short) \
|
||||
*(int *) va_arg (ap, void *) = done; \
|
||||
else \
|
||||
*(short int *) va_arg (ap, void *) = done; \
|
||||
} \
|
||||
else \
|
||||
if (is_longlong) \
|
||||
*(long long int *) args_value[fspec->data_arg].pa_pointer = done; \
|
||||
else if (is_long_num) \
|
||||
*(long int *) args_value[fspec->data_arg].pa_pointer = done; \
|
||||
else if (!is_short) \
|
||||
*(int *) args_value[fspec->data_arg].pa_pointer = done; \
|
||||
else \
|
||||
*(short int *) args_value[fspec->data_arg].pa_pointer = done; \
|
||||
break; \
|
||||
\
|
||||
LABEL (form_strerror): \
|
||||
/* Print description of error ERRNO. */ \
|
||||
string = \
|
||||
(UCHAR_T *) __strerror_r (save_errno, (char *) work_buffer, \
|
||||
sizeof work_buffer); \
|
||||
is_long = 0; /* This is no wide-char string. */ \
|
||||
goto LABEL (print_string)
|
||||
|
||||
#ifdef COMPILE_WPRINTF
|
||||
# define process_string_arg(fspec) \
|
||||
LABEL (form_character): \
|
||||
/* Character. */ \
|
||||
if (is_long) \
|
||||
goto LABEL (form_wcharacter); \
|
||||
--width; /* Account for the character itself. */ \
|
||||
if (!left) \
|
||||
PAD (L' '); \
|
||||
if (fspec == NULL) \
|
||||
outchar (btowc ((unsigned char) va_arg (ap, int))); /* Promoted. */ \
|
||||
else \
|
||||
outchar (btowc ((unsigned char) args_value[fspec->data_arg].pa_char));\
|
||||
if (left) \
|
||||
PAD (L' '); \
|
||||
break; \
|
||||
\
|
||||
LABEL (form_wcharacter): \
|
||||
{ \
|
||||
/* Wide character. */ \
|
||||
--width; \
|
||||
if (!left) \
|
||||
PAD (L' '); \
|
||||
if (fspec == NULL) \
|
||||
outchar (va_arg (ap, wint_t)); \
|
||||
else \
|
||||
outchar (args_value[fspec->data_arg].pa_wchar); \
|
||||
if (left) \
|
||||
PAD (L' '); \
|
||||
} \
|
||||
break; \
|
||||
\
|
||||
LABEL (form_string): \
|
||||
{ \
|
||||
size_t len; \
|
||||
\
|
||||
/* The string argument could in fact be `char *' or `wchar_t *'. \
|
||||
But this should not make a difference here. */ \
|
||||
if (fspec == NULL) \
|
||||
string = (UCHAR_T *) va_arg (ap, const wchar_t *); \
|
||||
else \
|
||||
string = (UCHAR_T *) args_value[fspec->data_arg].pa_wstring; \
|
||||
\
|
||||
/* Entry point for printing other strings. */ \
|
||||
LABEL (print_string): \
|
||||
\
|
||||
if (string == NULL) \
|
||||
{ \
|
||||
/* Write "(null)" if there's space. */ \
|
||||
if (prec == -1 \
|
||||
|| prec >= (int) (sizeof (null) / sizeof (null[0])) - 1) \
|
||||
{ \
|
||||
string = (UCHAR_T *) null; \
|
||||
len = (sizeof (null) / sizeof (null[0])) - 1; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
string = (UCHAR_T *) L""; \
|
||||
len = 0; \
|
||||
} \
|
||||
} \
|
||||
else if (!is_long && spec != L_('S')) \
|
||||
{ \
|
||||
/* This is complicated. We have to transform the multibyte \
|
||||
string into a wide character string. */ \
|
||||
const char *mbs = (const char *) string; \
|
||||
mbstate_t mbstate; \
|
||||
\
|
||||
len = prec == -1 ? strnlen (mbs, prec) : strlen (mbs); \
|
||||
\
|
||||
/* Allocate dynamically an array which definitely is long \
|
||||
enough for the wide character version. */ \
|
||||
string = (UCHAR_T *) alloca ((len + 1) * sizeof (wchar_t)); \
|
||||
\
|
||||
memset (&mbstate, '\0', sizeof (mbstate_t)); \
|
||||
len = __mbsrtowcs ((wchar_t *) string, &mbs, len + 1, &mbstate); \
|
||||
if (len == (size_t) -1) \
|
||||
{ \
|
||||
/* Illegal multibyte character. */ \
|
||||
done = -1; \
|
||||
goto all_done; \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if (prec != -1) \
|
||||
/* Search for the end of the string, but don't search past \
|
||||
the length specified by the precision. */ \
|
||||
len = __wcsnlen ((wchar_t *) string, prec); \
|
||||
else \
|
||||
len = __wcslen ((wchar_t *) string); \
|
||||
} \
|
||||
\
|
||||
if ((width -= len) < 0) \
|
||||
{ \
|
||||
outstring (string, len); \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
if (!left) \
|
||||
PAD (L' '); \
|
||||
outstring (string, len); \
|
||||
if (left) \
|
||||
PAD (L' '); \
|
||||
} \
|
||||
break;
|
||||
#else
|
||||
# define process_string_arg(fspec) \
|
||||
LABEL (form_character): \
|
||||
/* Character. */ \
|
||||
if (is_long) \
|
||||
@@ -917,7 +1082,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
if (prec != -1) \
|
||||
/* Search for the end of the string, but don't search past \
|
||||
the length specified by the precision. */ \
|
||||
len = strnlen (string, prec); \
|
||||
len = __strnlen (string, prec); \
|
||||
else \
|
||||
len = strlen (string); \
|
||||
} \
|
||||
@@ -939,7 +1104,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
s2 = (const wchar_t *) string; \
|
||||
string = alloca (len + 1); \
|
||||
(void) __wcsrtombs (string, &s2, len + 1, &mbstate); \
|
||||
if (prec < len) \
|
||||
if (prec > 0 && prec < len) \
|
||||
len = prec; \
|
||||
} \
|
||||
\
|
||||
@@ -955,75 +1120,23 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
if (left) \
|
||||
PAD (' '); \
|
||||
} \
|
||||
break; \
|
||||
\
|
||||
LABEL (form_pointer): \
|
||||
/* Generic pointer. */ \
|
||||
{ \
|
||||
const void *ptr; \
|
||||
if (fspec == NULL) \
|
||||
ptr = va_arg (ap, void *); \
|
||||
else \
|
||||
ptr = args_value[fspec->data_arg].pa_pointer; \
|
||||
if (ptr != NULL) \
|
||||
{ \
|
||||
/* If the pointer is not NULL, write it as a %#x spec. */ \
|
||||
base = 16; \
|
||||
number.word = (unsigned long int) ptr; \
|
||||
is_negative = 0; \
|
||||
alt = 1; \
|
||||
group = 0; \
|
||||
spec = 'x'; \
|
||||
goto LABEL (number); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
/* Write "(nil)" for a nil pointer. */ \
|
||||
string = (char *) "(nil)"; \
|
||||
/* Make sure the full string "(nil)" is printed. */ \
|
||||
if (prec < 5) \
|
||||
prec = 5; \
|
||||
is_long = 0; /* This is no wide-char string. */ \
|
||||
goto LABEL (print_string); \
|
||||
} \
|
||||
} \
|
||||
/* NOTREACHED */ \
|
||||
\
|
||||
LABEL (form_number): \
|
||||
/* Answer the count of characters written. */ \
|
||||
if (fspec == NULL) \
|
||||
{ \
|
||||
if (is_longlong) \
|
||||
*(long long int *) va_arg (ap, void *) = done; \
|
||||
else if (is_long_num) \
|
||||
*(long int *) va_arg (ap, void *) = done; \
|
||||
else if (!is_short) \
|
||||
*(int *) va_arg (ap, void *) = done; \
|
||||
else \
|
||||
*(short int *) va_arg (ap, void *) = done; \
|
||||
} \
|
||||
else \
|
||||
if (is_longlong) \
|
||||
*(long long int *) args_value[fspec->data_arg].pa_pointer = done; \
|
||||
else if (is_long_num) \
|
||||
*(long int *) args_value[fspec->data_arg].pa_pointer = done; \
|
||||
else if (!is_short) \
|
||||
*(int *) args_value[fspec->data_arg].pa_pointer = done; \
|
||||
else \
|
||||
*(short int *) args_value[fspec->data_arg].pa_pointer = done; \
|
||||
break; \
|
||||
\
|
||||
LABEL (form_strerror): \
|
||||
/* Print description of error ERRNO. */ \
|
||||
string = \
|
||||
(char *) __strerror_r (save_errno, work_buffer, sizeof work_buffer); \
|
||||
is_long = 0; /* This is no wide-char string. */ \
|
||||
goto LABEL (print_string)
|
||||
break;
|
||||
#endif
|
||||
|
||||
/* Orient the stream. */
|
||||
#ifdef ORIENT
|
||||
ORIENT;
|
||||
#endif
|
||||
|
||||
/* Sanity check of arguments. */
|
||||
ARGCHECK (s, format);
|
||||
|
||||
/* Check for correct orientation. */
|
||||
if (_IO_fwide (s, sizeof (CHAR_T) == 1 ? -1 : 1)
|
||||
!= (sizeof (CHAR_T) == 1 ? -1 : 1))
|
||||
/* The stream is already oriented otherwise. */
|
||||
return EOF;
|
||||
|
||||
if (UNBUFFERED_P (s))
|
||||
/* Use a helper function which will allocate a local temporary buffer
|
||||
for the stream and then call us again. */
|
||||
@@ -1041,11 +1154,16 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
#endif
|
||||
nspecs_done = 0;
|
||||
|
||||
#ifdef COMPILE_WPRINTF
|
||||
/* Find the first format specifier. */
|
||||
f = lead_str_end = find_spec ((const UCHAR_T *) format);
|
||||
#else
|
||||
/* Put state for processing format string in initial state. */
|
||||
memset (&mbstate, '\0', sizeof (mbstate_t));
|
||||
|
||||
/* Find the first format specifier. */
|
||||
f = lead_str_end = find_spec (format, &mbstate);
|
||||
#endif
|
||||
|
||||
/* Lock stream. */
|
||||
#ifdef USE_IN_LIBIO
|
||||
@@ -1081,7 +1199,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
} number;
|
||||
int base;
|
||||
union printf_arg the_arg;
|
||||
char *string; /* Pointer to argument string. */
|
||||
UCHAR_T *string; /* Pointer to argument string. */
|
||||
int alt = 0; /* Alternate format. */
|
||||
int space = 0; /* Use space prefix if no sign is needed. */
|
||||
int left = 0; /* Left-justify output. */
|
||||
@@ -1093,10 +1211,10 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
int is_char = 0; /* Argument is promoted (unsigned) char. */
|
||||
int width = 0; /* Width of output; 0 means none specified. */
|
||||
int prec = -1; /* Precision of output; -1 means none specified. */
|
||||
char pad = ' '; /* Padding character. */
|
||||
UCHAR_T pad = L_(' ');/* Padding character. */
|
||||
CHAR_T spec;
|
||||
|
||||
workend = &work_buffer[sizeof (work_buffer) - 1];
|
||||
workend = &work_buffer[sizeof (work_buffer) / sizeof (CHAR_T) - 1];
|
||||
|
||||
/* Get current character in format string. */
|
||||
JUMP (*++f, step0_jumps);
|
||||
@@ -1172,10 +1290,11 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
left = 1;
|
||||
}
|
||||
|
||||
if (width + 32 >= sizeof (work_buffer))
|
||||
if (width + 32 >= sizeof (work_buffer) / sizeof (work_buffer[0]))
|
||||
/* We have to use a special buffer. The "32" is just a safe
|
||||
bet for all the output which is not counted in the width. */
|
||||
workend = alloca (width + 32) + (width + 31);
|
||||
workend = ((UCHAR_T *) alloca ((width + 32) * sizeof (CHAR_T))
|
||||
+ (width + 31));
|
||||
}
|
||||
JUMP (*f, step1_jumps);
|
||||
|
||||
@@ -1183,10 +1302,11 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
LABEL (width):
|
||||
width = read_int (&f);
|
||||
|
||||
if (width + 32 >= sizeof (work_buffer))
|
||||
if (width + 32 >= sizeof (work_buffer) / sizeof (work_buffer[0]))
|
||||
/* We have to use a special buffer. The "32" is just a safe
|
||||
bet for all the output which is not counted in the width. */
|
||||
workend = alloca (width + 32) + (width + 31);
|
||||
workend = ((UCHAR_T *) alloca ((width + 32) * sizeof (CHAR_T))
|
||||
+ (width + 31));
|
||||
if (*f == L_('$'))
|
||||
/* Oh, oh. The argument comes from a positional parameter. */
|
||||
goto do_positional;
|
||||
@@ -1213,7 +1333,8 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
prec = read_int (&f);
|
||||
else
|
||||
prec = 0;
|
||||
if (prec > width && prec + 32 > sizeof (work_buffer))
|
||||
if (prec > width
|
||||
&& prec + 32 > sizeof (work_buffer) / sizeof (work_buffer[0]))
|
||||
workend = alloca (spec + 32) + (spec + 31);
|
||||
JUMP (*f, step2_jumps);
|
||||
|
||||
@@ -1258,6 +1379,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
while (1)
|
||||
{
|
||||
process_arg (((struct printf_spec *) NULL));
|
||||
process_string_arg (((struct printf_spec *) NULL));
|
||||
|
||||
LABEL (form_unknown):
|
||||
if (spec == L_('\0'))
|
||||
@@ -1276,7 +1398,11 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
++nspecs_done;
|
||||
|
||||
/* Look for next format specifier. */
|
||||
#ifdef COMPILE_WPRINTF
|
||||
f = find_spec ((end_of_spec = ++f));
|
||||
#else
|
||||
f = find_spec ((end_of_spec = ++f), &mbstate);
|
||||
#endif
|
||||
|
||||
/* Write the following constant string. */
|
||||
outstring (end_of_spec, f - end_of_spec);
|
||||
@@ -1301,7 +1427,7 @@ do_positional:
|
||||
attributes. */
|
||||
size_t nargs = 0;
|
||||
int *args_type;
|
||||
union printf_arg *args_value;
|
||||
union printf_arg *args_value = NULL;
|
||||
|
||||
/* Positional parameters refer to arguments directly. This could
|
||||
also determine the maximum number of arguments. Track the
|
||||
@@ -1329,7 +1455,7 @@ do_positional:
|
||||
grouping = NULL;
|
||||
}
|
||||
|
||||
for (f = lead_str_end; *f != '\0'; f = specs[nspecs++].next_fmt)
|
||||
for (f = lead_str_end; *f != L_('\0'); f = specs[nspecs++].next_fmt)
|
||||
{
|
||||
if (nspecs >= nspecs_max)
|
||||
{
|
||||
@@ -1356,8 +1482,12 @@ do_positional:
|
||||
}
|
||||
|
||||
/* Parse the format specifier. */
|
||||
#ifdef COMPILE_WPRINTF
|
||||
nargs += parse_one_spec (f, nargs, &specs[nspecs], &max_ref_arg);
|
||||
#else
|
||||
nargs += parse_one_spec (f, nargs, &specs[nspecs], &max_ref_arg,
|
||||
&mbstate);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Determine the number of arguments the format string consumes. */
|
||||
@@ -1449,7 +1579,7 @@ do_positional:
|
||||
} number;
|
||||
int base;
|
||||
union printf_arg the_arg;
|
||||
char *string; /* Pointer to argument string. */
|
||||
UCHAR_T *string; /* Pointer to argument string. */
|
||||
|
||||
/* Fill variables from values in struct. */
|
||||
int alt = specs[nspecs_done].info.alt;
|
||||
@@ -1498,8 +1628,10 @@ do_positional:
|
||||
}
|
||||
|
||||
/* Maybe the buffer is too small. */
|
||||
if (MAX (prec, width) + 32 > sizeof (work_buffer))
|
||||
workend = alloca (MAX (prec, width) + 32) + (MAX (prec, width) + 31);
|
||||
if (MAX (prec, width) + 32 > sizeof (work_buffer) / sizeof (UCHAR_T))
|
||||
workend = ((UCHAR_T *) alloca ((MAX (prec, width) + 32)
|
||||
* sizeof (UCHAR_T))
|
||||
+ (MAX (prec, width) + 31));
|
||||
|
||||
/* Process format specifiers. */
|
||||
while (1)
|
||||
@@ -1507,6 +1639,7 @@ do_positional:
|
||||
JUMP (spec, step4_jumps);
|
||||
|
||||
process_arg ((&specs[nspecs_done]));
|
||||
process_string_arg ((&specs[nspecs_done]));
|
||||
|
||||
LABEL (form_unknown):
|
||||
{
|
||||
@@ -1564,21 +1697,6 @@ all_done:
|
||||
|
||||
return done;
|
||||
}
|
||||
|
||||
#ifdef USE_IN_LIBIO
|
||||
# undef vfprintf
|
||||
# ifdef strong_alias
|
||||
/* This is for glibc. */
|
||||
strong_alias (_IO_vfprintf, vfprintf);
|
||||
# else
|
||||
# if defined __ELF__ || defined __GNU_LIBRARY__
|
||||
# include <gnu-stabs.h>
|
||||
# ifdef weak_alias
|
||||
weak_alias (_IO_vfprintf, vfprintf);
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Handle an unknown format specifier. This prints out a canonicalized
|
||||
representation of the format spec itself. */
|
||||
@@ -1588,24 +1706,25 @@ printf_unknown (FILE *s, const struct printf_info *info,
|
||||
|
||||
{
|
||||
int done = 0;
|
||||
char work_buffer[MAX (info->width, info->spec) + 32];
|
||||
char *const workend = &work_buffer[sizeof (work_buffer) - 1];
|
||||
register char *w;
|
||||
CHAR_T work_buffer[MAX (info->width, info->spec) + 32];
|
||||
CHAR_T *const workend = &work_buffer[sizeof (work_buffer) / sizeof (CHAR_T)
|
||||
- 1];
|
||||
register CHAR_T *w;
|
||||
|
||||
outchar ('%');
|
||||
outchar (L_('%'));
|
||||
|
||||
if (info->alt)
|
||||
outchar ('#');
|
||||
outchar (L_('#'));
|
||||
if (info->group)
|
||||
outchar ('\'');
|
||||
outchar (L_('\''));
|
||||
if (info->showsign)
|
||||
outchar ('+');
|
||||
outchar (L_('+'));
|
||||
else if (info->space)
|
||||
outchar (' ');
|
||||
outchar (L_(' '));
|
||||
if (info->left)
|
||||
outchar ('-');
|
||||
outchar (L_('-'));
|
||||
if (info->pad == '0')
|
||||
outchar ('0');
|
||||
outchar (L_('0'));
|
||||
|
||||
if (info->width != 0)
|
||||
{
|
||||
@@ -1622,7 +1741,7 @@ printf_unknown (FILE *s, const struct printf_info *info,
|
||||
outchar (*w++);
|
||||
}
|
||||
|
||||
if (info->spec != '\0')
|
||||
if (info->spec != L_('\0'))
|
||||
outchar (info->spec);
|
||||
|
||||
all_done:
|
||||
@@ -1631,13 +1750,13 @@ printf_unknown (FILE *s, const struct printf_info *info,
|
||||
|
||||
/* Group the digits according to the grouping rules of the current locale.
|
||||
The interpretation of GROUPING is as in `struct lconv' from <locale.h>. */
|
||||
static char *
|
||||
static UCHAR_T *
|
||||
internal_function
|
||||
group_number (CHAR_T *w, CHAR_T *rear_ptr, const CHAR_T *grouping,
|
||||
group_number (UCHAR_T *w, UCHAR_T *rear_ptr, const char *grouping,
|
||||
wchar_t thousands_sep)
|
||||
{
|
||||
int len;
|
||||
char *src, *s;
|
||||
UCHAR_T *src, *s;
|
||||
|
||||
/* We treat all negative values like CHAR_MAX. */
|
||||
|
||||
@@ -1648,8 +1767,9 @@ group_number (CHAR_T *w, CHAR_T *rear_ptr, const CHAR_T *grouping,
|
||||
len = *grouping;
|
||||
|
||||
/* Copy existing string so that nothing gets overwritten. */
|
||||
src = (char *) alloca (rear_ptr - w);
|
||||
s = (char *) __mempcpy (src, w + 1, rear_ptr - w) - 1;
|
||||
src = (UCHAR_T *) alloca ((rear_ptr - w) * sizeof (UCHAR_T));
|
||||
s = (UCHAR_T *) __mempcpy (src, w + 1,
|
||||
(rear_ptr - w) * sizeof (UCHAR_T)) - 1;
|
||||
w = rear_ptr;
|
||||
|
||||
/* Process all characters in the string. */
|
||||
@@ -1699,12 +1819,22 @@ static int
|
||||
_IO_helper_overflow (_IO_FILE *s, int c)
|
||||
{
|
||||
_IO_FILE *target = ((struct helper_file*) s)->_put_stream;
|
||||
#ifdef COMPILE_WPRINTF
|
||||
int used = s->_wide_data->_IO_write_ptr - s->_wide_data->_IO_write_base;
|
||||
if (used)
|
||||
{
|
||||
_IO_size_t written = _IO_sputn (target, s->_wide_data->_IO_write_base,
|
||||
used);
|
||||
s->_wide_data->_IO_write_ptr -= written;
|
||||
}
|
||||
#else
|
||||
int used = s->_IO_write_ptr - s->_IO_write_base;
|
||||
if (used)
|
||||
{
|
||||
_IO_size_t written = _IO_sputn (target, s->_IO_write_base, used);
|
||||
s->_IO_write_ptr -= written;
|
||||
}
|
||||
#endif
|
||||
return PUTC (c, s);
|
||||
}
|
||||
|
||||
@@ -1735,16 +1865,18 @@ internal_function
|
||||
buffered_vfprintf (register _IO_FILE *s, const CHAR_T *format,
|
||||
_IO_va_list args)
|
||||
{
|
||||
char buf[_IO_BUFSIZ];
|
||||
CHAR_T buf[_IO_BUFSIZ];
|
||||
struct helper_file helper;
|
||||
register _IO_FILE *hp = (_IO_FILE *) &helper;
|
||||
int result, to_flush;
|
||||
|
||||
/* Initialize helper. */
|
||||
helper._put_stream = s;
|
||||
hp->_IO_write_base = buf;
|
||||
hp->_IO_write_ptr = buf;
|
||||
hp->_IO_write_end = buf + sizeof buf;
|
||||
#ifdef COMPILE_WPRINTF
|
||||
_IO_wsetp (hp, buf, buf + sizeof buf / sizeof (CHAR_T));
|
||||
#else
|
||||
_IO_setp (hp, buf, buf + sizeof buf);
|
||||
#endif
|
||||
hp->_IO_file_flags = _IO_MAGIC|_IO_NO_READS;
|
||||
#if _IO_JUMPS_OFFSET
|
||||
hp->_vtable_offset = 0;
|
||||
@@ -1756,14 +1888,24 @@ buffered_vfprintf (register _IO_FILE *s, const CHAR_T *format,
|
||||
_IO_JUMPS (hp) = (struct _IO_jump_t *) &_IO_helper_jumps;
|
||||
|
||||
/* Now print to helper instead. */
|
||||
result = _IO_vfprintf (hp, format, args);
|
||||
result = vfprintf (hp, format, args);
|
||||
|
||||
/* Now flush anything from the helper to the S. */
|
||||
#ifdef COMPILE_WPRINTF
|
||||
if ((to_flush = (hp->_wide_data->_IO_write_ptr
|
||||
- hp->_wide_data->_IO_write_base)) > 0)
|
||||
{
|
||||
if ((int) _IO_sputn (s, hp->_wide_data->_IO_write_base, to_flush)
|
||||
!= to_flush)
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
if ((to_flush = hp->_IO_write_ptr - hp->_IO_write_base) > 0)
|
||||
{
|
||||
if ((int) _IO_sputn (s, hp->_IO_write_base, to_flush) != to_flush)
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1826,3 +1968,26 @@ __wprintf_pad (FILE *s, wchar_t pad, size_t count)
|
||||
}
|
||||
#undef PADSIZE
|
||||
#endif /* USE_IN_LIBIO */
|
||||
|
||||
#ifdef USE_IN_LIBIO
|
||||
# undef vfprintf
|
||||
# ifdef strong_alias
|
||||
/* This is for glibc. */
|
||||
# ifdef COMPILE_WPRINTF
|
||||
strong_alias (_IO_vfwprintf, vfwprintf);
|
||||
# else
|
||||
strong_alias (_IO_vfprintf, vfprintf);
|
||||
# endif
|
||||
# else
|
||||
# if defined __ELF__ || defined __GNU_LIBRARY__
|
||||
# include <gnu-stabs.h>
|
||||
# ifdef weak_alias
|
||||
# ifdef COMPILE_WPRINTF
|
||||
weak_alias (_IO_vfwprintf, vfwprintf);
|
||||
# else
|
||||
weak_alias (_IO_vfprintf, vfprintf);
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
3
stdio-common/vfwprintf.c
Normal file
3
stdio-common/vfwprintf.c
Normal file
@@ -0,0 +1,3 @@
|
||||
#include <wctype.h>
|
||||
#define COMPILE_WPRINTF 1
|
||||
#include "vfprintf.c"
|
2
stdio-common/vfwscanf.c
Normal file
2
stdio-common/vfwscanf.c
Normal file
@@ -0,0 +1,2 @@
|
||||
#define COMPILE_WPRINTF 1
|
||||
#include "vfscanf.c"
|
Reference in New Issue
Block a user