/*===========================================================================
  Copyright (C) 1995-2009 European Southern Observatory (ESO)
 
  This program is free software; you can redistribute it and/or 
  modify it under the terms of the GNU General Public License as 
  published by the Free Software Foundation; either version 2 of 
  the License, or (at your option) any later version.
 
  This program 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 General Public License for more details.
 
  You should have received a copy of the GNU General Public 
  License along with this program; if not, write to the Free 
  Software Foundation, Inc., 675 Massachusetts Ave, Cambridge, 
  MA 02139, USA.
 
  Correspondence concerning ESO-MIDAS should be addressed as follows:
	Internet e-mail: midas@eso.org
	Postal address: European Southern Observatory
			Data Management Division 
			Karl-Schwarzschild-Strasse 2
			D 85748 Garching bei Muenchen 
			GERMANY
===========================================================================*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.TYPE        Module
.NAME        TZ4.C
.LANGUAGE    C
.AUTHOR      J.D.Ponz  IPG-ESO Garching
.CATEGORY    table interface (Design 2.0) low level routines.
.COMMENTS    This module contains the lower level routines handling errors
		on tables.
	
\begin{TeX}
\begin{enumerate}
	There are two modes for using the error routine:
	\item {\em verbose} mode, i.e. display immediately what is passed 
		to routines TBL\_eput
		(simple text error message), 
		TBL_errf (formatted error messages), 
		or TBL_errs (most frequent errors). 
		This is the default mode.
	\item	{\em quiet} mode, i.e. just keep in memory the error, 
		which can then be retrieved
		later by TBL_eget. This mode is in effect after having
		called {\em TBL\_set({\tt 0})}
\end{enumerate}
\end{TeX}

.VERSION  3.0 	20-Aug-1990   Extracted from tz1
	  3.1 	27-Feb-1991 Corrected bug in TBL_errs

 090406		last modif
------------------------------------------------------------*/

#include <midas_def.h>		/* General MIDAS Symbols	*/
#include <stdarg.h>		/* System	*/

#include <tblsys.h>		/* Table System parameters	*/
#include <tblerr.h>		/* Table System parameters	*/

#include <stdio.h>




#define DEPTH	0		/* Change if depth to be used	*/

static	char	locbuf[132] = "";	/* Saved Message	*/
static  int	locstat = 0;		/* Local Status		*/
static  int	flags = 1;		/* To display or not	*/

#if DEPTH
static	int	depth = 0;		/* Routine TCx depth	*/
#endif
static  char	*routine = (char *)0;	/* Routine Name		*/

/*===============================================================*/
#ifdef __STDC__
static int save_message (int status,char *message)
#else
static int save_message (status, message)
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Insert an error (Implies status > 0 !!)
.RETURNS Length of message
------------------------------------------------------------------*/
	int	status;		/* IN: Status			*/
	char 	*message;	/* IN: Message to display	*/
#endif
{
	int	len;
	
				/* Copy message to memory (if error)	*/
  if (status > 0) {
	locstat = status;
  	len = strlen (message);
  	if (len > sizeof(locbuf)-1)	len = sizeof(locbuf) - 1;
  	oscopy (locbuf, message, len);
  	locbuf[len] = '\0';
  }
  else	len = 0;

  return (len);
}

/*===============================================================*/

void TBL_ERROR(name, tid, status)
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Display error
.RETURNS nothing
------------------------------------------------------------------*/
	char	*name		/* routine name */;
        int	tid		/* tid */;
	int	status		/* status */;
{
	char line[132];
	TABLE *tp;

  tp = TBL_ptr (tid);
  if (tp)	sprintf(line, "%s, table: %s", name, tp->phname);
  else		sprintf(line, "%s, tid: %d",name,tid);
  save_message (status, line);

				/* Pass & Print Message to Midas */
  if (flags & 1) MID_ERROR("MIDAS", line, status, 1);

  return;
}

/*===============================================================*/
char *TBL_eget ()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Get the last error
.RETURNS The last error message / NULL if no error
------------------------------------------------------------------*/
{
  return (locbuf[0] ? locbuf : (char *)0);
}

