235 lines
9.0 KiB
C
235 lines
9.0 KiB
C
/*
|
|
* Copyright (c) 1990 The Regents of the University of California.
|
|
* All rights reserved.
|
|
*
|
|
* This code is derived from software contributed to Berkeley by
|
|
* Chris Torek.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. Neither the name of the University nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
* SUCH DAMAGE.
|
|
*/
|
|
|
|
/*
|
|
* Copyright (c) 2012-2014 ARM Ltd
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. The name of the company may not be used to endorse or promote
|
|
* products derived from this software without specific prior written
|
|
* permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
* IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#ifndef VFPRINTF_LOCAL
|
|
#define VFPRINTF_LOCAL
|
|
|
|
#ifndef NO_FLOATING_POINT
|
|
# define FLOATING_POINT
|
|
#endif
|
|
|
|
#define _NO_POS_ARGS
|
|
#undef _WANT_IO_C99_FORMATS
|
|
|
|
/* Currently a test is made to see if long double processing is warranted.
|
|
This could be changed in the future should the _ldtoa_r code be
|
|
preferred over _dtoa_r. */
|
|
#define _NO_LONGDBL
|
|
|
|
#define _NO_LONGLONG
|
|
|
|
#define _PRINTF_FLOAT_TYPE double
|
|
|
|
#if defined (FLOATING_POINT)
|
|
# include <locale.h>
|
|
#endif
|
|
#ifdef FLOATING_POINT
|
|
# include <math.h>
|
|
|
|
/* For %La, an exponent of 15 bits occupies the exponent character,
|
|
a sign, and up to 5 digits. */
|
|
# define MAXEXPLEN 7
|
|
# define DEFPREC 6
|
|
|
|
extern char *_dtoa_r _PARAMS((struct _reent *, double, int,
|
|
int, int *, int *, char **));
|
|
|
|
# define _DTOA_R _dtoa_r
|
|
# define FREXP frexp
|
|
|
|
#endif /* FLOATING_POINT. */
|
|
|
|
/* BUF must be big enough for the maximum %#llo (assuming long long is
|
|
at most 64 bits, this would be 23 characters), the maximum
|
|
multibyte character %C, and the maximum default precision of %La
|
|
(assuming long double is at most 128 bits with 113 bits of
|
|
mantissa, this would be 29 characters). %e, %f, and %g use
|
|
reentrant storage shared with mprec. All other formats that use
|
|
buf get by with fewer characters. Making BUF slightly bigger
|
|
reduces the need for malloc in %.*a and %S, when large precision or
|
|
long strings are processed.
|
|
The bigger size of 100 bytes is used on systems which allow number
|
|
strings using the locale's grouping character. Since that's a multibyte
|
|
value, we should use a conservative value. */
|
|
#define BUF 40
|
|
|
|
#define quad_t long
|
|
#define u_quad_t unsigned long
|
|
|
|
typedef quad_t * quad_ptr_t;
|
|
typedef _PTR void_ptr_t;
|
|
typedef char * char_ptr_t;
|
|
typedef long * long_ptr_t;
|
|
typedef int * int_ptr_t;
|
|
typedef short * short_ptr_t;
|
|
|
|
/* Macros for converting digits to letters and vice versa. */
|
|
#define to_digit(c) ((c) - '0')
|
|
#define is_digit(c) ((unsigned)to_digit (c) <= 9)
|
|
#define to_char(n) ((n) + '0')
|
|
|
|
/* Flags used during conversion. */
|
|
#define ALT 0x001 /* Alternate form. */
|
|
#define LADJUST 0x002 /* Left adjustment. */
|
|
#define ZEROPAD 0x004 /* Zero (as opposed to blank) pad. */
|
|
#define PLUSSGN 0x008 /* Plus sign flag. */
|
|
#define SPACESGN 0x010 /* Space flag. */
|
|
#define HEXPREFIX 0x020 /* Add 0x or 0X prefix. */
|
|
#define SHORTINT 0x040 /* Short integer. */
|
|
#define LONGINT 0x080 /* Long integer. */
|
|
#define LONGDBL 0x100 /* Long double. */
|
|
/* 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 FPT 0x400 /* Floating point number. */
|
|
/* Define as 0, to make SARG and UARG occupy fewer instructions. */
|
|
# define CHARINT 0
|
|
|
|
/* Macros to support positional arguments. */
|
|
#define GET_ARG(n, ap, type) (va_arg ((ap), type))
|
|
|
|
/* To extend shorts properly, we need both signed and unsigned
|
|
argument extraction methods. Also they should be used in nano-vfprintf_i.c
|
|
and nano-vfprintf_float.c only, since ap is a pointer to va_list. */
|
|
#define SARG(flags) \
|
|
(flags&LONGINT ? GET_ARG (N, (*ap), long) : \
|
|
flags&SHORTINT ? (long)(short)GET_ARG (N, (*ap), int) : \
|
|
flags&CHARINT ? (long)(signed char)GET_ARG (N, (*ap), int) : \
|
|
(long)GET_ARG (N, (*ap), int))
|
|
#define UARG(flags) \
|
|
(flags&LONGINT ? GET_ARG (N, (*ap), u_long) : \
|
|
flags&SHORTINT ? (u_long)(u_short)GET_ARG (N, (*ap), int) : \
|
|
flags&CHARINT ? (u_long)(unsigned char)GET_ARG (N, (*ap), int) : \
|
|
(u_long)GET_ARG (N, (*ap), u_int))
|
|
|
|
/* BEWARE, these `goto error' on error. And they are used
|
|
in more than one functions.
|
|
|
|
Following macros are each referred about twice in printf for integer,
|
|
so it is not worth to rewrite them into functions. This situation may
|
|
change in the future. */
|
|
#define PRINT(ptr, len) { \
|
|
if (pfunc (data, fp, (ptr), (len)) == EOF) \
|
|
goto error; \
|
|
}
|
|
#define PAD(howmany, ch) { \
|
|
int temp_i = 0; \
|
|
while (temp_i < (howmany)) \
|
|
{ \
|
|
if (pfunc (data, fp, &(ch), 1) == EOF) \
|
|
goto error; \
|
|
temp_i++; \
|
|
} \
|
|
}
|
|
#define PRINTANDPAD(p, ep, len, ch) { \
|
|
int temp_n = (ep) - (p); \
|
|
if (temp_n > (len)) \
|
|
temp_n = (len); \
|
|
if (temp_n > 0) \
|
|
PRINT((p), temp_n); \
|
|
PAD((len) - (temp_n > 0 ? temp_n : 0), (ch)); \
|
|
}
|
|
|
|
/* All data needed to decode format string are kept in below struct. */
|
|
struct _prt_data_t
|
|
{
|
|
int flags; /* Flags. */
|
|
int prec; /* Precision. */
|
|
int dprec; /* Decimal precision. */
|
|
int width; /* Width. */
|
|
int size; /* Size of converted field or string. */
|
|
int ret; /* Return value accumulator. */
|
|
char code; /* Current conversion specifier. */
|
|
char blank; /* Blank character. */
|
|
char zero; /* Zero character. */
|
|
char buf[BUF]; /* Output buffer for non-floating point number. */
|
|
char l_buf[3]; /* Sign&hex_prefix, "+/-" and "0x/X". */
|
|
#ifdef FLOATING_POINT
|
|
_PRINTF_FLOAT_TYPE _double_; /* Double value. */
|
|
char expstr[MAXEXPLEN]; /* Buffer for exponent string. */
|
|
int lead; /* The sig figs before decimal or group sep. */
|
|
#endif
|
|
};
|
|
|
|
extern int
|
|
_printf_common (struct _reent *data,
|
|
struct _prt_data_t *pdata,
|
|
int *realsz,
|
|
FILE *fp,
|
|
int (*pfunc)(struct _reent *, FILE *,
|
|
_CONST char *, size_t len));
|
|
|
|
extern int
|
|
_printf_i (struct _reent *data, struct _prt_data_t *pdata, FILE *fp,
|
|
int (*pfunc)(struct _reent *, FILE *, _CONST char *, size_t len),
|
|
va_list *ap);
|
|
|
|
/* Make _printf_float weak symbol, so it won't be linked in if target program
|
|
does not need it. */
|
|
extern int
|
|
_printf_float (struct _reent *data,
|
|
struct _prt_data_t *pdata,
|
|
FILE *fp,
|
|
int (*pfunc)(struct _reent *, FILE *,
|
|
_CONST char *, size_t len),
|
|
va_list *ap) _ATTRIBUTE((__weak__));
|
|
#endif
|