1*4887Schin /*********************************************************************** 2*4887Schin * * 3*4887Schin * This software is part of the ast package * 4*4887Schin * Copyright (c) 1985-2007 AT&T Knowledge Ventures * 5*4887Schin * and is licensed under the * 6*4887Schin * Common Public License, Version 1.0 * 7*4887Schin * by AT&T Knowledge Ventures * 8*4887Schin * * 9*4887Schin * A copy of the License is available at * 10*4887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 11*4887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12*4887Schin * * 13*4887Schin * Information and Software Systems Research * 14*4887Schin * AT&T Research * 15*4887Schin * Florham Park NJ * 16*4887Schin * * 17*4887Schin * Glenn Fowler <gsf@research.att.com> * 18*4887Schin * David Korn <dgk@research.att.com> * 19*4887Schin * Phong Vo <kpv@research.att.com> * 20*4887Schin * * 21*4887Schin ***********************************************************************/ 22*4887Schin #pragma prototyped 23*4887Schin /* 24*4887Schin * Glenn Fowler 25*4887Schin * AT&T Research 26*4887Schin * 27*4887Schin * error and message formatter 28*4887Schin * 29*4887Schin * level is the error level 30*4887Schin * level >= error_info.core!=0 dumps core 31*4887Schin * level >= ERROR_FATAL calls error_info.exit 32*4887Schin * level < 0 is for debug tracing 33*4887Schin * 34*4887Schin * NOTE: id && ERROR_NOID && !ERROR_USAGE implies format=id for errmsg() 35*4887Schin */ 36*4887Schin 37*4887Schin #include "lclib.h" 38*4887Schin 39*4887Schin #include <ctype.h> 40*4887Schin #include <ccode.h> 41*4887Schin #include <namval.h> 42*4887Schin #include <sig.h> 43*4887Schin #include <stk.h> 44*4887Schin #include <times.h> 45*4887Schin #include <regex.h> 46*4887Schin 47*4887Schin /* 48*4887Schin * 2007-03-19 move error_info from _error_info_ to (*_error_infop_) 49*4887Schin * to allow future Error_info_t growth 50*4887Schin * by 2009 _error_info_ can be static 51*4887Schin */ 52*4887Schin 53*4887Schin #if _BLD_ast && defined(__EXPORT__) 54*4887Schin #define extern extern __EXPORT__ 55*4887Schin #endif 56*4887Schin 57*4887Schin extern Error_info_t _error_info_; 58*4887Schin 59*4887Schin Error_info_t _error_info_ = 60*4887Schin { 61*4887Schin 2, exit, write, 62*4887Schin 0,0,0,0,0,0,0,0, 63*4887Schin 0, /* version */ 64*4887Schin 0, /* auxilliary */ 65*4887Schin 0,0,0,0,0,0,0, /* top of old context stack */ 66*4887Schin 0,0,0,0,0,0,0, /* old empty context */ 67*4887Schin 0, /* time */ 68*4887Schin translate, 69*4887Schin 0 /* catalog */ 70*4887Schin }; 71*4887Schin 72*4887Schin #undef extern 73*4887Schin 74*4887Schin __EXTERN__(Error_info_t, _error_info_); 75*4887Schin 76*4887Schin __EXTERN__(Error_info_t*, _error_infop_); 77*4887Schin 78*4887Schin Error_info_t* _error_infop_ = &_error_info_; 79*4887Schin 80*4887Schin /* 81*4887Schin * these should probably be in error_info 82*4887Schin */ 83*4887Schin 84*4887Schin static struct State_s 85*4887Schin { 86*4887Schin char* prefix; 87*4887Schin Sfio_t* tty; 88*4887Schin unsigned long count; 89*4887Schin int breakpoint; 90*4887Schin regex_t* match; 91*4887Schin } error_state; 92*4887Schin 93*4887Schin #undef ERROR_CATALOG 94*4887Schin #define ERROR_CATALOG (ERROR_LIBRARY<<1) 95*4887Schin 96*4887Schin #define OPT_BREAK 1 97*4887Schin #define OPT_CATALOG 2 98*4887Schin #define OPT_CORE 3 99*4887Schin #define OPT_COUNT 4 100*4887Schin #define OPT_FD 5 101*4887Schin #define OPT_LIBRARY 6 102*4887Schin #define OPT_MASK 7 103*4887Schin #define OPT_MATCH 8 104*4887Schin #define OPT_PREFIX 9 105*4887Schin #define OPT_SYSTEM 10 106*4887Schin #define OPT_TIME 11 107*4887Schin #define OPT_TRACE 12 108*4887Schin 109*4887Schin static const Namval_t options[] = 110*4887Schin { 111*4887Schin "break", OPT_BREAK, 112*4887Schin "catalog", OPT_CATALOG, 113*4887Schin "core", OPT_CORE, 114*4887Schin "count", OPT_COUNT, 115*4887Schin "debug", OPT_TRACE, 116*4887Schin "fd", OPT_FD, 117*4887Schin "library", OPT_LIBRARY, 118*4887Schin "mask", OPT_MASK, 119*4887Schin "match", OPT_MATCH, 120*4887Schin "prefix", OPT_PREFIX, 121*4887Schin "system", OPT_SYSTEM, 122*4887Schin "time", OPT_TIME, 123*4887Schin "trace", OPT_TRACE, 124*4887Schin 0, 0 125*4887Schin }; 126*4887Schin 127*4887Schin /* 128*4887Schin * called by stropt() to set options 129*4887Schin */ 130*4887Schin 131*4887Schin static int 132*4887Schin setopt(void* a, const void* p, register int n, register const char* v) 133*4887Schin { 134*4887Schin NoP(a); 135*4887Schin if (p) 136*4887Schin switch (((Namval_t*)p)->value) 137*4887Schin { 138*4887Schin case OPT_BREAK: 139*4887Schin case OPT_CORE: 140*4887Schin if (n) 141*4887Schin switch (*v) 142*4887Schin { 143*4887Schin case 'e': 144*4887Schin case 'E': 145*4887Schin error_state.breakpoint = ERROR_ERROR; 146*4887Schin break; 147*4887Schin case 'f': 148*4887Schin case 'F': 149*4887Schin error_state.breakpoint = ERROR_FATAL; 150*4887Schin break; 151*4887Schin case 'p': 152*4887Schin case 'P': 153*4887Schin error_state.breakpoint = ERROR_PANIC; 154*4887Schin break; 155*4887Schin default: 156*4887Schin error_state.breakpoint = strtol(v, NiL, 0); 157*4887Schin break; 158*4887Schin } 159*4887Schin else 160*4887Schin error_state.breakpoint = 0; 161*4887Schin if (((Namval_t*)p)->value == OPT_CORE) 162*4887Schin error_info.core = error_state.breakpoint; 163*4887Schin break; 164*4887Schin case OPT_CATALOG: 165*4887Schin if (n) 166*4887Schin error_info.set |= ERROR_CATALOG; 167*4887Schin else 168*4887Schin error_info.clear |= ERROR_CATALOG; 169*4887Schin break; 170*4887Schin case OPT_COUNT: 171*4887Schin if (n) 172*4887Schin error_state.count = strtol(v, NiL, 0); 173*4887Schin else 174*4887Schin error_state.count = 0; 175*4887Schin break; 176*4887Schin case OPT_FD: 177*4887Schin error_info.fd = n ? strtol(v, NiL, 0) : -1; 178*4887Schin break; 179*4887Schin case OPT_LIBRARY: 180*4887Schin if (n) 181*4887Schin error_info.set |= ERROR_LIBRARY; 182*4887Schin else 183*4887Schin error_info.clear |= ERROR_LIBRARY; 184*4887Schin break; 185*4887Schin case OPT_MASK: 186*4887Schin if (n) 187*4887Schin error_info.mask = strtol(v, NiL, 0); 188*4887Schin else 189*4887Schin error_info.mask = 0; 190*4887Schin break; 191*4887Schin case OPT_MATCH: 192*4887Schin if (error_state.match) 193*4887Schin regfree(error_state.match); 194*4887Schin if (n) 195*4887Schin { 196*4887Schin if ((error_state.match || (error_state.match = newof(0, regex_t, 1, 0))) && regcomp(error_state.match, v, REG_EXTENDED|REG_LENIENT)) 197*4887Schin { 198*4887Schin free(error_state.match); 199*4887Schin error_state.match = 0; 200*4887Schin } 201*4887Schin } 202*4887Schin else if (error_state.match) 203*4887Schin { 204*4887Schin free(error_state.match); 205*4887Schin error_state.match = 0; 206*4887Schin } 207*4887Schin break; 208*4887Schin case OPT_PREFIX: 209*4887Schin if (n) 210*4887Schin error_state.prefix = strdup(v); 211*4887Schin else if (error_state.prefix) 212*4887Schin { 213*4887Schin free(error_state.prefix); 214*4887Schin error_state.prefix = 0; 215*4887Schin } 216*4887Schin break; 217*4887Schin case OPT_SYSTEM: 218*4887Schin if (n) 219*4887Schin error_info.set |= ERROR_SYSTEM; 220*4887Schin else 221*4887Schin error_info.clear |= ERROR_SYSTEM; 222*4887Schin break; 223*4887Schin case OPT_TIME: 224*4887Schin error_info.time = n ? 1 : 0; 225*4887Schin break; 226*4887Schin case OPT_TRACE: 227*4887Schin if (n) 228*4887Schin error_info.trace = -strtol(v, NiL, 0); 229*4887Schin else 230*4887Schin error_info.trace = 0; 231*4887Schin break; 232*4887Schin } 233*4887Schin return 0; 234*4887Schin } 235*4887Schin 236*4887Schin /* 237*4887Schin * print a name with optional delimiter, converting unprintable chars 238*4887Schin */ 239*4887Schin 240*4887Schin static void 241*4887Schin print(register Sfio_t* sp, register char* name, char* delim) 242*4887Schin { 243*4887Schin if (mbwide()) 244*4887Schin sfputr(sp, name, -1); 245*4887Schin else 246*4887Schin { 247*4887Schin #if CC_NATIVE != CC_ASCII 248*4887Schin register int c; 249*4887Schin register unsigned char* n2a; 250*4887Schin register unsigned char* a2n; 251*4887Schin register int aa; 252*4887Schin register int as; 253*4887Schin 254*4887Schin n2a = ccmap(CC_NATIVE, CC_ASCII); 255*4887Schin a2n = ccmap(CC_ASCII, CC_NATIVE); 256*4887Schin aa = n2a['A']; 257*4887Schin as = n2a[' ']; 258*4887Schin while (c = *name++) 259*4887Schin { 260*4887Schin c = n2a[c]; 261*4887Schin if (c & 0200) 262*4887Schin { 263*4887Schin c &= 0177; 264*4887Schin sfputc(sp, '?'); 265*4887Schin } 266*4887Schin if (c < as) 267*4887Schin { 268*4887Schin c += aa - 1; 269*4887Schin sfputc(sp, '^'); 270*4887Schin } 271*4887Schin c = a2n[c]; 272*4887Schin sfputc(sp, c); 273*4887Schin } 274*4887Schin #else 275*4887Schin register int c; 276*4887Schin 277*4887Schin while (c = *name++) 278*4887Schin { 279*4887Schin if (c & 0200) 280*4887Schin { 281*4887Schin c &= 0177; 282*4887Schin sfputc(sp, '?'); 283*4887Schin } 284*4887Schin if (c < ' ') 285*4887Schin { 286*4887Schin c += 'A' - 1; 287*4887Schin sfputc(sp, '^'); 288*4887Schin } 289*4887Schin sfputc(sp, c); 290*4887Schin } 291*4887Schin #endif 292*4887Schin } 293*4887Schin if (delim) 294*4887Schin sfputr(sp, delim, -1); 295*4887Schin } 296*4887Schin 297*4887Schin /* 298*4887Schin * print error context FIFO stack 299*4887Schin */ 300*4887Schin 301*4887Schin #define CONTEXT(f,p) (((f)&ERROR_PUSH)?((Error_context_t*)&(p)->context->context):((Error_context_t*)(p))) 302*4887Schin 303*4887Schin static void 304*4887Schin context(register Sfio_t* sp, register Error_context_t* cp) 305*4887Schin { 306*4887Schin if (cp->context) 307*4887Schin context(sp, CONTEXT(cp->flags, cp->context)); 308*4887Schin if (!(cp->flags & ERROR_SILENT)) 309*4887Schin { 310*4887Schin if (cp->id) 311*4887Schin print(sp, cp->id, NiL); 312*4887Schin if (cp->line > ((cp->flags & ERROR_INTERACTIVE) != 0)) 313*4887Schin { 314*4887Schin if (cp->file) 315*4887Schin sfprintf(sp, ": \"%s\", %s %d", cp->file, ERROR_translate(NiL, NiL, ast.id, "line"), cp->line); 316*4887Schin else 317*4887Schin sfprintf(sp, "[%d]", cp->line); 318*4887Schin } 319*4887Schin sfputr(sp, ": ", -1); 320*4887Schin } 321*4887Schin } 322*4887Schin 323*4887Schin /* 324*4887Schin * debugging breakpoint 325*4887Schin */ 326*4887Schin 327*4887Schin extern void 328*4887Schin error_break(void) 329*4887Schin { 330*4887Schin char* s; 331*4887Schin 332*4887Schin if (error_state.tty || (error_state.tty = sfopen(NiL, "/dev/tty", "r+"))) 333*4887Schin { 334*4887Schin sfprintf(error_state.tty, "error breakpoint: "); 335*4887Schin if (s = sfgetr(error_state.tty, '\n', 1)) 336*4887Schin { 337*4887Schin if (streq(s, "q") || streq(s, "quit")) 338*4887Schin exit(0); 339*4887Schin stropt(s, options, sizeof(*options), setopt, NiL); 340*4887Schin } 341*4887Schin } 342*4887Schin } 343*4887Schin 344*4887Schin void 345*4887Schin error(int level, ...) 346*4887Schin { 347*4887Schin va_list ap; 348*4887Schin 349*4887Schin va_start(ap, level); 350*4887Schin errorv(NiL, level, ap); 351*4887Schin va_end(ap); 352*4887Schin } 353*4887Schin 354*4887Schin void 355*4887Schin errorv(const char* id, int level, va_list ap) 356*4887Schin { 357*4887Schin register int n; 358*4887Schin int fd; 359*4887Schin int flags; 360*4887Schin char* s; 361*4887Schin char* t; 362*4887Schin char* format; 363*4887Schin char* library; 364*4887Schin const char* catalog; 365*4887Schin 366*4887Schin int line; 367*4887Schin char* file; 368*4887Schin 369*4887Schin #if !_PACKAGE_astsa 370*4887Schin unsigned long d; 371*4887Schin struct tms us; 372*4887Schin #endif 373*4887Schin 374*4887Schin if (!error_info.init) 375*4887Schin { 376*4887Schin error_info.init = 1; 377*4887Schin stropt(getenv("ERROR_OPTIONS"), options, sizeof(*options), setopt, NiL); 378*4887Schin } 379*4887Schin if (level > 0) 380*4887Schin { 381*4887Schin flags = level & ~ERROR_LEVEL; 382*4887Schin level &= ERROR_LEVEL; 383*4887Schin } 384*4887Schin else 385*4887Schin flags = 0; 386*4887Schin if ((flags & (ERROR_USAGE|ERROR_NOID)) == ERROR_NOID) 387*4887Schin { 388*4887Schin format = (char*)id; 389*4887Schin id = 0; 390*4887Schin } 391*4887Schin else 392*4887Schin format = 0; 393*4887Schin if (id) 394*4887Schin { 395*4887Schin catalog = (char*)id; 396*4887Schin if (!*catalog || *catalog == ':') 397*4887Schin { 398*4887Schin catalog = 0; 399*4887Schin library = 0; 400*4887Schin } 401*4887Schin else if ((library = strchr(catalog, ':')) && !*++library) 402*4887Schin library = 0; 403*4887Schin } 404*4887Schin else 405*4887Schin { 406*4887Schin catalog = 0; 407*4887Schin library = 0; 408*4887Schin } 409*4887Schin if (catalog) 410*4887Schin id = 0; 411*4887Schin else 412*4887Schin { 413*4887Schin id = (const char*)error_info.id; 414*4887Schin catalog = error_info.catalog; 415*4887Schin } 416*4887Schin 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)))) 417*4887Schin { 418*4887Schin if (level >= ERROR_FATAL) 419*4887Schin (*error_info.exit)(level - 1); 420*4887Schin return; 421*4887Schin } 422*4887Schin if (error_info.trace < 0) 423*4887Schin flags |= ERROR_LIBRARY|ERROR_SYSTEM; 424*4887Schin flags |= error_info.set | error_info.flags; 425*4887Schin flags &= ~error_info.clear; 426*4887Schin if (!library) 427*4887Schin flags &= ~ERROR_LIBRARY; 428*4887Schin fd = (flags & ERROR_OUTPUT) ? va_arg(ap, int) : error_info.fd; 429*4887Schin if (error_info.write) 430*4887Schin { 431*4887Schin long off; 432*4887Schin char* bas; 433*4887Schin 434*4887Schin bas = stkptr(stkstd, 0); 435*4887Schin if (off = stktell(stkstd)) 436*4887Schin stkfreeze(stkstd, 0); 437*4887Schin file = error_info.id; 438*4887Schin if (error_state.prefix) 439*4887Schin sfprintf(stkstd, "%s: ", error_state.prefix); 440*4887Schin if (flags & ERROR_USAGE) 441*4887Schin { 442*4887Schin if (flags & ERROR_NOID) 443*4887Schin sfprintf(stkstd, " "); 444*4887Schin else 445*4887Schin sfprintf(stkstd, "%s: ", ERROR_translate(NiL, NiL, ast.id, "Usage")); 446*4887Schin if (file || opt_info.argv && (file = opt_info.argv[0])) 447*4887Schin print(stkstd, file, " "); 448*4887Schin } 449*4887Schin else 450*4887Schin { 451*4887Schin if (level && !(flags & ERROR_NOID)) 452*4887Schin { 453*4887Schin if (error_info.context && level > 0) 454*4887Schin context(stkstd, CONTEXT(error_info.flags, error_info.context)); 455*4887Schin if (file) 456*4887Schin print(stkstd, file, (flags & ERROR_LIBRARY) ? " " : ": "); 457*4887Schin if (flags & (ERROR_CATALOG|ERROR_LIBRARY)) 458*4887Schin { 459*4887Schin sfprintf(stkstd, "["); 460*4887Schin if (flags & ERROR_CATALOG) 461*4887Schin sfprintf(stkstd, "%s %s%s", 462*4887Schin catalog ? catalog : ERROR_translate(NiL, NiL, ast.id, "DEFAULT"), 463*4887Schin ERROR_translate(NiL, NiL, ast.id, "catalog"), 464*4887Schin (flags & ERROR_LIBRARY) ? ", " : ""); 465*4887Schin if (flags & ERROR_LIBRARY) 466*4887Schin sfprintf(stkstd, "%s %s", 467*4887Schin library, 468*4887Schin ERROR_translate(NiL, NiL, ast.id, "library")); 469*4887Schin sfprintf(stkstd, "]: "); 470*4887Schin } 471*4887Schin } 472*4887Schin if (level > 0 && error_info.line > ((flags & ERROR_INTERACTIVE) != 0)) 473*4887Schin { 474*4887Schin if (error_info.file && *error_info.file) 475*4887Schin sfprintf(stkstd, "\"%s\", ", error_info.file); 476*4887Schin sfprintf(stkstd, "%s %d: ", ERROR_translate(NiL, NiL, ast.id, "line"), error_info.line); 477*4887Schin } 478*4887Schin } 479*4887Schin #if !_PACKAGE_astsa 480*4887Schin if (error_info.time) 481*4887Schin { 482*4887Schin if ((d = times(&us)) < error_info.time || error_info.time == 1) 483*4887Schin error_info.time = d; 484*4887Schin sfprintf(stkstd, " %05lu.%05lu.%05lu ", d - error_info.time, (unsigned long)us.tms_utime, (unsigned long)us.tms_stime); 485*4887Schin } 486*4887Schin #endif 487*4887Schin switch (level) 488*4887Schin { 489*4887Schin case 0: 490*4887Schin flags &= ~ERROR_SYSTEM; 491*4887Schin break; 492*4887Schin case ERROR_WARNING: 493*4887Schin sfprintf(stkstd, "%s: ", ERROR_translate(NiL, NiL, ast.id, "warning")); 494*4887Schin break; 495*4887Schin case ERROR_PANIC: 496*4887Schin sfprintf(stkstd, "%s: ", ERROR_translate(NiL, NiL, ast.id, "panic")); 497*4887Schin break; 498*4887Schin default: 499*4887Schin if (level < 0) 500*4887Schin { 501*4887Schin s = ERROR_translate(NiL, NiL, ast.id, "debug"); 502*4887Schin if (error_info.trace < -1) 503*4887Schin sfprintf(stkstd, "%s%d:%s", s, level, level > -10 ? " " : ""); 504*4887Schin else 505*4887Schin sfprintf(stkstd, "%s: ", s); 506*4887Schin for (n = 0; n < error_info.indent; n++) 507*4887Schin { 508*4887Schin sfputc(stkstd, ' '); 509*4887Schin sfputc(stkstd, ' '); 510*4887Schin } 511*4887Schin } 512*4887Schin break; 513*4887Schin } 514*4887Schin if (flags & ERROR_SOURCE) 515*4887Schin { 516*4887Schin /* 517*4887Schin * source ([version], file, line) message 518*4887Schin */ 519*4887Schin 520*4887Schin file = va_arg(ap, char*); 521*4887Schin line = va_arg(ap, int); 522*4887Schin s = ERROR_translate(NiL, NiL, ast.id, "line"); 523*4887Schin if (error_info.version) 524*4887Schin sfprintf(stkstd, "(%s: \"%s\", %s %d) ", error_info.version, file, s, line); 525*4887Schin else 526*4887Schin sfprintf(stkstd, "(\"%s\", %s %d) ", file, s, line); 527*4887Schin } 528*4887Schin if (format || (format = va_arg(ap, char*))) 529*4887Schin { 530*4887Schin if (!(flags & ERROR_USAGE)) 531*4887Schin format = ERROR_translate(NiL, id, catalog, format); 532*4887Schin sfvprintf(stkstd, format, ap); 533*4887Schin } 534*4887Schin if (!(flags & ERROR_PROMPT)) 535*4887Schin { 536*4887Schin /* 537*4887Schin * level&ERROR_OUTPUT on return means message 538*4887Schin * already output 539*4887Schin */ 540*4887Schin 541*4887Schin if ((flags & ERROR_SYSTEM) && errno && errno != error_info.last_errno) 542*4887Schin { 543*4887Schin sfprintf(stkstd, " [%s]", fmterror(errno)); 544*4887Schin if (error_info.set & ERROR_SYSTEM) 545*4887Schin errno = 0; 546*4887Schin error_info.last_errno = (level >= 0) ? 0 : errno; 547*4887Schin } 548*4887Schin if (error_info.auxilliary && level >= 0) 549*4887Schin level = (*error_info.auxilliary)(stkstd, level, flags); 550*4887Schin sfputc(stkstd, '\n'); 551*4887Schin } 552*4887Schin if (level > 0) 553*4887Schin { 554*4887Schin if ((level & ~ERROR_OUTPUT) > 1) 555*4887Schin error_info.errors++; 556*4887Schin else 557*4887Schin error_info.warnings++; 558*4887Schin } 559*4887Schin if (level < 0 || !(level & ERROR_OUTPUT)) 560*4887Schin { 561*4887Schin n = stktell(stkstd); 562*4887Schin s = stkptr(stkstd, 0); 563*4887Schin if (t = memchr(s, '\f', n)) 564*4887Schin { 565*4887Schin n -= ++t - s; 566*4887Schin s = t; 567*4887Schin } 568*4887Schin #if HUH_19980401 /* nasty problems if sfgetr() is in effect! */ 569*4887Schin sfsync(sfstdin); 570*4887Schin #endif 571*4887Schin sfsync(sfstdout); 572*4887Schin sfsync(sfstderr); 573*4887Schin if (fd == sffileno(sfstderr) && error_info.write == write) 574*4887Schin { 575*4887Schin sfwrite(sfstderr, s, n); 576*4887Schin sfsync(sfstderr); 577*4887Schin } 578*4887Schin else 579*4887Schin (*error_info.write)(fd, s, n); 580*4887Schin } 581*4887Schin else 582*4887Schin { 583*4887Schin s = 0; 584*4887Schin level &= ERROR_LEVEL; 585*4887Schin } 586*4887Schin stkset(stkstd, bas, off); 587*4887Schin } 588*4887Schin else 589*4887Schin s = 0; 590*4887Schin 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)) 591*4887Schin { 592*4887Schin if (error_info.core) 593*4887Schin { 594*4887Schin #ifndef SIGABRT 595*4887Schin #ifdef SIGQUIT 596*4887Schin #define SIGABRT SIGQUIT 597*4887Schin #else 598*4887Schin #ifdef SIGIOT 599*4887Schin #define SIGABRT SIGIOT 600*4887Schin #endif 601*4887Schin #endif 602*4887Schin #endif 603*4887Schin #ifdef SIGABRT 604*4887Schin signal(SIGABRT, SIG_DFL); 605*4887Schin kill(getpid(), SIGABRT); 606*4887Schin pause(); 607*4887Schin #else 608*4887Schin abort(); 609*4887Schin #endif 610*4887Schin } 611*4887Schin else 612*4887Schin error_break(); 613*4887Schin } 614*4887Schin if (level >= ERROR_FATAL) 615*4887Schin (*error_info.exit)(level - ERROR_FATAL + 1); 616*4887Schin } 617*4887Schin 618*4887Schin /* 619*4887Schin * error_info context control 620*4887Schin */ 621*4887Schin 622*4887Schin #include <error.h> 623*4887Schin 624*4887Schin static Error_info_t* freecontext; 625*4887Schin 626*4887Schin Error_info_t* 627*4887Schin errorctx(Error_info_t* p, int op, int flags) 628*4887Schin { 629*4887Schin if (op & ERROR_POP) 630*4887Schin { 631*4887Schin if (!(_error_infop_ = p->context)) 632*4887Schin _error_infop_ = &_error_info_; 633*4887Schin if (op & ERROR_FREE) 634*4887Schin { 635*4887Schin p->context = freecontext; 636*4887Schin freecontext = p; 637*4887Schin } 638*4887Schin p = _error_infop_; 639*4887Schin } 640*4887Schin else 641*4887Schin { 642*4887Schin if (!p) 643*4887Schin { 644*4887Schin if (p = freecontext) 645*4887Schin freecontext = freecontext->context; 646*4887Schin else if (!(p = newof(0, Error_info_t, 1, 0))) 647*4887Schin return 0; 648*4887Schin *p = *_error_infop_; 649*4887Schin p->errors = p->flags = p->line = p->warnings = 0; 650*4887Schin p->catalog = p->file = 0; 651*4887Schin } 652*4887Schin if (op & ERROR_PUSH) 653*4887Schin { 654*4887Schin p->flags = flags; 655*4887Schin p->context = _error_infop_; 656*4887Schin _error_infop_ = p; 657*4887Schin } 658*4887Schin p->flags |= ERROR_PUSH; 659*4887Schin } 660*4887Schin return p; 661*4887Schin } 662