/* error.c: communication of informational, warning, error and 
 * fatal error messages for the vrml library. */

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

#include "error.H"
#include "parser.H"

extern int lineno;
extern char *yyfilename;

/* default callback for showing error messages */
static void vrml_printerr(char *message)
{
  fprintf(stderr, "%s\n", message);
}

VRML_MSG_CALLBACK_FUNC vrml_info_callback_func = NULL,
                        vrml_warning_callback_func = vrml_printerr,
                        vrml_error_callback_func = vrml_printerr,
                        vrml_fatal_callback_func = vrml_printerr;

/* The SetCallback functions return the previously set callback function */
VRML_MSG_CALLBACK_FUNC VrmlSetInfoCallback(VRML_MSG_CALLBACK_FUNC func)
{
  VRML_MSG_CALLBACK_FUNC old_func = vrml_info_callback_func;
  vrml_info_callback_func = func;
  return old_func;
}

VRML_MSG_CALLBACK_FUNC VrmlSetWarningCallback(VRML_MSG_CALLBACK_FUNC func)
{
  VRML_MSG_CALLBACK_FUNC old_func = vrml_warning_callback_func;
  vrml_warning_callback_func = func;
  return old_func;
}

VRML_MSG_CALLBACK_FUNC VrmlSetErrorCallback(VRML_MSG_CALLBACK_FUNC func)
{
  VRML_MSG_CALLBACK_FUNC old_func = vrml_error_callback_func;
  vrml_error_callback_func = func;
  return old_func;
}

VRML_MSG_CALLBACK_FUNC VrmlSetFatalCallback(VRML_MSG_CALLBACK_FUNC func)
{
  VRML_MSG_CALLBACK_FUNC old_func = vrml_fatal_callback_func;
  vrml_fatal_callback_func = func;
  return old_func;
}

/* prints an informational message */
void VRMLInfo(char *routine, char *text, ...)
{
  va_list pvar;
  char buf[VRML_MAX_MESSAGE_LENGTH], *p;
  int n;

  p = buf;
  if (lineno > 0) {
    sprintf(p, "%s:%d: %n", yyfilename, lineno, &n);
    p += n;
  }

  if (routine) {
    sprintf(p, "%s(): %n", routine, &n);
    p += n;
  }
  
  va_start(pvar, text);
  vsprintf(p, text, pvar);
  va_end(pvar);

  if (vrml_info_callback_func)
    vrml_info_callback_func(buf);
}

/* prints a warning message */
void VRMLWarning(char *routine, char *text, ...)
{
  va_list pvar;
  char buf[VRML_MAX_MESSAGE_LENGTH], *p;
  int n;

  p = buf;
  if (lineno > 0) {
    sprintf(p, "%s:%d: %n", yyfilename, lineno, &n);
    p += n;
  }

  if (routine) {
    sprintf(p, "%s(): %n", routine, &n);
    p += n;
  }

  sprintf(p, "warning: %n", &n);
  p += n;
  
  va_start(pvar, text);
  vsprintf(p, text, pvar);
  va_end(pvar);
  
  if (vrml_warning_callback_func)
    vrml_warning_callback_func(buf);
}

/* prints an error message */
void VRMLError(char *routine, char *text, ...)
{
  va_list pvar;
  char buf[VRML_MAX_MESSAGE_LENGTH], *p;
  int n;

  p = buf;
  if (lineno > 0) {
    sprintf(p, "%s:%d: %n", yyfilename, lineno, &n);
    p += n;
  }

  if (routine) {
    sprintf(p, "%s(): %n", routine, &n);
    p += n;
  }

  va_start(pvar, text);
  vsprintf(p, text, pvar);
  va_end(pvar);
  
  if (vrml_error_callback_func)
    vrml_error_callback_func(buf);
}

/* prints a fatal error message */
void VRMLFatal(int errcode, char *routine, char *text, ...)
{
  va_list pvar;
  char buf[VRML_MAX_MESSAGE_LENGTH], *p;
  int n;

  p = buf;
  if (lineno > 0) {
    sprintf(p, "%s:%d: %n", yyfilename, lineno, &n);
    p += n;
  }

  if (routine) {
    sprintf(p, "%s(): %n", routine, &n);
    p += n;
  }

  va_start(pvar, text);
  vsprintf(p, text, pvar);
  va_end(pvar);
  
  if (vrml_fatal_callback_func)
    vrml_fatal_callback_func(buf);
  exit(errcode);
}

