static char rcs[] = "@(#)$Id: print_errors.c,v 1.3 2009/01/09 18:50:44 leavens Exp leavens $";

/* print_errors -- routines to print error messages with name of the program
 *
 * SYNOPSIS: All output is to standard error
 *     program_usage_init(argv[0], "options arguments");
 *     sys_warning("can't open file %s, continuing", f);
 *     sys_err("can't open file %s", f);
 *     warning("This is your %drd warning", 3);
 *     error("you blew it");
 *     usage();
 */

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

static char * Name = NULL;
static char * Usage = "USAGE NOT DEFINED";

void program_usage_init(char *name, char *usage_mesg)
     /* effect: initialize the error printing system */
{
  char * lastslash = strrchr(name, '/');
  Name = (lastslash != NULL) ? lastslash+1 : name;
  Usage = usage_mesg;
}

static void print_name(void)
     /* effect: if Name is defined, print it, a colon, and a space */
{
  if (Name) {
    fprintf(stderr, "%s: ", Name);
  }
}

static void warn_head(void)
     /* effect: if Name is defined, print it, and "Warning: " */
{
  print_name();
  fprintf(stderr, "Warning: ");
}

static void error_head(void)
     /* effect: if Name is defined, print it, and "ERROR: " */
{
  print_name();
  fprintf(stderr, "ERROR: ");
}

void warning(const char *fmt, ...)
     /* effect: print Name (if defined), "Warning: ",
	then a message controlled by fmt and the other args,
	then a newline on standard error output.
      */
{
  va_list args;

  va_start(args, fmt);
  warn_head();
  vfprintf(stderr, fmt, args);
  fprintf(stderr, "\n");
  va_end(args);
}


void error(const char *fmt, ...)
     /* effect: print Name (if defined), "Warning: ",
	then a message controlled by fmt and the other args,
	then a newline on standard error output.
      */
{
  va_list args;

  va_start(args, fmt);
  error_head();
  vfprintf(stderr, fmt, args);
  fprintf(stderr, "\n");
  va_end(args);

  exit(1);
}


void usage()
     /* effect: print usage message on standard error output, and exit(1)
      */
{
  fprintf(stderr, "Usage: %s %s\n", Name, Usage);
  exit(1);
}

#include <errno.h>

#ifndef __APPLE__
extern int sys_nerr;
extern const char * const sys_errlist[];
extern int errno;
#endif

void sys_err(const char *fmt, ...)
     /* requires: 0 <= errno && errno < sys_nerr */
     /* effect: print Name (if defined), "ERROR: ", msg, a colon, a space,
        the standard Unix system error message, and a newline
        on standard error output, then exit(1).
      */
{
  va_list args;

  va_start(args, fmt);
  error_head();
  vfprintf(stderr, fmt, args);
  if (0 <= errno && errno < sys_nerr) {
    fprintf(stderr, ": %s", sys_errlist[errno]);
  }
  fprintf(stderr, "\n");
  va_end(args);
  exit(1);
}


void sys_warning(const char *fmt, ...)
     /* requires: 0 <= errno && errno < sys_nerr */
     /* effect: print Name (if defined), "Warning: ", msg, a colon,
        a space, then the standard Unix system error message, and a newline
        on standard error output, then exit(1).
      */
{
  va_list args;

  va_start(args, fmt);
  warn_head();
  vfprintf(stderr, fmt, args);
  if (0 <= errno && errno < sys_nerr) {
    fprintf(stderr, ": %s", sys_errlist[errno]);
  }
  fprintf(stderr, "\n");
  va_end(args);
}
