14887Schin /***********************************************************************
24887Schin * *
34887Schin * This software is part of the ast package *
4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1985-2010 AT&T Intellectual Property *
54887Schin * and is licensed under the *
64887Schin * Common Public License, Version 1.0 *
78462SApril.Chin@Sun.COM * by AT&T Intellectual Property *
84887Schin * *
94887Schin * A copy of the License is available at *
104887Schin * http://www.opensource.org/licenses/cpl1.0.txt *
114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
124887Schin * *
134887Schin * Information and Software Systems Research *
144887Schin * AT&T Research *
154887Schin * Florham Park NJ *
164887Schin * *
174887Schin * Glenn Fowler <gsf@research.att.com> *
184887Schin * David Korn <dgk@research.att.com> *
194887Schin * Phong Vo <kpv@research.att.com> *
204887Schin * *
214887Schin ***********************************************************************/
224887Schin #pragma prototyped
234887Schin /*
244887Schin * Glenn Fowler
254887Schin * AT&T Research
264887Schin *
274887Schin * error and message formatter
284887Schin *
294887Schin * level is the error level
304887Schin * level >= error_info.core!=0 dumps core
314887Schin * level >= ERROR_FATAL calls error_info.exit
324887Schin * level < 0 is for debug tracing
334887Schin *
344887Schin * NOTE: id && ERROR_NOID && !ERROR_USAGE implies format=id for errmsg()
354887Schin */
364887Schin
374887Schin #include "lclib.h"
384887Schin
394887Schin #include <ctype.h>
404887Schin #include <ccode.h>
414887Schin #include <namval.h>
424887Schin #include <sig.h>
434887Schin #include <stk.h>
444887Schin #include <times.h>
454887Schin #include <regex.h>
464887Schin
474887Schin /*
484887Schin * 2007-03-19 move error_info from _error_info_ to (*_error_infop_)
494887Schin * to allow future Error_info_t growth
504887Schin * by 2009 _error_info_ can be static
514887Schin */
524887Schin
534887Schin #if _BLD_ast && defined(__EXPORT__)
544887Schin #define extern extern __EXPORT__
554887Schin #endif
564887Schin
574887Schin extern Error_info_t _error_info_;
584887Schin
594887Schin Error_info_t _error_info_ =
604887Schin {
614887Schin 2, exit, write,
624887Schin 0,0,0,0,0,0,0,0,
634887Schin 0, /* version */
644887Schin 0, /* auxilliary */
654887Schin 0,0,0,0,0,0,0, /* top of old context stack */
664887Schin 0,0,0,0,0,0,0, /* old empty context */
674887Schin 0, /* time */
684887Schin translate,
694887Schin 0 /* catalog */
704887Schin };
714887Schin
724887Schin #undef extern
734887Schin
744887Schin __EXTERN__(Error_info_t, _error_info_);
754887Schin
764887Schin __EXTERN__(Error_info_t*, _error_infop_);
774887Schin
784887Schin Error_info_t* _error_infop_ = &_error_info_;
794887Schin
804887Schin /*
814887Schin * these should probably be in error_info
824887Schin */
834887Schin
844887Schin static struct State_s
854887Schin {
864887Schin char* prefix;
874887Schin Sfio_t* tty;
884887Schin unsigned long count;
894887Schin int breakpoint;
904887Schin regex_t* match;
914887Schin } error_state;
924887Schin
934887Schin #undef ERROR_CATALOG
944887Schin #define ERROR_CATALOG (ERROR_LIBRARY<<1)
954887Schin
964887Schin #define OPT_BREAK 1
974887Schin #define OPT_CATALOG 2
984887Schin #define OPT_CORE 3
994887Schin #define OPT_COUNT 4
1004887Schin #define OPT_FD 5
1014887Schin #define OPT_LIBRARY 6
1024887Schin #define OPT_MASK 7
1034887Schin #define OPT_MATCH 8
1044887Schin #define OPT_PREFIX 9
1054887Schin #define OPT_SYSTEM 10
1064887Schin #define OPT_TIME 11
1074887Schin #define OPT_TRACE 12
1084887Schin
1094887Schin static const Namval_t options[] =
1104887Schin {
1114887Schin "break", OPT_BREAK,
1124887Schin "catalog", OPT_CATALOG,
1134887Schin "core", OPT_CORE,
1144887Schin "count", OPT_COUNT,
1154887Schin "debug", OPT_TRACE,
1164887Schin "fd", OPT_FD,
1174887Schin "library", OPT_LIBRARY,
1184887Schin "mask", OPT_MASK,
1194887Schin "match", OPT_MATCH,
1204887Schin "prefix", OPT_PREFIX,
1214887Schin "system", OPT_SYSTEM,
1224887Schin "time", OPT_TIME,
1234887Schin "trace", OPT_TRACE,
1244887Schin 0, 0
1254887Schin };
1264887Schin
1274887Schin /*
1284887Schin * called by stropt() to set options
1294887Schin */
1304887Schin
1314887Schin static int
setopt(void * a,const void * p,register int n,register const char * v)1324887Schin setopt(void* a, const void* p, register int n, register const char* v)
1334887Schin {
1344887Schin NoP(a);
1354887Schin if (p)
1364887Schin switch (((Namval_t*)p)->value)
1374887Schin {
1384887Schin case OPT_BREAK:
1394887Schin case OPT_CORE:
1404887Schin if (n)
1414887Schin switch (*v)
1424887Schin {
1434887Schin case 'e':
1444887Schin case 'E':
1454887Schin error_state.breakpoint = ERROR_ERROR;
1464887Schin break;
1474887Schin case 'f':
1484887Schin case 'F':
1494887Schin error_state.breakpoint = ERROR_FATAL;
1504887Schin break;
1514887Schin case 'p':
1524887Schin case 'P':
1534887Schin error_state.breakpoint = ERROR_PANIC;
1544887Schin break;
1554887Schin default:
1564887Schin error_state.breakpoint = strtol(v, NiL, 0);
1574887Schin break;
1584887Schin }
1594887Schin else
1604887Schin error_state.breakpoint = 0;
1614887Schin if (((Namval_t*)p)->value == OPT_CORE)
1624887Schin error_info.core = error_state.breakpoint;
1634887Schin break;
1644887Schin case OPT_CATALOG:
1654887Schin if (n)
1664887Schin error_info.set |= ERROR_CATALOG;
1674887Schin else
1684887Schin error_info.clear |= ERROR_CATALOG;
1694887Schin break;
1704887Schin case OPT_COUNT:
1714887Schin if (n)
1724887Schin error_state.count = strtol(v, NiL, 0);
1734887Schin else
1744887Schin error_state.count = 0;
1754887Schin break;
1764887Schin case OPT_FD:
1774887Schin error_info.fd = n ? strtol(v, NiL, 0) : -1;
1784887Schin break;
1794887Schin case OPT_LIBRARY:
1804887Schin if (n)
1814887Schin error_info.set |= ERROR_LIBRARY;
1824887Schin else
1834887Schin error_info.clear |= ERROR_LIBRARY;
1844887Schin break;
1854887Schin case OPT_MASK:
1864887Schin if (n)
1874887Schin error_info.mask = strtol(v, NiL, 0);
1884887Schin else
1894887Schin error_info.mask = 0;
1904887Schin break;
1914887Schin case OPT_MATCH:
1924887Schin if (error_state.match)
1934887Schin regfree(error_state.match);
1944887Schin if (n)
1954887Schin {
1964887Schin if ((error_state.match || (error_state.match = newof(0, regex_t, 1, 0))) && regcomp(error_state.match, v, REG_EXTENDED|REG_LENIENT))
1974887Schin {
1984887Schin free(error_state.match);
1994887Schin error_state.match = 0;
2004887Schin }
2014887Schin }
2024887Schin else if (error_state.match)
2034887Schin {
2044887Schin free(error_state.match);
2054887Schin error_state.match = 0;
2064887Schin }
2074887Schin break;
2084887Schin case OPT_PREFIX:
2094887Schin if (n)
2104887Schin error_state.prefix = strdup(v);
2114887Schin else if (error_state.prefix)
2124887Schin {
2134887Schin free(error_state.prefix);
2144887Schin error_state.prefix = 0;
2154887Schin }
2164887Schin break;
2174887Schin case OPT_SYSTEM:
2184887Schin if (n)
2194887Schin error_info.set |= ERROR_SYSTEM;
2204887Schin else
2214887Schin error_info.clear |= ERROR_SYSTEM;
2224887Schin break;
2234887Schin case OPT_TIME:
2244887Schin error_info.time = n ? 1 : 0;
2254887Schin break;
2264887Schin case OPT_TRACE:
2274887Schin if (n)
2284887Schin error_info.trace = -strtol(v, NiL, 0);
2294887Schin else
2304887Schin error_info.trace = 0;
2314887Schin break;
2324887Schin }
2334887Schin return 0;
2344887Schin }
2354887Schin
2364887Schin /*
2374887Schin * print a name with optional delimiter, converting unprintable chars
2384887Schin */
2394887Schin
2404887Schin static void
print(register Sfio_t * sp,register char * name,char * delim)2414887Schin print(register Sfio_t* sp, register char* name, char* delim)
2424887Schin {
2434887Schin if (mbwide())
2444887Schin sfputr(sp, name, -1);
2454887Schin else
2464887Schin {
2474887Schin #if CC_NATIVE != CC_ASCII
2484887Schin register int c;
2494887Schin register unsigned char* n2a;
2504887Schin register unsigned char* a2n;
2514887Schin register int aa;
2524887Schin register int as;
2534887Schin
2544887Schin n2a = ccmap(CC_NATIVE, CC_ASCII);
2554887Schin a2n = ccmap(CC_ASCII, CC_NATIVE);
2564887Schin aa = n2a['A'];
2574887Schin as = n2a[' '];
2584887Schin while (c = *name++)
2594887Schin {
2604887Schin c = n2a[c];
2614887Schin if (c & 0200)
2624887Schin {
2634887Schin c &= 0177;
2644887Schin sfputc(sp, '?');
2654887Schin }
2664887Schin if (c < as)
2674887Schin {
2684887Schin c += aa - 1;
2694887Schin sfputc(sp, '^');
2704887Schin }
2714887Schin c = a2n[c];
2724887Schin sfputc(sp, c);
2734887Schin }
2744887Schin #else
2754887Schin register int c;
2764887Schin
2774887Schin while (c = *name++)
2784887Schin {
2794887Schin if (c & 0200)
2804887Schin {
2814887Schin c &= 0177;
2824887Schin sfputc(sp, '?');
2834887Schin }
2844887Schin if (c < ' ')
2854887Schin {
2864887Schin c += 'A' - 1;
2874887Schin sfputc(sp, '^');
2884887Schin }
2894887Schin sfputc(sp, c);
2904887Schin }
2914887Schin #endif
2924887Schin }
2934887Schin if (delim)
2944887Schin sfputr(sp, delim, -1);
2954887Schin }
2964887Schin
2974887Schin /*
2984887Schin * print error context FIFO stack
2994887Schin */
3004887Schin
3014887Schin #define CONTEXT(f,p) (((f)&ERROR_PUSH)?((Error_context_t*)&(p)->context->context):((Error_context_t*)(p)))
3024887Schin
3034887Schin static void
context(register Sfio_t * sp,register Error_context_t * cp)3044887Schin context(register Sfio_t* sp, register Error_context_t* cp)
3054887Schin {
3064887Schin if (cp->context)
3074887Schin context(sp, CONTEXT(cp->flags, cp->context));
3084887Schin if (!(cp->flags & ERROR_SILENT))
3094887Schin {
3104887Schin if (cp->id)
3114887Schin print(sp, cp->id, NiL);
3124887Schin if (cp->line > ((cp->flags & ERROR_INTERACTIVE) != 0))
3134887Schin {
3144887Schin if (cp->file)
3154887Schin sfprintf(sp, ": \"%s\", %s %d", cp->file, ERROR_translate(NiL, NiL, ast.id, "line"), cp->line);
3164887Schin else
3174887Schin sfprintf(sp, "[%d]", cp->line);
3184887Schin }
3194887Schin sfputr(sp, ": ", -1);
3204887Schin }
3214887Schin }
3224887Schin
3234887Schin /*
3244887Schin * debugging breakpoint
3254887Schin */
3264887Schin
3274887Schin extern void
error_break(void)3284887Schin error_break(void)
3294887Schin {
3304887Schin char* s;
3314887Schin
3324887Schin if (error_state.tty || (error_state.tty = sfopen(NiL, "/dev/tty", "r+")))
3334887Schin {
3344887Schin sfprintf(error_state.tty, "error breakpoint: ");
3354887Schin if (s = sfgetr(error_state.tty, '\n', 1))
3364887Schin {
3374887Schin if (streq(s, "q") || streq(s, "quit"))
3384887Schin exit(0);
3394887Schin stropt(s, options, sizeof(*options), setopt, NiL);
3404887Schin }
3414887Schin }
3424887Schin }
3434887Schin
3444887Schin void
error(int level,...)3454887Schin error(int level, ...)
3464887Schin {
3474887Schin va_list ap;
3484887Schin
3494887Schin va_start(ap, level);
3504887Schin errorv(NiL, level, ap);
3514887Schin va_end(ap);
3524887Schin }
3534887Schin
3544887Schin void
errorv(const char * id,int level,va_list ap)3554887Schin errorv(const char* id, int level, va_list ap)
3564887Schin {
3574887Schin register int n;
3584887Schin int fd;
3594887Schin int flags;
3604887Schin char* s;
3614887Schin char* t;
3624887Schin char* format;
3634887Schin char* library;
3644887Schin const char* catalog;
3654887Schin
3664887Schin int line;
3674887Schin char* file;
3684887Schin
3694887Schin #if !_PACKAGE_astsa
3704887Schin unsigned long d;
3714887Schin struct tms us;
3724887Schin #endif
3734887Schin
3744887Schin if (!error_info.init)
3754887Schin {
3764887Schin error_info.init = 1;
3774887Schin stropt(getenv("ERROR_OPTIONS"), options, sizeof(*options), setopt, NiL);
3784887Schin }
3794887Schin if (level > 0)
3804887Schin {
3814887Schin flags = level & ~ERROR_LEVEL;
3824887Schin level &= ERROR_LEVEL;
3834887Schin }
3844887Schin else
3854887Schin flags = 0;
3864887Schin if ((flags & (ERROR_USAGE|ERROR_NOID)) == ERROR_NOID)
3874887Schin {
3884887Schin format = (char*)id;
3894887Schin id = 0;
3904887Schin }
3914887Schin else
3924887Schin format = 0;
3934887Schin if (id)
3944887Schin {
3954887Schin catalog = (char*)id;
3964887Schin if (!*catalog || *catalog == ':')
3974887Schin {
3984887Schin catalog = 0;
3994887Schin library = 0;
4004887Schin }
4014887Schin else if ((library = strchr(catalog, ':')) && !*++library)
4024887Schin library = 0;
4034887Schin }
4044887Schin else
4054887Schin {
4064887Schin catalog = 0;
4074887Schin library = 0;
4084887Schin }
4094887Schin if (catalog)
4104887Schin id = 0;
4114887Schin else
4124887Schin {
4134887Schin id = (const char*)error_info.id;
4144887Schin catalog = error_info.catalog;
4154887Schin }
4164887Schin 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))))
4174887Schin {
4184887Schin if (level >= ERROR_FATAL)
4194887Schin (*error_info.exit)(level - 1);
4204887Schin return;
4214887Schin }
4224887Schin if (error_info.trace < 0)
4234887Schin flags |= ERROR_LIBRARY|ERROR_SYSTEM;
4244887Schin flags |= error_info.set | error_info.flags;
4254887Schin flags &= ~error_info.clear;
4264887Schin if (!library)
4274887Schin flags &= ~ERROR_LIBRARY;
4284887Schin fd = (flags & ERROR_OUTPUT) ? va_arg(ap, int) : error_info.fd;
4294887Schin if (error_info.write)
4304887Schin {
4314887Schin long off;
4324887Schin char* bas;
4334887Schin
4344887Schin bas = stkptr(stkstd, 0);
4354887Schin if (off = stktell(stkstd))
4364887Schin stkfreeze(stkstd, 0);
4374887Schin file = error_info.id;
4384887Schin if (error_state.prefix)
4394887Schin sfprintf(stkstd, "%s: ", error_state.prefix);
4404887Schin if (flags & ERROR_USAGE)
4414887Schin {
4424887Schin if (flags & ERROR_NOID)
4434887Schin sfprintf(stkstd, " ");
4444887Schin else
4454887Schin sfprintf(stkstd, "%s: ", ERROR_translate(NiL, NiL, ast.id, "Usage"));
4464887Schin if (file || opt_info.argv && (file = opt_info.argv[0]))
4474887Schin print(stkstd, file, " ");
4484887Schin }
4494887Schin else
4504887Schin {
4514887Schin if (level && !(flags & ERROR_NOID))
4524887Schin {
4534887Schin if (error_info.context && level > 0)
4544887Schin context(stkstd, CONTEXT(error_info.flags, error_info.context));
4554887Schin if (file)
4564887Schin print(stkstd, file, (flags & ERROR_LIBRARY) ? " " : ": ");
4574887Schin if (flags & (ERROR_CATALOG|ERROR_LIBRARY))
4584887Schin {
4594887Schin sfprintf(stkstd, "[");
4604887Schin if (flags & ERROR_CATALOG)
4614887Schin sfprintf(stkstd, "%s %s%s",
4624887Schin catalog ? catalog : ERROR_translate(NiL, NiL, ast.id, "DEFAULT"),
4634887Schin ERROR_translate(NiL, NiL, ast.id, "catalog"),
4644887Schin (flags & ERROR_LIBRARY) ? ", " : "");
4654887Schin if (flags & ERROR_LIBRARY)
4664887Schin sfprintf(stkstd, "%s %s",
4674887Schin library,
4684887Schin ERROR_translate(NiL, NiL, ast.id, "library"));
4694887Schin sfprintf(stkstd, "]: ");
4704887Schin }
4714887Schin }
4724887Schin if (level > 0 && error_info.line > ((flags & ERROR_INTERACTIVE) != 0))
4734887Schin {
4744887Schin if (error_info.file && *error_info.file)
4754887Schin sfprintf(stkstd, "\"%s\", ", error_info.file);
4764887Schin sfprintf(stkstd, "%s %d: ", ERROR_translate(NiL, NiL, ast.id, "line"), error_info.line);
4774887Schin }
4784887Schin }
4794887Schin #if !_PACKAGE_astsa
4804887Schin if (error_info.time)
4814887Schin {
4824887Schin if ((d = times(&us)) < error_info.time || error_info.time == 1)
4834887Schin error_info.time = d;
4844887Schin sfprintf(stkstd, " %05lu.%05lu.%05lu ", d - error_info.time, (unsigned long)us.tms_utime, (unsigned long)us.tms_stime);
4854887Schin }
4864887Schin #endif
4874887Schin switch (level)
4884887Schin {
4894887Schin case 0:
4904887Schin flags &= ~ERROR_SYSTEM;
4914887Schin break;
4924887Schin case ERROR_WARNING:
4934887Schin sfprintf(stkstd, "%s: ", ERROR_translate(NiL, NiL, ast.id, "warning"));
4944887Schin break;
4954887Schin case ERROR_PANIC:
4964887Schin sfprintf(stkstd, "%s: ", ERROR_translate(NiL, NiL, ast.id, "panic"));
4974887Schin break;
4984887Schin default:
4994887Schin if (level < 0)
5004887Schin {
5014887Schin s = ERROR_translate(NiL, NiL, ast.id, "debug");
5024887Schin if (error_info.trace < -1)
5034887Schin sfprintf(stkstd, "%s%d:%s", s, level, level > -10 ? " " : "");
5044887Schin else
5054887Schin sfprintf(stkstd, "%s: ", s);
5064887Schin for (n = 0; n < error_info.indent; n++)
5074887Schin {
5084887Schin sfputc(stkstd, ' ');
5094887Schin sfputc(stkstd, ' ');
5104887Schin }
5114887Schin }
5124887Schin break;
5134887Schin }
5144887Schin if (flags & ERROR_SOURCE)
5154887Schin {
5164887Schin /*
5174887Schin * source ([version], file, line) message
5184887Schin */
5194887Schin
5204887Schin file = va_arg(ap, char*);
5214887Schin line = va_arg(ap, int);
5224887Schin s = ERROR_translate(NiL, NiL, ast.id, "line");
5234887Schin if (error_info.version)
5244887Schin sfprintf(stkstd, "(%s: \"%s\", %s %d) ", error_info.version, file, s, line);
5254887Schin else
5264887Schin sfprintf(stkstd, "(\"%s\", %s %d) ", file, s, line);
5274887Schin }
5284887Schin if (format || (format = va_arg(ap, char*)))
5294887Schin {
5304887Schin if (!(flags & ERROR_USAGE))
5314887Schin format = ERROR_translate(NiL, id, catalog, format);
5324887Schin sfvprintf(stkstd, format, ap);
5334887Schin }
5344887Schin if (!(flags & ERROR_PROMPT))
5354887Schin {
5364887Schin /*
5374887Schin * level&ERROR_OUTPUT on return means message
5384887Schin * already output
5394887Schin */
5404887Schin
5414887Schin if ((flags & ERROR_SYSTEM) && errno && errno != error_info.last_errno)
5424887Schin {
5434887Schin sfprintf(stkstd, " [%s]", fmterror(errno));
5444887Schin if (error_info.set & ERROR_SYSTEM)
5454887Schin errno = 0;
5464887Schin error_info.last_errno = (level >= 0) ? 0 : errno;
5474887Schin }
5484887Schin if (error_info.auxilliary && level >= 0)
5494887Schin level = (*error_info.auxilliary)(stkstd, level, flags);
5504887Schin sfputc(stkstd, '\n');
5514887Schin }
5524887Schin if (level > 0)
5534887Schin {
5544887Schin if ((level & ~ERROR_OUTPUT) > 1)
5554887Schin error_info.errors++;
5564887Schin else
5574887Schin error_info.warnings++;
5584887Schin }
5594887Schin if (level < 0 || !(level & ERROR_OUTPUT))
5604887Schin {
5614887Schin n = stktell(stkstd);
5624887Schin s = stkptr(stkstd, 0);
5634887Schin if (t = memchr(s, '\f', n))
5644887Schin {
5654887Schin n -= ++t - s;
5664887Schin s = t;
5674887Schin }
5684887Schin #if HUH_19980401 /* nasty problems if sfgetr() is in effect! */
5694887Schin sfsync(sfstdin);
5704887Schin #endif
5714887Schin sfsync(sfstdout);
5724887Schin sfsync(sfstderr);
5734887Schin if (fd == sffileno(sfstderr) && error_info.write == write)
5744887Schin {
5754887Schin sfwrite(sfstderr, s, n);
5764887Schin sfsync(sfstderr);
5774887Schin }
5784887Schin else
5794887Schin (*error_info.write)(fd, s, n);
5804887Schin }
5814887Schin else
5824887Schin {
5834887Schin s = 0;
5844887Schin level &= ERROR_LEVEL;
5854887Schin }
5864887Schin stkset(stkstd, bas, off);
5874887Schin }
5884887Schin else
5894887Schin s = 0;
5904887Schin 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))
5914887Schin {
5924887Schin if (error_info.core)
5934887Schin {
5944887Schin #ifndef SIGABRT
5954887Schin #ifdef SIGQUIT
5964887Schin #define SIGABRT SIGQUIT
5974887Schin #else
5984887Schin #ifdef SIGIOT
5994887Schin #define SIGABRT SIGIOT
6004887Schin #endif
6014887Schin #endif
6024887Schin #endif
6034887Schin #ifdef SIGABRT
6044887Schin signal(SIGABRT, SIG_DFL);
6054887Schin kill(getpid(), SIGABRT);
6064887Schin pause();
6074887Schin #else
6084887Schin abort();
6094887Schin #endif
6104887Schin }
6114887Schin else
6124887Schin error_break();
6134887Schin }
6144887Schin if (level >= ERROR_FATAL)
6154887Schin (*error_info.exit)(level - ERROR_FATAL + 1);
6164887Schin }
6174887Schin
6184887Schin /*
6194887Schin * error_info context control
6204887Schin */
6214887Schin
6224887Schin static Error_info_t* freecontext;
6234887Schin
6244887Schin Error_info_t*
errorctx(Error_info_t * p,int op,int flags)6254887Schin errorctx(Error_info_t* p, int op, int flags)
6264887Schin {
6274887Schin if (op & ERROR_POP)
6284887Schin {
6294887Schin if (!(_error_infop_ = p->context))
6304887Schin _error_infop_ = &_error_info_;
6314887Schin if (op & ERROR_FREE)
6324887Schin {
6334887Schin p->context = freecontext;
6344887Schin freecontext = p;
6354887Schin }
6364887Schin p = _error_infop_;
6374887Schin }
6384887Schin else
6394887Schin {
6404887Schin if (!p)
6414887Schin {
6424887Schin if (p = freecontext)
6434887Schin freecontext = freecontext->context;
6444887Schin else if (!(p = newof(0, Error_info_t, 1, 0)))
6454887Schin return 0;
6464887Schin *p = *_error_infop_;
6474887Schin p->errors = p->flags = p->line = p->warnings = 0;
6484887Schin p->catalog = p->file = 0;
6494887Schin }
6504887Schin if (op & ERROR_PUSH)
6514887Schin {
6524887Schin p->flags = flags;
6534887Schin p->context = _error_infop_;
6544887Schin _error_infop_ = p;
6554887Schin }
6564887Schin p->flags |= ERROR_PUSH;
6574887Schin }
6584887Schin return p;
6594887Schin }
660