#ifndef XPKMASTER_DEBUF_C
#define XPKMASTER_DEBUG_C

/* Routinesheader

	Name:		debug.c
	Main:		xpkmaster
	Versionstring:	$VER: debug.c 1.6 (12.04.97)
	Author:		SDI
	Distribution:	PD
	Description:	the debug stuff

 1.0   05.10.96 : first real version
 1.1   20.10.96 : added the external debug modes
 1.2   21.10.96 : changed debug totally
 1.3   01.01.97 : changed output a bit - "XpkM before stuff - find in lots
 	of other debuf stuff"
 1.4   09.03.97 : output contained 0 byte - removed
 1.5   01.04.97 : little changes
 1.6   12.04.97 : added TagList output, therefor changed XPKDEBUG contents
*/

#include <exec/types.h>
#include <pragma/exec_lib.h>
#include <pragma/dos_lib.h>
#include <pragma/utility_lib.h>
#include <utility/tagitem.h>
#include <dos/var.h>
#include <xpk/xpk.h>

extern struct Library *UtilityBase;

typedef void (*putchtype) ();

#ifdef __MAXON__
  #define __asm
#endif

#define FLAG_ERROR	(1<<0)
#define FLAG_RUNTIME	(1<<1)
#define FLAG_TAGLIST	(1<<2)

extern KPutChar(LONG);
extern DPutChar(LONG);
extern struct DosLibrary *DOSBase;
extern void DoDebug(UBYTE mode, STRPTR fmt, APTR data);

static void __asm serfunc(register __d0 UBYTE c, register __a3 ULONG pd)
{ if(c) KPutChar(c); }

static void __asm parfunc(register __d0 UBYTE c, register __a3 ULONG pd)
{ if(c) DPutChar(c); }

static void __asm normfunc(register __d0 UBYTE c, register __a3 ULONG pd)
{
  UBYTE d = c;
  if(c)
    Write(pd, &d, 1);
}

void DebugTagList(STRPTR fmt, struct TagItem *taglist)
{
  DoDebug(FLAG_TAGLIST, fmt, taglist);
}

void DebugError(STRPTR format, ...)
{
  DoDebug(FLAG_RUNTIME, format, (APTR)((ULONG)(&format)+sizeof(STRPTR)));
}

void DebugRunTime(STRPTR format, ...)
{
  DoDebug(FLAG_ERROR, format, (APTR)((ULONG)(&format)+sizeof(STRPTR)));
}

void DoDebug(UBYTE mode, STRPTR fmt, APTR data)
{
  ULONG fh = 0, i, Flags = 0;
  UBYTE Mode[5] = "";
  void __asm (*function)(register __d0 UBYTE, register __a3 ULONG) = 0;

  Forbid();

  GetVar("XPKDEBUG", (STRPTR) &Mode, 5, GVF_GLOBAL_ONLY);

  for(i=1; Mode[i] && i < 5; ++i)
  {
    switch(Mode[i])
    {
      case 'E': Flags |= FLAG_ERROR; break;
      case 'R': Flags |= FLAG_RUNTIME; break;
      case 'T': Flags |= FLAG_TAGLIST; break;
    }
  }

  mode &= Flags;

  if(mode)
  {
    switch(Mode[0])
    {
    case 'S': function = serfunc; break;
    case 'P': function = parfunc; break;
    case 'F':
      if((fh = Open("T:XpkMasterOut", MODE_READWRITE)))
      {
        Seek(fh, 0, OFFSET_END);
        function = normfunc;
      }
      break;
    }
    if(function)
    {
      i = (ULONG) FindTask(0);
      RawDoFmt("XpkM(%08lx):", &i, (putchtype) function, (APTR) fh);

      RawDoFmt(fmt, data, (putchtype) function, (APTR) fh);
      RawDoFmt("\n", 0, (putchtype) function, (APTR) fh);

      if(mode & FLAG_TAGLIST)
      {
        struct TagItem *ti;
        while((ti = NextTagItem((struct TagItem **) &data)))
        {
          RawDoFmt("   %08lx, %lu", ti, (putchtype) function, (APTR) fh);
          if((ti->ti_Tag == XPK_InName) || (ti->ti_Tag == XPK_OutName) ||
          (ti->ti_Tag == XPK_FileName) || (ti->ti_Tag == XPK_Password) ||
          (ti->ti_Tag == XPK_PackMethod))
            RawDoFmt(" (%s)", &ti->ti_Data, (putchtype) function, (APTR) fh);
          RawDoFmt("\n", 0, (putchtype) function, (APTR) fh);
        }
      }
    }

    if(fh)
      Close(fh);
  }

  Permit();
}

#endif /* XPKMASTER_DEBUG_C */
