/***********************************************************************
     "indent.o": code INDENTation functions.
***********************************************************************/

/***********************************
  (C) Copyright 1992-1993; dit/upm
   Distributed under the conditions stated in the
   EPS General Public License (see file LICENSE)
 ***********************************
 $Log: indent.c,v $
 * Revision 1.7  1995/01/17  09:46:47  eps
 * fix a bug: insufficient buffer space
 *
 * Revision 1.6  1993/01/12  18:19:06  eps
 * portability issues
 *
 * Revision 1.5  1993/01/12  16:37:24  eps
 * portability issues
 *
 * Revision 1.4  1992/03/04  08:34:38  eps
 * macros into functions for poor C compilers (as HP's)
 *
 * Revision 1.3  92/03/03  19:47:07  eps
 * use macro or function for HP
 *
 * Revision 1.2  92/01/14  15:45:59  eps
 * distribution issues
 *
 * Revision 1.1  91/12/02  18:58:02  eps
 * Initial revision
 *
 ***********************************/

/* KJT 29/10/04: changed to use "stdarg" instead of "varargs" */

#ifndef lint
static char rcsid[]= "$Id: indent.c,v 1.7 1995/01/17 09:46:47 eps Exp $";
#endif

/* LINTLIBRARY */

#define indent_IMP

#include <stdio.h>
#include <stdarg.h>
#include "bsc_dcls.hh"
#include "lnt_pass.hh"
#include "err_handl.hh"
#include "prg_error.hh"
#include "mem_alloc.hh"
#include "indent.hh"


#define INDT_EXP_UNIT	10	/* indentation stack expansion unit */

PUBLIC void
init_indt (dflt)
  int dflt;
{
  if (_INDT.size != NULL)
    tfree(_INDT.size);
  _INDT.level= 0;
  _INDT.incr= 0;
  if (dflt > 0)
  { _INDT.limit= INDT_EXP_UNIT - 1;
    talloc(_INDT.size, _INDT.limit + 1);
    _INDT.size[0]= 0;
    _INDT.dflt= dflt;
  }
  else
  { _INDT.limit= 0;
    _INDT.size= NULL;
    _INDT.dflt= 0;
  }
}

/* expands the indentation stack */

PUBLIC void
_exp_indt ()
{
  abort_if(_INDT.size == NULL)
  _INDT.limit+= INDT_EXP_UNIT;
  trealloc(_INDT.size, _INDT.limit + 1);
}

#ifndef test_HP_bug	/* stupid HP C compilers!!! */
PRIVATE void
_incr_indt ()
{
  if (_INDT.level == _INDT.limit) _exp_indt();
  _INDT.size[++_INDT.level]=
    _INDT.size[_INDT.level - 1] + _INDT.incr;
}

PUBLIC void
incr_indt (_incr)
  int _incr;
{
  _INDT.incr= _incr;
  if (_INDT.dflt > 0)
  { if (_INDT.incr < 0)
      _INDT.incr= _INDT.dflt;
    _incr_indt();
  }
}
#endif

#ifndef test_HP_bug	/* stupid HP C compilers!!! */
PRIVATE void
_decr_indt ()
{
  abort_if(_INDT.level <= 0)
  --_INDT.level;
}

PUBLIC void
decr_indt ()
{
  if (_INDT.dflt > 0) _decr_indt();
}
#endif

/* writes the indentation given its size */

PUBLIC void
_wrt_indt (size)
  int size;
{
  static int first= TRUE;
  static char indt_str[2 * INDT_EXP_UNIT + 1];
  static int incr= sizeof(indt_str) - 1;

  abort_if(size < 0)
  if (first)
  { int i;

    for (i= 0; i < incr; ++i)
      indt_str[i]= ' ';
    indt_str[i]= '\0';
    first= FALSE;
  }
  for (; size >= incr; size-= incr)
    (void) fputs(indt_str, stdout);
  if (size > 0)
  { indt_str[size]= '\0';
    (void) fputs(indt_str, stdout);
    indt_str[size]= ' ';
  }
}

PUBLIC void
advc_indt (int incr, int fill, char *format, ...)
{
  va_list args;
  int advc;

  va_start(args, format);
  advc= vprintf(format, args);
  if (_INDT.dflt > 0)
  { _INDT.incr= incr < 0? _INDT.dflt: incr;
    if (_INDT.incr < advc)
      _INDT.incr= advc;
    else if (_INDT.incr > advc && fill)
      _wrt_indt(_INDT.incr - advc);
    _incr_indt();
  }
  va_end(args);
}
