/********************************************
error.c
libmawk changes (C) 2009-2010, Tibor 'Igor2' Palinkas;
based on mawk code coming with the below copyright:
copyright 1991, 1992 Michael D. Brennan
This is a source file for mawk, an implementation of
the AWK programming language.
Mawk is distributed without warranty under the terms of
the GNU General Public License, version 2, 1991.
********************************************/
#include "conf.h"
TODO("this should be gone:")
#include <stdio.h>
#include "mawk.h"
#include "scan.h"
#include "bi_vars.h"
#include "vargs.h"
#include "zmalloc.h"
#include "memory.h"
#include "cell.h"
#ifndef EOF
#define EOF (-1)
#endif
static void rt_where(mawk_state_t *);
static char *type_to_str(mawk_state_t *, int);
static const char *strerrors[] = {
"succes",
"can not open file",
"internal error: header size mismatch",
"bad file magic",
"wrong byte order",
"version not supported",
"wrong instruction size",
"wrong numeric size",
"can not allocate memory",
NULL
};
const char *mawk_strerror(mawk_errno_t err)
{
if (err > 0)
return "Unknown error (positive)";
if (err < MAWK_Elast)
return "Unknown error (negative)";
return strerrors[-err];
}
#ifdef NO_VFPRINTF
#define vfprintf simple_vfprintf
#endif
/* generic error message with a hook into the system error
messages if errnum > 0 */
void mawk_errmsg VA_ALIST2(int, errnum, char *, format)
{
va_list args;
fprintf(stderr, "%s: ", MAWK->progname);
VA_START2(args, int, errnum, char *, format);
vfprintf(stderr, format, args);
va_end(args);
if (errnum > 0)
fprintf(stderr, " (%s)", strerror(errnum));
fprintf(stderr, "\n");
}
void mawk_compile_error VA_ALIST(const char *, format)
{
va_list args;
const char *s0, *s1;
/* with multiple program files put program name in
error message */
if (MAWK->ps.pfile_name) {
s0 = MAWK->ps.pfile_name;
s1 = ": ";
}
else {
s0 = s1 = "";
}
fprintf(stderr, "%s: %s%sline %u: ", MAWK->progname, s0, s1, MAWK->token_lineno);
VA_START(args, char *, format);
vfprintf(stderr, format, args);
va_end(args);
fprintf(stderr, "\n");
if (++(MAWK->compile_error_count) == MAX_COMPILE_ERRORS)
mawk_exit(MAWK, 2);
}
void mawk_rt_error VA_ALIST(const char *, format)
{
va_list args;
fprintf(stderr, "%s: run time error: ", MAWK->progname);
VA_START(args, char *, format);
vfprintf(stderr, format, args);
va_end(args);
putc('\n', stderr);
rt_where(MAWK);
MAWK->rt_exit_code = 2;
mawk_exit(MAWK, 2);
}
void mawk_bozo(MAWK, s)
mawk_state_t *MAWK;
char *s;
{
mawk_errmsg(MAWK, 0, "mawk_bozo: %s", s);
#ifdef CELLDEBUG
abort();
#endif
#ifdef DEBUG
abort();
#endif
mawk_exit(MAWK, 3);
}
void mawk_overflow(mawk_state_t *MAWK, char *s, unsigned size)
{
mawk_errmsg(MAWK, 0, "program limit exceeded: %s size=%u", s, size);
mawk_exit(MAWK, 2);
}
/* print as much as we know about where a rt error occured */
static void rt_where(mawk_state_t * MAWK)
{
if (FILENAME->type != C_STRING)
mawk_cast1_to_str(MAWK, FILENAME);
fprintf(stderr, "\tFILENAME=\"%s\" FNR=%u NR=%u\n", string(FILENAME)->str, MAWK->rt_fnr, MAWK->rt_nr);
}
/* run time */
void mawk_rt_overflow(mawk_state_t *MAWK, char *s, unsigned size)
{
mawk_errmsg(MAWK, 0, "program limit exceeded: %s size=%u", s, size);
rt_where(MAWK);
mawk_exit(MAWK, 2);
}
static char *type_to_str(mawk_state_t *MAWK, int type)
{
char *retval;
switch (type) {
case ST_VAR:
retval = "variable";
break;
case ST_ARRAY:
retval = "array";
break;
case ST_FUNCT:
retval = "function";
break;
case ST_LOCAL_VAR:
retval = "local variable";
break;
case ST_LOCAL_ARRAY:
retval = "local array";
break;
default:
mawk_bozo(MAWK, "type_to_str");
}
return retval;
}
/* emit an error message about a type clash */
void mawk_type_error(mawk_state_t *MAWK, SYMTAB *p)
{
mawk_compile_error(MAWK, "illegal reference to %s %s", type_to_str(MAWK, p->type), p->name);
}
#ifdef NO_VFPRINTF
/* a minimal vfprintf */
int simple_vfprintf(FILE *fp, char *format, va_list argp)
{
char *q, *p, *t;
int l_flag;
char xbuff[64];
q = format;
xbuff[0] = '%';
while (*q != 0) {
if (*q != '%') {
putc(*q, fp);
q++;
continue;
}
/* mark the start with p */
p = ++q;
t = xbuff + 1;
if (*q == '-')
*t++ = *q++;
while (scan_code[*(unsigned char *) q] == SC_DIGIT)
*t++ = *q++;
if (*q == '.') {
*t++ = *q++;
while (scan_code[*(unsigned char *) q] == SC_DIGIT)
*t++ = *q++;
}
if (*q == 'l') {
l_flag = 1;
*t++ = *q++;
}
else
l_flag = 0;
*t = *q++;
t[1] = 0;
switch (*t) {
case 'c':
case 'd':
case 'o':
case 'x':
case 'u':
if (l_flag)
fprintf(fp, xbuff, va_arg(argp, long));
else
fprintf(fp, xbuff, va_arg(argp, int));
break;
case 's':
fprintf(fp, xbuff, va_arg(argp, char *));
break;
#ifndef MAWK_NO_FLOAT
case 'g':
case 'f':
fprintf(fp, xbuff, va_arg(argp, double));
break;
#endif
default:
putc('%', fp);
q = p;
break;
}
}
return 0; /* shut up */
}
#endif /* USE_SIMPLE_VFPRINTF */
void mawk_set_errno(mawk_state_t * MAWK, const char *error)
{
mawk_cell_destroy(MAWK, ERRNO);
ERRNO->type = C_STRING;
ERRNO->ptr = (PTR) mawk_new_STRING(MAWK, error);
}