diff --git a/reactos/lib/crtdll/stdlib/ecvt.c b/reactos/lib/crtdll/stdlib/ecvt.c new file mode 100644 index 00000000000..f3a7fd1e1fc --- /dev/null +++ b/reactos/lib/crtdll/stdlib/ecvt.c @@ -0,0 +1,10 @@ +/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +char * +_ecvt (double value, int ndigits, int *decpt, int *sign) +{ + static char ecvt_buf[DBL_MAX_10_EXP + 10]; + return ecvtbuf (value, ndigits, decpt, sign, ecvt_buf); +} diff --git a/reactos/lib/crtdll/stdlib/ecvtbuf.c b/reactos/lib/crtdll/stdlib/ecvtbuf.c new file mode 100644 index 00000000000..6b978fc2862 --- /dev/null +++ b/reactos/lib/crtdll/stdlib/ecvtbuf.c @@ -0,0 +1,107 @@ +/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include +#include + +void __ecvround (char *, char *, const char *, int *); + +void +__ecvround (char *numbuf, char *last_digit, const char *after_last, int *decpt) +{ + char *p; + int carry = 0; + + /* Do we have at all to round the last digit? */ + if (*after_last > '4') + { + p = last_digit; + carry = 1; + + /* Propagate the rounding through trailing '9' digits. */ + do { + int sum = *p + carry; + carry = sum > '9'; + *p-- = sum - carry * 10; + } while (carry && p >= numbuf); + + /* We have 9999999... which needs to be rounded to 100000.. */ + if (carry && p == numbuf) + { + *p = '1'; + *decpt += 1; + } + } +} + +char * +ecvtbuf (double value, int ndigits, int *decpt, int *sign, char *buf) +{ + static char INFINITY[] = "Infinity"; + char decimal = localeconv()->decimal_point[0]; + char *cvtbuf = (char *)alloca (ndigits + 20); /* +3 for sign, dot, null; */ + /* two extra for rounding */ + /* 15 extra for alignment */ + char *s = cvtbuf, *d = buf; + + /* Produce two extra digits, so we could round properly. */ + sprintf (cvtbuf, "%-+.*E", ndigits + 2, value); + *decpt = 0; + + /* The sign. */ + if (*s++ == '-') + *sign = 1; + else + *sign = 0; + + /* Special values get special treatment. */ + if (strncmp (s, "Inf", 3) == 0) + { + /* SunOS docs says we have return "Infinity" for NDIGITS >= 8. */ + memcpy (buf, INFINITY, ndigits >= 8 ? 9 : 3); + if (ndigits < 8) + buf[3] = '\0'; + } + else if (strcmp (s, "NaN") == 0) + memcpy (buf, s, 4); + else + { + char *last_digit, *digit_after_last; + + /* Copy (the single) digit before the decimal. */ + while (*s && *s != decimal && d - buf < ndigits) + *d++ = *s++; + + /* If we don't see any exponent, here's our decimal point. */ + *decpt = d - buf; + if (*s) + s++; + + /* Copy the fraction digits. */ + while (*s && *s != 'E' && d - buf < ndigits) + *d++ = *s++; + + /* Remember the last digit copied and the one after it. */ + last_digit = d > buf ? d - 1 : d; + digit_after_last = s; + + /* Get past the E in exponent field. */ + while (*s && *s++ != 'E') + ; + + /* Adjust the decimal point by the exponent value. */ + *decpt += atoi (s); + + /* Pad with zeroes if needed. */ + while (d - buf < ndigits) + *d++ = '0'; + + /* Zero-terminate. */ + *d = '\0'; + + /* Round if necessary. */ + __ecvround (buf, last_digit, digit_after_last, decpt); + } + return buf; +} diff --git a/reactos/lib/crtdll/stdlib/fcvt.c b/reactos/lib/crtdll/stdlib/fcvt.c new file mode 100644 index 00000000000..40a7dcc9191 --- /dev/null +++ b/reactos/lib/crtdll/stdlib/fcvt.c @@ -0,0 +1,10 @@ +/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +char * +_fcvt (double value, int ndigits, int *decpt, int *sign) +{ + static char fcvt_buf[2 * DBL_MAX_10_EXP + 10]; + return fcvtbuf (value, ndigits, decpt, sign, fcvt_buf); +} diff --git a/reactos/lib/crtdll/stdlib/fcvtbuf.c b/reactos/lib/crtdll/stdlib/fcvtbuf.c new file mode 100644 index 00000000000..f34526fe805 --- /dev/null +++ b/reactos/lib/crtdll/stdlib/fcvtbuf.c @@ -0,0 +1,59 @@ +/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include +#include + +void __ecvround (char *, char *, const char *, int *); + +char * +fcvtbuf (double value, int ndigits, int *decpt, int *sign, char *buf) +{ + static char INFINITY[] = "Infinity"; + char decimal = localeconv()->decimal_point[0]; + int digits = ndigits >= 0 ? ndigits : 0; + char *cvtbuf = (char *)alloca (2*DBL_MAX_10_EXP + 16); + char *s = cvtbuf; + char *dot; + + sprintf (cvtbuf, "%-+#.*f", DBL_MAX_10_EXP + digits + 1, value); + + /* The sign. */ + if (*s++ == '-') + *sign = 1; + else + *sign = 0; + + /* Where's the decimal point? */ + dot = strchr (s, decimal); + *decpt = dot ? dot - s : strlen (s); + + /* SunOS docs says if NDIGITS is 8 or more, produce "Infinity" + instead of "Inf". */ + if (strncmp (s, "Inf", 3) == 0) + { + memcpy (buf, INFINITY, ndigits >= 8 ? 9 : 3); + if (ndigits < 8) + buf[3] = '\0'; + return buf; + } + else if (ndigits < 0) + return ecvtbuf (value, *decpt + ndigits, decpt, sign, buf); + else if (*s == '0' && value != 0.0) + return ecvtbuf (value, ndigits, decpt, sign, buf); + else + { + memcpy (buf, s, *decpt); + if (s[*decpt] == decimal) + { + memcpy (buf + *decpt, s + *decpt + 1, ndigits); + buf[*decpt + ndigits] = '\0'; + } + else + buf[*decpt] = '\0'; + __ecvround (buf, buf + *decpt + ndigits - 1, + s + *decpt + ndigits + 1, decpt); + return buf; + } +} diff --git a/reactos/lib/crtdll/stdlib/gcvt.c b/reactos/lib/crtdll/stdlib/gcvt.c new file mode 100644 index 00000000000..6ce9adf44df --- /dev/null +++ b/reactos/lib/crtdll/stdlib/gcvt.c @@ -0,0 +1,31 @@ +/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include + +char * +_gcvt (double value, int ndigits, char *buf) +{ + char *p = buf; + + sprintf (buf, "%-#.*g", ndigits, value); + + /* It seems they expect us to return .XXXX instead of 0.XXXX */ + if (*p == '-') + p++; + if (*p == '0' && p[1] == '.') + memmove (p, p + 1, strlen (p + 1) + 1); + + /* They want Xe-YY, not X.e-YY, and XXXX instead of XXXX. */ + p = strchr (buf, 'e'); + if (!p) + { + p = buf + strlen (buf); + /* They don't want trailing zeroes. */ + while (p[-1] == '0' && p > buf + 2) + *--p = '\0'; + } + if (p > buf && p[-1] == '.') + memmove (p - 1, p, strlen (p) + 1); + return buf; +} diff --git a/reactos/lib/crtdll/stdlib/itoa.c b/reactos/lib/crtdll/stdlib/itoa.c new file mode 100644 index 00000000000..9cf210965f7 --- /dev/null +++ b/reactos/lib/crtdll/stdlib/itoa.c @@ -0,0 +1,101 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/stdlib/itoa.c + * PURPOSE: converts a integer to ascii + * PROGRAMER: + * UPDATE HISTORY: + * 1995: Created + * 1998: Added ltoa Boudewijn Dekker + */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +char * +itoa(int value, char *string, int radix) +{ + char tmp[33]; + char *tp = tmp; + int i; + unsigned v; + int sign; + char *sp; + + if (radix > 36 || radix <= 1) + { + errno = EDOM; + return 0; + } + + sign = (radix == 10 && value < 0); + if (sign) + v = -value; + else + v = (unsigned)value; + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + *tp++ = i+'0'; + else + *tp++ = i + 'a' - 10; + } + + if (string == 0) + string = (char *)malloc((tp-tmp)+sign+1); + sp = string; + + if (sign) + *sp++ = '-'; + while (tp > tmp) + *sp++ = *--tp; + *sp = 0; + return string; +} + + +char * +ltoa(long value, char *string, int radix) +{ + char tmp[33]; + char *tp = tmp; + long i; + unsigned long v; + int sign; + char *sp; + + if (radix > 36 || radix <= 1) + { + errno = EDOM; + return 0; + } + + sign = (radix == 10 && value < 0); + if (sign) + v = -value; + else + v = (unsigned long)value; + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + *tp++ = i+'0'; + else + *tp++ = i + 'a' - 10; + } + + if (string == 0) + string = (char *)malloc((tp-tmp)+sign+1); + sp = string; + + if (sign) + *sp++ = '-'; + while (tp > tmp) + *sp++ = *--tp; + *sp = 0; + return string; +} +