/*===============================================================*/
int TBL_eput (status, message)
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Insert an error (Implies status > 0 !!)
.RETURNS Length of message
------------------------------------------------------------------*/
	int	status;		/* IN: Status			*/
	char 	*message;	/* IN: Message to display	*/
{
	int	i;
	
			/* ... Write out the error message	*/

  MID_ERROR("MIDAS", message, status, 1);
			/* Copy message to memory (if error)	*/
  i = save_message (status, message);

  return (i);
}

/*===============================================================*/
int TBL_eclear ()
/*+++
.PURPOSE Clear the error state. 
.RETURNS Number of freed errors (0 or 1)
----*/
{
	int	n;
	
  n = (locbuf[0] ? 1 : 0);
  locbuf[0] = '\0';
  locstat = 0;
  routine = (char *)0;
  return (n);
}

/*===============================================================*/
int TBL_eset (opt)
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Set the option flags
.RETURNS The previous flags
------------------------------------------------------------------*/
	int	opt;	/* IN: New options  (1 = Display Errors)  */
{
	int	old_flags;
  
  old_flags = flags;
  flags = opt;
  return (old_flags);
}

/*===============================================================*/
int TBL_enter (name)
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Specify the routine name
.METHOD  Place here the routine name, if it is at null depth
.RETURNS The previous depth
------------------------------------------------------------------*/
	char	*name;	/* IN: The routine name	*/
{
#if DEPTH
  if (depth < 0)	depth = 0;
  if (!depth)	routine = name;
  return (depth++)  ;
#else
  routine = name;
  return(0);
#endif
}

int TBL_exit (status)
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE To be called at end of TCx routine
.RETURNS status
------------------------------------------------------------------*/
	int	status;	/* IN: Status	*/
{
#if DEPTH
  depth--;
#endif
  return (status)  ;
}

/*===============================================================*/
int TBL_errf (int status, char *fmt, ...)
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Display error with formats
.METHOD  Uses the `varargs' facility. 
Variable Number of Arguments:
status, fmt, args
.RETURNS The status (0=INFO, negative=WARNING, positive=ERROR)
------------------------------------------------------------------*/
{
	va_list	args;
	char	buffer[1024];
	char	*p;

  va_start(args,fmt);
  
		/* Start text with **** ++++ or .... 	*/

  buffer[0] = (status ? (status > 0 ? '*' : '+') : '.');
  buffer[1] = buffer[2] = buffer[3] = buffer[0] ;
  buffer[4] = ' ';
  p = &buffer[5];

 		/* ... add the routine name  ... 	*/
  if (routine)
  	sprintf (p, "%s: ", routine), p += strlen(p);
  	
 		/* ... add the formatted text ...	*/
  vsprintf (p, fmt, args);
  va_end (args);
  
		/* ... Finally pass the message		*/
  TBL_eput (status, buffer);
  
  return (status);
}

/*===============================================================*/
int TBL_errs (tid, status, value)
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Standard error display
.METHOD  Uses TBL_errf
.RETURNS The status (0=INFO, negative=WARNING, positive=ERROR)
------------------------------------------------------------------*/
	int	tid;		/* IN: Table designation	*/
	int	status;		/* IN: Error status		*/
	int	value;		/* IN: Further parameter	*/
{
	TABLE	*tp;

  tp = TBL_ptr(tid);
  switch (status) {
    case ERR_TBLENT:		/* Bad Table Number		*/
    	TBL_errf(status, "bad tid: %d", tid);
    	break;
    case ERR_TBLCOL:
    	if (value > tp->cols)
	    	TBL_errf(status, "bad column #%d (>%d), Table: %s",
	    	value, tp->cols, tp->phname);
	else   	TBL_errf(status, "bad column #%d (<1), Table: %s",  
		value, tp->phname);
	break;
    case ERR_TBLROW:
    	if (value < 1)
    		TBL_errf(status, "bad row @%d, Table: %s", 
		value, tp->phname);
    	else if (value > tp->arows)
    		TBL_errf(status, "row @%d exceeds allocated %d rows, Table: %s",
    		value, tp->arows, tp->phname);
	else   	TBL_errf(status, "row @%d exceeds %d rows, Table: %s", 
    		value, tp->rows, tp->phname);
	break;
    default:
        if (routine != (char *) 0)
    	   TBL_ERROR(routine, tid, status);
        else
    	   TBL_ERROR("table open", tid, status);
  }
  return(status);
}
