/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1985-2010 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* Glenn Fowler <gsf@research.att.com> *
* David Korn <dgk@research.att.com> *
* Phong Vo <kpv@research.att.com> *
* *
***********************************************************************/
#pragma prototyped
/*
* Glenn Fowler
* AT&T Research
*
* error and message formatter
*
* level is the error level
* level >= error_info.core!=0 dumps core
* level >= ERROR_FATAL calls error_info.exit
* level < 0 is for debug tracing
*
* NOTE: id && ERROR_NOID && !ERROR_USAGE implies format=id for errmsg()
*/
#include "lclib.h"
#include <ctype.h>
#include <ccode.h>
#include <namval.h>
#include <sig.h>
#include <stk.h>
#include <times.h>
#include <regex.h>
/*
* 2007-03-19 move error_info from _error_info_ to (*_error_infop_)
* to allow future Error_info_t growth
* by 2009 _error_info_ can be static
*/
#if _BLD_ast && defined(__EXPORT__)
#define extern extern __EXPORT__
#endif
extern Error_info_t _error_info_;
{
0,0,0,0,0,0,0,0,
0, /* version */
0, /* auxilliary */
0,0,0,0,0,0,0, /* top of old context stack */
0,0,0,0,0,0,0, /* old empty context */
0, /* time */
0 /* catalog */
};
#undef extern
/*
* these should probably be in error_info
*/
static struct State_s
{
char* prefix;
unsigned long count;
int breakpoint;
} error_state;
{
"break", OPT_BREAK,
"catalog", OPT_CATALOG,
"core", OPT_CORE,
"count", OPT_COUNT,
"debug", OPT_TRACE,
"fd", OPT_FD,
"library", OPT_LIBRARY,
"mask", OPT_MASK,
"match", OPT_MATCH,
"prefix", OPT_PREFIX,
"system", OPT_SYSTEM,
"time", OPT_TIME,
"trace", OPT_TRACE,
0, 0
};
/*
* called by stropt() to set options
*/
static int
setopt(void* a, const void* p, register int n, register const char* v)
{
NoP(a);
if (p)
{
case OPT_BREAK:
case OPT_CORE:
if (n)
switch (*v)
{
case 'e':
case 'E':
break;
case 'f':
case 'F':
break;
case 'p':
case 'P':
break;
default:
break;
}
else
error_state.breakpoint = 0;
break;
case OPT_CATALOG:
if (n)
else
break;
case OPT_COUNT:
if (n)
else
error_state.count = 0;
break;
case OPT_FD:
break;
case OPT_LIBRARY:
if (n)
else
break;
case OPT_MASK:
if (n)
else
error_info.mask = 0;
break;
case OPT_MATCH:
if (error_state.match)
if (n)
{
if ((error_state.match || (error_state.match = newof(0, regex_t, 1, 0))) && regcomp(error_state.match, v, REG_EXTENDED|REG_LENIENT))
{
error_state.match = 0;
}
}
else if (error_state.match)
{
error_state.match = 0;
}
break;
case OPT_PREFIX:
if (n)
else if (error_state.prefix)
{
error_state.prefix = 0;
}
break;
case OPT_SYSTEM:
if (n)
else
break;
case OPT_TIME:
break;
case OPT_TRACE:
if (n)
else
error_info.trace = 0;
break;
}
return 0;
}
/*
* print a name with optional delimiter, converting unprintable chars
*/
static void
{
if (mbwide())
else
{
register int c;
register unsigned char* n2a;
register unsigned char* a2n;
register int aa;
register int as;
while (c = *name++)
{
c = n2a[c];
if (c & 0200)
{
c &= 0177;
}
if (c < as)
{
c += aa - 1;
}
c = a2n[c];
}
#else
register int c;
while (c = *name++)
{
if (c & 0200)
{
c &= 0177;
}
if (c < ' ')
{
c += 'A' - 1;
}
}
#endif
}
if (delim)
}
/*
* print error context FIFO stack
*/
#define CONTEXT(f,p) (((f)&ERROR_PUSH)?((Error_context_t*)&(p)->context->context):((Error_context_t*)(p)))
static void
{
{
{
else
}
}
}
/*
* debugging breakpoint
*/
extern void
error_break(void)
{
char* s;
{
{
exit(0);
}
}
}
void
{
}
void
{
register int n;
int fd;
int flags;
char* s;
char* t;
char* format;
char* library;
const char* catalog;
int line;
char* file;
#if !_PACKAGE_astsa
unsigned long d;
#endif
if (!error_info.init)
{
}
if (level > 0)
{
level &= ERROR_LEVEL;
}
else
flags = 0;
{
id = 0;
}
else
format = 0;
if (id)
{
{
catalog = 0;
library = 0;
}
library = 0;
}
else
{
catalog = 0;
library = 0;
}
if (catalog)
id = 0;
else
{
}
if (level < error_info.trace || (flags & ERROR_LIBRARY) && !(((error_info.set | error_info.flags) ^ error_info.clear) & ERROR_LIBRARY) || level < 0 && error_info.mask && !(error_info.mask & (1<<(-level - 1))))
{
if (level >= ERROR_FATAL)
return;
}
if (error_info.trace < 0)
if (!library)
flags &= ~ERROR_LIBRARY;
if (error_info.write)
{
long off;
char* bas;
if (error_state.prefix)
if (flags & ERROR_USAGE)
{
if (flags & ERROR_NOID)
else
}
else
{
{
if (file)
{
if (flags & ERROR_CATALOG)
if (flags & ERROR_LIBRARY)
}
}
{
}
}
#if !_PACKAGE_astsa
if (error_info.time)
{
error_info.time = d;
sfprintf(stkstd, " %05lu.%05lu.%05lu ", d - error_info.time, (unsigned long)us.tms_utime, (unsigned long)us.tms_stime);
}
#endif
switch (level)
{
case 0:
flags &= ~ERROR_SYSTEM;
break;
case ERROR_WARNING:
break;
case ERROR_PANIC:
break;
default:
if (level < 0)
{
else
for (n = 0; n < error_info.indent; n++)
{
}
}
break;
}
if (flags & ERROR_SOURCE)
{
/*
* source ([version], file, line) message
*/
if (error_info.version)
else
}
{
if (!(flags & ERROR_USAGE))
}
if (!(flags & ERROR_PROMPT))
{
/*
* level&ERROR_OUTPUT on return means message
* already output
*/
{
errno = 0;
}
}
if (level > 0)
{
error_info.errors++;
else
}
{
if (t = memchr(s, '\f', n))
{
n -= ++t - s;
s = t;
}
#if HUH_19980401 /* nasty problems if sfgetr() is in effect! */
#endif
{
}
else
}
else
{
s = 0;
level &= ERROR_LEVEL;
}
}
else
s = 0;
if (level >= error_state.breakpoint && error_state.breakpoint && (!error_state.match || !regexec(error_state.match, s ? s : format, 0, NiL, 0)) && (!error_state.count || !--error_state.count))
{
if (error_info.core)
{
#ifndef SIGABRT
#ifdef SIGQUIT
#else
#ifdef SIGIOT
#endif
#endif
#endif
#ifdef SIGABRT
pause();
#else
abort();
#endif
}
else
error_break();
}
if (level >= ERROR_FATAL)
}
/*
* error_info context control
*/
{
{
if (!(_error_infop_ = p->context))
if (op & ERROR_FREE)
{
p->context = freecontext;
freecontext = p;
}
p = _error_infop_;
}
else
{
if (!p)
{
if (p = freecontext)
return 0;
*p = *_error_infop_;
}
if (op & ERROR_PUSH)
{
p->context = _error_infop_;
_error_infop_ = p;
}
p->flags |= ERROR_PUSH;
}
return p;
}