Sc6.10 missing function format.c
Jeffery A Buhrt
buhrt at sawmill.uucp
Tue Oct 30 00:28:48 AEST 1990
Sorry, format.c was not included in the patch set.
-Jeff Buhrt
317-477-6000
sequent!sawmill!buhrt
#!/bin/sh
# This is a shell archive (shar 3.20)
# made 10/29/1990 13:28 UTC by buhrt at sawmill
# Source directory /users/buhrt/src/sc
#
# existing files WILL be overwritten
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 13822 -r--r--r-- format.c
#
if touch 2>&1 | fgrep '[-amc]' > /dev/null
then TOUCH=touch
else TOUCH=true
fi
# ============= format.c ==============
echo "x - extracting format.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > format.c &&
X/*****************************************************************************
X *
X * Mark Nagel <nagel at ics.uci.edu>
X * 20 July 1989
X *
X * $Revision: 6.10 $
X *
X * bool
X * format(fmt, num, buf, buflen)
X * char *fmt;
X * double num;
X * char buf[];
X * int buflen;
X *
X * The format function will produce a string representation of a number
X * given a _format_ (described below) and a double value. The result is
X * written into the passed buffer -- if the resulting string is too
X * long to fit into the passed buffer, the function returns false.
X * Otherwise the function returns true.
X *
X * The fmt parameter contains the format to use to convert the number.
X *
X * # Digit placeholder. If the number has fewer digits on either
X * side of the decimal point than there are '#' characters in
X * the format, the extra '#' characters are ignored. The number
X * is rounded to the number of digit placeholders as there are
X * to the right of the decimal point. If there are more digits
X * in the number than there are digit placeholders on the left
X * side of the decimal point, then those digits are displayed.
X *
X * 0 Digit placeholder. Same as for '#' except that the number
X * is padded with zeroes on either side of the decimal point.
X * The number of zeroes used in padding is determined by the
X * number of digit placeholders after the '0' for digits on
X * the left side of the decimal point and by the number of
X * digit placeholders before the '0' for digits on the right
X * side of the decimal point.
X *
X * . Decimal point. Determines how many digits are placed on
X * the right and left sides of the decimal point in the number.
X * Note that numbers smaller than 1 will begin with a decimal
X * point if the left side of the decimal point contains only
X * a '#' digit placeholder. Use a '0' placeholder to get a
X * leading zero in decimal formats.
X *
X * % Percentage. For each '%' character in the format, the actual
X * number gets multiplied by 100 (only for purposes of formatting
X * -- the original number is left unmodified) and the '%' character
X * is placed in the same position as it is in the format.
X *
X * , Thousands separator. The presence of a ',' in the format
X * (multiple commas are treated as one) will cause the number
X * to be formatted with a ',' separating each set of three digits
X * in the integer part of the number with numbering beginning
X * from the right end of the integer.
X *
X * \ Quote. This character causes the next character to be
X * inserted into the formatted string directly with no
X * special interpretation.
X *
X * E- E+ e- e+
X * Scientific format. Causes the number to formatted in scientific
X * notation. The case of the 'E' or 'e' given is preserved. If
X * the format uses a '+', then the sign is always given for the
X * exponent value. If the format uses a '-', then the sign is
X * only given when the exponent value is negative. Note that if
X * there is no digit placeholder following the '+' or '-', then
X * that part of the formatted number is left out. In general,
X * there should be one or more digit placeholders after the '+'
X * or '-'.
X *
X * ; Format selector. Use this character to separate the format
X * into two distinct formats. The format to the left of the
X * ';' character will be used if the number given is zero or
X * positive. The format to the right of the ';' character is
X * used if the number given is negative.
X *
X * Any
X * Self insert. Any other character will be inserted directly
X * into the formatted number with no change made to the actual
X * number.
X *
X *****************************************************************************/
X
X/*****************************************************************************/
X
X#include <stdio.h>
X
X#define bool int
X#define true 1
X#define false 0
X#define EOS '\0'
X#define MAXBUF 256
X
Xextern char
X *strcpy();
X
Xstatic char
X *fmt_int(),
X *fmt_frac(),
X *fmt_exp();
X
Xstatic void
X reverse();
X
X/*****************************************************************************/
X
Xbool
Xformat(fmt, val, buf, buflen)
X char *fmt;
X double val;
X char *buf;
X int buflen;
X{
X register char *cp;
X char *tmp, *tp, *tmpfmt;
X bool comma = false, negative = false;
X char *integer = NULL, *decimal = NULL;
X char *exponent = NULL;
X int exp_val, width;
X char prtfmt[32];
X char *mantissa;
X char *fraction = NULL;
X int zero_pad = 0;
X
X if (fmt == NULL)
X return(true);
X
X fmt = tmpfmt = strcpy((char *) xmalloc(strlen(fmt) + 1), fmt);
X mantissa = (char *) xmalloc(buflen + 1);
X
X /*
X * select positive or negative format if necessary
X */
X for (cp = fmt; *cp != ';' && *cp != EOS; cp++)
X {
X if (*cp == '\\')
X cp++;
X }
X if (*cp == ';')
X {
X if (val < 0.0)
X {
X val = -val; /* format should provide sign if desired */
X fmt = cp + 1;
X }
X else
X {
X *cp = EOS;
X }
X }
X
X /*
X * extract other information from format and produce new
X * malloc'ed format string
X */
X tmp = (char *) xmalloc(strlen(fmt) + 1);
X for (cp = fmt, tp = tmp; *cp != EOS; cp++)
X {
X switch (*cp)
X {
X case '\\':
X *tp++ = *cp++;
X *tp++ = *cp;
X break;
X
X case ',':
X comma = true;
X break;
X
X case '.':
X if (decimal == NULL)
X decimal = tp;
X *tp++ = *cp;
X break;
X
X case '%':
X val *= 100.0;
X *tp++ = *cp;
X break;
X
X default:
X *tp++ = *cp;
X break;
X }
X }
X *tp = EOS;
X xfree(tmpfmt);
X fmt = tmp;
X
X /*
X * extract the exponent from the format if present
X */
X for (cp = fmt; *cp != EOS; cp++)
X {
X if (*cp == '\\')
X {
X cp++;
X }
X else if (*cp == 'e' || *cp == 'E')
X {
X if (cp[1] == '+' || cp[1] == '-')
X {
X tmp = (char *) xmalloc(strlen(cp) + 1);
X exponent = strcpy(tmp, cp);
X *cp = EOS;
X exp_val = 0;
X while (val < 1.0)
X {
X val *= 10.0;
X exp_val--;
X }
X while (val >= 10.0)
X {
X val /= 10.0;
X exp_val++;
X }
X break;
X }
X }
X }
X
X /*
X * determine maximum decimal places and use sprintf
X * to build initial character form of formatted value.
X */
X width = 0;
X if (decimal)
X {
X *decimal++ = EOS;
X for (cp = decimal; *cp != EOS; cp++)
X {
X switch (*cp)
X {
X case '\\':
X cp++;
X break;
X
X case '#':
X width++;
X break;
X
X case '0':
X zero_pad = ++width;
X break;
X }
X }
X zero_pad = strlen(decimal) - zero_pad;
X }
X if (val < 0.0)
X {
X negative = true;
X val = -val;
X }
X sprintf(prtfmt, "%%.%dlf", width);
X sprintf(mantissa, prtfmt, val);
X for (cp = integer = mantissa; *cp != '.' && *cp != EOS; cp++)
X {
X if (*integer == '0')
X integer++;
X }
X if (*cp == '.')
X {
X fraction = cp + 1;
X *cp = EOS;
X cp = fraction + strlen(fraction) - 1;
X for (; zero_pad > 0; zero_pad--, cp--)
X {
X if (*cp == '0')
X *cp = EOS;
X }
X }
X
X /*
X * format the puppy
X */
X {
X char *ci, *cf, *ce;
X int len_ci, len_cf, len_ce;
X bool ret = false;
X
X ci = fmt_int(integer, fmt, comma, negative);
X ci = strcpy((char *)xmalloc((len_ci = strlen(ci)) + 1), ci);
X cf = (fraction) ? fmt_frac(fraction, decimal) : "";
X cf = strcpy((char *)xmalloc((len_cf = strlen(cf)) + 1), cf);
X ce = (exponent) ? fmt_exp(exp_val, exponent) : "";
X ce = strcpy((char *)xmalloc((len_ce = strlen(ce)) + 1), ce);
X if (len_ci + len_cf + len_ce < buflen)
X {
X sprintf(buf, "%s%s%s", ci, cf, ce);
X ret = true;
X }
X
X /*
X * free up malloc'ed memory
X */
X xfree(mantissa);
X xfree(fmt);
X if (exponent) xfree(exponent);
X xfree(ci);
X xfree(cf);
X xfree(ce);
X
X return (ret);
X }
X}
X
X/*****************************************************************************/
X
Xstatic char *
Xfmt_int(val, fmt, comma, negative)
X char *val; /* integer part of the value to be formatted */
X char *fmt; /* integer part of the format */
X bool comma; /* true if we should comma-ify the value */
X bool negative; /* true if the value is actually negative */
X{
X int digit, f, v;
X int thousands = 0;
X char *cp;
X static char buf[MAXBUF];
X char *bufptr = buf;
X
X /*
X * locate the leftmost digit placeholder
X */
X for (cp = fmt; *cp != EOS; cp++)
X {
X if (*cp == '\\')
X cp++;
X else if (*cp == '#' || *cp == '0')
X break;
X }
X digit = (*cp == EOS) ? -1 : cp - fmt;
X
X /*
X * format the value
X */
X f = strlen(fmt) - 1;
X v = (digit >= 0) ? strlen(val) - 1 : -1;
X while (f >= 0 || v >= 0)
X {
X if (f > 0 && fmt[f-1] == '\\')
X {
X *bufptr++ = fmt[f--];
X }
X else if (f >= 0 && (fmt[f] == '#' || fmt[f] == '0'))
X {
X if (v >= 0 || fmt[f] == '0')
X {
X *bufptr++ = v < 0 ? '0' : val[v];
X if (comma && (thousands = (thousands + 1) % 3) == 0 && v > 0)
X {
X *bufptr++ = ',';
X }
X v--;
X }
X }
X else if (f >= 0)
X {
X *bufptr++ = fmt[f];
X }
X if (v >= 0 && f == digit)
X {
X continue;
X }
X f--;
X }
X
X if (negative && digit >= 0)
X *bufptr++ = '-';
X *bufptr = EOS;
X reverse(buf);
X
X return (buf);
X}
X
X/*****************************************************************************/
X
Xstatic char *
Xfmt_frac(val, fmt)
X char *val; /* fractional part of the value to be formatted */
X char *fmt; /* fractional portion of format */
X{
X static char buf[MAXBUF];
X register char *bufptr = buf;
X register char *fmtptr = fmt, *valptr = val;
X
X *bufptr++ = '.';
X while (*fmtptr != EOS)
X {
X if (*fmtptr == '\\')
X {
X *bufptr++ = *++fmtptr;
X }
X else if (*fmtptr == '#' || *fmtptr == '0')
X {
X if (*valptr != EOS || *fmtptr == '0')
X {
X *bufptr++ = (*valptr != EOS) ? *valptr++ : *fmtptr;
X }
X }
X else
X {
X *bufptr++ = *fmtptr;
X }
X fmtptr++;
X }
X *bufptr = EOS;
X
X return (buf);
X}
X
X/*****************************************************************************/
X
Xstatic char *
Xfmt_exp(val, fmt)
X int val; /* value of the exponent */
X char *fmt; /* exponent part of the format */
X{
X static char buf[MAXBUF];
X register char *bufptr = buf;
X char valbuf[64];
X bool negative = false;
X
X *bufptr++ = *fmt++;
X if (*fmt++ == '+')
X *bufptr++ = (val < 0) ? '-' : '+';
X else if (val < 0)
X *bufptr++ = '-';
X *bufptr = EOS;
X
X if (val < 0)
X {
X val = -val;
X negative = true;
X }
X sprintf(valbuf, "%d", val);
X
X strcat(buf, fmt_int(valbuf, fmt, false, negative));
X return (buf);
X}
X
X/*****************************************************************************/
X
Xstatic void
Xreverse(buf)
X register char *buf;
X{
X register char *cp = buf + strlen(buf) - 1;
X register char tmp;
X
X while (buf < cp)
X {
X tmp = *cp;
X *cp-- = *buf;
X *buf++ = tmp;
X }
X}
X
X/*****************************************************************************/
X/*
X * Tom Anderson <toma at hpsad.hp.com>
X * 10/14/90
X *
X * This routine takes a value and formats it using fixed, scientific,
X * or engineering notation. The format command 'f' determines which
X * format is used. The formats are: example
X * 0: Fixed point (default) 0.00010
X * 1: Scientific 1.00E-04
X * 2: Engineering 100.00u
X *
X * The format command 'f' now uses three values. The first two are the
X * width and precision, and the last one is the format value 0, 1, or 2 as
X * described above. The format value is passed in the variable fmt.
X *
X * This formatted value is written into the passed buffer. if the
X * resulting string is too long to fit into the passed buffer, the
X * function returns false. Otherwise the function returns true.
X *
X * When a number is formatted as engineering and is outside of the range
X * of typically used engineering exponents, the format reverts to
X * scientific.
X *
X * To preserve compatability with old spreadsheet files, the third value
X * may be missing, and the default will be fixed point (format 0).
X *
X * When an old style sheet is saved, the third value will be stored.
X *
X */
X
X#define REFMTFIX 0
X#define REFMTFLT 1
X#define REFMTENG 2
Xchar engmult[] = "afpnum kMGT";
X
Xbool
Xengformat(fmt, width, precision, val, buf, buflen)
Xint fmt;
Xint width;
Xint precision;
Xdouble val;
Xchar *buf;
Xint buflen;
X{
X int engind = 0;
X double engmant, pow(), engabs, engexp;
X if (buflen < width) return (false);
X if (fmt == REFMTFIX)
X (void)sprintf(buf,"%*.*f", width, precision, val);
X if (fmt == REFMTFLT)
X (void)sprintf(buf,"%*.*E", width, precision, val);
X if (fmt == REFMTENG)
X {
X if (val == 0e0) /* Hack to get zeroes to line up in engr fmt */
X {
X (void)sprintf((buf-1),"%*.*f ", width, precision, val);
X }
X else
X {
X engabs=(val);
X if (engabs < 0e0) engabs= -engabs;
X if ((engabs >= 1e-18) && (engabs < 1e-15 )) engind=0;
X if ((engabs >= 1e-15) && (engabs < 1e-12 )) engind=1;
X if ((engabs >= 1e-12) && (engabs < 1e-9 )) engind=2;
X if ((engabs >= 1e-9) && (engabs < 1e-6 )) engind=3;
X if ((engabs >= 1e-6) && (engabs < 1e-3 )) engind=4;
X if ((engabs >= 1e-3) && (engabs < 1 )) engind=5;
X if ((engabs >= 1) && (engabs < 1e3 )) engind=6;
X if ((engabs >= 1e3) && (engabs < 1e6 )) engind=7;
X if ((engabs >= 1e6) && (engabs < 1e9 )) engind=8;
X if ((engabs >= 1e9) && (engabs < 1e12 )) engind=9;
X if ((engabs >= 1e12) && (engabs < 1e15 )) engind=10;
X if ((engabs <1e-18) || (engabs >=1e15))
X {
X /* Revert to floating point */
X (void)sprintf(buf,"%*.*E", width, precision, val);
X }
X else
X {
X engexp= (double) (engind-6)*3;
X engmant= val/pow(10.0e0,engexp);
X (void)sprintf(buf,"%*.*f%c", width-1,
X precision, engmant, engmult[engind]);
X }
X }
X }
X return (true);
X}
SHAR_EOF
$TOUCH -am 1026165790 format.c &&
chmod 0444 format.c ||
echo "restore of format.c failed"
set `wc -c format.c`;Wc_c=$1
if test "$Wc_c" != "13822"; then
echo original size 13822, current size $Wc_c
fi
exit 0
More information about the Comp.sources.bugs
mailing list