/* ---------------------------------------------------------------------- */
/*                   Copyright (C) 1992 by Natrlich!                     */
/*                      This file is copyrighted!                         */
/*                Refer to the documentation for details.                 */
/* ---------------------------------------------------------------------- */
#include <stdio.h>
#include <stddef.h>
#define lword unsigned long

#define DBG_LONG  0
#define DBG_INT   1
#define DBG_CHARP 2
#define DBG_CHAR  3

#define DEBUGDEBUG 0
#define MAXRECURS 1000
#define ESTREAM   stdout
#define dswitch turn_debug_off_while_in_a_debugger

char          *__debug_prefix;

static char   *cproc[MAXRECURS];
static int    pcproc = 0;
int           dswitch;
static int    fstflag;

#define check()                                       \
   if( pcproc > MAXRECURS || pcproc < 0)              \
      nierror("debug: Internal pointer corrupted")

void ENTER( name)
char   *name;
{
   int   i = pcproc;

   if( ! fstflag)
   {
      fstflag = 1;
      setvbuf( ESTREAM, NULL, _IONBF, (size_t) 0);
   }
   if( dswitch)
      return;
   check();
   if( ! name)
      nierror("debug: ENTER called w/o name");
# if DEBUGDEBUG
   fprintf( ESTREAM,
         "ENTER with %s. pcproc = %d  cproc[ pcproc -1 ]=\"%s\"\n",
         name,
         pcproc,
         pcproc || cproc[ pcproc - 1] ? cproc[ pcproc - 1] : "(nil)");
# endif
   while( i--)
   {
      putc( ' ', ESTREAM);
      putc( ' ', ESTREAM);
   }
   if( __debug_prefix)
      fprintf( ESTREAM, "<%s> [ENTER: \"%s\"]\n", __debug_prefix, name);
   else
      fprintf( ESTREAM, "[ENTER: \"%s\"]\n",  name);
   if( pcproc == MAXRECURS - 1)
      nierror("\tdebug: Recursion depth exceeded");
   else
      cproc[ pcproc++] = name;
}


void SMESS( mess)
char *mess;
{
   if( dswitch)
      return;
   check();
   if( ! mess)
      nierror("debug: SMESS called w/o message");
# if DEBUGDEBUG
   fprintf( ESTREAM,
         "SMESS with %s.  pcproc = %d  cproc[ pcproc -1 ]=\"%s\"\n",
         mess,
         pcproc,
         pcproc || cproc[ pcproc - 1] ? cproc[ pcproc - 1] : "(nil)");
# endif
   if( ! cproc[ pcproc - 1])
      nierror("debug: MESS Internal stack corrupted");
   if( __debug_prefix)
      fprintf( ESTREAM, "<%s> %s\n", __debug_prefix, mess);
   else
      fprintf( ESTREAM, mess);
}


void MESS( mess)
char *mess;
{
   int   i = pcproc;

   if( dswitch)
      return;
   check();
   if( ! mess)
      nierror("debug: MESS called w/o message");
# if DEBUGDEBUG
   fprintf( ESTREAM,
         "MESS with %s.  pcproc = %d  cproc[ pcproc -1 ]=\"%s\"\n",
         mess,
         pcproc,
         pcproc || cproc[ pcproc - 1] ? cproc[ pcproc - 1] : "(nil)");
# endif
   while( i--)
   {
      putc( ' ', ESTREAM);
      putc( ' ', ESTREAM);
   }
   if( ! cproc[ pcproc - 1])
      nierror("debug: MESS Internal stack corrupted");
   if( __debug_prefix)
      fprintf( ESTREAM, "<%s> [<%s>: \"%s\"]\n",
               __debug_prefix, cproc[ pcproc - 1], mess);
   else
      fprintf( ESTREAM, "[<%s>: \"%s\"]\n",
               cproc[ pcproc - 1], mess);
}


void IMESS( form, value, bytes)
char           *form;
lword          value;
int            bytes;
{
   int   i = pcproc;

   if( dswitch)
      return;
   check();
# if DEBUGDEBUG
   fprintf( ESTREAM,
         "IMESS with %s.  pcproc = %d  cproc[ pcproc -1 ]=\"%s\"\n",
         form,
         pcproc,
         pcproc || cproc[ pcproc - 1] ? cproc[ pcproc - 1] : "(nil)");
# endif
   while( i--)
   {
      putc( ' ', ESTREAM);
      putc( ' ', ESTREAM);
   }
   if( ! cproc[ pcproc - 1])
      nierror("debug: IMESS Internal stack corrupted");
   if( __debug_prefix)
      fprintf( ESTREAM, "<%s> [<%s>: \"",
               __debug_prefix, cproc[ pcproc - 1]);
   else
      fprintf( ESTREAM, "[<%s>: \"", cproc[ pcproc - 1]);

   switch( bytes)
   {
      case DBG_CHARP : 
         fprintf( ESTREAM, form, (char *) value); 
         break;

      case DBG_INT   : 
         fprintf( ESTREAM, form, (int) value);
         break;

      case DBG_CHAR  :
         fprintf( ESTREAM, form, (char) value);
         break;
         
      default: 
         fprintf( ESTREAM, form, value);
   }
   fprintf( ESTREAM, "\"]\n");
}

