#include "f2c.h"
#include "fio.h"
#ifndef VAX
#include <ctype.h>
#endif

#undef abs
#undef min
#undef max
#include <stdlib.h>
#include <string.h>

#include "fmt.h"
#include "fp.h"

int
wrt_E (ufloat * p, int w, int d, int e, ftnlen len)
{
  char buf[FMAX + EXPMAXDIGS + 4], *s, *se;
  int d1, delta, e1, i, sign, signspace;
  double dd;
#ifdef WANT_LEAD_0
  int insert0 = 0;
#endif
#ifndef VAX
  int e0 = e;
#endif

  if (e <= 0)
    e = 2;
  if (f__scale)
    {
      if (f__scale >= d + 2 || f__scale <= -d)
	goto nogood;
    }
  if (f__scale <= 0)
    --d;
  if (len == sizeof (real))
    dd = p->pf;
  else
    dd = p->pd;
  if (dd < 0.)
    {
      signspace = sign = 1;
      dd = -dd;
    }
  else
    {
      sign = 0;
      signspace = (int) f__cplus;
#ifndef VAX
      if (!dd)
	dd = 0.;		/* avoid -0 */
#endif
    }
  delta = w - (2		/* for the . and the d adjustment above */
	       + 2 /* for the E+ */  + signspace + d + e);
#ifdef WANT_LEAD_0
  if (f__scale <= 0 && delta > 0)
    {
      delta--;
      insert0 = 1;
    }
  else
#endif
  if (delta < 0)
    {
    nogood:
      while (--w >= 0)
	PUT ('*');
      return (0);
    }
  if (f__scale < 0)
    d += f__scale;
  if (d > FMAX)
    {
      d1 = d - FMAX;
      d = FMAX;
    }
  else
    d1 = 0;
  sprintf (buf, "%#.*E", d, dd);
#ifndef VAX
  /* check for NaN, Infinity */
  if (!isdigit ((unsigned char) buf[0]))
    {
      switch (buf[0])
	{
	case 'n':
	case 'N':
	  signspace = 0;	/* no sign for NaNs */
	}
      delta = w - strlen (buf) - signspace;
      if (delta < 0)
	goto nogood;
      while (--delta >= 0)
	PUT (' ');
      if (signspace)
	PUT (sign ? '-' : '+');
      for (s = buf; *s; s++)
	PUT (*s);
      return 0;
    }
#endif
  se = buf + d + 3;
#ifdef GOOD_SPRINTF_EXPONENT	/* When possible, exponent has 2 digits. */
  if (f__scale != 1 && dd)
    sprintf (se, "%+.2d", atoi (se) + 1 - f__scale);
#else
  if (dd)
    sprintf (se, "%+.2d", atoi (se) + 1 - f__scale);
  else
    strcpy (se, "+00");
#endif
  s = ++se;
  if (e < 2)
    {
      if (*s != '0')
	goto nogood;
    }
#ifndef VAX
  /* accommodate 3 significant digits in exponent */
  if (s[2])
    {
#ifdef Pedantic
      if (!e0 && !s[3])
	for (s -= 2, e1 = 2; s[0] = s[1]; s++);

      /* Pedantic gives the behavior that Fortran 77 specifies,       */
      /* i.e., requires that E be specified for exponent fields       */
      /* of more than 3 digits.  With Pedantic undefined, we get      */
      /* the behavior that Cray displays -- you get a bigger          */
      /* exponent field if it fits.   */
#else
      if (!e0)
	{
	  for (s -= 2, e1 = 2; (s[0] = s[1]); s++)
#ifdef CRAY
	    delta--;
	  if ((delta += 4) < 0)
	    goto nogood
#endif
	      ;
	}
#endif
      else if (e0 >= 0)
	goto shift;
      else
	e1 = e;
    }
  else
  shift:
#endif
    for (s += 2, e1 = 2; *s; ++e1, ++s)
      if (e1 >= e)
	goto nogood;
  while (--delta >= 0)
    PUT (' ');
  if (signspace)
    PUT (sign ? '-' : '+');
  s = buf;
  i = f__scale;
  if (f__scale <= 0)
    {
#ifdef WANT_LEAD_0
      if (insert0)
	PUT ('0');
#endif
      PUT ('.');
      for (; i < 0; ++i)
	PUT ('0');
      PUT (*s);
      s += 2;
    }
  else if (f__scale > 1)
    {
      PUT (*s);
      s += 2;
      while (--i > 0)
	PUT (*s++);
      PUT ('.');
    }
  if (d1)
    {
      se -= 2;
      while (s < se)
	PUT (*s++);
      se += 2;
      do
	PUT ('0');
      while (--d1 > 0);
    }
  while (s < se)
    PUT (*s++);
  if (e < 2)
    PUT (s[1]);
  else
    {
      while (++e1 <= e)
	PUT ('0');
      while (*s)
	PUT (*s++);
    }
  return 0;
}

int
wrt_F (ufloat * p, int w, int d, ftnlen len)
{
  int d1, sign, n;
  double x;
  char *b, buf[MAXINTDIGS + MAXFRACDIGS + 4], *s;

  x = (len == sizeof (real) ? p->pf : p->pd);
  if (d < MAXFRACDIGS)
    d1 = 0;
  else
    {
      d1 = d - MAXFRACDIGS;
      d = MAXFRACDIGS;
    }
  if (x < 0.)
    {
      x = -x;
      sign = 1;
    }
  else
    {
      sign = 0;
#ifndef VAX
      if (!x)
	x = 0.;
#endif
    }

  if ((n = f__scale))
    {
      if (n > 0)
	do
	  x *= 10.;
	while (--n > 0);
      else
	do
	  x *= 0.1;
	while (++n < 0);
    }

#ifdef USE_STRLEN
  sprintf (b = buf, "%#.*f", d, x);
  n = strlen (b) + d1;
#else
  n = sprintf (b = buf, "%#.*f", d, x) + d1;
#endif

#ifndef WANT_LEAD_0
  if (buf[0] == '0' && d)
    {
      ++b;
      --n;
    }
#endif
  if (sign)
    {
      /* check for all zeros */
      for (s = b;;)
	{
	  while (*s == '0')
	    s++;
	  switch (*s)
	    {
	    case '.':
	      s++;
	      continue;
	    case 0:
	      sign = 0;
	    }
	  break;
	}
    }
  if (sign || f__cplus)
    ++n;
  if (n > w)
    {
#ifdef WANT_LEAD_0
      if (buf[0] == '0' && --n == w)
	++b;
      else
#endif
	{
	  while (--w >= 0)
	    PUT ('*');
	  return 0;
	}
    }
  for (w -= n; --w >= 0;)
    PUT (' ');
  if (sign)
    PUT ('-');
  else if (f__cplus)
    PUT ('+');
  while ((n = *b++))
    PUT (n);
  while (--d1 >= 0)
    PUT ('0');
  return 0;
}
