/* Rutines to send debug-info to the debug-handler. */

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/ports.h>

#include <proto/exec.h>

#include <stdio.h>
#include <string.h>
#include <stdarg.h>

#include <DebugPrc.h>


void opendebug(void){
   struct debugmsg *openmsg;
   int len;
   struct MsgPort *port;
   
   len=strlen(OPENCMD)+1;
   if(openmsg=AllocMem(len+=sizeof(struct Message),MEMF_PUBLIC)){
      openmsg->msg.mn_Node.ln_Succ=NULL;
      openmsg->msg.mn_Node.ln_Pred=NULL;
      openmsg->msg.mn_Node.ln_Type=NT_MESSAGE;
      openmsg->msg.mn_Node.ln_Pri=0;
      openmsg->msg.mn_Node.ln_Name=openmsg->string;
      openmsg->msg.mn_ReplyPort=NULL;
      openmsg->msg.mn_Length=len;
      strcpy(openmsg->string,OPENCMD);
      Forbid();
      if(port=FindPort(PORTNAME)){
         PutMsg(port,openmsg);
         Permit();
      }else{
         Permit();
         FreeMem(openmsg,len);
      }
   }
}

void closedebug(void){
   struct debugmsg *closemsg;
   int len;
   struct MsgPort *port;
   
   port=FindPort(PORTNAME);
   if(port){
      len=strlen(CLOSECMD)+1;
      if(closemsg=AllocMem(len+=sizeof(struct Message),MEMF_PUBLIC)){
         closemsg->msg.mn_Node.ln_Succ=NULL;
         closemsg->msg.mn_Node.ln_Pred=NULL;
         closemsg->msg.mn_Node.ln_Type=NT_MESSAGE;
         closemsg->msg.mn_Node.ln_Pri=0;
         closemsg->msg.mn_Node.ln_Name=closemsg->string;
         closemsg->msg.mn_ReplyPort=NULL;
         closemsg->msg.mn_Length=len;
         strcpy(closemsg->string,CLOSECMD);
         PutMsg(port,closemsg);
      }
   }
}


#ifdef __GNUC__
void myputchar(void){
  register char regd0 asm("d0");
  char ch = regd0;
  register char ** rega3 asm("a3");
  char **p=rega3;
#else
  void __asm myputchar(register __d0 char ch,register __a3 char ** p){
#endif

  *(*p)++=ch;
}

void myvsprintf(char *buf,char *format,va_list args){
   char *pos=buf;
   
   RawDoFmt(format,(APTR)args,myputchar,&pos);
}

/*
 * rawdprintf uses RawDoFmt() for doing vsprintf() (Lattice vsprintf()
 * breaks sometimes when called from certain non-process environments.
 * Because of this, things like rawdprintf("%*s",5,"Hello123") are not
 * supported.
 */
 
void rawdprintf(char *format,...){
   char buf[256];
   va_list vl;
   int len;
   struct debugmsg *msg;
   struct MsgPort *port;
   
   va_start(vl,format);
   port=FindPort(PORTNAME);
   if(port){
      myvsprintf(buf,format,vl);
      len=strlen(buf)+1;
      if(msg=AllocMem(len+=sizeof(struct Message),MEMF_PUBLIC)){
         msg->msg.mn_Node.ln_Succ=NULL;
         msg->msg.mn_Node.ln_Pred=NULL;
         msg->msg.mn_Node.ln_Type=NT_MESSAGE;
         msg->msg.mn_Node.ln_Pri=0;
         msg->msg.mn_Node.ln_Name=msg->string;
         msg->msg.mn_ReplyPort=NULL;
         msg->msg.mn_Length=len;
         strcpy(msg->string,buf);
         PutMsg(port,msg);
      }
   }
   va_end(vl);
}


/*
 * dprintf() uses the standard c vsprintf(), so it is more flexible than
 * rawdprintf(), but seems to cause troubles in non-standard contexts.
 */
 
void dprintf(char *format,...){
   char buf[256];
   va_list vl;
   int len;
   struct debugmsg *msg;
   struct MsgPort *port;
   
   va_start(vl,format);
   port=FindPort(PORTNAME);
   if(port){
      vsprintf(buf,format,vl);
      /* Could derive from vsprintf's return, but this is sure to be safe */
      len=strlen(buf)+1;
      if(msg=AllocMem(len+=sizeof(struct Message),MEMF_PUBLIC)){
         msg->msg.mn_Node.ln_Succ=NULL;
         msg->msg.mn_Node.ln_Pred=NULL;
         msg->msg.mn_Node.ln_Type=NT_MESSAGE;
         msg->msg.mn_Node.ln_Pri=0;
         msg->msg.mn_Node.ln_Name=msg->string;
         msg->msg.mn_ReplyPort=NULL;
         msg->msg.mn_Length=len;
         strcpy(msg->string,buf);
         PutMsg(port,msg);
      }
   }
   va_end(vl);
}

