/* $Id: c,v.throwback 1.26 1998/09/01 20:46:53 stoklund Exp $ */
/* throwback.c: Support for throwback in LaCheck

   Copyright (C) 1998 Jakob Stoklund Olesen

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

   This library 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
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public
   License along with this library; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 -
   1307, USA. */


#include "kpathsea:config.h"
#include "kpathsea:riscos.h"

#include "kernel.h"
#include "throwback.h"

#define DDEUtils_ThrowbackStart 0x42587
#define DDEUtils_ThrowbackSend 0x42588
#define DDEUtils_ThrowbackEnd 0x42589

/* The full name of the primary input file */
static string primary_file = NULL;

/* The current status of the trowback protocol */
static enum
  {
    not_started, started, not_available
  }
status = not_started;

static void
Throwback_Processing (string file)
{
  _kernel_swi_regs regs;

  regs.r[0] = 0;		/* ReasonProcessing */
  regs.r[2] = (unsigned) file;
  _kernel_swi (DDEUtils_ThrowbackSend, &regs, &regs);
}

/* Set the name of the primary input file */
extern void
throwback_primary (const_string filename)
{
  string name = riscos_ensure_prefix (filename);

  /* maybe we started before setting the primary file? */
  /* call Throwback_ReasonProcessing */
  if (status == started)
    Throwback_Processing (name);

  if (primary_file)
    free (primary_file);

  primary_file = name;
}

/* Stop the throwback session. */
static void
tb_end ()
{
  _kernel_swi_regs regs;
  _kernel_swi (DDEUtils_ThrowbackEnd, &regs, &regs);
}

void
throwback_send (const_string filename, int lineno, const_string msg)
{
  _kernel_swi_regs regs;
  string full_name;

  switch (status)
    {
    case not_available:	/* don't try another initialise */
      return;
    case not_started:		/* Try a startup */
      if (_kernel_swi (DDEUtils_ThrowbackStart, &regs, &regs))
	{
	  status = not_available;	/* some error */
	  return;
	}
      status = started;
      atexit (tb_end);
      /* Set the primary filename --- Throwback_ReasonProcessing */
      if (primary_file)
	Throwback_Processing (primary_file);
      /* fall through */
    case started:
      full_name = riscos_ensure_prefix (filename);
      regs.r[0] = 1;		/* Throwback_ReasonErrorDetails */
      regs.r[2] = (unsigned) full_name;
      regs.r[3] = lineno;
      regs.r[4] = 0;		/* severity: warning */
      regs.r[5] = (unsigned) msg;
      _kernel_swi (DDEUtils_ThrowbackSend, &regs, &regs);
      free (full_name);
      break;
    }
}
