ack/lang/pc/comp/error.c

409 lines
6.3 KiB
C
Raw Normal View History

1988-10-26 15:21:11 +00:00
/* E R R O R A N D D I A G N O S T I C R O U T I N E S */
/* This file contains the (non-portable) error-message and diagnostic
giving functions. Be aware that they are called with a variable
number of arguments!
*/
#include "parameters.h"
1988-10-26 15:21:11 +00:00
#include "debug.h"
#if __STDC__
#include <stdarg.h>
#else
1989-10-30 17:51:31 +00:00
#include <varargs.h>
#endif
1988-10-26 15:21:11 +00:00
#include <em_arith.h>
#include <em_label.h>
1993-10-26 09:59:06 +00:00
#include <em_code.h>
#include <stdlib.h>
#include <stdio.h>
#include "print.h"
#include "system.h"
1988-10-26 15:21:11 +00:00
#include "LLlex.h"
#include "f_info.h"
#include "input.h"
#include "main.h"
#include "node.h"
/* error classes */
#define ERROR 1
#define WARNING 2
#define LEXERROR 3
#define LEXWARNING 4
#define CRASH 5
#define FATAL 6
#ifdef DEBUG
#define VDEBUG 7
#endif
int err_occurred;
static void _error(int, struct node *, char *, register va_list);
1988-10-26 15:21:11 +00:00
/* There are three general error-message functions:
lexerror() lexical and pre-processor error messages
error() syntactic and pre-processor messagese
node_error() errors in nodes
The difference lies in the place where the file name and line
number come from.
Lexical errors report from the global variables LineNumber and
FileName, node errors get their information from the
node, whereas other errors use the information in the token.
*/
#if __STDC__
#ifdef DEBUG
/*VARARGS*/
void debug(char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
{
_error(VDEBUG, NULLNODE, fmt, ap);
}
va_end(ap);
}
#endif /* DEBUG */
/*VARARGS*/
void error(char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
{
_error(ERROR, NULLNODE, fmt, ap);
}
va_end(ap);
}
/*VARARGS*/
void node_error(struct node *node, char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
{
_error(ERROR, node, fmt, ap);
}
va_end(ap);
}
/*VARARGS*/
void warning(char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
{
_error(WARNING, NULLNODE, fmt, ap);
}
va_end(ap);
}
/*VARARGS*/
void node_warning(struct node *node, char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
{
_error(WARNING, node, fmt, ap);
}
va_end(ap);
}
/*VARARGS*/
void lexerror(char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
{
_error(LEXERROR, NULLNODE, fmt, ap);
}
va_end(ap);
}
/*VARARGS*/
void lexwarning(char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
{
_error(LEXWARNING, NULLNODE, fmt, ap);
}
va_end(ap);
}
/*VARARGS*/
void fatal(char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
{
_error(FATAL, NULLNODE, fmt, ap);
}
va_end(ap);
exit(EXIT_FAILURE);
}
/*VARARGS*/
void crash(char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
{
_error(CRASH, NULLNODE, fmt, ap);
}
va_end(ap);
#ifdef DEBUG
abort();
#else
exit(EXIT_FAILURE);
#endif
}
#else
1988-10-26 15:21:11 +00:00
#ifdef DEBUG
1989-10-30 17:51:31 +00:00
/*VARARGS*/
void debug(va_alist)
1989-10-30 17:51:31 +00:00
va_dcl
1988-10-26 15:21:11 +00:00
{
1989-10-30 17:51:31 +00:00
va_list ap;
va_start(ap);
{
char *fmt = va_arg(ap, char *);
_error(VDEBUG, NULLNODE, fmt, ap);
1989-10-30 17:51:31 +00:00
}
va_end(ap);
1988-10-26 15:21:11 +00:00
}
#endif /* DEBUG */
1988-10-26 15:21:11 +00:00
1989-10-30 17:51:31 +00:00
/*VARARGS*/
void error(va_alist)
1989-10-30 17:51:31 +00:00
va_dcl
1988-10-26 15:21:11 +00:00
{
1989-10-30 17:51:31 +00:00
va_list ap;
va_start(ap);
{
char *fmt = va_arg(ap, char *);
_error(ERROR, NULLNODE, fmt, ap);
1989-10-30 17:51:31 +00:00
}
va_end(ap);
1988-10-26 15:21:11 +00:00
}
1989-10-30 17:51:31 +00:00
/*VARARGS*/
void node_error(va_alist)
1989-10-30 17:51:31 +00:00
va_dcl
1988-10-26 15:21:11 +00:00
{
1989-10-30 17:51:31 +00:00
va_list ap;
va_start(ap);
{
struct node *node = va_arg(ap, struct node *);
char *fmt = va_arg(ap, char *);
_error(ERROR, node, fmt, ap);
1989-10-30 17:51:31 +00:00
}
va_end(ap);
1988-10-26 15:21:11 +00:00
}
1989-10-30 17:51:31 +00:00
/*VARARGS*/
void warning(va_alist)
1989-10-30 17:51:31 +00:00
va_dcl
1988-10-26 15:21:11 +00:00
{
1989-10-30 17:51:31 +00:00
va_list ap;
va_start(ap);
{
char *fmt = va_arg(ap, char *);
_error(WARNING, NULLNODE, fmt, ap);
1989-10-30 17:51:31 +00:00
}
va_end(ap);
1988-10-26 15:21:11 +00:00
}
1989-10-30 17:51:31 +00:00
/*VARARGS*/
void node_warning(va_alist)
1989-10-30 17:51:31 +00:00
va_dcl
1988-10-26 15:21:11 +00:00
{
1989-10-30 17:51:31 +00:00
va_list ap;
va_start(ap);
{
char *fmt = va_arg(ap, char *);
1989-10-30 17:51:31 +00:00
struct node *node = va_arg(ap, struct node *);
_error(WARNING, node, fmt, ap);
1989-10-30 17:51:31 +00:00
}
va_end(ap);
1988-10-26 15:21:11 +00:00
}
1989-10-30 17:51:31 +00:00
/*VARARGS*/
void lexerror(va_alist)
1989-10-30 17:51:31 +00:00
va_dcl
1988-10-26 15:21:11 +00:00
{
1989-10-30 17:51:31 +00:00
va_list ap;
va_start(ap);
{
char *fmt = va_arg(ap, char *);
_error(LEXERROR, NULLNODE, fmt, ap);
1989-10-30 17:51:31 +00:00
}
va_end(ap);
1988-10-26 15:21:11 +00:00
}
1989-10-30 17:51:31 +00:00
/*VARARGS*/
void lexwarning(va_alist)
1989-10-30 17:51:31 +00:00
va_dcl
1988-10-26 15:21:11 +00:00
{
1989-10-30 17:51:31 +00:00
va_list ap;
va_start(ap);
{
char *fmt = va_arg(ap, char *);
_error(LEXWARNING, NULLNODE, fmt, ap);
1989-10-30 17:51:31 +00:00
}
va_end(ap);
1988-10-26 15:21:11 +00:00
}
1989-10-30 17:51:31 +00:00
/*VARARGS*/
void fatal(va_alist)
1989-10-30 17:51:31 +00:00
va_dcl
1988-10-26 15:21:11 +00:00
{
1989-10-30 17:51:31 +00:00
va_list ap;
va_start(ap);
{
char *fmt = va_arg(ap, char *);
_error(FATAL, NULLNODE, fmt, ap);
1989-10-30 17:51:31 +00:00
}
va_end(ap);
exit(EXIT_FAILURE);
1988-10-26 15:21:11 +00:00
}
1989-10-30 17:51:31 +00:00
/*VARARGS*/
void crash(va_alist)
1989-10-30 17:51:31 +00:00
va_dcl
1988-10-26 15:21:11 +00:00
{
1989-10-30 17:51:31 +00:00
va_list ap;
va_start(ap);
{
char *fmt = va_arg(ap, char *);
_error(CRASH, NULLNODE, fmt, ap);
1989-10-30 17:51:31 +00:00
}
va_end(ap);
1988-10-26 15:21:11 +00:00
#ifdef DEBUG
abort();
1988-10-26 15:21:11 +00:00
#else
exit(EXIT_FAILURE);
1988-10-26 15:21:11 +00:00
#endif
}
#endif
1988-10-26 15:21:11 +00:00
static void _error(int class, struct node *node, char *fmt, register va_list ap)
1988-10-26 15:21:11 +00:00
{
/* _error attempts to limit the number of error messages
for a given line to MAXERR_LINE.
*/
static unsigned int last_ln = 0;
unsigned int ln = 0;
static char * last_fn = 0;
1989-05-03 10:30:22 +00:00
static int e_seen = 0, w_seen = 0;
1988-10-26 15:21:11 +00:00
register char *remark = 0;
/* Since name and number are gathered from different places
depending on the class, we first collect the relevant
values and then decide what to print.
*/
/* preliminaries */
switch( class ) {
case ERROR:
case LEXERROR:
case CRASH:
case FATAL:
if( C_busy() ) C_ms_err();
err_occurred = 1;
break;
}
/* the remark */
switch( class ) {
case WARNING:
case LEXWARNING:
1989-10-30 17:51:31 +00:00
if (options['w']) return;
1988-10-26 15:21:11 +00:00
remark = "(warning)";
break;
case CRASH:
remark = "CRASH\007";
break;
case FATAL:
remark = "fatal error --";
break;
#ifdef DEBUG
case VDEBUG:
remark = "(debug)";
break;
#endif /* DEBUG */
1988-10-26 15:21:11 +00:00
}
/* the place */
switch( class ) {
case ERROR:
case WARNING:
ln = node ? node->nd_lineno : dot.tk_lineno;
break;
case LEXWARNING:
case LEXERROR:
case CRASH:
case FATAL:
#ifdef DEBUG
case VDEBUG:
#endif /* DEBUG */
1988-10-26 15:21:11 +00:00
ln = LineNumber;
break;
}
#ifdef DEBUG
if( class != VDEBUG ) {
#endif
if( FileName == last_fn && ln == last_ln ) {
/* we've seen this place before */
1989-05-03 10:30:22 +00:00
if( class != WARNING && class != LEXWARNING ) {
e_seen++;
if( e_seen == MAXERR_LINE ) fmt = "etc ...";
else if( e_seen > MAXERR_LINE )
/* and too often, I'd say ! */
return;
}
else {
w_seen++;
if( w_seen == MAXERR_LINE ) fmt = "etc ...";
else if( w_seen > MAXERR_LINE )
return;
}
1988-10-26 15:21:11 +00:00
}
else {
/* brand new place */
last_ln = ln;
last_fn = FileName;
1989-05-03 10:30:22 +00:00
e_seen = w_seen = 0;
1988-10-26 15:21:11 +00:00
}
#ifdef DEBUG
}
#endif /* DEBUG */
1988-10-26 15:21:11 +00:00
if( FileName ) fprint(ERROUT, "\"%s\", line %u: ", FileName, ln);
if( remark ) fprint(ERROUT, "%s ", remark);
1989-10-30 17:51:31 +00:00
doprnt(ERROUT, fmt, ap); /* contents of error */
1988-10-26 15:21:11 +00:00
fprint(ERROUT, "\n");
}