summaryrefslogtreecommitdiff
path: root/newlib/libc
diff options
context:
space:
mode:
authorCorinna Vinschen <vinschen@redhat.com>2006-10-19 08:39:44 +0000
committerCorinna Vinschen <vinschen@redhat.com>2006-10-19 08:39:44 +0000
commit335ac4f0e9b2cfd42947e1ee20f6cd58a1ff457e (patch)
tree88fe45768802928d0421520b41af82d3af0423a8 /newlib/libc
parentb688de33249272dfb353ccd61bcf4b681337a0f5 (diff)
downloadgdb-335ac4f0e9b2cfd42947e1ee20f6cd58a1ff457e.tar.gz
Apply the following mainline patches to cr-0x5f1 branch:
2006-10-11 Yang Tse <yangsita@gmail.com> * libc/include/machine/setjmp.h: Use __extension__ keyword for gcc's braced-groups. 2006-10-11 Corinna Vinschen <corinna@vinschen.de> * libc/reent/reeent.c (_reclaim_reent): Free _REENT_MP_RESULT. 2006-09-13 Patrick Mansfield <patmans@us.ibm.com> * libc/include/math.h: Remove _CONST from _LIB_VERSION, as it is supposed to be writable. * libm/common/s_lib_ver.c: Ditto. 2006-09-06 Eric Blake <ebb9@byu.net> * libc/stdio/vfprintf.c (_vfprintf_r, get_arg): Add 'hh', 'j', 't', and 'z' modifiers. 2006-08-22 Eric Blake <ebb9@byu.net> * libc/posix/popen.c (popen): Don't close output end of pipe in child if stdout was closed on entry. [HAVE_FCNTL]: In parent, mark file as close-on-exec, per POSIX. 2006-08-17 Brian Ford <Brian.Ford@FlightSafety.com> * libc/time/gmtime.c: Correct man page; clock is not a local time and no conversion occurs.
Diffstat (limited to 'newlib/libc')
-rw-r--r--newlib/libc/include/machine/setjmp.h293
-rw-r--r--newlib/libc/include/math.h424
-rw-r--r--newlib/libc/posix/popen.c184
-rw-r--r--newlib/libc/reent/reent.c147
-rw-r--r--newlib/libc/stdio/vfprintf.c1875
-rw-r--r--newlib/libc/time/gmtime.c66
6 files changed, 2989 insertions, 0 deletions
diff --git a/newlib/libc/include/machine/setjmp.h b/newlib/libc/include/machine/setjmp.h
new file mode 100644
index 00000000000..3c9b6be831d
--- /dev/null
+++ b/newlib/libc/include/machine/setjmp.h
@@ -0,0 +1,293 @@
+
+_BEGIN_STD_C
+
+#if defined(__arm__) || defined(__thumb__)
+/*
+ * All callee preserved registers:
+ * v1 - v7, fp, ip, sp, lr, f4, f5, f6, f7
+ */
+#define _JBLEN 23
+#endif
+
+#if defined(__AVR__)
+#define _JBLEN 24
+#endif
+
+#ifdef __sparc__
+/*
+ * onsstack,sigmask,sp,pc,npc,psr,g1,o0,wbcnt (sigcontext).
+ * All else recovered by under/over(flow) handling.
+ */
+#define _JBLEN 13
+#endif
+
+/* necv70 was 9 as well. */
+
+#ifdef __mc68000__
+/*
+ * onsstack,sigmask,sp,pc,psl,d2-d7,a2-a6,
+ * fp2-fp7 for 68881.
+ * All else recovered by under/over(flow) handling.
+ */
+#define _JBLEN 34
+#endif
+
+#if defined(__mc68hc11__) || defined(__mc68hc12__) || defined(__mc68hc1x__)
+/*
+ * D, X, Y are not saved.
+ * Only take into account the pseudo soft registers (max 32).
+ */
+#define _JBLEN 32
+#endif
+
+#if defined(__Z8001__) || defined(__Z8002__)
+/* 16 regs + pc */
+#define _JBLEN 20
+#endif
+
+#ifdef _AM29K
+/*
+ * onsstack,sigmask,sp,pc,npc,psr,g1,o0,wbcnt (sigcontext).
+ * All else recovered by under/over(flow) handling.
+ */
+#define _JBLEN 9
+#endif
+
+#if defined(__CYGWIN__) && !defined (_JBLEN)
+#define _JBLEN (13 * 4)
+#elif defined (__i386__)
+#if defined(__unix__) || defined(__rtems__)
+# define _JBLEN 9
+#else
+#include "setjmp-dj.h"
+#endif
+#endif
+
+#ifdef __i960__
+#define _JBLEN 35
+#endif
+
+#ifdef __M32R__
+/* Only 8 words are currently needed. 10 gives us some slop if we need
+ to expand. */
+#define _JBLEN 10
+#endif
+
+#ifdef __mips__
+#ifdef __mips64
+#define _JBTYPE long long
+#endif
+#ifdef __mips_soft_float
+#define _JBLEN 11
+#else
+#define _JBLEN 23
+#endif
+#endif
+
+#ifdef __m88000__
+#define _JBLEN 21
+#endif
+
+#ifdef __H8300__
+#define _JBLEN 5
+#define _JBTYPE int
+#endif
+
+#ifdef __H8300H__
+/* same as H8/300 but registers are twice as big */
+#define _JBLEN 5
+#define _JBTYPE long
+#endif
+
+#if defined (__H8300S__) || defined (__H8300SX__)
+/* same as H8/300 but registers are twice as big */
+#define _JBLEN 5
+#define _JBTYPE long
+#endif
+
+#ifdef __H8500__
+#define _JBLEN 4
+#endif
+
+#ifdef __sh__
+#if __SH5__
+#define _JBLEN 50
+#define _JBTYPE long long
+#else
+#define _JBLEN 20
+#endif /* __SH5__ */
+#endif
+
+#ifdef __v800
+#define _JBLEN 28
+#endif
+
+#ifdef __PPC__
+#ifdef __ALTIVEC__
+#define _JBLEN 64
+#else
+#define _JBLEN 32
+#endif
+#define _JBTYPE double
+#endif
+
+#ifdef __hppa__
+/* %r30, %r2-%r18, %r27, pad, %fr12-%fr15.
+ Note space exists for the FP registers, but they are not
+ saved. */
+#define _JBLEN 28
+#endif
+
+#if defined(__mn10300__) || defined(__mn10200__)
+#ifdef __AM33_2__
+#define _JBLEN 26
+#else
+/* A guess */
+#define _JBLEN 10
+#endif
+#endif
+
+#ifdef __v850
+/* I think our setjmp is saving 15 regs at the moment. Gives us one word
+ slop if we need to expand. */
+#define _JBLEN 16
+#endif
+
+#if defined(_C4x)
+#define _JBLEN 10
+#endif
+#if defined(_C3x)
+#define _JBLEN 9
+#endif
+
+#ifdef __TIC80__
+#define _JBLEN 13
+#endif
+
+#ifdef __D10V__
+#define _JBLEN 8
+#endif
+
+#ifdef __D30V__
+#define _JBLEN ((64 /* GPR */ + (2*2) /* ACs */ + 18 /* CRs */) / 2)
+#define _JBTYPE double
+#endif
+
+#ifdef __frv__
+#define _JBLEN (68/2) /* room for 68 32-bit regs */
+#define _JBTYPE double
+#endif
+
+#ifdef __CRX__
+#define _JBLEN 9
+#endif
+
+#ifdef __fr30__
+#define _JBLEN 10
+#endif
+
+#ifdef __iq2000__
+#define _JBLEN 32
+#endif
+
+#ifdef __mcore__
+#define _JBLEN 16
+#endif
+
+#ifdef __MMIX__
+/* Using a layout compatible with GCC's built-in. */
+#define _JBLEN 5
+#define _JBTYPE unsigned long
+#endif
+
+#ifdef __mt__
+#define _JBLEN 16
+#endif
+
+#ifdef __SPU__
+#define _JBLEN 50
+#define _JBTYPE __attribute__ (( __vector_size__ (16) )) int
+#endif
+
+#ifdef __xstormy16__
+/* 4 GPRs plus SP plus PC. */
+#define _JBLEN 8
+#endif
+
+#ifdef __CRIS__
+#define _JBLEN 18
+#endif
+
+#ifdef __m32c__
+#if defined(__r8c_cpu__) || defined(__m16c_cpu__)
+#define _JBLEN (22/2)
+#else
+#define _JBLEN (34/2)
+#endif
+#define _JBTYPE unsigned short
+#endif /* __m32c__ */
+
+#ifdef _JBLEN
+#ifdef _JBTYPE
+typedef _JBTYPE jmp_buf[_JBLEN];
+#else
+typedef int jmp_buf[_JBLEN];
+#endif
+#endif
+
+_END_STD_C
+
+#if defined(__CYGWIN__) || defined(__rtems__)
+#include <signal.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* POSIX sigsetjmp/siglongjmp macros */
+typedef int sigjmp_buf[_JBLEN+2];
+
+#define _SAVEMASK _JBLEN
+#define _SIGMASK (_JBLEN+1)
+
+#ifdef __CYGWIN__
+# define _CYGWIN_WORKING_SIGSETJMP
+#endif
+
+#if defined(__GNUC__)
+
+#define sigsetjmp(env, savemask) \
+ __extension__ \
+ ({ \
+ sigjmp_buf *_sjbuf = &(env); \
+ ((*_sjbuf)[_SAVEMASK] = savemask,\
+ sigprocmask (SIG_SETMASK, 0, (sigset_t *)((*_sjbuf) + _SIGMASK)),\
+ setjmp (*_sjbuf)); \
+ })
+
+#define siglongjmp(env, val) \
+ __extension__ \
+ ({ \
+ sigjmp_buf *_sjbuf = &(env); \
+ ((((*_sjbuf)[_SAVEMASK]) ? \
+ sigprocmask (SIG_SETMASK, (sigset_t *)((*_sjbuf) + _SIGMASK), 0)\
+ : 0), \
+ longjmp (*_sjbuf, val)); \
+ })
+
+#else /* !__GNUC__ */
+
+#define sigsetjmp(env, savemask) ((env)[_SAVEMASK] = savemask,\
+ sigprocmask (SIG_SETMASK, 0, (sigset_t *) ((env) + _SIGMASK)),\
+ setjmp (env))
+
+#define siglongjmp(env, val) ((((env)[_SAVEMASK])?\
+ sigprocmask (SIG_SETMASK, (sigset_t *) ((env) + _SIGMASK), 0):0),\
+ longjmp (env, val))
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __CYGWIN__ or __rtems__ */
diff --git a/newlib/libc/include/math.h b/newlib/libc/include/math.h
new file mode 100644
index 00000000000..2e1533ad8ae
--- /dev/null
+++ b/newlib/libc/include/math.h
@@ -0,0 +1,424 @@
+
+#ifndef _MATH_H_
+#define _MATH_H_
+
+#include <sys/reent.h>
+#include <machine/ieeefp.h>
+#include "_ansi.h"
+
+_BEGIN_STD_C
+
+union __dmath
+{
+ __ULong i[2];
+ double d;
+};
+
+union __fmath
+{
+ __ULong i[1];
+ float f;
+};
+
+union __ldmath
+{
+ __ULong i[4];
+ _LONG_DOUBLE ld;
+};
+
+#if defined(__GNUC__) && \
+ ( (__GNUC__ >= 4) || \
+ ( (__GNUC__ >= 3) && defined(__GNUC_MINOR__) && (__GNUC_MINOR__ >= 3) ) )
+
+ /* gcc >= 3.3 implicitly defines builtins for HUGE_VALx values. */
+
+ #ifndef HUGE_VAL
+ #define HUGE_VAL (__builtin_huge_val())
+ #endif
+
+ #ifndef HUGE_VALF
+ #define HUGE_VALF (__builtin_huge_valf())
+ #endif
+
+ #ifndef HUGE_VALL
+ #define HUGE_VALL (__builtin_huge_vall())
+ #endif
+
+#else /* !gcc >= 3.3 */
+
+ /* No builtins. Use floating-point unions instead. Declare as an array
+ without bounds so no matter what small data support a port and/or
+ library has, the reference will be via the general method for accessing
+ globals. */
+
+ #ifndef HUGE_VAL
+ extern __IMPORT const union __dmath __infinity[];
+ #define HUGE_VAL (__infinity[0].d)
+ #endif
+
+ #ifndef HUGE_VALF
+ extern __IMPORT const union __fmath __infinityf[];
+ #define HUGE_VALF (__infinityf[0].f)
+ #endif
+
+ #ifndef HUGE_VALL
+ extern __IMPORT const union __ldmath __infinityld[];
+ #define HUGE_VALL (__infinityld[0].ld)
+ #endif
+
+#endif /* !gcc >= 3.3 */
+
+/* Reentrant ANSI C functions. */
+
+#ifndef __math_68881
+extern double atan _PARAMS((double));
+extern double cos _PARAMS((double));
+extern double sin _PARAMS((double));
+extern double tan _PARAMS((double));
+extern double tanh _PARAMS((double));
+extern double frexp _PARAMS((double, int *));
+extern double modf _PARAMS((double, double *));
+extern double ceil _PARAMS((double));
+extern double fabs _PARAMS((double));
+extern double floor _PARAMS((double));
+#endif /* ! defined (__math_68881) */
+
+/* Non reentrant ANSI C functions. */
+
+#ifndef _REENT_ONLY
+#ifndef __math_6881
+extern double acos _PARAMS((double));
+extern double asin _PARAMS((double));
+extern double atan2 _PARAMS((double, double));
+extern double cosh _PARAMS((double));
+extern double sinh _PARAMS((double));
+extern double exp _PARAMS((double));
+extern double ldexp _PARAMS((double, int));
+extern double log _PARAMS((double));
+extern double log10 _PARAMS((double));
+extern double pow _PARAMS((double, double));
+extern double sqrt _PARAMS((double));
+extern double fmod _PARAMS((double, double));
+#endif /* ! defined (__math_68881) */
+#endif /* ! defined (_REENT_ONLY) */
+
+#ifndef __STRICT_ANSI__
+
+/* ISO C99 types and macros. */
+
+#ifndef FLT_EVAL_METHOD
+#define FLT_EVAL_METHOD 0
+typedef float float_t;
+typedef double double_t;
+#endif /* FLT_EVAL_METHOD */
+
+#define FP_NAN 0
+#define FP_INFINITE 1
+#define FP_ZERO 2
+#define FP_SUBNORMAL 3
+#define FP_NORMAL 4
+
+extern int __isinff (float x);
+extern int __isinfd (double x);
+extern int __isnanf (float x);
+extern int __isnand (double x);
+extern int __fpclassifyf (float x);
+extern int __fpclassifyd (double x);
+extern int __signbitf (float x);
+extern int __signbitd (double x);
+
+#define fpclassify(x) \
+ (__extension__ ({__typeof__(x) __x = (x); \
+ (sizeof (__x) == sizeof (float)) ? __fpclassifyf(__x) : __fpclassifyd(__x);}))
+
+#define isfinite(y) \
+ (__extension__ ({__typeof__(y) __y = (y); \
+ fpclassify(__y) != FP_INFINITE && fpclassify(__y) != FP_NAN;}))
+
+/* Note: isinf and isnan were once functions in newlib that took double
+ * arguments. C99 specifies that these names are reserved for macros
+ * supporting multiple floating point types. Thus, they are
+ * now defined as macros. Implementations of the old functions
+ * taking double arguments still exist for compatibility purposes. */
+#define isinf(x) \
+ (__extension__ ({__typeof__(x) __x = (x); \
+ (sizeof (__x) == sizeof (float)) ? __isinff(__x) : __isinfd(__x);}))
+#define isnan(x) \
+ (__extension__ ({__typeof__(x) __x = (x); \
+ (sizeof (__x) == sizeof (float)) ? __isnanf(__x) : __isnand(__x);}))
+#define isnormal(y) (fpclassify(y) == FP_NORMAL)
+#define signbit(x) \
+ (__extension__ ({__typeof__(x) __x = (x); \
+ (sizeof(__x) == sizeof(float)) ? __signbitf(__x) : __signbitd(__x);}))
+
+#define isgreater(x,y) \
+ (__extension__ ({__typeof__(x) __x = (x); __typeof__(y) __y = (y); \
+ !isunordered(__x,__y) && (__x > __y);}))
+#define isgreaterequal(x,y) \
+ (__extension__ ({__typeof__(x) __x = (x); __typeof__(y) __y = (y); \
+ !isunordered(__x,__y) && (__x >= __y);}))
+#define isless(x,y) \
+ (__extension__ ({__typeof__(x) __x = (x); __typeof__(y) __y = (y); \
+ !isunordered(__x,__y) && (__x < __y);}))
+#define islessequal(x,y) \
+ (__extension__ ({__typeof__(x) __x = (x); __typeof__(y) __y = (y); \
+ !isunordered(__x,__y) && (__x <= __y);}))
+#define islessgreater(x,y) \
+ (__extension__ ({__typeof__(x) __x = (x); __typeof__(y) __y = (y); \
+ !isunordered(__x,__y) && (__x < __y || __x > __y);}))
+
+#define isunordered(a,b) \
+ (__extension__ ({__typeof__(a) __a = (a); __typeof__(b) __b = (b); \
+ fpclassify(__a) == FP_NAN || fpclassify(__b) == FP_NAN;}))
+
+/* Non ANSI double precision functions. */
+
+extern double infinity _PARAMS((void));
+extern double nan _PARAMS((const char *));
+extern int finite _PARAMS((double));
+extern double copysign _PARAMS((double, double));
+extern int ilogb _PARAMS((double));
+
+extern double asinh _PARAMS((double));
+extern double cbrt _PARAMS((double));
+extern double nextafter _PARAMS((double, double));
+extern double rint _PARAMS((double));
+extern double scalbn _PARAMS((double, int));
+
+extern double exp2 _PARAMS((double));
+extern double scalbln _PARAMS((double, long int));
+extern double tgamma _PARAMS((double));
+extern double nearbyint _PARAMS((double));
+extern long int lrint _PARAMS((double));
+extern double round _PARAMS((double));
+extern long int lround _PARAMS((double));
+extern double trunc _PARAMS((double));
+extern double remquo _PARAMS((double, double, int *));
+extern double copysign _PARAMS((double, double));
+extern double fdim _PARAMS((double, double));
+extern double fmax _PARAMS((double, double));
+extern double fmin _PARAMS((double, double));
+extern double fma _PARAMS((double, double, double));
+extern void sincos _PARAMS((double, double *, double *));
+
+#ifndef __math_68881
+extern double log1p _PARAMS((double));
+extern double expm1 _PARAMS((double));
+#endif /* ! defined (__math_68881) */
+
+#ifndef _REENT_ONLY
+extern double acosh _PARAMS((double));
+extern double atanh _PARAMS((double));
+extern double remainder _PARAMS((double, double));
+extern double gamma _PARAMS((double));
+extern double gamma_r _PARAMS((double, int *));
+extern double lgamma _PARAMS((double));
+extern double lgamma_r _PARAMS((double, int *));
+extern double erf _PARAMS((double));
+extern double erfc _PARAMS((double));
+extern double y0 _PARAMS((double));
+extern double y1 _PARAMS((double));
+extern double yn _PARAMS((int, double));
+extern double j0 _PARAMS((double));
+extern double j1 _PARAMS((double));
+extern double jn _PARAMS((int, double));
+#define log2(x) (log (x) / M_LOG2_E)
+
+#ifndef __math_68881
+extern double hypot _PARAMS((double, double));
+#endif
+
+extern double cabs();
+extern double drem _PARAMS((double, double));
+
+#endif /* ! defined (_REENT_ONLY) */
+
+#endif /* ! defined (__STRICT_ANSI__) */
+
+#if !defined(__STRICT_ANSI__) || defined(__cplusplus)
+
+/* Single precision versions of ANSI functions. */
+
+extern float atanf _PARAMS((float));
+extern float cosf _PARAMS((float));
+extern float sinf _PARAMS((float));
+extern float tanf _PARAMS((float));
+extern float tanhf _PARAMS((float));
+extern float frexpf _PARAMS((float, int *));
+extern float modff _PARAMS((float, float *));
+extern float ceilf _PARAMS((float));
+extern float fabsf _PARAMS((float));
+extern float floorf _PARAMS((float));
+
+#ifndef _REENT_ONLY
+extern float acosf _PARAMS((float));
+extern float asinf _PARAMS((float));
+extern float atan2f _PARAMS((float, float));
+extern float coshf _PARAMS((float));
+extern float sinhf _PARAMS((float));
+extern float expf _PARAMS((float));
+extern float ldexpf _PARAMS((float, int));
+extern float logf _PARAMS((float));
+extern float log10f _PARAMS((float));
+extern float powf _PARAMS((float, float));
+extern float sqrtf _PARAMS((float));
+extern float fmodf _PARAMS((float, float));
+#endif /* ! defined (_REENT_ONLY) */
+
+#endif /* !defined(__STRICT_ANSI__) || defined(__cplusplus) */
+
+#ifndef __STRICT_ANSI__
+
+/* Other single precision functions. */
+
+extern float exp2f _PARAMS((float));
+extern float scalblnf _PARAMS((float, long int));
+extern float tgammaf _PARAMS((float));
+extern float nearbyintf _PARAMS((float));
+extern long int lrintf _PARAMS((float));
+extern float roundf _PARAMS((float));
+extern long int lroundf _PARAMS((float));
+extern float truncf _PARAMS((float));
+extern float remquof _PARAMS((float, float, int *));
+extern float copysignf _PARAMS((float, float));
+extern float fdimf _PARAMS((float, float));
+extern float fmaxf _PARAMS((float, float));
+extern float fminf _PARAMS((float, float));
+extern float fmaf _PARAMS((float, float, float));
+
+extern float infinityf _PARAMS((void));
+extern float nanf _PARAMS((const char *));
+extern int isnanf _PARAMS((float));
+extern int isinff _PARAMS((float));
+extern int finitef _PARAMS((float));
+extern float copysignf _PARAMS((float, float));
+extern int ilogbf _PARAMS((float));
+
+extern float asinhf _PARAMS((float));
+extern float cbrtf _PARAMS((float));
+extern float nextafterf _PARAMS((float, float));
+extern float rintf _PARAMS((float));
+extern float scalbnf _PARAMS((float, int));
+extern float log1pf _PARAMS((float));
+extern float expm1f _PARAMS((float));
+extern void sincosf _PARAMS((float, float *, float *));
+
+#ifndef _REENT_ONLY
+extern float acoshf _PARAMS((float));
+extern float atanhf _PARAMS((float));
+extern float remainderf _PARAMS((float, float));
+extern float gammaf _PARAMS((float));
+extern float gammaf_r _PARAMS((float, int *));
+extern float lgammaf _PARAMS((float));
+extern float lgammaf_r _PARAMS((float, int *));
+extern float erff _PARAMS((float));
+extern float erfcf _PARAMS((float));
+extern float y0f _PARAMS((float));
+extern float y1f _PARAMS((float));
+extern float ynf _PARAMS((int, float));
+extern float j0f _PARAMS((float));
+extern float j1f _PARAMS((float));
+extern float jnf _PARAMS((int, float));
+#define log2f(x) (logf (x) / (float) M_LOG2_E)
+extern float hypotf _PARAMS((float, float));
+
+extern float cabsf();
+extern float dremf _PARAMS((float, float));
+
+#endif /* ! defined (_REENT_ONLY) */
+
+/* The gamma functions use a global variable, signgam. */
+#ifndef _REENT_ONLY
+#define signgam (*__signgam())
+extern int *__signgam _PARAMS((void));
+#endif /* ! defined (_REENT_ONLY) */
+
+#define __signgam_r(ptr) _REENT_SIGNGAM(ptr)
+
+/* The exception structure passed to the matherr routine. */
+
+#ifdef __cplusplus
+struct __exception
+#else
+struct exception
+#endif
+{
+ int type;
+ char *name;
+ double arg1;
+ double arg2;
+ double retval;
+ int err;
+};
+
+#ifdef __cplusplus
+extern int matherr _PARAMS((struct __exception *e));
+#else
+extern int matherr _PARAMS((struct exception *e));
+#endif
+
+/* Values for the type field of struct exception. */
+
+#define DOMAIN 1
+#define SING 2
+#define OVERFLOW 3
+#define UNDERFLOW 4
+#define TLOSS 5
+#define PLOSS 6
+
+/* Useful constants. */
+
+#define MAXFLOAT 3.40282347e+38F
+
+#define M_E 2.7182818284590452354
+#define M_LOG2E 1.4426950408889634074
+#define M_LOG10E 0.43429448190325182765
+#define M_LN2 0.69314718055994530942
+#define M_LN10 2.30258509299404568402
+#define M_PI 3.14159265358979323846
+#define M_TWOPI (M_PI * 2.0)
+#define M_PI_2 1.57079632679489661923
+#define M_PI_4 0.78539816339744830962
+#define M_3PI_4 2.3561944901923448370E0
+#define M_SQRTPI 1.77245385090551602792981
+#define M_1_PI 0.31830988618379067154
+#define M_2_PI 0.63661977236758134308
+#define M_2_SQRTPI 1.12837916709551257390
+#define M_SQRT2 1.41421356237309504880
+#define M_SQRT1_2 0.70710678118654752440
+#define M_LN2LO 1.9082149292705877000E-10
+#define M_LN2HI 6.9314718036912381649E-1
+#define M_SQRT3 1.73205080756887719000
+#define M_IVLN10 0.43429448190325182765 /* 1 / log(10) */
+#define M_LOG2_E 0.693147180559945309417
+#define M_INVLN2 1.4426950408889633870E0 /* 1 / log(2) */
+
+/* Global control over fdlibm error handling. */
+
+enum __fdlibm_version
+{
+ __fdlibm_ieee = -1,
+ __fdlibm_svid,
+ __fdlibm_xopen,
+ __fdlibm_posix
+};
+
+#define _LIB_VERSION_TYPE enum __fdlibm_version
+#define _LIB_VERSION __fdlib_version
+
+extern __IMPORT _LIB_VERSION_TYPE _LIB_VERSION;
+
+#define _IEEE_ __fdlibm_ieee
+#define _SVID_ __fdlibm_svid
+#define _XOPEN_ __fdlibm_xopen
+#define _POSIX_ __fdlibm_posix
+
+#endif /* ! defined (__STRICT_ANSI__) */
+
+_END_STD_C
+
+#ifdef __FAST_MATH__
+#include <machine/fastmath.h>
+#endif
+
+#endif /* _MATH_H_ */
diff --git a/newlib/libc/posix/popen.c b/newlib/libc/posix/popen.c
new file mode 100644
index 00000000000..2d3777133ff
--- /dev/null
+++ b/newlib/libc/posix/popen.c
@@ -0,0 +1,184 @@
+/* $NetBSD: popen.c,v 1.11 1995/06/16 07:05:33 jtc Exp $ */
+
+/*
+ * Copyright (c) 1988, 1993, 2006
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software written by Ken Arnold and
+ * published in UNIX Review, Vol. 6, No. 8.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)popen.c 8.1 (Berkeley) 6/4/93";
+#else
+static char rcsid[] = "$NetBSD: popen.c,v 1.11 1995/06/16 07:05:33 jtc Exp $";
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <paths.h>
+#include <fcntl.h>
+
+static struct pid {
+ struct pid *next;
+ FILE *fp;
+ pid_t pid;
+} *pidlist;
+
+FILE *
+_DEFUN(popen, (program, type),
+ const char *program _AND
+ const char *type)
+{
+ struct pid *cur;
+ FILE *iop;
+ int pdes[2], pid;
+
+ if ((*type != 'r' && *type != 'w')
+ || (type[1]
+#ifdef __CYGWIN__
+ && (type[2] || (type[1] != 'b' && type[1] != 't'))
+#endif
+ )) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ if ((cur = malloc(sizeof(struct pid))) == NULL)
+ return (NULL);
+
+ if (pipe(pdes) < 0) {
+ free(cur);
+ return (NULL);
+ }
+
+ switch (pid = vfork()) {
+ case -1: /* Error. */
+ (void)close(pdes[0]);
+ (void)close(pdes[1]);
+ free(cur);
+ return (NULL);
+ /* NOTREACHED */
+ case 0: /* Child. */
+ if (*type == 'r') {
+ if (pdes[1] != STDOUT_FILENO) {
+ (void)dup2(pdes[1], STDOUT_FILENO);
+ (void)close(pdes[1]);
+ }
+ if (pdes[0] != STDOUT_FILENO) {
+ (void) close(pdes[0]);
+ }
+ } else {
+ if (pdes[0] != STDIN_FILENO) {
+ (void)dup2(pdes[0], STDIN_FILENO);
+ (void)close(pdes[0]);
+ }
+ (void)close(pdes[1]);
+ }
+ execl(_PATH_BSHELL, "sh", "-c", program, NULL);
+#ifdef __CYGWIN__
+ /* On cygwin32, we may not have /bin/sh. In that
+ case, try to find sh on PATH. */
+ execlp("sh", "sh", "-c", program, NULL);
+#endif
+ _exit(127);
+ /* NOTREACHED */
+ }
+
+ /* Parent; assume fdopen can't fail. */
+ if (*type == 'r') {
+ iop = fdopen(pdes[0], type);
+ (void)close(pdes[1]);
+ } else {
+ iop = fdopen(pdes[1], type);
+ (void)close(pdes[0]);
+ }
+
+#ifdef HAVE_FCNTL
+ /* Hide pipe from future popens; assume fcntl can't fail. */
+ fcntl (fileno (iop), F_SETFD,
+ fcntl (fileno (iop), F_GETFD, 0) | FD_CLOEXEC);
+#endif /* HAVE_FCNTL */
+
+ /* Link into list of file descriptors. */
+ cur->fp = iop;
+ cur->pid = pid;
+ cur->next = pidlist;
+ pidlist = cur;
+
+ return (iop);
+}
+
+/*
+ * pclose --
+ * Pclose returns -1 if stream is not associated with a `popened' command,
+ * if already `pclosed', or waitpid returns an error.
+ */
+int
+_DEFUN(pclose, (iop),
+ FILE *iop)
+{
+ register struct pid *cur, *last;
+ int pstat;
+ pid_t pid;
+
+ (void)fclose(iop);
+
+ /* Find the appropriate file pointer. */
+ for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next)
+ if (cur->fp == iop)
+ break;
+ if (cur == NULL)
+ return (-1);
+
+ do {
+ pid = waitpid(cur->pid, &pstat, 0);
+ } while (pid == -1 && errno == EINTR);
+
+ /* Remove the entry from the linked list. */
+ if (last == NULL)
+ pidlist = cur->next;
+ else
+ last->next = cur->next;
+ free(cur);
+
+ return (pid == -1 ? -1 : pstat);
+}
diff --git a/newlib/libc/reent/reent.c b/newlib/libc/reent/reent.c
new file mode 100644
index 00000000000..5270ef6eb31
--- /dev/null
+++ b/newlib/libc/reent/reent.c
@@ -0,0 +1,147 @@
+/*
+FUNCTION
+ <<reent>>---definition of impure data.
+
+INDEX
+ reent
+
+DESCRIPTION
+ This module defines the impure data area used by the
+ non-reentrant functions, such as strtok.
+*/
+
+#include <stdlib.h>
+#include <reent.h>
+
+#ifdef _REENT_ONLY
+#ifndef REENTRANT_SYSCALLS_PROVIDED
+#define REENTRANT_SYSCALLS_PROVIDED
+#endif
+#endif
+
+#ifndef REENTRANT_SYSCALLS_PROVIDED
+
+/* We use the errno variable used by the system dependent layer. */
+#undef errno
+int errno;
+
+#endif
+
+/* Interim cleanup code */
+
+void
+_DEFUN (cleanup_glue, (ptr, glue),
+ struct _reent *ptr _AND
+ struct _glue *glue)
+{
+ /* Have to reclaim these in reverse order: */
+ if (glue->_next)
+ cleanup_glue (ptr, glue->_next);
+
+ _free_r (ptr, glue);
+}
+
+void
+_DEFUN (_reclaim_reent, (ptr),
+ struct _reent *ptr)
+{
+ if (ptr != _impure_ptr)
+ {
+ /* used by mprec routines. */
+#ifdef _REENT_SMALL
+ if (ptr->_mp) /* don't bother allocating it! */
+#endif
+ if (_REENT_MP_FREELIST(ptr))
+ {
+ int i;
+ for (i = 0; i < 15 /* _Kmax */; i++)
+ {
+ struct _Bigint *thisone, *nextone;
+
+ nextone = _REENT_MP_FREELIST(ptr)[i];
+ while (nextone)
+ {
+ thisone = nextone;
+ nextone = nextone->_next;
+ _free_r (ptr, thisone);
+ }
+ }
+
+ _free_r (ptr, _REENT_MP_FREELIST(ptr));
+ }
+ if (_REENT_MP_RESULT(ptr))
+ _free_r (ptr, _REENT_MP_RESULT(ptr));
+
+#ifdef _REENT_SMALL
+ if (ptr->_emergency)
+ _free_r (ptr, ptr->_emergency);
+ if (ptr->_mp)
+ _free_r (ptr, ptr->_mp);
+ if (ptr->_r48)
+ _free_r (ptr, ptr->_r48);
+ if (ptr->_localtime_buf)
+ _free_r (ptr, ptr->_localtime_buf);
+ if (ptr->_asctime_buf)
+ _free_r (ptr, ptr->_asctime_buf);
+ if (ptr->_atexit->_on_exit_args_ptr)
+ _free_r (ptr, ptr->_atexit->_on_exit_args_ptr);
+#else
+ /* atexit stuff */
+ if ((ptr->_atexit) && (ptr->_atexit != &ptr->_atexit0))
+ {
+ struct _atexit *p, *q;
+ for (p = ptr->_atexit; p != &ptr->_atexit0;)
+ {
+ q = p;
+ p = p->_next;
+ _free_r (ptr, q);
+ }
+ }
+#endif
+
+ if (ptr->_cvtbuf)
+ _free_r (ptr, ptr->_cvtbuf);
+
+ if (ptr->__sdidinit)
+ {
+ /* cleanup won't reclaim memory 'coz usually it's run
+ before the program exits, and who wants to wait for that? */
+ ptr->__cleanup (ptr);
+
+ if (ptr->__sglue._next)
+ cleanup_glue (ptr, ptr->__sglue._next);
+ }
+
+ /* Malloc memory not reclaimed; no good way to return memory anyway. */
+
+ }
+}
+
+/*
+ * Do atexit() processing and cleanup
+ *
+ * NOTE: This is to be executed at task exit. It does not tear anything
+ * down which is used on a global basis.
+ */
+
+void
+_DEFUN (_wrapup_reent, (ptr), struct _reent *ptr)
+{
+ register struct _atexit *p;
+ register int n;
+
+ if (ptr == 0)
+ ptr = _REENT;
+
+#ifdef _REENT_SMALL
+ for (p = &ptr->_atexit, n = p->_ind; --n >= 0;)
+ (*p->_fns[n]) ();
+#else
+ for (p = ptr->_atexit; p; p = p->_next)
+ for (n = p->_ind; --n >= 0;)
+ (*p->_fns[n]) ();
+#endif
+ if (ptr->__cleanup)
+ (*ptr->__cleanup) (ptr);
+}
+
diff --git a/newlib/libc/stdio/vfprintf.c b/newlib/libc/stdio/vfprintf.c
new file mode 100644
index 00000000000..9e5477aa6fc
--- /dev/null
+++ b/newlib/libc/stdio/vfprintf.c
@@ -0,0 +1,1875 @@
+/*
+ * Copyright (c) 1990, 2006 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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.
+ */
+
+/*
+FUNCTION
+<<vprintf>>, <<vfprintf>>, <<vsprintf>>---format argument list
+
+INDEX
+ vprintf
+INDEX
+ vfprintf
+INDEX
+ vsprintf
+INDEX
+ vsnprintf
+
+ANSI_SYNOPSIS
+ #include <stdio.h>
+ #include <stdarg.h>
+ int vprintf(const char *<[fmt]>, va_list <[list]>);
+ int vfprintf(FILE *<[fp]>, const char *<[fmt]>, va_list <[list]>);
+ int vsprintf(char *<[str]>, const char *<[fmt]>, va_list <[list]>);
+ int vasprintf(char **<[strp]>, const char *<[fmt]>, va_list <[list]>);
+ int vsnprintf(char *<[str]>, size_t <[size]>, const char *<[fmt]>,
+ va_list <[list]>);
+
+ int _vprintf_r(struct _reent *<[reent]>, const char *<[fmt]>,
+ va_list <[list]>);
+ int _vfprintf_r(struct _reent *<[reent]>, FILE *<[fp]>, const char *<[fmt]>,
+ va_list <[list]>);
+ int _vasprintf_r(struct _reent *<[reent]>, char **<[str]>,
+ const char *<[fmt]>, va_list <[list]>);
+ int _vsprintf_r(struct _reent *<[reent]>, char *<[str]>,
+ const char *<[fmt]>, va_list <[list]>);
+ int _vsnprintf_r(struct _reent *<[reent]>, char *<[str]>, size_t <[size]>,
+ const char *<[fmt]>, va_list <[list]>);
+
+TRAD_SYNOPSIS
+ #include <stdio.h>
+ #include <varargs.h>
+ int vprintf( <[fmt]>, <[list]>)
+ char *<[fmt]>;
+ va_list <[list]>;
+
+ int vfprintf(<[fp]>, <[fmt]>, <[list]>)
+ FILE *<[fp]>;
+ char *<[fmt]>;
+ va_list <[list]>;
+
+ int vasprintf(<[strp]>, <[fmt]>, <[list]>)
+ char **<[strp]>;
+ char *<[fmt]>;
+ va_list <[list]>;
+
+ int vsprintf(<[str]>, <[fmt]>, <[list]>)
+ char *<[str]>;
+ char *<[fmt]>;
+ va_list <[list]>;
+
+ int vsnprintf(<[str]>, <[size]>, <[fmt]>, <[list]>)
+ char *<[str]>;
+ size_t <[size]>;
+ char *<[fmt]>;
+ va_list <[list]>;
+
+ int _vprintf_r(<[reent]>, <[fmt]>, <[list]>)
+ struct _reent *<[reent]>;
+ char *<[fmt]>;
+ va_list <[list]>;
+
+ int _vfprintf_r(<[reent]>, <[fp]>, <[fmt]>, <[list]>)
+ struct _reent *<[reent]>;
+ FILE *<[fp]>;
+ char *<[fmt]>;
+ va_list <[list]>;
+
+ int _vasprintf_r(<[reent]>, <[strp]>, <[fmt]>, <[list]>)
+ struct _reent *<[reent]>;
+ char **<[strp]>;
+ char *<[fmt]>;
+ va_list <[list]>;
+
+ int _vsprintf_r(<[reent]>, <[str]>, <[fmt]>, <[list]>)
+ struct _reent *<[reent]>;
+ char *<[str]>;
+ char *<[fmt]>;
+ va_list <[list]>;
+
+ int _vsnprintf_r(<[reent]>, <[str]>, <[size]>, <[fmt]>, <[list]>)
+ struct _reent *<[reent]>;
+ char *<[str]>;
+ size_t <[size]>;
+ char *<[fmt]>;
+ va_list <[list]>;
+
+DESCRIPTION
+<<vprintf>>, <<vfprintf>>, <<vasprintf>>, <<vsprintf>> and <<vsnprintf>> are
+(respectively) variants of <<printf>>, <<fprintf>>, <<asprintf>>, <<sprintf>>,
+and <<snprintf>>. They differ only in allowing their caller to pass the
+variable argument list as a <<va_list>> object (initialized by <<va_start>>)
+rather than directly accepting a variable number of arguments.
+
+RETURNS
+The return values are consistent with the corresponding functions:
+<<vasprintf>>/<<vsprintf>> returns the number of bytes in the output string,
+save that the concluding <<NULL>> is not counted.
+<<vprintf>> and <<vfprintf>> return the number of characters transmitted.
+If an error occurs, <<vprintf>> and <<vfprintf>> return <<EOF>> and
+<<vasprintf>> returns -1. No error returns occur for <<vsprintf>>.
+
+PORTABILITY
+ANSI C requires all three functions.
+
+Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
+<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
+*/
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)vfprintf.c 5.50 (Berkeley) 12/16/92";*/
+static char *rcsid = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * Actual printf innards.
+ *
+ * This code is large and complicated...
+ */
+#include <newlib.h>
+
+#ifdef INTEGER_ONLY
+#define VFPRINTF vfiprintf
+#define _VFPRINTF_R _vfiprintf_r
+#else
+#define VFPRINTF vfprintf
+#define _VFPRINTF_R _vfprintf_r
+#ifndef NO_FLOATING_POINT
+#define FLOATING_POINT
+#endif
+#endif
+
+#define _NO_POS_ARGS
+#if defined _WANT_IO_POS_ARGS
+# undef _NO_POS_ARGS
+#endif
+
+#include <_ansi.h>
+#include <reent.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <stdint.h>
+#include <wchar.h>
+#include <string.h>
+#include <sys/lock.h>
+#ifdef _HAVE_STDC
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include "local.h"
+#include "fvwrite.h"
+#include "vfieeefp.h"
+
+/* 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
+#if defined _WANT_IO_LONG_DOUBLE && (LDBL_MANT_DIG > DBL_MANT_DIG)
+#undef _NO_LONGDBL
+#endif
+
+#define _NO_LONGLONG
+#if defined _WANT_IO_LONG_LONG && defined __GNUC__
+# undef _NO_LONGLONG
+#endif
+
+/*
+ * Flush out all the vectors defined by the given uio,
+ * then reset it so that it can be reused.
+ */
+static int
+_DEFUN(__sprint_r, (ptr, fp, uio),
+ struct _reent *ptr _AND
+ FILE *fp _AND
+ register struct __suio *uio)
+{
+ register int err;
+
+ if (uio->uio_resid == 0) {
+ uio->uio_iovcnt = 0;
+ return (0);
+ }
+ err = __sfvwrite_r(ptr, fp, uio);
+ uio->uio_resid = 0;
+ uio->uio_iovcnt = 0;
+ return (err);
+}
+
+/*
+ * Helper function for `fprintf to unbuffered unix file': creates a
+ * temporary buffer. We only work on write-only files; this avoids
+ * worries about ungetc buffers and so forth.
+ */
+static int
+_DEFUN(__sbprintf, (rptr, fp, fmt, ap),
+ struct _reent *rptr _AND
+ register FILE *fp _AND
+ _CONST char *fmt _AND
+ va_list ap)
+{
+ int ret;
+ FILE fake;
+ unsigned char buf[BUFSIZ];
+
+ /* copy the important variables */
+ fake._flags = fp->_flags & ~__SNBF;
+ fake._file = fp->_file;
+ fake._cookie = fp->_cookie;
+ fake._write = fp->_write;
+
+ /* set up the buffer */
+ fake._bf._base = fake._p = buf;
+ fake._bf._size = fake._w = sizeof (buf);
+ fake._lbfsize = 0; /* not actually used, but Just In Case */
+#ifndef __SINGLE_THREAD__
+ __lock_init_recursive (fake._lock);
+#endif
+
+ /* do the work, then copy any error status */
+ ret = _VFPRINTF_R (rptr, &fake, fmt, ap);
+ if (ret >= 0 && fflush(&fake))
+ ret = EOF;
+ if (fake._flags & __SERR)
+ fp->_flags |= __SERR;
+
+#ifndef __SINGLE_THREAD__
+ __lock_close_recursive (fake._lock);
+#endif
+ return (ret);
+}
+
+
+#ifdef FLOATING_POINT
+#include <locale.h>
+#include <math.h>
+#include "floatio.h"
+
+#if ((MAXEXP+MAXFRACT+1) > MB_LEN_MAX)
+# define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */
+#else
+# define BUF MB_LEN_MAX
+#endif
+
+#define DEFPREC 6
+
+#ifdef _NO_LONGDBL
+static char *
+_EXFUN(cvt, (struct _reent *, double, int, int, char *, int *, int, int *));
+#else
+static char *
+_EXFUN(cvt, (struct _reent *, _LONG_DOUBLE, int, int, char *, int *, int, int *));
+extern int _EXFUN(_ldcheck,(_LONG_DOUBLE *));
+#endif
+
+static int _EXFUN(exponent, (char *, int, int));
+
+#else /* no FLOATING_POINT */
+
+#define BUF 40
+
+#endif /* FLOATING_POINT */
+
+#ifndef _NO_LONGLONG
+#define quad_t long long
+#define u_quad_t unsigned long long
+#else
+#define quad_t long
+#define u_quad_t unsigned long
+#endif
+
+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;
+
+#ifndef _NO_POS_ARGS
+#define MAX_POS_ARGS 32
+
+union arg_val
+{
+ int val_int;
+ u_int val_u_int;
+ long val_long;
+ u_long val_u_long;
+ float val_float;
+ double val_double;
+ _LONG_DOUBLE val__LONG_DOUBLE;
+ int_ptr_t val_int_ptr_t;
+ short_ptr_t val_short_ptr_t;
+ long_ptr_t val_long_ptr_t;
+ char_ptr_t val_char_ptr_t;
+ quad_ptr_t val_quad_ptr_t;
+ void_ptr_t val_void_ptr_t;
+ quad_t val_quad_t;
+ u_quad_t val_u_quad_t;
+ wint_t val_wint_t;
+};
+
+static union arg_val *
+_EXFUN(get_arg, (struct _reent *data, int n, char *fmt,
+ va_list *ap, int *numargs, union arg_val *args,
+ int *arg_type, char **last_fmt));
+#endif /* !_NO_POS_ARGS */
+
+/*
+ * 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 HEXPREFIX 0x002 /* add 0x or 0X prefix */
+#define LADJUST 0x004 /* left adjustment */
+#define LONGDBL 0x008 /* long double */
+#define LONGINT 0x010 /* long integer */
+#ifndef _NO_LONGLONG
+#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
+#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 */
+
+int _EXFUN(_VFPRINTF_R, (struct _reent *, FILE *, _CONST char *, va_list));
+
+int
+_DEFUN(VFPRINTF, (fp, fmt0, ap),
+ FILE * fp _AND
+ _CONST char *fmt0 _AND
+ va_list ap)
+{
+ int result;
+ result = _VFPRINTF_R (_REENT, fp, fmt0, ap);
+ return result;
+}
+
+int
+_DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap),
+ struct _reent *data _AND
+ FILE * fp _AND
+ _CONST char *fmt0 _AND
+ va_list ap)
+{
+ register char *fmt; /* format string */
+ register int ch; /* character from fmt */
+ register int n, m; /* handy integers (short term usage) */
+ register char *cp; /* handy char pointer (short term usage) */
+ register struct __siov *iovp;/* for PRINT macro */
+ register int flags; /* flags as above */
+ char *fmt_anchor; /* current format spec being processed */
+ int N; /* arg number */
+ int arg_index; /* index into args processed directly */
+#ifndef _NO_POS_ARGS
+ int numargs; /* number of varargs read */
+ char *saved_fmt; /* saved fmt pointer */
+ union arg_val args[MAX_POS_ARGS];
+ int arg_type[MAX_POS_ARGS];
+ int is_pos_arg; /* is current format positional? */
+ int old_is_pos_arg; /* is current format positional? */
+#endif
+ int ret; /* return value accumulator */
+ int width; /* width from format (%8d), or 0 */
+ int prec; /* precision from format (%.3d), or -1 */
+ char sign; /* sign prefix (' ', '+', '-', or \0) */
+#ifdef FLOATING_POINT
+ char *decimal_point = localeconv()->decimal_point;
+ char softsign; /* temporary negative sign for floats */
+#ifdef _NO_LONGDBL
+ union { int i; double d; } _double_ = {0};
+ #define _fpvalue (_double_.d)
+#else
+ union { int i; _LONG_DOUBLE ld; } _long_double_ = {0};
+ #define _fpvalue (_long_double_.ld)
+ int tmp;
+#endif
+ int expt; /* integer value of exponent */
+ int expsize = 0; /* character count for expstr */
+ int ndig = 0; /* actual number of digits returned by cvt */
+ char expstr[7]; /* buffer for exponent string */
+#endif
+ u_quad_t _uquad; /* integer arguments %[diouxX] */
+ enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */
+ int dprec; /* a copy of prec if [diouxX], 0 otherwise */
+ int realsz; /* field size expanded by dprec */
+ int size; /* size of converted field or string */
+ char *xdigs = NULL; /* digits for [xX] conversion */
+#define NIOV 8
+ struct __suio uio; /* output information: summary */
+ struct __siov iov[NIOV];/* ... and individual io vectors */
+ char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */
+ char ox[2]; /* space for 0x hex-prefix */
+#ifdef _MB_CAPABLE
+ wchar_t wc;
+ mbstate_t state; /* mbtowc calls from library must not change state */
+#endif
+ char *malloc_buf = NULL;/* handy pointer for malloced buffers */
+
+ /*
+ * Choose PADSIZE to trade efficiency vs. size. If larger printf
+ * fields occur frequently, increase PADSIZE and make the initialisers
+ * below longer.
+ */
+#define PADSIZE 16 /* pad chunk size */
+ static _CONST char blanks[PADSIZE] =
+ {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
+ static _CONST char zeroes[PADSIZE] =
+ {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
+
+#ifdef _MB_CAPABLE
+ memset (&state, '\0', sizeof (state));
+#endif
+ /*
+ * BEWARE, these `goto error' on error, and PAD uses `n'.
+ */
+#define PRINT(ptr, len) { \
+ iovp->iov_base = (ptr); \
+ iovp->iov_len = (len); \
+ uio.uio_resid += (len); \
+ iovp++; \
+ if (++uio.uio_iovcnt >= NIOV) { \
+ if (__sprint_r(data, fp, &uio)) \
+ goto error; \
+ iovp = iov; \
+ } \
+}
+#define PAD(howmany, with) { \
+ if ((n = (howmany)) > 0) { \
+ while (n > PADSIZE) { \
+ PRINT (with, PADSIZE); \
+ n -= PADSIZE; \
+ } \
+ PRINT (with, n); \
+ } \
+}
+#define FLUSH() { \
+ if (uio.uio_resid && __sprint_r(data, fp, &uio)) \
+ goto error; \
+ uio.uio_iovcnt = 0; \
+ iovp = iov; \
+}
+
+ /* Macros to support positional arguments */
+#ifndef _NO_POS_ARGS
+#define GET_ARG(n, ap, type) \
+ ( is_pos_arg \
+ ? n < numargs \
+ ? args[n].val_##type \
+ : get_arg (data, n, fmt_anchor, &ap, &numargs, args, arg_type, &saved_fmt)->val_##type \
+ : arg_index++ < numargs \
+ ? args[n].val_##type \
+ : numargs < MAX_POS_ARGS \
+ ? args[numargs++].val_##type = va_arg (ap, type) \
+ : va_arg (ap, type) \
+ )
+#else
+#define GET_ARG(n, ap, type) (va_arg (ap, type))
+#endif
+
+ /*
+ * To extend shorts properly, we need both signed and unsigned
+ * argument extraction methods.
+ */
+#ifndef _NO_LONGLONG
+#define SARG() \
+ (flags&QUADINT ? GET_ARG (N, ap, quad_t) : \
+ 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&QUADINT ? GET_ARG (N, ap, u_quad_t) : \
+ 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))
+#else
+#define SARG() \
+ (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&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))
+#endif
+
+ CHECK_INIT (data);
+ _flockfile (fp);
+
+ /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
+ if (cantwrite (fp)) {
+ _funlockfile (fp);
+ return (EOF);
+ }
+
+ /* optimise fprintf(stderr) (and other unbuffered Unix files) */
+ if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
+ fp->_file >= 0) {
+ _funlockfile (fp);
+ return (__sbprintf (data, fp, fmt0, ap));
+ }
+
+ fmt = (char *)fmt0;
+ uio.uio_iov = iovp = iov;
+ uio.uio_resid = 0;
+ uio.uio_iovcnt = 0;
+ ret = 0;
+ arg_index = 0;
+#ifndef _NO_POS_ARGS
+ saved_fmt = NULL;
+ arg_type[0] = -1;
+ numargs = 0;
+ is_pos_arg = 0;
+#endif
+
+ /*
+ * Scan the format for conversions (`%' character).
+ */
+ for (;;) {
+ cp = fmt;
+#ifdef _MB_CAPABLE
+ while ((n = _mbtowc_r (data, &wc, fmt, MB_CUR_MAX, &state)) > 0) {
+ if (wc == '%')
+ break;
+ fmt += n;
+ }
+#else
+ while (*fmt != '\0' && *fmt != '%')
+ fmt += 1;
+#endif
+ if ((m = fmt - cp) != 0) {
+ PRINT (cp, m);
+ ret += m;
+ }
+#ifdef _MB_CAPABLE
+ if (n <= 0)
+ goto done;
+#else
+ if (*fmt == '\0')
+ goto done;
+#endif
+ fmt_anchor = fmt;
+ fmt++; /* skip over '%' */
+
+ flags = 0;
+ dprec = 0;
+ width = 0;
+ prec = -1;
+ sign = '\0';
+ N = arg_index;
+#ifndef _NO_POS_ARGS
+ is_pos_arg = 0;
+#endif
+
+rflag: ch = *fmt++;
+reswitch: switch (ch) {
+ case ' ':
+ /*
+ * ``If the space and + flags both appear, the space
+ * flag will be ignored.''
+ * -- ANSI X3J11
+ */
+ if (!sign)
+ sign = ' ';
+ goto rflag;
+ case '#':
+ flags |= ALT;
+ goto rflag;
+ case '*':
+ n = N;
+#ifndef _NO_POS_ARGS
+ /* we must check for positional arg used for dynamic width */
+ old_is_pos_arg = is_pos_arg;
+ is_pos_arg = 0;
+ if (is_digit (*fmt)) {
+ char *old_fmt = fmt;
+
+ n = 0;
+ ch = *fmt++;
+ do {
+ n = 10 * n + to_digit (ch);
+ ch = *fmt++;
+ } while (is_digit (ch));
+
+ if (ch == '$') {
+ if (n <= MAX_POS_ARGS) {
+ n -= 1;
+ is_pos_arg = 1;
+ }
+ else
+ goto error;
+ }
+ else {
+ fmt = old_fmt;
+ goto rflag;
+ }
+ }
+#endif /* !_NO_POS_ARGS */
+
+ /*
+ * ``A negative field width argument is taken as a
+ * - flag followed by a positive field width.''
+ * -- ANSI X3J11
+ * They don't exclude field widths read from args.
+ */
+ width = GET_ARG (n, ap, int);
+#ifndef _NO_POS_ARGS
+ is_pos_arg = old_is_pos_arg;
+#endif
+ if (width >= 0)
+ goto rflag;
+ width = -width;
+ /* FALLTHROUGH */
+ case '-':
+ flags |= LADJUST;
+ goto rflag;
+ case '+':
+ sign = '+';
+ goto rflag;
+ case '.':
+ if ((ch = *fmt++) == '*') {
+ n = N;
+#ifndef _NO_POS_ARGS
+ /* we must check for positional arg used for dynamic width */
+ old_is_pos_arg = is_pos_arg;
+ is_pos_arg = 0;
+ if (is_digit (*fmt)) {
+ char *old_fmt = fmt;
+
+ n = 0;
+ ch = *fmt++;
+ do {
+ n = 10 * n + to_digit (ch);
+ ch = *fmt++;
+ } while (is_digit (ch));
+
+ if (ch == '$') {
+ if (n <= MAX_POS_ARGS) {
+ n -= 1;
+ is_pos_arg = 1;
+ }
+ else
+ goto error;
+ }
+ else {
+ fmt = old_fmt;
+ goto rflag;
+ }
+ }
+#endif /* !_NO_POS_ARGS */
+ prec = GET_ARG (n, ap, int);
+#ifndef _NO_POS_ARGS
+ is_pos_arg = old_is_pos_arg;
+#endif
+ if (prec < 0)
+ prec = -1;
+ goto rflag;
+ }
+ n = 0;
+ while (is_digit (ch)) {
+ n = 10 * n + to_digit (ch);
+ ch = *fmt++;
+ }
+ prec = n < 0 ? -1 : n;
+ goto reswitch;
+ case '0':
+ /*
+ * ``Note that 0 is taken as a flag, not as the
+ * beginning of a field width.''
+ * -- ANSI X3J11
+ */
+ flags |= ZEROPAD;
+ goto rflag;
+ case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ n = 0;
+ do {
+ n = 10 * n + to_digit (ch);
+ ch = *fmt++;
+ } while (is_digit (ch));
+#ifndef _NO_POS_ARGS
+ if (ch == '$') {
+ if (n <= MAX_POS_ARGS) {
+ N = n - 1;
+ is_pos_arg = 1;
+ goto rflag;
+ }
+ else
+ goto error;
+ }
+#endif /* !_NO_POS_ARGS */
+ width = n;
+ goto reswitch;
+#ifdef FLOATING_POINT
+ case 'L':
+ flags |= LONGDBL;
+ goto rflag;
+#endif
+ case 'h':
+ if (*fmt == 'h') {
+ fmt++;
+ flags |= CHARINT;
+ } else {
+ flags |= SHORTINT;
+ }
+ goto rflag;
+ case 'l':
+ if (*fmt == 'l') {
+ fmt++;
+ flags |= QUADINT;
+ } else {
+ flags |= LONGINT;
+ }
+ goto rflag;
+ case 'q':
+ flags |= QUADINT;
+ goto rflag;
+ case 'j':
+ if (sizeof (intmax_t) == sizeof (long))
+ flags |= LONGINT;
+ else
+ flags |= QUADINT;
+ goto rflag;
+ case 'z':
+ if (sizeof (size_t) < sizeof (int))
+ /* POSIX states size_t is 16 or more bits, as is short. */
+ flags |= SHORTINT;
+ else if (sizeof (size_t) == sizeof (int))
+ /* no flag needed */;
+ else if (sizeof (size_t) <= sizeof (long))
+ flags |= LONGINT;
+ else
+ /* POSIX states that at least one programming
+ environment must support size_t no wider than
+ long, but that means other environments can
+ have size_t as wide as long long. */
+ flags |= QUADINT;
+ goto rflag;
+ case 't':
+ if (sizeof (ptrdiff_t) < sizeof (int))
+ /* POSIX states ptrdiff_t is 16 or more bits, as
+ is short. */
+ flags |= SHORTINT;
+ else if (sizeof (ptrdiff_t) == sizeof (int))
+ /* no flag needed */;
+ else if (sizeof (ptrdiff_t) <= sizeof (long))
+ flags |= LONGINT;
+ else
+ /* POSIX states that at least one programming
+ environment must support ptrdiff_t no wider than
+ long, but that means other environments can
+ have ptrdiff_t as wide as long long. */
+ flags |= QUADINT;
+ goto rflag;
+ case 'c':
+ case 'C':
+ cp = buf;
+ if (ch == 'C' || (flags & LONGINT)) {
+ mbstate_t ps;
+
+ memset ((_PTR)&ps, '\0', sizeof (mbstate_t));
+ if ((size = (int)_wcrtomb_r (data, cp,
+ (wchar_t)GET_ARG (N, ap, wint_t),
+ &ps)) == -1) {
+ fp->_flags |= __SERR;
+ goto error;
+ }
+ }
+ else {
+ *cp = GET_ARG (N, ap, int);
+ size = 1;
+ }
+ sign = '\0';
+ break;
+ case 'D':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'd':
+ case 'i':
+ _uquad = SARG ();
+#ifndef _NO_LONGLONG
+ if ((quad_t)_uquad < 0)
+#else
+ if ((long) _uquad < 0)
+#endif
+ {
+
+ _uquad = -_uquad;
+ sign = '-';
+ }
+ base = DEC;
+ goto number;
+#ifdef FLOATING_POINT
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'F':
+ case 'g':
+ case 'G':
+ if (prec == -1) {
+ prec = DEFPREC;
+ } else if ((ch == 'g' || ch == 'G') && prec == 0) {
+ prec = 1;
+ }
+
+#ifdef _NO_LONGDBL
+ if (flags & LONGDBL) {
+ _fpvalue = (double) GET_ARG (N, ap, _LONG_DOUBLE);
+ } else {
+ _fpvalue = GET_ARG (N, ap, double);
+ }
+
+ /* do this before tricky precision changes */
+ if (isinf (_fpvalue)) {
+ if (_fpvalue < 0)
+ sign = '-';
+ if (ch == 'E' || ch == 'F' || ch == 'G')
+ cp = "INF";
+ else
+ cp = "inf";
+ size = 3;
+ break;
+ }
+ if (isnan (_fpvalue)) {
+ if (ch == 'E' || ch == 'F' || ch == 'G')
+ cp = "NAN";
+ else
+ cp = "nan";
+ size = 3;
+ break;
+ }
+
+#else /* !_NO_LONGDBL */
+
+ if (flags & LONGDBL) {
+ _fpvalue = GET_ARG (N, ap, _LONG_DOUBLE);
+ } else {
+ _fpvalue = (_LONG_DOUBLE)GET_ARG (N, ap, double);
+ }
+
+ /* do this before tricky precision changes */
+ tmp = _ldcheck (&_fpvalue);
+ if (tmp == 2) {
+ if (_fpvalue < 0)
+ sign = '-';
+ if (ch == 'E' || ch == 'F' || ch == 'G')
+ cp = "INF";
+ else
+ cp = "inf";
+ size = 3;
+ break;
+ }
+ if (tmp == 1) {
+ if (ch == 'E' || ch == 'F' || ch == 'G')
+ cp = "NAN";
+ else
+ cp = "nan";
+ size = 3;
+ break;
+ }
+#endif /* !_NO_LONGDBL */
+
+ flags |= FPT;
+
+ cp = cvt (data, _fpvalue, prec, flags, &softsign,
+ &expt, ch, &ndig);
+
+ if (ch == 'g' || ch == 'G') {
+ if (expt <= -4 || expt > prec)
+ ch = (ch == 'g') ? 'e' : 'E';
+ else
+ ch = 'g';
+ }
+ if (ch <= 'e') { /* 'e' or 'E' fmt */
+ --expt;
+ expsize = exponent (expstr, expt, ch);
+ size = expsize + ndig;
+ if (ndig > 1 || flags & ALT)
+ ++size;
+ } else if (ch == 'f') { /* f fmt */
+ if (expt > 0) {
+ size = expt;
+ if (prec || flags & ALT)
+ size += prec + 1;
+ } else /* "0.X" */
+ size = (prec || flags & ALT)
+ ? prec + 2
+ : 1;
+ } else if (expt >= ndig) { /* fixed g fmt */
+ size = expt;
+ if (flags & ALT)
+ ++size;
+ } else
+ size = ndig + (expt > 0 ?
+ 1 : 2 - expt);
+
+ if (softsign)
+ sign = '-';
+ break;
+#endif /* FLOATING_POINT */
+ case 'n':
+#ifndef _NO_LONGLONG
+ if (flags & QUADINT)
+ *GET_ARG (N, ap, quad_ptr_t) = ret;
+ else
+#endif
+ if (flags & LONGINT)
+ *GET_ARG (N, ap, long_ptr_t) = ret;
+ else if (flags & SHORTINT)
+ *GET_ARG (N, ap, short_ptr_t) = ret;
+ else if (flags & CHARINT)
+ *GET_ARG (N, ap, char_ptr_t) = ret;
+ else
+ *GET_ARG (N, ap, int_ptr_t) = ret;
+ continue; /* no output */
+ case 'O':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'o':
+ _uquad = UARG ();
+ base = OCT;
+ goto nosign;
+ case 'p':
+ /*
+ * ``The argument shall be a pointer to void. The
+ * value of the pointer is converted to a sequence
+ * of printable characters, in an implementation-
+ * defined manner.''
+ * -- ANSI X3J11
+ */
+ /* NOSTRICT */
+ _uquad = (u_long)(unsigned _POINTER_INT)GET_ARG (N, ap, void_ptr_t);
+ base = HEX;
+ xdigs = "0123456789abcdef";
+ flags |= HEXPREFIX;
+ ch = 'x';
+ goto nosign;
+ case 's':
+ case 'S':
+ sign = '\0';
+ if ((cp = GET_ARG (N, ap, char_ptr_t)) == NULL) {
+ cp = "(null)";
+ size = 6;
+ }
+ else if (ch == 'S' || (flags & LONGINT)) {
+ mbstate_t ps;
+ _CONST wchar_t *wcp;
+
+ wcp = (_CONST wchar_t *)cp;
+ size = m = 0;
+ memset ((_PTR)&ps, '\0', sizeof (mbstate_t));
+
+ /* Count number of bytes needed for multibyte
+ string that will be produced from widechar
+ string. */
+ if (prec >= 0) {
+ while (1) {
+ if (wcp[m] == L'\0')
+ break;
+ if ((n = (int)_wcrtomb_r (data,
+ buf, wcp[m], &ps)) == -1) {
+ fp->_flags |= __SERR;
+ goto error;
+ }
+ if (n + size > prec)
+ break;
+ m += 1;
+ size += n;
+ if (size == prec)
+ break;
+ }
+ }
+ else {
+ if ((size = (int)_wcsrtombs_r (data,
+ NULL, &wcp, 0, &ps)) == -1) {
+ fp->_flags |= __SERR;
+ goto error;
+ }
+ wcp = (_CONST wchar_t *)cp;
+ }
+
+ if (size == 0)
+ break;
+
+ if ((malloc_buf =
+ (char *)_malloc_r (data, size + 1)) == NULL) {
+ fp->_flags |= __SERR;
+ goto error;
+ }
+
+ /* Convert widechar string to multibyte string. */
+ memset ((_PTR)&ps, '\0', sizeof (mbstate_t));
+ if (_wcsrtombs_r (data, malloc_buf,
+ &wcp, size, &ps) != size) {
+ fp->_flags |= __SERR;
+ goto error;
+ }
+ cp = malloc_buf;
+ cp[size] = '\0';
+ }
+ else if (prec >= 0) {
+ /*
+ * can't use strlen; can only look for the
+ * NUL in the first `prec' characters, and
+ * strlen () will go further.
+ */
+ char *p = memchr (cp, 0, prec);
+
+ if (p != NULL) {
+ size = p - cp;
+ if (size > prec)
+ size = prec;
+ } else
+ size = prec;
+ } else
+ size = strlen (cp);
+
+ break;
+ case 'U':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'u':
+ _uquad = UARG ();
+ base = DEC;
+ goto nosign;
+ case 'X':
+ xdigs = "0123456789ABCDEF";
+ goto hex;
+ case 'x':
+ xdigs = "0123456789abcdef";
+hex: _uquad = UARG ();
+ base = HEX;
+ /* leading 0x/X only if non-zero */
+ if (flags & ALT && _uquad != 0)
+ flags |= HEXPREFIX;
+
+ /* unsigned conversions */
+nosign: sign = '\0';
+ /*
+ * ``... diouXx conversions ... if a precision is
+ * specified, the 0 flag will be ignored.''
+ * -- ANSI X3J11
+ */
+number: if ((dprec = prec) >= 0)
+ flags &= ~ZEROPAD;
+
+ /*
+ * ``The result of converting a zero value with an
+ * explicit precision of zero is no characters.''
+ * -- ANSI X3J11
+ */
+ cp = buf + BUF;
+ if (_uquad != 0 || prec != 0) {
+ /*
+ * Unsigned mod is hard, and unsigned mod
+ * by a constant is easier than that by
+ * a variable; hence this switch.
+ */
+ switch (base) {
+ case OCT:
+ do {
+ *--cp = to_char (_uquad & 7);
+ _uquad >>= 3;
+ } while (_uquad);
+ /* handle octal leading 0 */
+ if (flags & ALT && *cp != '0')
+ *--cp = '0';
+ break;
+
+ case DEC:
+ /* many numbers are 1 digit */
+ while (_uquad >= 10) {
+ *--cp = to_char (_uquad % 10);
+ _uquad /= 10;
+ }
+ *--cp = to_char (_uquad);
+ break;
+
+ case HEX:
+ do {
+ *--cp = xdigs[_uquad & 15];
+ _uquad >>= 4;
+ } while (_uquad);
+ break;
+
+ default:
+ cp = "bug in vfprintf: bad base";
+ size = strlen (cp);
+ goto skipsize;
+ }
+ }
+ /*
+ * ...result is to be converted to an 'alternate form'.
+ * For o conversion, it increases the precision to force
+ * the first digit of the result to be a zero."
+ * -- ANSI X3J11
+ *
+ * To demonstrate this case, compile and run:
+ * printf ("%#.0o",0);
+ */
+ else if (base == OCT && (flags & ALT))
+ *--cp = '0';
+
+ size = buf + BUF - cp;
+ skipsize:
+ break;
+ default: /* "%?" prints ?, unless ? is NUL */
+ if (ch == '\0')
+ goto done;
+ /* pretend it was %c with argument ch */
+ cp = buf;
+ *cp = ch;
+ size = 1;
+ sign = '\0';
+ break;
+ }
+
+ /*
+ * All reasonable formats wind up here. At this point, `cp'
+ * points to a string which (if not flags&LADJUST) should be
+ * padded out to `width' places. If flags&ZEROPAD, it should
+ * first be prefixed by any sign or other prefix; otherwise,
+ * it should be blank padded before the prefix is emitted.
+ * After any left-hand padding and prefixing, emit zeroes
+ * required by a decimal [diouxX] precision, then print the
+ * string proper, then emit zeroes required by any leftover
+ * floating precision; finally, if LADJUST, pad with blanks.
+ *
+ * Compute actual size, so we know how much to pad.
+ * size excludes decimal prec; realsz includes it.
+ */
+ realsz = dprec > size ? dprec : size;
+ if (sign)
+ realsz++;
+ else if (flags & HEXPREFIX)
+ realsz+= 2;
+
+ /* right-adjusting blank padding */
+ if ((flags & (LADJUST|ZEROPAD)) == 0)
+ PAD (width - realsz, blanks);
+
+ /* prefix */
+ if (sign) {
+ PRINT (&sign, 1);
+ } else if (flags & HEXPREFIX) {
+ ox[0] = '0';
+ ox[1] = ch;
+ PRINT (ox, 2);
+ }
+
+ /* right-adjusting zero padding */
+ if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
+ PAD (width - realsz, zeroes);
+
+ /* leading zeroes from decimal precision */
+ PAD (dprec - size, zeroes);
+
+ /* the string or number proper */
+#ifdef FLOATING_POINT
+ if ((flags & FPT) == 0) {
+ PRINT (cp, size);
+ } else { /* glue together f_p fragments */
+ if (ch >= 'f') { /* 'f' or 'g' */
+ if (_fpvalue == 0) {
+ /* kludge for __dtoa irregularity */
+ PRINT ("0", 1);
+ if (expt < ndig || (flags & ALT) != 0) {
+ PRINT (decimal_point, 1);
+ PAD (ndig - 1, zeroes);
+ }
+ } else if (expt <= 0) {
+ PRINT ("0", 1);
+ if(expt || ndig) {
+ PRINT (decimal_point, 1);
+ PAD (-expt, zeroes);
+ PRINT (cp, ndig);
+ }
+ } else if (expt >= ndig) {
+ PRINT (cp, ndig);
+ PAD (expt - ndig, zeroes);
+ if (flags & ALT)
+ PRINT (".", 1);
+ } else {
+ PRINT (cp, expt);
+ cp += expt;
+ PRINT (".", 1);
+ PRINT (cp, ndig-expt);
+ }
+ } else { /* 'e' or 'E' */
+ if (ndig > 1 || flags & ALT) {
+ ox[0] = *cp++;
+ ox[1] = '.';
+ PRINT (ox, 2);
+ if (_fpvalue) {
+ PRINT (cp, ndig-1);
+ } else /* 0.[0..] */
+ /* __dtoa irregularity */
+ PAD (ndig - 1, zeroes);
+ } else /* XeYYY */
+ PRINT (cp, 1);
+ PRINT (expstr, expsize);
+ }
+ }
+#else
+ PRINT (cp, size);
+#endif
+ /* left-adjusting padding (always blank) */
+ if (flags & LADJUST)
+ PAD (width - realsz, blanks);
+
+ /* finally, adjust ret */
+ ret += width > realsz ? width : realsz;
+
+ FLUSH (); /* copy out the I/O vectors */
+
+ if (malloc_buf != NULL) {
+ _free_r (data, malloc_buf);
+ malloc_buf = NULL;
+ }
+ }
+done:
+ FLUSH ();
+error:
+ if (malloc_buf != NULL)
+ _free_r (data, malloc_buf);
+ _funlockfile (fp);
+ return (__sferror (fp) ? EOF : ret);
+ /* NOTREACHED */
+}
+
+#ifdef FLOATING_POINT
+
+#ifdef _NO_LONGDBL
+extern char *_dtoa_r _PARAMS((struct _reent *, double, int,
+ int, int *, int *, char **));
+#else
+extern char *_ldtoa_r _PARAMS((struct _reent *, _LONG_DOUBLE, int,
+ int, int *, int *, char **));
+#undef word0
+#define word0(x) ldword0(x)
+#endif
+
+#ifdef _NO_LONGDBL
+static char *
+_DEFUN(cvt, (data, value, ndigits, flags, sign, decpt, ch, length),
+ struct _reent *data _AND
+ double value _AND
+ int ndigits _AND
+ int flags _AND
+ char *sign _AND
+ int *decpt _AND
+ int ch _AND
+ int *length)
+#else
+static char *
+_DEFUN(cvt, (data, value, ndigits, flags, sign, decpt, ch, length),
+ struct _reent *data _AND
+ _LONG_DOUBLE value _AND
+ int ndigits _AND
+ int flags _AND
+ char *sign _AND
+ int *decpt _AND
+ int ch _AND
+ int *length)
+#endif
+{
+ int mode, dsgn;
+ char *digits, *bp, *rve;
+#ifdef _NO_LONGDBL
+ union double_union tmp;
+#else
+ union
+ {
+ struct ldieee ieee;
+ _LONG_DOUBLE val;
+ } ld;
+#endif
+
+ if (ch == 'f') {
+ mode = 3; /* ndigits after the decimal point */
+ } else {
+ /* To obtain ndigits after the decimal point for the 'e'
+ * and 'E' formats, round to ndigits + 1 significant
+ * figures.
+ */
+ if (ch == 'e' || ch == 'E') {
+ ndigits++;
+ }
+ mode = 2; /* ndigits significant digits */
+ }
+
+#ifdef _NO_LONGDBL
+ tmp.d = value;
+
+ if (word0 (tmp) & Sign_bit) { /* this will check for < 0 and -0.0 */
+ value = -value;
+ *sign = '-';
+ } else
+ *sign = '\000';
+
+ digits = _dtoa_r (data, value, mode, ndigits, decpt, &dsgn, &rve);
+#else /* !_NO_LONGDBL */
+ ld.val = value;
+ if (ld.ieee.sign) { /* this will check for < 0 and -0.0 */
+ value = -value;
+ *sign = '-';
+ } else
+ *sign = '\000';
+
+ digits = _ldtoa_r (data, value, mode, ndigits, decpt, &dsgn, &rve);
+#endif /* !_NO_LONGDBL */
+
+ if ((ch != 'g' && ch != 'G') || flags & ALT) { /* Print trailing zeros */
+ bp = digits + ndigits;
+ if (ch == 'f') {
+ if (*digits == '0' && value)
+ *decpt = -ndigits + 1;
+ bp += *decpt;
+ }
+ if (value == 0) /* kludge for __dtoa irregularity */
+ rve = bp;
+ while (rve < bp)
+ *rve++ = '0';
+ }
+ *length = rve - digits;
+ return (digits);
+}
+
+static int
+_DEFUN(exponent, (p0, exp, fmtch),
+ char *p0 _AND
+ int exp _AND
+ int fmtch)
+{
+ register char *p, *t;
+ char expbuf[40];
+
+ p = p0;
+ *p++ = fmtch;
+ if (exp < 0) {
+ exp = -exp;
+ *p++ = '-';
+ }
+ else
+ *p++ = '+';
+ t = expbuf + 40;
+ if (exp > 9) {
+ do {
+ *--t = to_char (exp % 10);
+ } while ((exp /= 10) > 9);
+ *--t = to_char (exp);
+ for (; t < expbuf + 40; *p++ = *t++);
+ }
+ else {
+ *p++ = '0';
+ *p++ = to_char (exp);
+ }
+ return (p - p0);
+}
+#endif /* FLOATING_POINT */
+
+
+#ifndef _NO_POS_ARGS
+
+/* Positional argument support.
+ Written by Jeff Johnston
+
+ Copyright (c) 2002 Red Hat Incorporated.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 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.
+
+ The name of Red Hat Incorporated may not be used to endorse
+ or promote products derived from this software without specific
+ prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 RED HAT INCORPORATED 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. */
+
+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] = {
+ /* 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,
+ /* 18-1f */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
+ /* 20-27 */ FLAG, OTHER, OTHER, FLAG, DOLLAR, OTHER, OTHER, OTHER,
+ /* 28-2f */ OTHER, OTHER, STAR, FLAG, OTHER, FLAG, DOT, OTHER,
+ /* 30-37 */ ZERO, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT,
+ /* 38-3f */ DIGIT, DIGIT, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
+ /* 40-47 */ OTHER, OTHER, OTHER, SPEC, SPEC, SPEC, OTHER, SPEC,
+ /* 48-4f */ OTHER, OTHER, OTHER, OTHER, MODFR, OTHER, OTHER, SPEC,
+ /* 50-57 */ OTHER, OTHER, OTHER, SPEC, OTHER, SPEC, OTHER, SPEC,
+ /* 58-5f */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
+ /* 60-67 */ OTHER, OTHER, OTHER, SPEC, SPEC, SPEC, SPEC, SPEC,
+ /* 68-6f */ MODFR, SPEC, OTHER, OTHER, MODFR, OTHER, OTHER, SPEC,
+ /* 70-77 */ SPEC, MODFR, OTHER, SPEC, OTHER, SPEC, OTHER, OTHER,
+ /* 78-7f */ SPEC, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
+ /* 80-87 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
+ /* 88-8f */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
+ /* 90-97 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
+ /* 98-9f */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
+ /* a0-a7 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
+ /* a8-af */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
+ /* b0-b7 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
+ /* b8-bf */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
+ /* c0-c7 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
+ /* c8-cf */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
+ /* d0-d7 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
+ /* d8-df */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
+ /* e0-e7 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
+ /* e8-ef */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
+ /* f0-f7 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
+ /* f8-ff */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
+};
+
+_CONST static 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 },
+ /* WDIG */ { DONE, DONE, WIDTH, SMOD, DONE, SDOT, DONE, DONE, DONE },
+ /* WIDTH */ { DONE, DONE, DONE, SMOD, DONE, SDOT, DONE, DONE, DONE },
+ /* SMOD */ { DONE, DONE, DONE, DONE, DONE, DONE, DONE, DONE, DONE },
+ /* SDOT */ { SDOT, PREC, DONE, SMOD, DONE, DONE, VARP, DONE, DONE },
+ /* VARW */ { DONE, VWDIG, DONE, SMOD, DONE, SDOT, DONE, DONE, DONE },
+ /* VARP */ { DONE, VPDIG, DONE, SMOD, DONE, DONE, DONE, DONE, DONE },
+ /* PREC */ { DONE, DONE, DONE, SMOD, DONE, DONE, DONE, DONE, DONE },
+ /* VWDIG */ { DONE, DONE, WIDTH, DONE, DONE, DONE, DONE, DONE, DONE },
+ /* VPDIG */ { DONE, DONE, PREC, DONE, DONE, DONE, DONE, DONE, DONE },
+};
+
+_CONST static 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 },
+ /* WDIG */ { NOOP, NOOP, GETPOS, GETMOD, GETARG, NOOP, NOOP, NOOP, NOOP },
+ /* WIDTH */ { NOOP, NOOP, NOOP, GETMOD, GETARG, NOOP, NOOP, NOOP, NOOP },
+ /* SMOD */ { NOOP, NOOP, NOOP, NOOP, GETARG, NOOP, NOOP, NOOP, NOOP },
+ /* SDOT */ { NOOP, SKIPNUM, NOOP, GETMOD, GETARG, NOOP, NOOP, NOOP, NOOP },
+ /* VARW */ { NOOP, NUMBER, NOOP, GETPW, GETPWB, GETPW, NOOP, NOOP, NOOP },
+ /* VARP */ { NOOP, NUMBER, NOOP, GETPW, GETPWB, NOOP, NOOP, NOOP, NOOP },
+ /* PREC */ { NOOP, NOOP, NOOP, GETMOD, GETARG, NOOP, NOOP, NOOP, NOOP },
+ /* VWDIG */ { NOOP, NOOP, PWPOS, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP },
+ /* VPDIG */ { NOOP, NOOP, PWPOS, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP },
+};
+
+/* 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),
+ struct _reent *data _AND
+ int n _AND
+ char *fmt _AND
+ va_list *ap _AND
+ int *numargs_p _AND
+ union arg_val *args _AND
+ int *arg_type _AND
+ char **last_fmt)
+{
+ int ch;
+ int number, flags;
+ int spec_type;
+ int numargs = *numargs_p;
+ CH_CLASS chtype;
+ STATE state, next_state;
+ ACTION action;
+ int pos, last_arg;
+ int max_pos_arg = n;
+ enum types { INT, LONG_INT, SHORT_INT, CHAR_INT, QUAD_INT, CHAR, CHAR_PTR, DOUBLE, LONG_DOUBLE, WIDE_CHAR };
+#ifdef _MB_CAPABLE
+ wchar_t wc;
+ mbstate_t wc_state;
+ 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
+ memset (&wc_state, '\0', sizeof (wc_state));
+#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
+ while ((nbytes = _mbtowc_r (data, &wc, fmt, MB_CUR_MAX, &wc_state)) > 0)
+ {
+ fmt += nbytes;
+ if (wc == '%')
+ break;
+ }
+
+ if (nbytes <= 0)
+ break;
+#else
+ while (*fmt != '\0' && *fmt != '%')
+ fmt += 1;
+
+ if (*fmt == '\0')
+ break;
+#endif
+ state = START;
+ flags = 0;
+ pos = -1;
+ number = 0;
+ spec_type = INT;
+
+ /* Use state/action table to process format specifiers. We ignore invalid
+ formats and we are only interested in information that tells us how to
+ read the vararg list. */
+ while (state != DONE)
+ {
+ ch = *fmt++;
+ chtype = chclass[ch];
+ 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':
+ if (*fmt == 'h')
+ {
+ flags |= CHARINT;
+ ++fmt;
+ }
+ else
+ flags |= SHORTINT;
+ break;
+ case 'L':
+ flags |= LONGDBL;
+ break;
+ case 'q':
+ flags |= QUADINT;
+ break;
+ case 'j':
+ if (sizeof (intmax_t) == sizeof (long))
+ flags |= LONGINT;
+ else
+ flags |= QUADINT;
+ break;
+ case 'z':
+ if (sizeof (size_t) < sizeof (int))
+ /* POSIX states size_t is 16 or more bits, as is short. */
+ flags |= SHORTINT;
+ else if (sizeof (size_t) == sizeof (int))
+ /* no flag needed */;
+ else if (sizeof (size_t) <= sizeof (long))
+ flags |= LONGINT;
+ else
+ /* POSIX states that at least one programming
+ environment must support size_t no wider than
+ long, but that means other environments can
+ have size_t as wide as long long. */
+ flags |= QUADINT;
+ break;
+ case 't':
+ if (sizeof (ptrdiff_t) < sizeof (int))
+ /* POSIX states ptrdiff_t is 16 or more bits, as
+ is short. */
+ flags |= SHORTINT;
+ else if (sizeof (ptrdiff_t) == sizeof (int))
+ /* no flag needed */;
+ else if (sizeof (ptrdiff_t) <= sizeof (long))
+ flags |= LONGINT;
+ else
+ /* POSIX states that at least one programming
+ environment must support ptrdiff_t no wider than
+ long, but that means other environments can
+ have ptrdiff_t as wide as long long. */
+ flags |= QUADINT;
+ break;
+ case 'l':
+ default:
+ if (*fmt == 'l')
+ {
+ flags |= QUADINT;
+ ++fmt;
+ }
+ else
+ flags |= LONGINT;
+ break;
+ }
+ break;
+ case GETARG: /* we have format specifier */
+ {
+ numargs &= (MAX_POS_ARGS - 1);
+ /* process the specifier and translate it to a type to fetch from varargs */
+ switch (ch)
+ {
+ case 'd':
+ case 'i':
+ case 'o':
+ case 'x':
+ case 'X':
+ case 'u':
+ if (flags & LONGINT)
+ spec_type = LONG_INT;
+ else if (flags & SHORTINT)
+ spec_type = SHORT_INT;
+ else if (flags & CHARINT)
+ spec_type = CHAR_INT;
+#ifndef _NO_LONGLONG
+ else if (flags & QUADINT)
+ spec_type = QUAD_INT;
+#endif
+ else
+ spec_type = INT;
+ break;
+ case 'D':
+ case 'U':
+ case 'O':
+ spec_type = LONG_INT;
+ break;
+ case 'f':
+ case 'g':
+ case 'G':
+ case 'E':
+ case 'e':
+#ifndef _NO_LONGDBL
+ if (flags & LONGDBL)
+ spec_type = LONG_DOUBLE;
+ else
+#endif
+ spec_type = DOUBLE;
+ break;
+ case 's':
+ case 'S':
+ case 'p':
+ spec_type = CHAR_PTR;
+ break;
+ case 'c':
+ spec_type = CHAR;
+ break;
+ case 'C':
+ spec_type = WIDE_CHAR;
+ break;
+ }
+
+ /* if we have a positional parameter, just store the type, otherwise
+ fetch the parameter from the vararg list */
+ if (pos != -1)
+ arg_type[pos] = spec_type;
+ else
+ {
+ switch (spec_type)
+ {
+ case LONG_INT:
+ args[numargs++].val_long = va_arg (*ap, long);
+ break;
+ case QUAD_INT:
+ args[numargs++].val_quad_t = va_arg (*ap, quad_t);
+ break;
+ case WIDE_CHAR:
+ args[numargs++].val_wint_t = va_arg (*ap, wint_t);
+ break;
+ case CHAR:
+ case CHAR_INT:
+ case SHORT_INT:
+ case INT:
+ args[numargs++].val_int = va_arg (*ap, int);
+ break;
+ case CHAR_PTR:
+ args[numargs++].val_char_ptr_t = va_arg (*ap, char *);
+ break;
+ case DOUBLE:
+ args[numargs++].val_double = va_arg (*ap, double);
+ break;
+ case LONG_DOUBLE:
+ args[numargs++].val__LONG_DOUBLE = va_arg (*ap, _LONG_DOUBLE);
+ break;
+ }
+ }
+ }
+ break;
+ case GETPOS: /* we have positional specifier */
+ if (arg_type[0] == -1)
+ memset (arg_type, 0, sizeof (int) * MAX_POS_ARGS);
+ pos = number - 1;
+ max_pos_arg = (max_pos_arg > pos ? max_pos_arg : pos);
+ break;
+ case PWPOS: /* we have positional specifier for width or precision */
+ if (arg_type[0] == -1)
+ memset (arg_type, 0, sizeof (int) * MAX_POS_ARGS);
+ number -= 1;
+ arg_type[number] = INT;
+ max_pos_arg = (max_pos_arg > number ? max_pos_arg : number);
+ break;
+ case GETPWB: /* we require format pushback */
+ --fmt;
+ /* fallthrough */
+ case GETPW: /* we have a variable precision or width to acquire */
+ args[numargs++].val_int = va_arg (*ap, int);
+ break;
+ case NUMBER: /* we have a number to process */
+ number = (ch - '0');
+ while ((ch = *fmt) != '\0' && is_digit (ch))
+ {
+ number = number * 10 + (ch - '0');
+ ++fmt;
+ }
+ break;
+ case SKIPNUM: /* we have a number to skip */
+ while ((ch = *fmt) != '\0' && is_digit (ch))
+ ++fmt;
+ break;
+ case NOOP:
+ default:
+ break; /* do nothing */
+ }
+ }
+ }
+
+ /* process all arguments up to at least the one we are looking for and if we
+ have seen the end of the string, then process up to the max argument needed */
+ if (*fmt == '\0')
+ last_arg = max_pos_arg;
+ else
+ last_arg = n;
+
+ while (numargs <= last_arg)
+ {
+ switch (arg_type[numargs])
+ {
+ case LONG_INT:
+ args[numargs++].val_long = va_arg (*ap, long);
+ break;
+ case QUAD_INT:
+ args[numargs++].val_quad_t = va_arg (*ap, quad_t);
+ break;
+ case CHAR_PTR:
+ args[numargs++].val_char_ptr_t = va_arg (*ap, char *);
+ break;
+ case DOUBLE:
+ args[numargs++].val_double = va_arg (*ap, double);
+ break;
+ case LONG_DOUBLE:
+ args[numargs++].val__LONG_DOUBLE = va_arg (*ap, _LONG_DOUBLE);
+ break;
+ case WIDE_CHAR:
+ args[numargs++].val_wint_t = va_arg (*ap, wint_t);
+ break;
+ case INT:
+ case CHAR_INT:
+ case SHORT_INT:
+ case CHAR:
+ default:
+ args[numargs++].val_int = va_arg (*ap, int);
+ break;
+ }
+ }
+
+ /* alter the global numargs value and keep a reference to the last bit of the fmt
+ string we processed here because the caller will continue processing where we started */
+ *numargs_p = numargs;
+ *last_fmt = fmt;
+ return &args[n];
+}
+#endif /* !_NO_POS_ARGS */
diff --git a/newlib/libc/time/gmtime.c b/newlib/libc/time/gmtime.c
new file mode 100644
index 00000000000..40116c28589
--- /dev/null
+++ b/newlib/libc/time/gmtime.c
@@ -0,0 +1,66 @@
+/*
+ * gmtime.c
+ * Original Author: G. Haley
+ *
+ * Converts the calendar time pointed to by tim_p into a broken-down time
+ * expressed as Greenwich Mean Time (GMT). Returns a pointer to a structure
+ * containing the broken-down time, or a null pointer if GMT is not
+ * available.
+ */
+
+/*
+FUNCTION
+<<gmtime>>---convert time to UTC traditional form
+
+INDEX
+ gmtime
+
+ANSI_SYNOPSIS
+ #include <time.h>
+ struct tm *gmtime(const time_t *<[clock]>);
+ struct tm *gmtime_r(const time_t *<[clock]>, struct tm *<[res]>);
+
+TRAD_SYNOPSIS
+ #include <time.h>
+ struct tm *gmtime(<[clock]>)
+ const time_t *<[clock]>;
+ struct tm *gmtime_r(<[clock]>, <[res]>)
+ const time_t *<[clock]>;
+ struct tm *<[res]>;
+
+DESCRIPTION
+<<gmtime>> takes the time at <[clock]> representing the number
+of elapsed seconds since 00:00:00 on January 1, 1970, Universal
+Coordinated Time (UTC, also known in some countries as GMT,
+Greenwich Mean time) and converts it to a <<struct tm>>
+representation.
+
+<<gmtime>> constructs the traditional time representation in static
+storage; each call to <<gmtime>> or <<localtime>> will overwrite the
+information generated by previous calls to either function.
+
+RETURNS
+A pointer to the traditional time representation (<<struct tm>>).
+
+PORTABILITY
+ANSI C requires <<gmtime>>.
+
+<<gmtime>> requires no supporting OS subroutines.
+*/
+
+#include <stdlib.h>
+#include <time.h>
+
+#define _GMT_OFFSET 0
+
+#ifndef _REENT_ONLY
+
+struct tm *
+_DEFUN (gmtime, (tim_p),
+ _CONST time_t * tim_p)
+{
+ _REENT_CHECK_TM(_REENT);
+ return gmtime_r (tim_p, (struct tm *)_REENT_TM(_REENT));
+}
+
+#endif