|
|
1.1 ! root 1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ ! 2: ! 3: /* ! 4: $Header: b3err.c,v 1.4 85/08/22 16:57:50 timo Exp $ ! 5: */ ! 6: ! 7: /* B error message handling */ ! 8: ! 9: /* There are two kinds of errors: ! 10: 1) parsing, when the line in error is in a buffer ! 11: 2) execution, when the line in error is a parse-tree, and must ! 12: therefore be reconstructed. ! 13: */ ! 14: ! 15: /* All error messages are collected in a file, both to save data space ! 16: and to ease translation to other languages. The English version ! 17: of the database can be recreated from the program sources by scanning ! 18: for the pattern "MESS(". This is a macro whose first argument is ! 19: the message number and whose second number is the message string; ! 20: this macro expands to only the message number which is passed to ! 21: the error routines. The error routines then dig the message from ! 22: the error message file, or just print the number if the file can't be ! 23: opened. There is also a way to pass a message that is determined ! 24: at runtime. ! 25: */ ! 26: ! 27: #include "b.h" ! 28: #include "b0fea.h" ! 29: #include "b0fil.h" ! 30: #include "b1obj.h" ! 31: #include "b2syn.h" ! 32: #include "b3env.h" ! 33: #include "b3fil.h" ! 34: #include "b3err.h" ! 35: #include "b3scr.h" ! 36: #include "b3sig.h" ! 37: #include "b3sou.h" ! 38: ! 39: Visible bool still_ok, interrupted; ! 40: ! 41: Visible parsetree curline= Vnil; ! 42: Visible value curlino; ! 43: Visible context how_context, act_context; ! 44: ! 45: FILE *errfile; /* The first thing a visible routine must do is set this */ ! 46: /* usually by calling line() */ ! 47: ! 48: #define Interactive (errfile == stderr) ! 49: ! 50: /*********************************************************************/ ! 51: ! 52: /* While we are reading the Messages file, we build an index. ! 53: probe[k] contains the first message number found in block k. ! 54: blocks are BUFSIZ in size. */ ! 55: ! 56: #define FILESIZE 12916 /* Approximated current size of Messages file */ ! 57: #define MAXPROBE (10 + FILESIZE/BUFSIZ) /* Allow some growth */ ! 58: ! 59: Hidden short probe[MAXPROBE]; ! 60: Hidden int nprobes= 1; ! 61: ! 62: Hidden FILE *messfp; ! 63: Hidden string savedmess; ! 64: ! 65: Visible int MESSMAKE(mess) string mess; { ! 66: savedmess= mess; ! 67: return -1; ! 68: } ! 69: ! 70: Visible string getmess(nr) int nr; { ! 71: int last, c; char *cp= NULL; ! 72: static char buf[80]; bool new; int block; long ftell(); ! 73: char *filename; ! 74: if (nr == 0) return ""; ! 75: if (nr < 0) { return savedmess; } ! 76: if (messfp == NULL) ! 77: messfp= fopen(messfile, "r"); ! 78: if (messfp) { ! 79: for (block= nprobes-1; block > 0; --block) { ! 80: if (probe[block] <= nr) ! 81: break; ! 82: } ! 83: new= block == nprobes-1; ! 84: fseek(messfp, (long)block*BUFSIZ, 0); ! 85: last= 0; ! 86: while (last < nr) { ! 87: if (new) block= ftell(messfp) / BUFSIZ; ! 88: if (fgets(buf, sizeof buf, messfp) == NULL) break; ! 89: last= atoi(buf); ! 90: if (last <= 0) ! 91: continue; ! 92: if (new && block >= nprobes && nprobes < MAXPROBE) { ! 93: probe[block]= last; ! 94: nprobes= block+1; ! 95: } ! 96: } ! 97: if (last == nr) { ! 98: cp= index(buf, '\n'); ! 99: if (cp != NULL) *cp = '\0'; /* strip terminating \n */ ! 100: cp= buf; ! 101: cp= index(buf, '\t'); ! 102: if (cp != NULL) return cp+1; ! 103: } ! 104: } ! 105: sprintf(buf, " (error %d) ", nr); ! 106: return buf; ! 107: } ! 108: ! 109: Hidden Procedure prmess(nr) int nr; { ! 110: errmess(getmess(nr)); ! 111: } ! 112: ! 113: /*********************************************************************/ ! 114: ! 115: Hidden Procedure putch(c) char c; { ! 116: putc(c, errfile); ! 117: } ! 118: ! 119: Hidden Procedure line() { ! 120: #ifdef EXT_COMMAND ! 121: e_done(); ! 122: #endif ! 123: fflush(stdout); ! 124: if (cntxt == In_read) { ! 125: if (rd_interactive) { ! 126: errfile= stderr; at_nwl= Yes; ! 127: } else errfile= stdout; ! 128: } else if (interactive) errfile= stderr; ! 129: else errfile= stdout; ! 130: if (!at_nwl) putch('\n'); ! 131: at_nwl= Yes; ! 132: } ! 133: ! 134: Hidden Procedure errmess(m) string m; { ! 135: fputs(m, errfile); ! 136: } ! 137: ! 138: #ifdef NOT_USED ! 139: Hidden Procedure core_dump() { ! 140: errmess("*** Core-dump for inspection purposes: "); ! 141: fflush(stdout); ! 142: dump(); ! 143: } ! 144: #endif ! 145: ! 146: Hidden Procedure prname(name) value name; { ! 147: if (Is_text(name)) { ! 148: still_ok= Yes; ! 149: writ(name); ! 150: still_ok= No; ! 151: } ! 152: } ! 153: ! 154: Visible value erruname= Vnil; ! 155: Visible intlet errlino= 0; ! 156: ! 157: Hidden intlet pr_line(at) bool at; { ! 158: /*prints the line that tx is in, with an arrow pointing to the column ! 159: that tx is at. ! 160: */ ! 161: txptr lx= fcol(); intlet ap= -1, p= 0; char c; txptr ax= tx; ! 162: if (!at) do ax--; while (Space(Char(ax))); ! 163: while (!Eol(lx) && Char(lx) != Eotc) { ! 164: if (lx == ax) ap= p; ! 165: c= *lx++; ! 166: if (c == '\t') { ! 167: do { putch(' '); } while (((++p)%4)!=0); ! 168: } else { putch(c); p++; } ! 169: } ! 170: putch('\n'); ! 171: if (ap < 0) ap= p; ! 172: for (p= 0; p < ap+4; p++) putch(' '); ! 173: errmess("^\n"); ! 174: } ! 175: ! 176: Hidden bool sh_lino(lino) intlet lino; { ! 177: switch (cntxt) { ! 178: case In_command: ! 179: case In_read: ! 180: case In_edval: ! 181: case In_tarval: ! 182: case In_prmnv: return No; ! 183: case In_unit: return lino != 1; ! 184: default: return Yes; ! 185: } ! 186: } ! 187: ! 188: ! 189: Hidden Procedure show_line(in_node, at, node, line_no) ! 190: bool in_node, at; parsetree node; int line_no; ! 191: { ! 192: if (sh_lino(line_no)) ! 193: fprintf(errfile, " in line %d of your ", line_no); ! 194: else ! 195: errmess(" in your "); ! 196: switch (cntxt) { ! 197: case In_command: errmess("command"); break; ! 198: case In_read: errmess("expression to be read"); break; ! 199: case In_edval: errmess("edited value"); break; ! 200: case In_tarval: errmess("target value"); break; ! 201: case In_unit: errmess("unit "); ! 202: release(erruname); ! 203: if (Is_text(uname)) { ! 204: value name; literal type; ! 205: p_name_type(uname, &name, &type); ! 206: prname(name); release(name); ! 207: erruname= copy(uname); ! 208: errlino= line_no; ! 209: } else erruname= Vnil; ! 210: break; ! 211: case In_prmnv: errmess("permanent environment"); break; ! 212: default: errmess("???\n"); return; ! 213: } ! 214: errmess("\n"); ! 215: if (!in_node || node != Vnil) errmess(" "); ! 216: if (in_node) display(errfile, node, Yes); ! 217: else pr_line(at); ! 218: } ! 219: ! 220: Hidden bool unit_file() { ! 221: value *aa; ! 222: return cntxt == In_unit && Is_text(uname) && p_exists(uname, &aa); ! 223: } ! 224: ! 225: Hidden Procedure show_where(in_node, at, node) ! 226: bool in_node, at; parsetree node; { ! 227: ! 228: int line_no= in_node ? intval(curlino) : lino; ! 229: if (cntxt == In_formal) { /*can only happen when in_node*/ ! 230: context cc; ! 231: sv_context(&cc); ! 232: set_context(&how_context); ! 233: copy(uname); ! 234: show_line(Yes, Yes, curline, intval(curlino)); ! 235: errmess("*** originating"); ! 236: set_context(&act_context); ! 237: copy(uname); ! 238: show_line(Yes, Yes, curline, intval(curlino)); ! 239: set_context(&cc); ! 240: } else ! 241: show_line(in_node, at, node, line_no); ! 242: if (!Interactive && !unit_file()) { ! 243: fprintf(errfile, ! 244: "*** (detected after reading %d input line%s of your input file ", ! 245: f_lino, f_lino == 1 ? "" : "s"); ! 246: if (iname == Vnil) errmess("standard input"); ! 247: else prname(iname); ! 248: errmess(")\n"); ! 249: } ! 250: } ! 251: ! 252: Hidden Procedure fatal(m, in_node) int m; bool in_node; { ! 253: line(); ! 254: errmess("*** Sorry, B system malfunction"); ! 255: show_where(in_node, Yes, curline); ! 256: errmess("*** The problem is: "); ! 257: prmess(m); errmess("\n"); ! 258: errmess("*** Please save pertinent data for inspection by B guru\n"); ! 259: bye(-1); ! 260: } ! 261: ! 262: Visible Procedure syserr(m) int m; { ! 263: fatal(m, Yes); ! 264: } ! 265: ! 266: #ifdef EXT_COMMAND ! 267: Visible Procedure psyserr(m) int m; { ! 268: fatal(m, No); ! 269: } ! 270: #endif ! 271: ! 272: Visible Procedure memexh() { ! 273: line(); ! 274: errmess("*** Sorry, memory exhausted"); ! 275: /* show_where(Yes, Yes); don't know if in node or not; to fix */ errmess("\n"); ! 276: errmess("*** Get your boss to buy a larger computer\n"); ! 277: bye(-1); ! 278: } ! 279: ! 280: Hidden Procedure fix_files() { ! 281: if (ifile != stdin) fclose(ifile); ! 282: if (f_interactive(stdin) || filtered) { ! 283: interactive= Yes; ! 284: release(iname); ! 285: iname = Vnil; ! 286: ifile = stdin; ! 287: sv_ifile= ifile; ! 288: Eof= No; ! 289: } ! 290: } ! 291: ! 292: Hidden Procedure message(m1, m2, v, m3, in_node, at) ! 293: string m1; int m2, m3; value v; bool in_node, at; { ! 294: still_ok= No; ! 295: line(); ! 296: errmess(m1); ! 297: show_where(in_node, at, curline); ! 298: errmess("*** The problem is: "); ! 299: prmess(m2); ! 300: if (v != Vnil) errmess(strval(v)); ! 301: prmess(m3); ! 302: errmess("\n"); ! 303: at_nwl=Yes; ! 304: } ! 305: ! 306: Visible Procedure pprerr(m) int m; { ! 307: if (still_ok) ! 308: message("*** There's something I don't understand", m, Vnil, 0, No, No); ! 309: } ! 310: ! 311: Visible Procedure pprerr2(tag, m) value tag; int m; { ! 312: if (still_ok) ! 313: message("*** There's something I don't understand", 0, tag, m, No, No); ! 314: } ! 315: ! 316: Visible Procedure parerr2(m, ss) int m, ss; { ! 317: if (still_ok) ! 318: message("*** There's something I don't understand", m, Vnil, ss, No, Yes); ! 319: } ! 320: ! 321: Visible Procedure parerr(m) int m; { ! 322: parerr2(m, 0); ! 323: } ! 324: ! 325: Visible Procedure fixerr3(m1, v, m2) value v; int m1, m2; { ! 326: if (still_ok) ! 327: message("*** There's something I can't resolve", m1, v, m2, Yes, Yes); ! 328: } ! 329: ! 330: Visible Procedure fixerr2(v, m) value v; int m; { ! 331: fixerr3(0, v, m); ! 332: } ! 333: ! 334: Visible Procedure fixerr(m) int m; { ! 335: fixerr3(0, Vnil, m); ! 336: } ! 337: ! 338: Visible Procedure error3(m1, v, m2) value v; int m1, m2; { ! 339: message("*** Can't cope with problem", m1, v, m2, Yes, No); ! 340: } ! 341: ! 342: Visible Procedure error2(m, v) int m; value v; { ! 343: error3(m, v, 0); ! 344: } ! 345: ! 346: Visible Procedure error(m) int m; { ! 347: error3(m, Vnil, 0); ! 348: } ! 349: ! 350: Visible Procedure checkerr() { ! 351: still_ok= No; ! 352: line(); ! 353: errmess("*** Your check failed"); ! 354: show_where(Yes, No, curline); ! 355: at_nwl= Yes; ! 356: } ! 357: ! 358: #ifdef SIGNAL ! 359: ! 360: Visible Procedure int_signal() { ! 361: interrupted= Yes; still_ok= No; ! 362: if (cntxt == In_prmnv) exit(-1); ! 363: if (!interactive) fix_files(); ! 364: if (!interactive) bye(1); ! 365: line(); fflush(stdout); ! 366: errmess("*** interrupted\n"); ! 367: #ifndef INTEGRATION ! 368: if (filtered) errmess("\177"); ! 369: #endif ! 370: if (cntxt == In_read) { ! 371: set_context(&read_context); ! 372: copy(uname); ! 373: } ! 374: at_nwl= Yes; ! 375: } ! 376: ! 377: #endif SIGNAL ! 378: ! 379: Visible bool bugs= No, testing= No, tracing= No; ! 380: ! 381: #ifdef NOT_USED ! 382: Visible Procedure debug(m) string m; { ! 383: if (bugs) { ! 384: line(); ! 385: errmess("*** Debugging "); ! 386: show_where(Yes, Yes, curline); ! 387: fprintf(errfile, "*** %s\n", m); ! 388: at_nwl= Yes; ! 389: } ! 390: } ! 391: #endif ! 392: ! 393: #ifdef EXT_COMMAND ! 394: ! 395: /* User-callable error message */ ! 396: Visible Procedure e_error(mesg) value mesg; { ! 397: value v= convert(mesg, Yes, Yes); ! 398: message("*** Halted", 0, v, 0, Yes, No); ! 399: release(v); ! 400: } ! 401: ! 402: #endif ! 403: ! 404: Visible Procedure bye(ex) int ex; { ! 405: #ifdef EXT_COMMAND ! 406: e_done(); ! 407: #endif ! 408: at_nwl= Yes; ! 409: putprmnv(); ! 410: endall(); ! 411: if (ex == 0) { ! 412: term_mem(); ! 413: endmem(); ! 414: } ! 415: #ifdef IBMPC ! 416: memstat("at end"); ! 417: #endif IBMPC ! 418: exit(ex); ! 419: } ! 420: ! 421: Visible Procedure initerr() { ! 422: still_ok= Yes; interrupted= No; curline= Vnil; curlino= zero; ! 423: } ! 424: ! 425: ! 426: #define HZ 60 /* 4.2BSD: not line frequency but historical constant */ ! 427: ! 428: showtime(whence) ! 429: string whence; ! 430: { ! 431: #ifdef TIMING ! 432: static long total[2]; ! 433: long buf[4]; ! 434: extern bool timing; /* Set in b3mai.c by -T option */ ! 435: ! 436: if (!timing) return; ! 437: times(buf); ! 438: line(); ! 439: fprintf(errfile, "*** Times %s: user %.2f sys %.2f (total %.2f %.2f)\n", ! 440: whence, ! 441: (float)(buf[0]-total[0])/HZ, (float)(buf[1]-total[1])/HZ, ! 442: (float)total[0]/HZ, (float)total[1]/HZ ! 443: ); ! 444: total[0]= buf[0]; total[1]= buf[1]; ! 445: #endif TIMING ! 446: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.