#if EXPERIMENTAL
void VMESS( form, ...)
char  *form;
{
   va_list  p;
   int   i = pcproc;

   if( dswitch)
      return;
   check();
# if DEBUGDEBUG
   fprintf( ESTREAM,
         "VMESS ... pcproc = %d  cproc[ pcproc -1 ]=\"%s\"\n",
         pcproc,
         pcproc || cproc[ pcproc - 1] ? cproc[ pcproc - 1] : "(nil)");
# endif
   while( i--)
   {
      putc( ' ', ESTREAM);
      putc( ' ', ESTREAM);
   }
   if( ! cproc[ pcproc - 1])
      nierror("debug: VMESS Internal stack corrupted");
   va_start( p, form);
   if( __debug_prefix)
      fprintf( ESTREAM, "<%s> [<%s>: \"",
               __debug_prefix, cproc[ pcproc - 1]);
   else
      fprintf( ESTREAM, "[<%s>: \"", cproc[ pcproc - 1]);
   vfprintf( ESTREAM, form, p);
   va_end( p);
   fprintf( ESTREAM, "]\n");
}
#endif

void LEAVE()
{
   int   i;

   if( dswitch)
      return;
   if( (i = pcproc) <= 0)
      nierror("LEAVE counter was 0 or negative");
   check();
# if DEBUGDEBUG
   fprintf( ESTREAM,
         "LEAVE.  pcproc = %d  cproc[ pcproc -1 ]=\"%s\"\n",
         pcproc,
         pcproc || cproc[ pcproc - 1] ? cproc[ pcproc - 1] : "(nil)");
# endif
   while( --i)
   {
      putc( ' ', ESTREAM);
      putc( ' ', ESTREAM);
   }
   if( ! cproc[ pcproc - 1])
      nierror("debug: LEAVE Internal stack corrupted");
   if( __debug_prefix)
      fprintf( ESTREAM, "<%s> [LEAVE: \"%s\"]\n", 
              __debug_prefix, cproc[ --pcproc]);
   else
      fprintf( ESTREAM, "[LEAVE: \"%s\"]\n", cproc[ --pcproc]);
}

void ALEAVE()
{
   int   i;

   if( dswitch)
      return;
   if( (i = pcproc) <= 0)
      nierror("LEAVE counter was 0 or negative");
   check();
# if DEBUGDEBUG
   fprintf( ESTREAM,
         "ALEAVE.  pcproc = %d  cproc[ pcproc -1 ]=\"%s\"\n",
         pcproc,
         pcproc || cproc[ pcproc - 1] ? cproc[ pcproc - 1] : "(nil)");
# endif
   while( --i)
   {
      putc( ' ', ESTREAM);
      putc( ' ', ESTREAM);
   }
   if( ! cproc[ pcproc - 1])
      nierror("debug: ALEAVE Internal stack corrupted");
   if( __debug_prefix)
      fprintf( ESTREAM, "<%s> [DONE with: \"%s\"]\n", 
              __debug_prefix, cproc[ --pcproc]);
   else
      fprintf( ESTREAM, "[DONE with: \"%s\"]\n", cproc[ --pcproc]);
}

void SETBACK( i)
{
   if( dswitch)
      return;
   check();
# if DEBUGDEBUG
   fprintf( ESTREAM,
         "SETBACK.  pcproc = %d  cproc[ pcproc -1 ]=\"%s\"\n",
         pcproc,
         pcproc || cproc[ pcproc - 1] ? cproc[ pcproc - 1] : "(nil)");
# endif
   if( i > pcproc || ! i)
      fprintf( ESTREAM, "debug: SETBACKing now would be an ERROR!!\n");
   else
   pcproc = i;
}

void   SAVESTATE( p)
int   *p;
{
   check();
# if DEBUGDEBUG
   fprintf( ESTREAM,
         "SAVESTATE.  pcproc = %d  cproc[ pcproc -1 ]=\"%s\"\n",
         pcproc,
         pcproc || cproc[ pcproc - 1] ? cproc[ pcproc - 1] : "(nil)");
# endif
   *p = pcproc;
}

