/* sts.c -- Implementation File (module.c template V1.0)
   Copyright (C) 1995 Free Software Foundation, Inc.
   Contributed by James Craig Burley (burley@gnu.org).

This file is part of GNU Fortran.

GNU Fortran is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Fortran 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Fortran; see the file COPYING.  If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.

   Related Modules:
      None (despite the name, it doesn't really depend on ffest*)

   Description:
      Provides an arbitrary-length string facility for the limited needs of
      GNU Fortran FORMAT statement generation.

   Modifications:
*/

/* Include files. */

#include "proj.h"
#include "sts.h"
#include "com.h"
#include "malloc.h"

/* Externals defined here. */


/* Simple definitions and enumerations. */


/* Internal typedefs. */


/* Private include files. */


/* Internal structure definitions. */


/* Static objects accessed by functions in this module. */


/* Static functions (internal). */


/* Internal macros. */


/* ffests_kill -- Kill a varying-length string

   ffests s;
   ffests_kill(s);

   The storage associated with the string <s> is freed.	 */

void
ffests_kill (ffests s)
{
  if (s->text_ != NULL)
    malloc_kill_ksr (s->pool_, s->text_, s->max_);
}

/* ffests_new -- Make a varying-length string

   ffests s;
   ffests_new(s,malloc_pool_image(),0);

   The string is initialized to hold, in this case, 0 characters, and
   current and future heap manipulations to hold the string will use
   the image pool.  */

void
ffests_new (ffests s, mallocPool pool, ffestsLength size)
{
  s->pool_ = pool;
  s->len_ = 0;
  s->max_ = size;

  if (size == 0)
    s->text_ = NULL;
  else
    s->text_ = malloc_new_ksr (pool, "ffests", size);
}

/* ffests_printf_1D -- printf("...%ld...",(long)) to a string

   ffests s;
   ffests_printf_1D(s,"...%ld...",1);

   Like printf, but into a string.  */

void
ffests_printf_1D (ffests s, char *ctl, long arg1)
{
  char quickbuf[40];
  char *buff;
  ffestsLength len;

  if ((len = strlen (ctl) + 21) < ARRAY_SIZE (quickbuf))
    /* No # bigger than 20 digits. */
    {
      sprintf (&quickbuf[0], ctl, arg1);
      ffests_puttext (s, &quickbuf[0], strlen (quickbuf));
    }
  else
    {
      buff = malloc_new_ks (malloc_pool_image (), "ffests_printf_1D", len);
      sprintf (buff, ctl, arg1);
      ffests_puttext (s, buff, strlen (buff));
      malloc_kill_ks (malloc_pool_image (), buff, len);
    }
}

/* ffests_printf_1U -- printf("...%lu...",(unsigned long)) to a string

   ffests s;
   ffests_printf_1U(s,"...%lu...",1);

   Like printf, but into a string.  */

void
ffests_printf_1U (ffests s, char *ctl, unsigned long arg1)
{
  char quickbuf[40];
  char *buff;
  ffestsLength len;

  if ((len = strlen (ctl) + 21) < ARRAY_SIZE (quickbuf))
    /* No # bigger than 20 digits. */
    {
      sprintf (&quickbuf[0], ctl, arg1);
      ffests_puttext (s, &quickbuf[0], strlen (quickbuf));
    }
  else
    {
      buff = malloc_new_ks (malloc_pool_image (), "ffests_printf_1U", len);
      sprintf (buff, ctl, arg1);
      ffests_puttext (s, buff, strlen (buff));
      malloc_kill_ks (malloc_pool_image (), buff, len);
    }
}

/* ffests_printf_1s -- printf("...%s...",(char *)) to a string

   ffests s;
   ffests_printf_1s(s,"...%s...","hi there!");

   Like printf, but into a string.  */

void
ffests_printf_1s (ffests s, char *ctl, char *arg1)
{
  char quickbuf[40];
  char *buff;
  ffestsLength len;

  if ((len = strlen (ctl) + strlen (arg1) - 1) < ARRAY_SIZE (quickbuf))
    {
      sprintf (&quickbuf[0], ctl, arg1);
      ffests_puttext (s, &quickbuf[0], strlen (quickbuf));
    }
  else
    {
      buff = malloc_new_ks (malloc_pool_image (), "ffests_printf_1s", len);
      sprintf (buff, ctl, arg1);
      ffests_puttext (s, buff, strlen (buff));
      malloc_kill_ks (malloc_pool_image (), buff, len);
    }
}

/* ffests_printf_2Us -- printf("...%lu...%s...",...) to a string

   ffests s;
   ffests_printf_2Us(s,"...%lu...%s...",1,"hi there!");

   Like printf, but into a string.  */

void
ffests_printf_2Us (ffests s, char *ctl, unsigned long arg1, char *arg2)
{
  char quickbuf[60];
  char *buff;
  ffestsLength len;

  if ((len = strlen (ctl) + 21 + strlen (arg2) - 1) < ARRAY_SIZE (quickbuf))
    /* No # bigger than 20 digits. */
    {
      sprintf (&quickbuf[0], ctl, arg1, arg2);
      ffests_puttext (s, &quickbuf[0], strlen (quickbuf));
    }
  else
    {
      buff = malloc_new_ks (malloc_pool_image (), "ffests_printf_2Us", len);
      sprintf (buff, ctl, arg1, arg2);
      ffests_puttext (s, buff, strlen (buff));
      malloc_kill_ks (malloc_pool_image (), buff, len);
    }
}

/* ffests_putc -- Put a single character into string

   ffests s;
   ffests_putc(s,'*');	*/

void
ffests_putc (ffests s, char c)
{
  ffests_puttext (s, &c, 1);
}

/* ffests_puts -- Put a zero-terminated (C-style) string into string

   ffests s;
   ffests_puts(s,"append me");	*/

void
ffests_puts (ffests s, char *string)
{
  ffests_puttext (s, string, strlen (string));
}

/* ffests_puttext -- Put a number of characters into string

   ffests s;
   ffests_puttext(s,"hi there",8);

   The string need not be 0-terminated, because the passed length is used,
   and may be 0.  */

void
ffests_puttext (ffests s, char *text, ffestsLength length)
{
  ffestsLength newlen;
  ffestsLength newmax;

  if (length <= 0)
    return;

  newlen = s->len_ + length;
  if (newlen > s->max_)
    {
      if (s->text_ == NULL)
	{
	  s->max_ = 40;
	  s->text_ = malloc_new_ksr (s->pool_, "ffests", s->max_);
	}
      else
	{
	  newmax = s->max_ << 1;
	  while (newmax < newlen)
	    newmax <<= 1;
	  s->text_ = malloc_resize_ksr (s->pool_, s->text_, newmax, s->max_);
	  s->max_ = newmax;
	}
    }

  memcpy (s->text_ + s->len_, text, length);
  s->len_ = newlen;
}
