You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tellico/src/translators/btparse/error.c

349 lines
10 KiB

/* ------------------------------------------------------------------------
@NAME : error.c
@DESCRIPTION: Anything relating to reporting or recording errors and
warnings.
@GLOBALS : errclass_names
err_actions
err_handlers
errclass_counts
error_buf
@CALLS :
@CREATED : 1996/08/28, Greg Ward
@MODIFIED :
@VERSION : $Id: error.c,v 2.5 1999/11/29 01:13:10 greg Rel $
@COPYRIGHT : Copyright (c) 1996-99 by Gregory P. Ward. All rights reserved.
This file is part of the btparse library. This library 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.
-------------------------------------------------------------------------- */
/*#include "bt_config.h"*/
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "btparse.h"
#include "error.h"
/*#include "my_dmalloc.h"*/
#define NUM_ERRCLASSES ((int) BTERR_INTERNAL + 1)
static const char *errclass_names[NUM_ERRCLASSES] =
{
NULL, /* BTERR_NOTIFY */
"warning", /* BTERR_CONTENT */
"warning", /* BTERR_LEXWARN */
"warning", /* BTERR_USAGEWARN */
"error", /* BTERR_LEXERR */
"syntax error", /* BTERR_SYNTAX */
"fatal error", /* BTERR_USAGEERR */
"internal error" /* BTERR_INTERNAL */
};
static const bt_erraction err_actions[NUM_ERRCLASSES] =
{
BTACT_NONE, /* BTERR_NOTIFY */
BTACT_NONE, /* BTERR_CONTENT */
BTACT_NONE, /* BTERR_LEXWARN */
BTACT_NONE, /* BTERR_USAGEWARN */
BTACT_NONE, /* BTERR_LEXERR */
BTACT_NONE, /* BTERR_SYNTAX */
BTACT_CRASH, /* BTERR_USAGEERR */
BTACT_ABORT /* BTERR_INTERNAL */
};
void print_error (bt_error *err);
static bt_err_handler err_handlers[NUM_ERRCLASSES] =
{
print_error,
print_error,
print_error,
print_error,
print_error,
print_error,
print_error,
print_error
};
static int errclass_counts[NUM_ERRCLASSES] = { 0, 0, 0, 0, 0, 0, 0, 0 };
static char error_buf[MAX_ERROR+1];
/* ----------------------------------------------------------------------
* Error-handling functions.
*/
void print_error (bt_error *err)
{
const char * name;
boolean something_printed;
something_printed = FALSE;
if (err->filename)
{
fprintf (stderr, "%s", err->filename);
something_printed = TRUE;
}
if (err->line > 0) /* going to print a line number? */
{
if (something_printed)
fprintf (stderr, ", ");
fprintf (stderr, "line %d", err->line);
something_printed = TRUE;
}
if (err->item_desc && err->item > 0) /* going to print an item number? */
{
if (something_printed)
fprintf (stderr, ", ");
fprintf (stderr, "%s %d", err->item_desc, err->item);
something_printed = TRUE;
}
name = errclass_names[(int) err->errclass];
if (name)
{
if (something_printed)
fprintf (stderr, ", ");
fprintf (stderr, "%s", name);
something_printed = TRUE;
}
if (something_printed)
fprintf (stderr, ": ");
fprintf (stderr, "%s\n", err->message);
} /* print_error() */
/* ----------------------------------------------------------------------
* Error-reporting functions: these are called anywhere in the library
* when we encounter an error.
*/
void
report_error (bt_errclass errclass,
char * filename,
int line,
const char * item_desc,
int item,
const char * fmt,
va_list arglist)
{
bt_error err;
#if !HAVE_VSNPRINTF
int msg_len;
#endif
err.errclass = errclass;
err.filename = filename;
err.line = line;
err.item_desc = item_desc;
err.item = item;
errclass_counts[(int) errclass]++;
/*
* Blech -- we're writing to a static buffer because there's no easy
* way to know how long the error message is going to be. (Short of
* reimplementing printf(), or maybe printf()'ing to a dummy file
* and using the return value -- ugh!) The GNU C library conveniently
* supplies vsnprintf(), which neatly solves this problem by truncating
* the output string if it gets too long. (I could check for this
* truncation if I wanted to, but I don't think it's necessary given the
* ample size of the message buffer.) For non-GNU systems, though,
* we're stuck with using vsprintf()'s return value. This can't be
* trusted on all systems -- thus there's a check for it in configure.
* Also, this won't necessarily trigger the internal_error() if we
* do overflow; it's conceivable that vsprintf() itself would crash.
* At least doing it this way we avoid the possibility of vsprintf()
* silently corrupting some memory, and crashing unpredictably at some
* later point.
*/
#if HAVE_VSNPRINTF
vsnprintf (error_buf, MAX_ERROR, fmt, arglist);
#else
msg_len = vsprintf (error_buf, fmt, arglist);
if (msg_len > MAX_ERROR)
internal_error ("static error message buffer overflowed");
#endif
err.message = error_buf;
if (err_handlers[errclass])
(*err_handlers[errclass]) (&err);
switch (err_actions[errclass])
{
case BTACT_NONE: return;
case BTACT_CRASH: exit (1);
case BTACT_ABORT: abort ();
default: internal_error ("invalid error action %d for class %d (%s)",
(int) err_actions[errclass],
(int) errclass, errclass_names[errclass]);
}
} /* report_error() */
GEN_ERRFUNC (general_error,
(bt_errclass errclass,
char * filename,
int line,
const char * item_desc,
int item,
char * fmt,
...),
errclass, filename, line, item_desc, item, fmt)
GEN_ERRFUNC (error,
(bt_errclass errclass,
char * filename,
int line,
char * fmt,
...),
errclass, filename, line, NULL, -1, fmt)
GEN_ERRFUNC (ast_error,
(bt_errclass errclass,
AST * ast,
char * fmt,
...),
errclass, ast->filename, ast->line, NULL, -1, fmt)
GEN_ERRFUNC (notify,
(const char * fmt, ...),
BTERR_NOTIFY, NULL, -1, NULL, -1, fmt)
GEN_ERRFUNC (usage_warning,
(const char * fmt, ...),
BTERR_USAGEWARN, NULL, -1, NULL, -1, fmt)
GEN_ERRFUNC (usage_error,
(const char * fmt, ...),
BTERR_USAGEERR, NULL, -1, NULL, -1, fmt)
GEN_ERRFUNC (internal_error,
(const char * fmt, ...),
BTERR_INTERNAL, NULL, -1, NULL, -1, fmt)
/* ======================================================================
* Functions to be used outside of the library
*/
/* ------------------------------------------------------------------------
@NAME : bt_reset_error_counts()
@INPUT :
@OUTPUT :
@RETURNS :
@DESCRIPTION: Resets all the error counters to zero.
@GLOBALS :
@CALLS :
@CREATED : 1997/01/08, GPW
@MODIFIED :
-------------------------------------------------------------------------- */
void bt_reset_error_counts (void)
{
int i;
for (i = 0; i < NUM_ERRCLASSES; i++)
errclass_counts[i] = 0;
}
/* ------------------------------------------------------------------------
@NAME : bt_get_error_count()
@INPUT : errclass
@OUTPUT :
@RETURNS :
@DESCRIPTION: Returns number of errors seen in the specified class.
@GLOBALS : errclass_counts
@CALLS :
@CREATED :
@MODIFIED :
-------------------------------------------------------------------------- */
int bt_get_error_count (bt_errclass errclass)
{
return errclass_counts[errclass];
}
/* ------------------------------------------------------------------------
@NAME : bt_get_error_counts()
@INPUT : counts - pointer to an array big enough to hold all the counts
if NULL, the array will be allocated for you (and you
must free() it when done with it)
@OUTPUT :
@RETURNS : counts - either the passed-in pointer, or the newly-
allocated array if you pass in NULL
@DESCRIPTION: Returns a newly-allocated array with the number of errors
in each error class, indexed by the members of the
eclass_t enum.
@GLOBALS : errclass_counts
@CALLS :
@CREATED : 1997/01/06, GPW
@MODIFIED :
-------------------------------------------------------------------------- */
int *bt_get_error_counts (int *counts)
{
int i;
if (counts == NULL)
counts = (int *) malloc (sizeof (int) * NUM_ERRCLASSES);
for (i = 0; i < NUM_ERRCLASSES; i++)
counts[i] = errclass_counts[i];
return counts;
}
/* ------------------------------------------------------------------------
@NAME : bt_error_status
@INPUT : saved_counts - an array of error counts as returned by
bt_get_error_counts, or NULL not to compare
to a previous checkpoint
@OUTPUT :
@RETURNS :
@DESCRIPTION: Computes a bitmap where a bit is set for each error class
that has more errors now than it used to have (or, if
saved_counts is NULL, the bit is set of there are have been
any errors in the corresponding error class).
Eg. "x & (1<<E_SYNTAX)" (where x is returned by bt_error_status)
is true if there have been any syntax errors.
@GLOBALS :
@CALLS :
@CREATED :
@MODIFIED :
-------------------------------------------------------------------------- */
ushort bt_error_status (int *saved_counts)
{
int i;
ushort status;
status = 0;
if (saved_counts)
{
for (i = 0; i < NUM_ERRCLASSES; i++)
status |= ( (errclass_counts[i] > saved_counts[i]) << i);
}
else
{
for (i = 0; i < NUM_ERRCLASSES; i++)
status |= ( (errclass_counts[i] > 0) << i);
}
return status;
} /* bt_error_status () */