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