From 6becb71b7cc0094910c8b36c4cddaf7fce0ebfb5 Mon Sep 17 00:00:00 2001 From: Boudewijn Dekker Date: Sat, 17 Apr 1999 09:10:25 +0000 Subject: [PATCH] Replaced old version of printf and added some long long and long double support. svn path=/trunk/; revision=393 --- reactos/lib/crtdll/float/isnan.c | 73 +- reactos/lib/crtdll/makefile | 6 +- reactos/lib/crtdll/math/ceil.c | 6 + reactos/lib/crtdll/math/floor.c | 16 +- reactos/lib/crtdll/math/huge_val.c | 8 +- reactos/lib/crtdll/math/modf.c | 140 +++- reactos/lib/crtdll/quad/divdi3.c | 66 ++ reactos/lib/crtdll/quad/moddi3.c | 65 ++ reactos/lib/crtdll/quad/qdivrem.c | 281 +++++++ reactos/lib/crtdll/quad/udivdi3.c | 52 ++ reactos/lib/crtdll/quad/umoddi3.c | 54 ++ reactos/lib/crtdll/stdio/getc.c | 31 +- reactos/lib/crtdll/stdio/putc.c | 15 +- reactos/lib/crtdll/stdio/stdhnd.c | 12 +- reactos/lib/crtdll/stdio/vfprintf.c | 1167 +++++++-------------------- 15 files changed, 1072 insertions(+), 920 deletions(-) create mode 100644 reactos/lib/crtdll/quad/divdi3.c create mode 100644 reactos/lib/crtdll/quad/moddi3.c create mode 100644 reactos/lib/crtdll/quad/qdivrem.c create mode 100644 reactos/lib/crtdll/quad/udivdi3.c create mode 100644 reactos/lib/crtdll/quad/umoddi3.c diff --git a/reactos/lib/crtdll/float/isnan.c b/reactos/lib/crtdll/float/isnan.c index 8e0fb24be5d..03947eb5b54 100644 --- a/reactos/lib/crtdll/float/isnan.c +++ b/reactos/lib/crtdll/float/isnan.c @@ -1,21 +1,70 @@ +/* Copyright (C) 1991, 1992, 1995 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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + #include #include +#include - -int _isnan(double x) +int _isnan(double __x) { - if ( x>= 0.0 && x < HUGE_VAL ) - return 0; - else if ( x <= 0.0 && x > HUGE_VAL ) - return 0; - - return 1; + double_t * x = (double_t *)&__x; + return ( x->exponent == 0x7ff && ( x->mantissah != 0 || x->mantissal != 0 )); } -int _isinf(double x) +int _isnanl(long double __x) { - if ( fabs(x) == HUGE_VAL ) - return 1; + /* Intel's extended format has the normally implicit 1 explicit + present. Sigh! */ + + long_double_t * x = (long_double_t *)&__x; + + + /* IEEE 854 NaN's have the maximum possible + exponent and a nonzero mantissa. */ + + return (( x->exponent == 0x7fff) + && ( (x->mantissah & 0x80000000) != 0) + && ( (x->mantissah & (unsigned int)0x7fffffff) != 0 || x->mantissal != 0 )); +} + + +int _isinf(double __x) +{ + double_t * x = (double_t *)&__x; + return ( x->exponent == 0x7ff && ( x->mantissah == 0 && x->mantissal == 0 )); +} + +int _isinfl(long double __x) +{ + /* Intel's extended format has the normally implicit 1 explicit + present. Sigh! */ + + long_double_t * x = (long_double_t *)&__x; + + + /* An IEEE 854 infinity has an exponent with the + maximum possible value and a zero mantissa. */ + + + if ( x->exponent == 0x7fff && ( (x->mantissah == 0x80000000 ) && x->mantissal == 0 )) + return x->sign ? -1 : 1; return 0; -} \ No newline at end of file +} + + diff --git a/reactos/lib/crtdll/makefile b/reactos/lib/crtdll/makefile index 1619e767cd7..19209657fac 100644 --- a/reactos/lib/crtdll/makefile +++ b/reactos/lib/crtdll/makefile @@ -61,6 +61,7 @@ STDIO_OBJECTS = stdio/getenv.o stdio/filbuf.o \ stdio/ungetc.o stdio/vfprintf.o stdio/vprintf.o \ stdio/fdopen.o stdio/vsprintf.o stdio/frlist.o \ +QUAD_OBJECTS = quad/qdivrem.o quad/divdi3.o quad/moddi3.o quad/udivdi3.o quad/umoddi3.o IO_OBJECTS = io/access.o io/close.o io/create.o io/dup.o io/dup2.o io/find.o io/isatty.o io/lseek.o \ io/open.o io/read.o io/setmode.o io/unlink.o io/write.o io/fmode.o io/mktemp.o\ @@ -106,7 +107,7 @@ MATH_OBJECTS = math/acos.o math/acosh.o math/asin.o math/asinh.o math/atan.o mat # $(MISC_OBJECTS) $(STRING_OBJECTS) $(STDIO_OBJECTS) $(STDLIB_OBJECTS) \ # $(IO_OBJECTS) $(PROCESS_OBJECTS) $(TIME_OBJECTS) $(MALLOC_OBJECTS)\ # $(SYS_STAT_OBJECTS) $(SIGNAL_OBJECTS) $(MATH_OBJECTS) $(FLOAT_OBJECTS)\ -# $(SEARCH_OBJECTS) +# $(SEARCH_OBJECTS) $(QUAD_OBJECTS) OLD_OBJECTS = $(MISC_OBJECTS) stdlib/malloc.o stdlib/abort.o \ @@ -115,7 +116,8 @@ OLD_OBJECTS = $(MISC_OBJECTS) stdlib/malloc.o stdlib/abort.o \ stdio/vsprintf.o $(CTYPE_OBJECTS) stdlib/atoi.o stdlib/strtol.o \ stdio/flsbuf.o stdio/putc.o stdio/vfprintf.o $(STRING_OBJECTS)\ io/write.o io/isatty.o sys_stat/fstat.o misc/dllmain.o \ - stdlib/errno.o stdio/printf.o stdio/vprintf.o + stdlib/errno.o stdio/printf.o stdio/vprintf.o\ + $(QUAD_OBJECTS) OBJECTS = $(MISC_OBJECTS) $(STDLIB_OBJECTS) $(IO_OBJECTS) \ $(FLOAT_OBJECTS) $(ASSERT_OBJECTS) $(PROCESS_OBJECTS) \ diff --git a/reactos/lib/crtdll/math/ceil.c b/reactos/lib/crtdll/math/ceil.c index eb750a860f5..a27eab03f0c 100644 --- a/reactos/lib/crtdll/math/ceil.c +++ b/reactos/lib/crtdll/math/ceil.c @@ -12,4 +12,10 @@ double ceil (double __x) __asm __volatile ("fldcw %0" : : "m" (__cw)); return __value; +} + + +long double ceill (long double __x) +{ + return floor(__x)+1; } \ No newline at end of file diff --git a/reactos/lib/crtdll/math/floor.c b/reactos/lib/crtdll/math/floor.c index 3c316805a80..7403a52aa16 100644 --- a/reactos/lib/crtdll/math/floor.c +++ b/reactos/lib/crtdll/math/floor.c @@ -33,4 +33,18 @@ double floor (double __x) __asm __volatile ("fldcw %0" : : "m" (__cw)); return __value; -} \ No newline at end of file +} + +typedef struct IEEExp { + unsigned manl:32; + unsigned manh:32; + unsigned exp:15; + unsigned sign:1; + } long_double_t; + +long double floorl(long double x ) +{ + + return (long double)(long long int)x; +} + diff --git a/reactos/lib/crtdll/math/huge_val.c b/reactos/lib/crtdll/math/huge_val.c index b01e71969ae..91eefa00fed 100644 --- a/reactos/lib/crtdll/math/huge_val.c +++ b/reactos/lib/crtdll/math/huge_val.c @@ -1,12 +1,6 @@ /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ -typedef struct { - unsigned mantissal:32; - unsigned mantissah:20; - unsigned exponent:11; - unsigned sign:1; -} double_t; - +#include #undef _HUGE double_t _HUGE = { 0x00000, 0x00000, 0x7ff, 0x0 }; diff --git a/reactos/lib/crtdll/math/modf.c b/reactos/lib/crtdll/math/modf.c index 8de426b8137..ea77840fa5c 100644 --- a/reactos/lib/crtdll/math/modf.c +++ b/reactos/lib/crtdll/math/modf.c @@ -1,25 +1,135 @@ -// from linux libc + + +/* @(#)s_modf.c 1.3 95/01/18 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + #include +#include -long double modfl(long double x,long double *pint); -/* Slooow version. */ -double modf(double x,double *pint) +//static const double one = 1.0; + +double modf(double __x, double *__i) { - if (x >= 0) - *pint = floor(x); - else - *pint = ceil(x); - return x - *pint; + + double_t * x = (double_t *)&__x; + double_t * iptr = ( double_t *)__i; + + int j0; + unsigned int i; + j0 = x->exponent - 0x3ff; /* exponent of x */ + if(j0<20) { /* integer part in high x */ + if(j0<0) { /* |x|<1 */ + *__i = 0.0; + iptr->sign = x->sign; + return __x; + } else { + i = (0x000fffff)>>j0; + iptr->sign = x->sign; + iptr->exponent = x->exponent; + iptr->mantissah = x->mantissah&(~i); + iptr->mantissal = 0; + if ( __x == *__i ) { + __x = 0.0; + x->sign = iptr->sign; + return __x; + } + + return __x - *__i; + } + } else if (j0>51) { /* no fraction part */ + *__i = __x; + if ( _isnan(__x) || _isinf(__x) ) + return __x; + + + __x = 0.0; + x->sign = iptr->sign; + return __x; + } else { /* fraction part in low x */ + + + i = ((unsigned)(0xffffffff))>>(j0-20); + iptr->sign = x->sign; + iptr->exponent = x->exponent; + iptr->mantissah = x->mantissah; + iptr->mantissal = x->mantissal&(~i); + if ( __x == *__i ) { + __x = 0.0; + x->sign = iptr->sign; + return __x; + } + return __x - *__i; + } } -long double modfl(long double x,long double *pint) + +long double modfl(long double __x, long double *__i) { - if (x >= 0) - *pint = floor(x); - else - *pint = ceil(x); - return x - *pint; + + + long_double_t * x = (long_double_t *)&__x; + long_double_t * iptr = (long_double_t *)__i; + + int j0; + unsigned int i; + j0 = x->exponent - 0x3fff; /* exponent of x */ + + + if(j0<32) { /* integer part in high x */ + if(j0<0) { /* |x|<1 */ + *__i = 0.0; + iptr->sign = x->sign; + return __x; + } else { + + i = ((unsigned int)(0xffffffff))>>(j0); + iptr->sign = x->sign; + iptr->exponent = x->exponent; + iptr->mantissah = x->mantissah&((~i)); + iptr->mantissal = 0; + if ( __x == *__i ) { + __x = 0.0; + x->sign = iptr->sign; + return __x; + } + + return __x - *__i; + } + } else if (j0>63) { /* no fraction part */ + *__i = __x; + if ( _isnanl(__x) || _isinfl(__x) ) + return __x; + + __x = 0.0; + x->sign = iptr->sign; + return __x; + } else { /* fraction part in low x */ + + + i = ((unsigned int)(0xffffffff))>>(j0-32); + iptr->sign = x->sign; + iptr->exponent = x->exponent; + iptr->mantissah = x->mantissah; + iptr->mantissal = x->mantissal&(~i); + if ( __x == *__i ) { + __x = 0.0; + x->sign = iptr->sign; + return __x; + } + return __x - *__i; + + + } } \ No newline at end of file diff --git a/reactos/lib/crtdll/quad/divdi3.c b/reactos/lib/crtdll/quad/divdi3.c new file mode 100644 index 00000000000..899042e0b98 --- /dev/null +++ b/reactos/lib/crtdll/quad/divdi3.c @@ -0,0 +1,66 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * 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. + * + * $Id: divdi3.c,v 1.1 1999/04/17 09:10:23 ariadne Exp $ + */ + +#include + +/* + * Divide two signed quads. + * ??? if -1/2 should produce -1 on this machine, this code is wrong + */ +quad_t +__divdi3(a, b) + quad_t a, b; +{ + u_quad_t ua, ub, uq; + int neg; + + if (a < 0) + ua = -(u_quad_t)a, neg = 1; + else + ua = a, neg = 0; + if (b < 0) + ub = -(u_quad_t)b, neg ^= 1; + else + ub = b; + uq = __qdivrem(ua, ub, (u_quad_t *)0); + return (neg ? -uq : uq); +} + + + diff --git a/reactos/lib/crtdll/quad/moddi3.c b/reactos/lib/crtdll/quad/moddi3.c new file mode 100644 index 00000000000..61a2709c9de --- /dev/null +++ b/reactos/lib/crtdll/quad/moddi3.c @@ -0,0 +1,65 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * 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. + * + * $Id: moddi3.c,v 1.1 1999/04/17 09:10:23 ariadne Exp $ + */ + +#include + +/* + * Return remainder after dividing two signed quads. + * + * XXX + * If -1/2 should produce -1 on this machine, this code is wrong. + */ +quad_t +__moddi3(a, b) + quad_t a, b; +{ + u_quad_t ua, ub, ur; + int neg; + + if (a < 0) + ua = -(u_quad_t)a, neg = 1; + else + ua = a, neg = 0; + if (b < 0) + ub = -(u_quad_t)b, neg ^= 1; + else + ub = b; + (void)__qdivrem(ua, ub, &ur); + return (neg ? -ur : ur); +} \ No newline at end of file diff --git a/reactos/lib/crtdll/quad/qdivrem.c b/reactos/lib/crtdll/quad/qdivrem.c new file mode 100644 index 00000000000..7d0e8126d46 --- /dev/null +++ b/reactos/lib/crtdll/quad/qdivrem.c @@ -0,0 +1,281 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * 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. + * + * $Id: qdivrem.c,v 1.1 1999/04/17 09:10:23 ariadne Exp $ + */ + +/* + * Multiprecision divide. This algorithm is from Knuth vol. 2 (2nd ed), + * section 4.3.1, pp. 257--259. + */ + +#include + +#define B (1 << HALF_BITS) /* digit base */ + +/* Combine two `digits' to make a single two-digit number. */ +#define COMBINE(a, b) (((u_long)(a) << HALF_BITS) | (b)) + +/* select a type for digits in base B: use unsigned short if they fit */ +//#if (ULONG_MAX == 0xffffffff && USHRT_MAX >= 0xffff) +//typedef unsigned short digit; +//#else +typedef u_long digit; +//#endif + +/* + * Shift p[0]..p[len] left `sh' bits, ignoring any bits that + * `fall out' the left (there never will be any such anyway). + * We may assume len >= 0. NOTE THAT THIS WRITES len+1 DIGITS. + */ +static void +shl(register digit *p, register int len, register int sh) +{ + register int i; + + for (i = 0; i < len; i++) + p[i] = LHALF(p[i] << sh) | (p[i + 1] >> (HALF_BITS - sh)); + p[i] = LHALF(p[i] << sh); +} + +/* + * __qdivrem(u, v, rem) returns u/v and, optionally, sets *rem to u%v. + * + * We do this in base 2-sup-HALF_BITS, so that all intermediate products + * fit within u_long. As a consequence, the maximum length dividend and + * divisor are 4 `digits' in this base (they are shorter if they have + * leading zeros). + */ +u_quad_t +__qdivrem(uq, vq, arq) + u_quad_t uq, vq, *arq; +{ + union uu tmp; + digit *u, *v, *q; + register digit v1, v2; + u_long qhat, rhat, t; + int m, n, d, j, i; + digit uspace[5], vspace[5], qspace[5]; + + /* + * Take care of special cases: divide by zero, and u < v. + */ + if (vq == 0) { + /* divide by zero. */ + static volatile const unsigned int zero = 0; + + tmp.ul[H] = tmp.ul[L] = 1 / zero; + if (arq) + *arq = uq; + return (tmp.q); + } + if (uq < vq) { + if (arq) + *arq = uq; + return (0); + } + u = &uspace[0]; + v = &vspace[0]; + q = &qspace[0]; + + /* + * Break dividend and divisor into digits in base B, then + * count leading zeros to determine m and n. When done, we + * will have: + * u = (u[1]u[2]...u[m+n]) sub B + * v = (v[1]v[2]...v[n]) sub B + * v[1] != 0 + * 1 < n <= 4 (if n = 1, we use a different division algorithm) + * m >= 0 (otherwise u < v, which we already checked) + * m + n = 4 + * and thus + * m = 4 - n <= 2 + */ + tmp.uq = uq; + u[0] = 0; + u[1] = HHALF(tmp.ul[H]); + u[2] = LHALF(tmp.ul[H]); + u[3] = HHALF(tmp.ul[L]); + u[4] = LHALF(tmp.ul[L]); + tmp.uq = vq; + v[1] = HHALF(tmp.ul[H]); + v[2] = LHALF(tmp.ul[H]); + v[3] = HHALF(tmp.ul[L]); + v[4] = LHALF(tmp.ul[L]); + for (n = 4; v[1] == 0; v++) { + if (--n == 1) { + u_long rbj; /* r*B+u[j] (not root boy jim) */ + digit q1, q2, q3, q4; + + /* + * Change of plan, per exercise 16. + * r = 0; + * for j = 1..4: + * q[j] = floor((r*B + u[j]) / v), + * r = (r*B + u[j]) % v; + * We unroll this completely here. + */ + t = v[2]; /* nonzero, by definition */ + q1 = u[1] / t; + rbj = COMBINE(u[1] % t, u[2]); + q2 = rbj / t; + rbj = COMBINE(rbj % t, u[3]); + q3 = rbj / t; + rbj = COMBINE(rbj % t, u[4]); + q4 = rbj / t; + if (arq) + *arq = rbj % t; + tmp.ul[H] = COMBINE(q1, q2); + tmp.ul[L] = COMBINE(q3, q4); + return (tmp.q); + } + } + + /* + * By adjusting q once we determine m, we can guarantee that + * there is a complete four-digit quotient at &qspace[1] when + * we finally stop. + */ + for (m = 4 - n; u[1] == 0; u++) + m--; + for (i = 4 - m; --i >= 0;) + q[i] = 0; + q += 4 - m; + + /* + * Here we run Program D, translated from MIX to C and acquiring + * a few minor changes. + * + * D1: choose multiplier 1 << d to ensure v[1] >= B/2. + */ + d = 0; + for (t = v[1]; t < B / 2; t <<= 1) + d++; + if (d > 0) { + shl(&u[0], m + n, d); /* u <<= d */ + shl(&v[1], n - 1, d); /* v <<= d */ + } + /* + * D2: j = 0. + */ + j = 0; + v1 = v[1]; /* for D3 -- note that v[1..n] are constant */ + v2 = v[2]; /* for D3 */ + do { + register digit uj0, uj1, uj2; + + /* + * D3: Calculate qhat (\^q, in TeX notation). + * Let qhat = min((u[j]*B + u[j+1])/v[1], B-1), and + * let rhat = (u[j]*B + u[j+1]) mod v[1]. + * While rhat < B and v[2]*qhat > rhat*B+u[j+2], + * decrement qhat and increase rhat correspondingly. + * Note that if rhat >= B, v[2]*qhat < rhat*B. + */ + uj0 = u[j + 0]; /* for D3 only -- note that u[j+...] change */ + uj1 = u[j + 1]; /* for D3 only */ + uj2 = u[j + 2]; /* for D3 only */ + if (uj0 == v1) { + qhat = B; + rhat = uj1; + goto qhat_too_big; + } else { + u_long n = COMBINE(uj0, uj1); + qhat = n / v1; + rhat = n % v1; + } + while (v2 * qhat > COMBINE(rhat, uj2)) { + qhat_too_big: + qhat--; + if ((rhat += v1) >= B) + break; + } + /* + * D4: Multiply and subtract. + * The variable `t' holds any borrows across the loop. + * We split this up so that we do not require v[0] = 0, + * and to eliminate a final special case. + */ + for (t = 0, i = n; i > 0; i--) { + t = u[i + j] - v[i] * qhat - t; + u[i + j] = LHALF(t); + t = (B - HHALF(t)) & (B - 1); + } + t = u[j] - t; + u[j] = LHALF(t); + /* + * D5: test remainder. + * There is a borrow if and only if HHALF(t) is nonzero; + * in that (rare) case, qhat was too large (by exactly 1). + * Fix it by adding v[1..n] to u[j..j+n]. + */ + if (HHALF(t)) { + qhat--; + for (t = 0, i = n; i > 0; i--) { /* D6: add back. */ + t += u[i + j] + v[i]; + u[i + j] = LHALF(t); + t = HHALF(t); + } + u[j] = LHALF(u[j] + t); + } + q[j] = qhat; + } while (++j <= m); /* D7: loop on j. */ + + /* + * If caller wants the remainder, we have to calculate it as + * u[m..m+n] >> d (this is at most n digits and thus fits in + * u[m+1..m+n], but we may need more source digits). + */ + if (arq) { + if (d) { + for (i = m + n; i > m; --i) + u[i] = (u[i] >> d) | + LHALF(u[i - 1] << (HALF_BITS - d)); + u[i] = 0; + } + tmp.ul[H] = COMBINE(uspace[1], uspace[2]); + tmp.ul[L] = COMBINE(uspace[3], uspace[4]); + *arq = tmp.q; + } + + tmp.ul[H] = COMBINE(qspace[1], qspace[2]); + tmp.ul[L] = COMBINE(qspace[3], qspace[4]); + return (tmp.q); +} + + + + diff --git a/reactos/lib/crtdll/quad/udivdi3.c b/reactos/lib/crtdll/quad/udivdi3.c new file mode 100644 index 00000000000..f9d42c02a5d --- /dev/null +++ b/reactos/lib/crtdll/quad/udivdi3.c @@ -0,0 +1,52 @@ + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * 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. + * + * $Id: udivdi3.c,v 1.1 1999/04/17 09:10:23 ariadne Exp $ + */ + +#include + +/* + * Divide two unsigned quads. + */ +u_quad_t +__udivdi3(a, b) + u_quad_t a, b; +{ + + return (__qdivrem(a, b, (u_quad_t *)0)); +} diff --git a/reactos/lib/crtdll/quad/umoddi3.c b/reactos/lib/crtdll/quad/umoddi3.c new file mode 100644 index 00000000000..f3f37c9032c --- /dev/null +++ b/reactos/lib/crtdll/quad/umoddi3.c @@ -0,0 +1,54 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * 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. + * + * $Id: umoddi3.c,v 1.1 1999/04/17 09:10:23 ariadne Exp $ + */ + +#include + +/* + * Return remainder after dividing two unsigned quads. + */ +u_quad_t +__umoddi3(a, b) + u_quad_t a, b; +{ + u_quad_t r; + + (void)__qdivrem(a, b, &r); + return (r); +} + diff --git a/reactos/lib/crtdll/stdio/getc.c b/reactos/lib/crtdll/stdio/getc.c index afca093097d..a0d10f3c14f 100644 --- a/reactos/lib/crtdll/stdio/getc.c +++ b/reactos/lib/crtdll/stdio/getc.c @@ -1,19 +1,34 @@ #include #include #include +#include #include int getc(FILE *fp) { - if(fp->_cnt > 0) { - fp->_cnt--; - return (int)*fp->_ptr++; - } - else { - return _filbuf(fp); - } - return -1; + +// check for invalid stream + + if ( (int)fp == NULL ) { + __set_errno(EINVAL); + return -1; + } +// check for read access on stream + +// if ( (fp->_flag & _IOREAD) != _IOREAD ) { +// __set_errno(EINVAL); +// return -1; +// } + + if(fp->_cnt > 0) { + fp->_cnt--; + return (int)*fp->_ptr++; + } + else { + return _filbuf(fp); + } + return -1; } // not exported diff --git a/reactos/lib/crtdll/stdio/putc.c b/reactos/lib/crtdll/stdio/putc.c index 2d5197a3182..7b6dc5113de 100644 --- a/reactos/lib/crtdll/stdio/putc.c +++ b/reactos/lib/crtdll/stdio/putc.c @@ -2,6 +2,7 @@ #include #include #include +#include #include int putc(int c, FILE *fp) @@ -9,10 +10,22 @@ int putc(int c, FILE *fp) if ( c == 0 ) c = ' '; +// check for fp == NULL and for putc(fp,c) + + if ( (int)fp < 256 ) { + __set_errno(EINVAL); + return -1; + } +// check for write access on fp + +// if ( (fp->_flag & _IOWRT) != _IOWRT ) { +// __set_errno(EINVAL); +// return -1; +// } + if (fp->_cnt > 0 ) { fp->_cnt--; *(fp)->_ptr++ = (char)c; - *(fp)->_ptr = 0; return (int)c; } else { diff --git a/reactos/lib/crtdll/stdio/stdhnd.c b/reactos/lib/crtdll/stdio/stdhnd.c index 16ceb576eec..7f139e646e4 100644 --- a/reactos/lib/crtdll/stdio/stdhnd.c +++ b/reactos/lib/crtdll/stdio/stdhnd.c @@ -11,34 +11,34 @@ FILE _crtdll_iob[5] = { NULL, 0, NULL, _IOREAD | _IOLBF , - 0, 0,0, NULL, 0 + 0, 0,0, NULL }, // stdout { NULL, 0, NULL, _IOWRT | _IOLBF |_IOSTRG, - 1,0,0, NULL, 0 + 1,0,0, NULL }, // stderr { NULL, 0, NULL, _IOWRT | _IONBF, - 2,0,0, NULL, 0 + 2,0,0, NULL }, // stdaux { NULL, 0, NULL, _IORW | _IONBF, - 3,0,0, NULL, 0 + 3,0,0, NULL }, // stdprn { NULL, 0, NULL, _IOWRT | _IONBF, - 4, 0,0,NULL, 0 + 4, 0,0,NULL } }; FILE (*_iob)[] = &_crtdll_iob; -FILE (*__imp__iob)[] = &_crtdll_iob; + diff --git a/reactos/lib/crtdll/stdio/vfprintf.c b/reactos/lib/crtdll/stdio/vfprintf.c index 67d801745eb..3c4bbf263a8 100644 --- a/reactos/lib/crtdll/stdio/vfprintf.c +++ b/reactos/lib/crtdll/stdio/vfprintf.c @@ -3,7 +3,7 @@ #include #include -#define isascii __isascii + @@ -34,894 +34,325 @@ vfprintf(FILE *f, const char *fmt, va_list ap) } -/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ -/* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */ -/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ -//#include -#include + + + + + +/* + * linux/lib/vsprintf.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */ +/* + * Wirzenius wrote this portably, Torvalds fucked it up :-) + */ + +/* + * Appropiated for the reactos kernel, March 1998 -- David Welch + */ + #include -#include -#include -//#include -#include -#include -#include -//#include -//#include -//#include -static char decimal = '.'; +//#include +#include +#include +#include +#include -/* 11-bit exponent (VAX G floating point) is 308 decimal digits */ -#define MAXEXP 308 -#define MAXEXPLD 4952 /* this includes subnormal numbers */ -/* 128 bit fraction takes up 39 decimal digits; max reasonable precision */ -#define MAXFRACT 39 +//#undef isdigit -#define DEFPREC 6 -#define DEFLPREC 6 +size_t strnlen( const char *string, size_t count ); -#define BUF (MAXEXPLD+MAXFRACT+1) /* + decimal point */ -#define PUTC(ch) (void) putc(ch, fp) - -// adjustedn llong remove from first -#define ARG(basetype) _ulonglong = \ - flags&LONGDBL ? va_arg(argp, basetype) : \ - flags&LONGINT ? va_arg(argp, long basetype) : \ - flags&SHORTINT ? (short basetype)va_arg(argp, int) : \ - va_arg(argp, int) - -// changed name of nan due to conflict with cygwin math header -static int _nan = 0; - -#define MODFL modf -typedef double ldouble; -typedef long llong; -typedef unsigned long ullong; - -ldouble modfl(ldouble x,ldouble *pint); - -static __inline__ int todigit(char c) +static int skip_atoi(const char **s) { - if (c<='0') return 0; - if (c>='9') return 9; - return c-'0'; -} -static __inline__ char tochar(int n) -{ - if (n>=9) return '9'; - if (n<=0) return '0'; - return n+'0'; + int i=0; + + while (isdigit(**s)) + i = i*10 + *((*s)++) - '0'; + return i; } -/* have to deal with the negative buffer count kludge */ +#define ZEROPAD 1 /* pad with zero */ +#define SIGN 2 /* unsigned/signed long */ +#define PLUS 4 /* show plus */ +#define SPACE 8 /* space if plus */ +#define LEFT 16 /* left justified */ +#define SPECIAL 32 /* 0x */ +#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ -#define LONGINT 0x01 /* long integer */ -#define LONGDBL 0x02 /* ldouble */ -#define SHORTINT 0x04 /* short integer */ -#define ALT 0x08 /* alternate form */ -#define LADJUST 0x10 /* left adjustment */ -#define ZEROPAD 0x20 /* zero (as opposed to blank) pad */ -#define HEXPREFIX 0x40 /* add 0x or 0X prefix */ -static int cvtl(ldouble number, int prec, int flags, char *signp, - unsigned char fmtch, char *startp, char *endp); -static char *roundl(ldouble fract, int *expv, char *start, char *end, - char ch, char *signp); -static char *exponentl(char *p, int expv, unsigned char fmtch); -//#ifdef __GO32__ -static int isspeciall(ldouble d, char *bufp); -//#endif +static int __res; -static char NULL_REP[] = "(null)"; +int do_div(int *n,int base) { + +__res = ((unsigned long) *n) % (unsigned) base; +*n = ((unsigned long) *n) / (unsigned) base; +return __res; +} + +static char * number(FILE * f, long num, int base, int size, int precision + ,int type) +{ + char c,sign,tmp[66]; + const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; + int i; + + if (type & LARGE) + digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + if (type & LEFT) + type &= ~ZEROPAD; + if (base < 2 || base > 36) + return 0; + c = (type & ZEROPAD) ? '0' : ' '; + sign = 0; + if (type & SIGN) { + if (num < 0) { + sign = '-'; + num = -num; + size--; + } else if (type & PLUS) { + sign = '+'; + size--; + } else if (type & SPACE) { + sign = ' '; + size--; + } + } + if (type & SPECIAL) { + if (base == 16) + size -= 2; + else if (base == 8) + size--; + } + i = 0; + if (num == 0) + tmp[i++]='0'; + else while (num != 0) + tmp[i++] = digits[do_div(&num,base)]; + if (i > precision) + precision = i; + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + putc( ' ',f); + if (sign) + putc( sign,f); + if (type & SPECIAL) + if (base==8) + putc( '0',f); + else if (base==16) { + putc( '0', f); + putc( digits[33],f); + } + if (!(type & LEFT)) + while (size-- > 0) + putc( c,f); + while (i < precision--) + putc( '0', f); + while (i-- > 0) + putc( tmp[i],f); + while (size-- > 0) + putc( ' ', f); + __res = 0; + return 0; +} int -__vfprintf (FILE *fp, const char *fmt0, va_list argp) +__vfprintf(FILE *f, const char *fmt, va_list args) { - const char *fmt; /* format string */ - int ch; /* character from fmt */ - int cnt; /* return value accumulator */ - int n; /* random handy integer */ - char *t; /* buffer pointer */ - ldouble _ldouble; /* double and ldouble precision arguments - %L.[eEfgG] */ - ullong _ulonglong=0; /* integer arguments %[diouxX] */ - int base; /* base for [diouxX] conversion */ - int dprec; /* decimal precision in [diouxX] */ - int fieldsz; /* field size expanded by sign, etc */ - int flags; /* flags as above */ - int fpprec = 0; /* `extra' floating precision in [eEfgG] */ - int prec = 0; /* precision from format (%.3d), or -1 */ - int realsz; /* field size expanded by decimal precision */ - int size = 0; /* size of converted field or string */ - int width; /* width from format (%8d), or 0 */ - char sign; /* sign prefix (' ', '+', '-', or \0) */ - char softsign; /* temporary negative sign for floats */ - const char *digs; /* digits for [diouxX] conversion */ - char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */ - int neg_ldouble = 0; /* non-zero if _ldouble is negative */ + int len; + unsigned long num; + int i, base; - //decimal = localeconv()->decimal_point[0]; - decimal = '.'; + const char *s; + const short int* sw; - if (fp->_flag & _IORW) - { - fp->_flag |= _IOWRT; - fp->_flag &= ~(_IOEOF|_IOREAD); - } - if ((fp->_flag & _IOWRT) == 0) - return (EOF); + int flags; /* flags to number() */ - fmt = fmt0; - digs = "0123456789abcdef"; - for (cnt = 0;; ++fmt) - { - while ((ch = *fmt) && ch != '%') - { - PUTC (ch); - fmt++; - cnt++; - } - if (!ch) - return cnt; - flags = 0; dprec = 0; fpprec = 0; width = 0; - prec = -1; - sign = '\0'; - rflag: - switch (*++fmt) - { - 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 '*': - /* - * ``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. - */ - if ((width = va_arg(argp, int)) >= 0) - goto rflag; - width = -width; - /* FALLTHROUGH */ - case '-': - flags |= LADJUST; - goto rflag; - case '+': - sign = '+'; - goto rflag; - case '.': - if (*++fmt == '*') - n = va_arg(argp, int); - else - { - n = 0; - while (isascii(*fmt) && isdigit(*fmt)) - n = 10 * n + todigit(*fmt++); - --fmt; - } - prec = n < 0 ? -1 : n; - goto rflag; - 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 + todigit(*fmt); - } while (isascii(*++fmt) && isdigit(*fmt)); - width = n; - --fmt; - goto rflag; - case 'L': - flags |= LONGDBL; - goto rflag; - case 'h': - flags |= SHORTINT; - goto rflag; - case 'l': - if (flags&LONGINT) - flags |= LONGDBL; /* for 'll' - llong */ - else - flags |= LONGINT; - goto rflag; - case 'c': - *(t = buf) = va_arg(argp, int); - size = 1; - sign = '\0'; - goto pforw; - case 'D': - flags |= LONGINT; - /*FALLTHROUGH*/ - case 'd': - case 'i': - ARG(int); - if ((llong)_ulonglong < 0) - { - _ulonglong = -_ulonglong; - sign = '-'; - } - base = 10; - goto number; - case 'e': - case 'E': - case 'f': - case 'g': - case 'G': - if (flags & LONGDBL) - _ldouble = va_arg(argp, ldouble); - else - _ldouble = (ldouble)va_arg(argp, double); - /* - * don't do unrealistic precision; just pad it with - * zeroes later, so buffer size stays rational. - */ - if (prec > MAXFRACT) - { - if (*fmt != 'g' && (*fmt != 'G' || (flags&ALT))) - fpprec = prec - MAXFRACT; - prec = MAXFRACT; - } - else if (prec == -1) - { - if (flags&LONGINT) - prec = DEFLPREC; - else - prec = DEFPREC; - } - /* - * softsign avoids negative 0 if _double is < 0 and - * no significant digits will be shown - */ - if (_ldouble < 0) - { - softsign = '-'; - _ldouble = -_ldouble; - neg_ldouble = 1; - } - else - { - softsign = 0; - neg_ldouble = 0; - } - /* - * cvt may have to round up past the "start" of the - * buffer, i.e. ``intf("%.2f", (double)9.999);''; - * if the first char isn't NULL, it did. - */ - *buf = 0; - size = cvtl(_ldouble, prec, flags, &softsign, *fmt, buf, - buf + sizeof(buf)); - /* - * If the format specifier requested an explicit sign, - * we print a negative sign even if no significant digits - * will be shown, and we also print a sign for a NaN. In - * other words, "%+f" might print -0.000000, +NaN and -NaN. - */ - if (softsign || (sign == '+' && (neg_ldouble || _nan == -1))) - sign = '-'; - _nan = 0; - t = *buf ? buf : buf + 1; - goto pforw; - case 'n': - if (flags & LONGDBL) - *va_arg(argp, llong *) = cnt; - else if (flags & LONGINT) - *va_arg(argp, long *) = cnt; - else if (flags & SHORTINT) - *va_arg(argp, short *) = cnt; - else - *va_arg(argp, int *) = cnt; - break; - case 'O': - flags |= LONGINT; - /*FALLTHROUGH*/ - case 'o': - ARG(unsigned); - base = 8; - 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 */ - _ulonglong = (unsigned long)va_arg(argp, void *); - base = 16; - goto nosign; - case 's': - if (!(t = va_arg(argp, char *))) - t = NULL_REP; - 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() */; + int field_width; /* width of output field */ + int precision; /* min. # of digits for integers; max + number of chars for from string */ + int qualifier; /* 'h', 'l', or 'L' for integer fields */ + + for (; *fmt ; ++fmt) { + if (*fmt != '%') { + putc(*fmt,f); + continue; + } + + /* process flags */ + flags = 0; + repeat: + ++fmt; /* this also skips first '%' */ + switch (*fmt) { + case '-': flags |= LEFT; goto repeat; + case '+': flags |= PLUS; goto repeat; + case ' ': flags |= SPACE; goto repeat; + case '#': flags |= SPECIAL; goto repeat; + case '0': flags |= ZEROPAD; goto repeat; + } + + /* get field width */ + field_width = -1; + if (isdigit(*fmt)) + field_width = skip_atoi(&fmt); + else if (*fmt == '*') { + ++fmt; + /* it's the next argument */ + field_width = va_arg(args, int); + if (field_width < 0) { + field_width = -field_width; + flags |= LEFT; + } + } - if ((p = memchr(t, 0, prec))) - { - size = p - t; - if (size > prec) - size = prec; + /* get the precision */ + precision = -1; + if (*fmt == '.') { + ++fmt; + if (isdigit(*fmt)) + precision = skip_atoi(&fmt); + else if (*fmt == '*') { + ++fmt; + /* it's the next argument */ + precision = va_arg(args, int); + } + if (precision < 0) + precision = 0; + } + + /* get the conversion qualifier */ + qualifier = -1; + if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') { + qualifier = *fmt; + ++fmt; + } + + /* default base */ + base = 10; + + switch (*fmt) { + case 'c': + if (!(flags & LEFT)) + while (--field_width > 0) + putc(' ',f); + putc((unsigned char) va_arg(args, int),f); + while (--field_width > 0) + putc( ' ',f); + continue; + + case 'w': + sw = va_arg(args,short int *); +// DPRINT("L %x\n",sw); + if (sw==NULL) + { +// CHECKPOINT; + s = ""; + while ((*s)!=0) + { + putc( *s++,f); + } +// CHECKPOINT; +// DbgPrint("str %x\n",str); + } + else + { + while ((*sw)!=0) + { + putc( (char)(*sw++),f); + } + } +// CHECKPOINT; + continue; + + case 's': + s = va_arg(args, char *); + if (!s) + s = ""; + + len = strnlen(s, precision); + + if (!(flags & LEFT)) + while (len < field_width--) + putc( ' ', f); + for (i = 0; i < len; ++i) + putc( *s++,f); + while (len < field_width--) + putc( ' ', f); + continue; + + case 'p': + if (field_width == -1) { + field_width = 2*sizeof(void *); + flags |= ZEROPAD; + } + number(f, + (unsigned long) va_arg(args, void *), 16, + field_width, precision, flags); + continue; + + + case 'n': + if (qualifier == 'l') { + long * ip = va_arg(args, long *); + //*ip = (str - buf); + } else { + int * ip = va_arg(args, int *); + //*ip = (str - buf); + } + continue; + + /* integer number formats - set up the flags and "break" */ + case 'o': + base = 8; + break; + + case 'b': + base = 2; + break; + + case 'X': + flags |= LARGE; + case 'x': + base = 16; + break; + + case 'd': + case 'i': + flags |= SIGN; + case 'u': + break; + + default: + if (*fmt != '%') + putc( '%', f); + if (*fmt) + putc( *fmt, f); + else + --fmt; + continue; + } + if (qualifier == 'l') + num = va_arg(args, unsigned long); + else if (qualifier == 'h') + if (flags & SIGN) + num = va_arg(args, short); + else + num = va_arg(args, unsigned short); + else if (flags & SIGN) + num = va_arg(args, int); + else + num = va_arg(args, unsigned int); + number(f, num, base, field_width, precision, flags); } - else - size = prec; - } - else - size = strlen(t); - sign = '\0'; - goto pforw; - case 'U': - flags |= LONGINT; - /*FALLTHROUGH*/ - case 'u': - ARG(unsigned); - base = 10; - goto nosign; - case 'X': - digs = "0123456789ABCDEF"; - /* FALLTHROUGH */ - case 'x': - ARG(unsigned); - base = 16; - /* leading 0x/X only if non-zero */ - if (flags & ALT && _ulonglong != 0) - flags |= HEXPREFIX; - - nosign: - /* unsigned conversions */ - sign = '\0'; - number: - /* - * ``... diouXx conversions ... if a precision is - * specified, the 0 flag will be ignored.'' - * -- ANSI X3J11 - */ - if ((dprec = prec) >= 0) - flags &= ~ZEROPAD; - - /* - * ``The result of converting a zero value with an - * explicit precision of zero is no characters.'' - * -- ANSI X3J11 - */ - t = buf + BUF; - - if (_ulonglong != 0 || prec != 0) - { - /* conversion is done separately since operations - with llong are much slower */ -#define CONVERT(type) \ - { \ - register type _n = (type)_ulonglong; \ - do { \ - *--t = digs[_n % base]; \ - _n /= base; \ - } while (_n); \ - } - if (flags&LONGDBL) - CONVERT(ullong) /* no ; */ - else - CONVERT(unsigned long) /* no ; */ -#undef CONVERT - if (flags & ALT && base == 8 && *t != '0') - *--t = '0'; /* octal leading 0 */ - } - - digs = "0123456789abcdef"; - size = buf + BUF - t; - - pforw: - /* - * All reasonable formats wind up here. At this point, - * `t' 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 - * fieldsz excludes decimal prec; realsz includes it - */ - fieldsz = size + fpprec; - realsz = dprec > fieldsz ? dprec : fieldsz; - if (sign) - realsz++; - if (flags & HEXPREFIX) - realsz += 2; - - /* right-adjusting blank padding */ - if ((flags & (LADJUST|ZEROPAD)) == 0 && width) - for (n = realsz; n < width; n++) - PUTC(' '); - /* prefix */ - if (sign) - PUTC(sign); - if (flags & HEXPREFIX) - { - PUTC('0'); - PUTC((char)*fmt); - } - /* right-adjusting zero padding */ - if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) - for (n = realsz; n < width; n++) - PUTC('0'); - /* leading zeroes from decimal precision */ - for (n = fieldsz; n < dprec; n++) - PUTC('0'); - - /* the string or number proper */ - for (n = size; n > 0; n--) - PUTC(*t++); - /* trailing f.p. zeroes */ - while (--fpprec >= 0) - PUTC('0'); - /* left-adjusting padding (always blank) */ - if (flags & LADJUST) - for (n = realsz; n < width; n++) - PUTC(' '); - /* finally, adjust cnt */ - cnt += width > realsz ? width : realsz; - break; - case '\0': /* "%?" prints ?, unless ? is NULL */ - return cnt; - default: - PUTC((char)*fmt); - cnt++; - } - } - /* NOTREACHED */ -} - -static ldouble pten[] = -{ - 1e1L, 1e2L, 1e4L, 1e8L, 1e16L, 1e32L, 1e64L, 1e128L, 1e256L -}; - -// 1e512L, 1e1024L, 1e2048L, 1e4096L - -static ldouble ptenneg[] = -{ - 1e-1L, 1e-2L, 1e-4L, 1e-8L, 1e-16L, 1e-32L, 1e-64L, 1e-128L, 1e-256L -}; -// 1e-512L, 1e-1024L, 1e-2048L, 1e-4096L - -#define MAXP 4096 -#define NP 12 -#define P (4294967296.0L * 4294967296.0L * 2.0L) /* 2^65 */ -static ldouble INVPREC = P; -static ldouble PREC = 1.0L/P; -#undef P -/* - * Defining FAST_LDOUBLE_CONVERSION results in a little bit faster - * version, which might be less accurate (about 1 bit) for long - * double. For 'normal' double it doesn't matter. - */ -/* #define FAST_LDOUBLE_CONVERSION */ - -static int -cvtl(ldouble number, int prec, int flags, char *signp, unsigned char fmtch, - char *startp, char *endp) -{ - char *p, *t; - ldouble fract=0; - int dotrim, expcnt, gformat; - int doextradps=0; /* Do extra decimal places if the precision needs it */ - int doingzero=0; /* We're displaying 0.0 */ - ldouble integer, tmp; - - if ((expcnt = isspeciall(number, startp))) - return(expcnt); - - dotrim = expcnt = gformat = 0; - /* fract = modfl(number, &integer); */ - integer = number; - - /* get an extra slot for rounding. */ - t = ++startp; - - p = endp - 1; - if (integer) - { - int i, lp=NP, pt=MAXP; -#ifndef FAST_LDOUBLE_CONVERSION - ldouble oint = integer, dd=1.0L; -#endif - if (integer > INVPREC) - { - integer *= PREC; - while(lp >= 0) { - if (integer >= pten[lp]) - { - expcnt += pt; - integer *= ptenneg[lp]; -#ifndef FAST_LDOUBLE_CONVERSION - dd *= pten[lp]; -#endif - } - pt >>= 1; - lp--; - } -#ifndef FAST_LDOUBLE_CONVERSION - integer = oint/dd; -#else - integer *= INVPREC; -#endif - } - /* - * Do we really need this ? - */ - for (i = 0; i < expcnt; i++) - *p-- = '0'; - } - number = integer; - fract = MODFL(number, &integer); - /* If integer is zero then we need to look at where the sig figs are */ - if (integer<1) { - /* If fract is zero the zero before the decimal point is a sig fig */ - if (fract==0.0) doingzero=1; - /* If fract is non-zero all sig figs are in fractional part */ - else doextradps=1; - } - /* - * get integer portion of number; put into the end of the buffer; the - * .01 is added for modf(356.0 / 10, &integer) returning .59999999... - */ - for (; integer; ++expcnt) - { - tmp = MODFL(integer * 0.1L , &integer); - *p-- = tochar((int)((tmp + .01L) * 10)); - } - switch(fmtch) - { - case 'f': - /* reverse integer into beginning of buffer */ - if (expcnt) - for (; ++p < endp; *t++ = *p); - else - *t++ = '0'; - /* - * if precision required or alternate flag set, add in a - * decimal point. - */ - if (prec || flags&ALT) - *t++ = decimal; - /* if requires more precision and some fraction left */ - if (fract) - { - if (prec) - do { - fract = MODFL(fract * 10.0L, &tmp); - *t++ = tochar((int)tmp); - } while (--prec && fract); - if (fract) - startp = roundl(fract, (int *)NULL, startp, - t - 1, (char)0, signp); - } - for (; prec--; *t++ = '0'); - break; - case 'e': - case 'E': - eformat: - if (expcnt) - { - *t++ = *++p; - if (prec || flags&ALT) - *t++ = decimal; - /* if requires more precision and some integer left */ - for (; prec && ++p < endp; --prec) - *t++ = *p; - /* - * if done precision and more of the integer component, - * round using it; adjust fract so we don't re-round - * later. - */ - if (!prec && ++p < endp) - { - fract = 0; - startp = roundl((ldouble)0.0L, &expcnt, - startp, t - 1, *p, signp); - } - /* adjust expcnt for digit in front of decimal */ - --expcnt; - } - /* until first fractional digit, decrement exponent */ - else if (fract) - { - int lp=NP, pt=MAXP; -#ifndef FAST_LDOUBLE_CONVERSION - ldouble ofract = fract, dd=1.0L; -#endif - expcnt = -1; - if (fract < PREC) - { - fract *= INVPREC; - while(lp >= 0) - { - if (fract <= ptenneg[lp]) - { - expcnt -= pt; - fract *= pten[lp]; -#ifndef FAST_LDOUBLE_CONVERSION - dd *= pten[lp]; -#endif - } - pt >>= 1; - lp--; - } -#ifndef FAST_LDOUBLE_CONVERSION - fract = ofract*dd; -#else - fract *= PREC; -#endif - } - /* adjust expcnt for digit in front of decimal */ - for ( /* expcnt = -1 */ ;; --expcnt) - { - fract = MODFL(fract * 10.0L, &tmp); - if (tmp) - break; - } - *t++ = tochar((int)tmp); - if (prec || flags&ALT) - *t++ = decimal; - } - else - { - *t++ = '0'; - if (prec || flags&ALT) - *t++ = decimal; - } - /* if requires more precision and some fraction left */ - if (fract) - { - if (prec) - do { - fract = MODFL(fract * 10.0L, &tmp); - *t++ = tochar((int)tmp); - } while (--prec && fract); - if (fract) - startp = roundl(fract, &expcnt, startp, - t - 1, (char)0, signp); - } - /* if requires more precision */ - for (; prec--; *t++ = '0'); - - /* unless alternate flag, trim any g/G format trailing 0's */ - if (gformat && !(flags&ALT)) - { - while (t > startp && *--t == '0'); - if (*t == decimal) - --t; - ++t; - } - t = exponentl(t, expcnt, fmtch); - break; - case 'g': - case 'G': - if (prec) { - /* If doing zero and precision is greater than 0 count the - * 0 before the decimal place */ - if (doingzero) --prec; - } - else { - /* a precision of 0 is treated as precision of 1 unless doing zero */ - if (!doingzero) ++prec; - } - /* - * ``The style used depends on the value converted; style e - * will be used only if the exponent resulting from the - * conversion is less than -4 or greater than the precision.'' - * -- ANSI X3J11 - */ - if (expcnt > prec || (!expcnt && fract && fract < .0001)) - { - /* - * g/G format counts "significant digits, not digits of - * precision; for the e/E format, this just causes an - * off-by-one problem, i.e. g/G considers the digit - * before the decimal point significant and e/E doesn't - * count it as precision. - */ - --prec; - fmtch -= 2; /* G->E, g->e */ - gformat = 1; - goto eformat; - } - /* - * reverse integer into beginning of buffer, - * note, decrement precision - */ - if (expcnt) - for (; ++p < endp; *t++ = *p, --prec); - else - *t++ = '0'; - /* - * if precision required or alternate flag set, add in a - * decimal point. If no digits yet, add in leading 0. - */ - if (prec || flags&ALT) - { - dotrim = 1; - *t++ = decimal; - } - else - dotrim = 0; - /* if requires more precision and some fraction left */ - while (prec && fract) - { - fract = MODFL(fract * 10.0L, &tmp); - *t++ = tochar((int)tmp); - /* If we're not adding 0s - * or we are but they're sig figs: - * decrement the precision */ - if ((doextradps!=1) || ((int)tmp!=0)) { - doextradps=0; - prec--; - } - } - if (fract) - startp = roundl(fract, (int *)NULL, startp, t - 1, - (char)0, signp); - /* alternate format, adds 0's for precision, else trim 0's */ - if (flags&ALT) - for (; prec--; *t++ = '0'); - else if (dotrim) - { - while (t > startp && *--t == '0'); - if (*t != decimal) - ++t; - } - } - return t - startp; -} - -static char * -roundl(ldouble fract, int *expv, char *start, char *end, char ch, - char *signp) -{ - ldouble tmp; - - if (fract) - { - if (fract == 0.5L) - { - char *e = end; - if (*e == '.') - e--; - if (*e == '0' || *e == '2' || *e == '4' - || *e == '6' || *e == '8') - { - tmp = 3.0; - goto start; - } - } - (void)MODFL(fract * 10.0L, &tmp); - } - else - tmp = todigit(ch); - start: - if (tmp > 4) - for (;; --end) - { - if (*end == decimal) - --end; - if (++*end <= '9') - break; - *end = '0'; - if (end == start) - { - if (expv) - { /* e/E; increment exponent */ - *end = '1'; - ++*expv; - } - else - { /* f; add extra digit */ - *--end = '1'; - --start; - } - break; - } - } - /* ``"%.3f", (double)-0.0004'' gives you a negative 0. */ - else if (*signp == '-') - for (;; --end) - { - if (*end == decimal) - --end; - if (*end != '0') - break; - if (end == start) - *signp = 0; - } - return start; -} - -static char * -exponentl(char *p, int expv, unsigned char fmtch) -{ - char *t; - char expbuf[MAXEXPLD]; - - *p++ = fmtch; - if (expv < 0) - { - expv = -expv; - *p++ = '-'; - } - else - *p++ = '+'; - t = expbuf + MAXEXPLD; - if (expv > 9) - { - do { - *--t = tochar(expv % 10); - } while ((expv /= 10) > 9); - *--t = tochar(expv); - for (; t < expbuf + MAXEXPLD; *p++ = *t++); - } - else - { - *p++ = '0'; - *p++ = tochar(expv); - } - return p; -} - -static int -isspeciall(ldouble d, char *bufp) -{ - struct IEEExp { - unsigned manl:32; - unsigned manh:32; - unsigned exp:15; - unsigned sign:1; - } *ip = (struct IEEExp *)&d; - - _nan = 0; /* don't assume the static is 0 (emacs) */ - if (ip->exp != 0x7fff) - return(0); - if ((ip->manh & 0x7fffffff) || ip->manl) - { - strcpy(bufp, "NaN"); - _nan = ip->sign ? -1 : 1; /* kludge: we don't need the sign, it's not nice - but it should work */ - } - else - (void)strcpy(bufp, "Inf"); - return(3); + //putc('\0',f); + return 0; } +