1% errors.w 2% 3% Copyright 2009-2010 Taco Hoekwater <taco@@luatex.org> 4% 5% This file is part of LuaTeX. 6% 7% LuaTeX is free software; you can redistribute it and/or modify it under 8% the terms of the GNU General Public License as published by the Free 9% Software Foundation; either version 2 of the License, or (at your 10% option) any later version. 11% 12% LuaTeX is distributed in the hope that it will be useful, but WITHOUT 13% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14% FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15% License for more details. 16% 17% You should have received a copy of the GNU General Public License along 18% with LuaTeX; if not, see <http://www.gnu.org/licenses/>. 19 20@ @c 21 22 23#include "ptexlib.h" 24 25@ @c 26#define new_line_char int_par(new_line_char_code) 27 28 29@ When something anomalous is detected, \TeX\ typically does something like this: 30$$\vbox{\halign{#\hfil\cr 31|print_err("Something anomalous has been detected");|\cr 32|help3("This is the first line of my offer to help.")|\cr 33|("This is the second line. I'm trying to")|\cr 34|("explain the best way for you to proceed.");|\cr 35|error;|\cr}}$$ 36A two-line help message would be given using |help2|, etc.; these informal 37helps should use simple vocabulary that complements the words used in the 38official error message that was printed. (Outside the U.S.A., the help 39messages should preferably be translated into the local vernacular. Each 40line of help is at most 60 characters long, in the present implementation, 41so that |max_print_line| will not be exceeded.) 42 43The |print_err| procedure supplies a `\.!' before the official message, 44and makes sure that the terminal is awake if a stop is going to occur. 45The |error| procedure supplies a `\..' after the official message, then it 46shows the location of the error; and if |interaction=error_stop_mode|, 47it also enters into a dialog with the user, during which time the help 48message may be printed. 49@^system dependencies@> 50 51@c 52int interaction; /* current level of interaction */ 53int interactionoption; /* set from command line */ 54 55/* ls-hh: so, new code only kicks in when we have a callback defined */ 56 57char *last_error = NULL; 58int err_old_setting = 0 ; 59int in_error = 0 ; 60 61void flush_err(void) 62{ 63 str_number s_error; 64 char *s = NULL; 65 int callback_id ; 66 if (in_error) { 67 selector = err_old_setting; 68 str_room(1); 69 s_error = make_string(); 70 s = makecstring(s_error); 71 flush_str(s_error); 72 if (interaction == error_stop_mode) { 73 wake_up_terminal(); 74 } 75 xfree(last_error); 76 last_error = (string) xmalloc((unsigned) (strlen(s) + 1)); 77 strcpy(last_error,s); 78 callback_id = callback_defined(show_error_message_callback); 79 if (callback_id > 0) { 80 run_callback(callback_id, "->"); 81 } else { 82 tprint(s); 83 } 84 in_error = 0 ; 85 } 86} 87 88void print_err(const char *s) 89{ 90 int callback_id = callback_defined(show_error_message_callback); 91 if (interaction == error_stop_mode) { 92 wake_up_terminal(); 93 } 94 if (callback_id > 0) { 95 err_old_setting = selector; 96 selector = new_string; 97 in_error = 1 ; 98 } 99 if (filelineerrorstylep) { 100 print_file_line(); 101 } else { 102 tprint_nl("! "); 103 } 104 tprint(s); 105 if (callback_id <= 0) { 106 xfree(last_error); 107 last_error = (string) xmalloc((unsigned) (strlen(s) + 1)); 108 strcpy(last_error,s); 109 } 110} 111 112@ \TeX\ is careful not to call |error| when the print |selector| setting 113might be unusual. The only possible values of |selector| at the time of 114error messages are 115 116\yskip\hang|no_print| (when |interaction=batch_mode| 117 and |log_file| not yet open); 118 119\hang|term_only| (when |interaction>batch_mode| and |log_file| not yet open); 120 121\hang|log_only| (when |interaction=batch_mode| and |log_file| is open); 122 123\hang|term_and_log| (when |interaction>batch_mode| and |log_file| is open). 124 125@c 126void fixup_selector(boolean logopened) 127{ 128 if (interaction == batch_mode) 129 selector = no_print; 130 else 131 selector = term_only; 132 if (logopened) 133 selector = selector + 2; 134} 135 136 137@ A global variable |deletions_allowed| is set |false| if the |get_next| 138routine is active when |error| is called; this ensures that |get_next| 139and related routines like |get_token| will never be called recursively. 140A similar interlock is provided by |set_box_allowed|. 141@^recursion@> 142 143The global variable |history| records the worst level of error that 144has been detected. It has four possible values: |spotless|, |warning_issued|, 145|error_message_issued|, and |fatal_error_stop|. 146 147Another global variable, |error_count|, is increased by one when an 148|error| occurs without an interactive dialog, and it is reset to zero at 149the end of every paragraph. If |error_count| reaches 100, \TeX\ decides 150that there is no point in continuing further. 151 152@c 153boolean deletions_allowed; /* is it safe for |error| to call |get_token|? */ 154boolean set_box_allowed; /* is it safe to do a \.{\\setbox} assignment? */ 155int history; /* has the source input been clean so far? */ 156int error_count; /* the number of scrolled errors since the last paragraph ended */ 157int interrupt; /* should \TeX\ pause for instructions? */ 158boolean OK_to_interrupt; /* should interrupts be observed? */ 159 160 161 162@ The value of |history| is initially |fatal_error_stop|, but it will 163be changed to |spotless| if \TeX\ survives the initialization process. 164 165@c 166void initialize_errors(void) 167{ 168 if (interactionoption == unspecified_mode) 169 interaction = error_stop_mode; 170 else 171 interaction = interactionoption; 172 deletions_allowed = true; 173 set_box_allowed = true; 174 OK_to_interrupt = true; 175 /* |history| is initialized elsewhere */ 176} 177 178 179@ It is possible for |error| to be called recursively if some error arises 180when |get_token| is being used to delete a token, and/or if some fatal error 181occurs while \TeX\ is trying to fix a non-fatal one. But such recursion 182@^recursion@> 183is never more than two levels deep. 184 185@ Individual lines of help are recorded in the array |help_line|. 186 187@c 188const char *help_line[7]; /* helps for the next |error| */ 189boolean use_err_help; /* should the |err_help| list be shown? */ 190 191 192@ The |jump_out| procedure just cuts across all active procedure levels and 193exits the program. It is used when there is no recovery from a particular error. 194 195@c 196__attribute__ ((noreturn)) 197void do_final_end(void) 198{ 199 update_terminal(); 200 ready_already = 0; 201 if ((history != spotless) && (history != warning_issued)) 202 uexit(1); 203 else 204 uexit(0); 205} 206 207__attribute__ ((noreturn)) 208void jump_out(void) 209{ 210 close_files_and_terminate(); 211 do_final_end(); 212} 213 214@ @c 215void error(void) 216{ /* completes the job of error reporting */ 217 ASCII_code c; /* what the user types */ 218 int callback_id; 219 int s1, s2, s3, s4; /* used to save global variables when deleting tokens */ 220 int i; 221 flush_err(); /* hh-ls */ 222 if (history < error_message_issued) 223 history = error_message_issued; 224 callback_id = callback_defined(show_error_hook_callback); 225 if (callback_id > 0) { 226 run_callback(callback_id, "->"); 227 } else { 228 print_char('.'); 229 show_context(); 230 } 231 if (haltonerrorp) { 232 history = fatal_error_stop; 233 jump_out(); 234 } 235 if (interaction == error_stop_mode) { 236 /* Get user's advice and |return| */ 237 while (1) { 238 CONTINUE: 239 clear_for_error_prompt(); 240 prompt_input("? "); 241 if (last == first) 242 return; 243 c = buffer[first]; 244 if (c >= 'a') 245 c = c + 'A' - 'a'; /* convert to uppercase */ 246 /* Interpret code |c| and |return| if done */ 247 248 /* It is desirable to provide an `\.E' option here that gives the user 249 an easy way to return from \TeX\ to the system editor, with the offending 250 line ready to be edited. But such an extension requires some system 251 wizardry, so the present implementation simply types out the name of the 252 file that should be edited and the relevant line number. 253 254 There is a secret `\.D' option available when the debugging routines haven't 255 been commented~out. */ 256 257 switch (c) { 258 case '0': 259 case '1': 260 case '2': 261 case '3': 262 case '4': 263 case '5': 264 case '6': 265 case '7': 266 case '8': 267 case '9': 268 if (deletions_allowed) { 269 /* Delete |c-"0"| tokens and |goto continue| */ 270 /* We allow deletion of up to 99 tokens at a time */ 271 s1 = cur_tok; 272 s2 = cur_cmd; 273 s3 = cur_chr; 274 s4 = align_state; 275 align_state = 1000000; 276 OK_to_interrupt = false; 277 if ((last > first + 1) && (buffer[first + 1] >= '0') 278 && (buffer[first + 1] <= '9')) 279 c = c * 10 + buffer[first + 1] - '0' * 11; 280 else 281 c = c - '0'; 282 while (c > 0) { 283 get_token(); /* one-level recursive call of |error| is possible */ 284 decr(c); 285 } 286 cur_tok = s1; 287 cur_cmd = s2; 288 cur_chr = s3; 289 align_state = s4; 290 OK_to_interrupt = true; 291 help2("I have just deleted some text, as you asked.", 292 "You can now delete more, or insert, or whatever."); 293 show_context(); 294 goto CONTINUE; 295 } 296 break; 297#ifdef DEBUG 298 case 'D': 299 debug_help(); 300 goto CONTINUE; 301 break; 302#endif 303 case 'E': 304 if (base_ptr > 0) { 305 tprint_nl("You want to edit file "); 306 print(input_stack[base_ptr].name_field); 307 tprint(" at line "); 308 print_int(line); 309 interaction = scroll_mode; 310 jump_out(); 311 } 312 break; 313 case 'H': 314 /* Print the help information and |goto continue| */ 315 if (use_err_help) { 316 give_err_help(); 317 use_err_help = false; 318 } else { 319 if (help_line[0] == NULL) { 320 help2 321 ("Sorry, I don't know how to help in this situation.", 322 "Maybe you should try asking a human?"); 323 } 324 i = 0; 325 while (help_line[i] != NULL) 326 tprint_nl(help_line[i++]); 327 help4("Sorry, I already gave what help I could...", 328 "Maybe you should try asking a human?", 329 "An error might have occurred before I noticed any problems.", 330 "``If all else fails, read the instructions.''"); 331 goto CONTINUE; 332 } 333 break; 334 case 'I': 335 /* Introduce new material from the terminal and |return| */ 336 /* When the following code is executed, |buffer[(first+1)..(last-1)]| may 337 contain the material inserted by the user; otherwise another prompt will 338 be given. In order to understand this part of the program fully, you need 339 to be familiar with \TeX's input stacks. */ 340 341 begin_file_reading(); /* enter a new syntactic level for terminal input */ 342 /* now |state=mid_line|, so an initial blank space will count as a blank */ 343 if (last > first + 1) { 344 iloc = first + 1; 345 buffer[first] = ' '; 346 } else { 347 prompt_input("insert>"); 348 iloc = first; 349 } 350 first = last; 351 ilimit = last - 1; /* no |end_line_char| ends this line */ 352 return; 353 break; 354 case 'Q': 355 case 'R': 356 case 'S': 357 /* Change the interaction level and |return| */ 358 /* Here the author of \TeX\ apologizes for making use of the numerical 359 relation between |"Q"|, |"R"|, |"S"|, and the desired interaction settings 360 |batch_mode|, |nonstop_mode|, |scroll_mode|. */ 361 error_count = 0; 362 interaction = batch_mode + c - 'Q'; 363 tprint("OK, entering "); 364 switch (c) { 365 case 'Q': 366 tprint_esc("batchmode"); 367 decr(selector); 368 break; 369 case 'R': 370 tprint_esc("nonstopmode"); 371 break; 372 case 'S': 373 tprint_esc("scrollmode"); 374 break; 375 } 376 tprint("..."); 377 print_ln(); 378 update_terminal(); 379 return; 380 break; 381 case 'X': 382 interaction = scroll_mode; 383 jump_out(); 384 break; 385 default: 386 break; 387 } 388 /* Print the menu of available options */ 389 tprint 390 ("Type <return> to proceed, S to scroll future error messages,"); 391 tprint_nl("R to run without stopping, Q to run quietly,"); 392 tprint_nl("I to insert something, "); 393 if (base_ptr > 0) 394 tprint("E to edit your file,"); 395 if (deletions_allowed) 396 tprint_nl 397 ("1 or ... or 9 to ignore the next 1 to 9 tokens of input,"); 398 tprint_nl("H for help, X to quit."); 399 } 400 401 } 402 incr(error_count); 403 if (error_count == 100) { 404 tprint_nl("(That makes 100 errors; please try again.)"); 405 history = fatal_error_stop; 406 jump_out(); 407 } 408 /* Put help message on the transcript file */ 409 if (interaction > batch_mode) 410 decr(selector); /* avoid terminal output */ 411 if (use_err_help) { 412 print_ln(); 413 give_err_help(); 414 } else { 415 int i1 = 0; 416 while (help_line[i1] != NULL) 417 tprint_nl(help_line[i1++]); 418 } 419 print_ln(); 420 if (interaction > batch_mode) 421 incr(selector); /* re-enable terminal output */ 422 print_ln(); 423} 424 425 426 427@ A dozen or so error messages end with a parenthesized integer, so we 428save a teeny bit of program space by declaring the following procedure: 429 430@c 431void int_error(int n) 432{ 433 tprint(" ("); 434 print_int(n); 435 print_char(')'); 436 error(); 437} 438 439 440@ In anomalous cases, the print selector might be in an unknown state; 441the following subroutine is called to fix things just enough to keep 442running a bit longer. 443 444@c 445void normalize_selector(void) 446{ 447 if (log_opened_global) 448 selector = term_and_log; 449 else 450 selector = term_only; 451 if (job_name == 0) 452 open_log_file(); 453 if (interaction == batch_mode) 454 decr(selector); 455} 456 457@ The following procedure prints \TeX's last words before dying 458@c 459void succumb(void) 460{ 461 if (interaction == error_stop_mode) 462 interaction = scroll_mode; /* no more interaction */ 463 if (log_opened_global) 464 error(); 465#ifdef DEBUG 466 if (interaction > batch_mode) 467 debug_help(); 468#endif 469 history = fatal_error_stop; 470 jump_out(); /* irrecoverable error */ 471} 472 473@ @c 474void fatal_error(const char *s) 475{ /* prints |s|, and that's it */ 476 normalize_selector(); 477 print_err("Emergency stop"); 478 help1(s); 479 succumb(); 480} 481 482@ @c 483void lua_norm_error(const char *s) 484{ /* lua found a problem */ 485 int saved_new_line_char; 486 int report_id ; 487 saved_new_line_char = new_line_char; 488 new_line_char = 10; 489 report_id = callback_defined(show_lua_error_hook_callback); 490 if (report_id == 0) { 491 print_err("LuaTeX error "); 492 tprint(s); 493 } else { 494 (void) run_callback(report_id, "->"); 495 } 496 help2("The lua interpreter ran into a problem, so the", 497 "remainder of this lua chunk will be ignored."); 498 error(); 499 new_line_char = saved_new_line_char; 500} 501 502@ @c 503void lua_fatal_error(const char *s) 504{ /* lua found a problem */ 505 new_line_char = 10; 506 normalize_selector(); 507 print_err("LuaTeX fatal error "); 508 tprint(s); 509 succumb(); 510} 511 512@ Here is the most dreaded error message 513@c 514void overflow(const char *s, unsigned int n) 515{ /* stop due to finiteness */ 516 normalize_selector(); 517 print_err("TeX capacity exceeded, sorry ["); 518 tprint(s); 519 print_char('='); 520 print_int((int) n); 521 print_char(']'); 522 help2("If you really absolutely need more capacity,", 523 "you can ask a wizard to enlarge me."); 524 succumb(); 525} 526 527 528@ The program might sometime run completely amok, at which point there is 529no choice but to stop. If no previous error has been detected, that's bad 530news; a message is printed that is really intended for the \TeX\ 531maintenance person instead of the user (unless the user has been 532particularly diabolical). The index entries for `this can't happen' may 533help to pinpoint the problem. 534@^dry rot@> 535 536@c 537void confusion(const char *s) 538{ /* consistency check violated; |s| tells where */ 539 normalize_selector(); 540 if (history < error_message_issued) { 541 print_err("This can't happen ("); 542 tprint(s); 543 print_char(')'); 544 help1("I'm broken. Please show this to someone who can fix can fix"); 545 } else { 546 print_err("I can't go on meeting you like this"); 547 help2("One of your faux pas seems to have wounded me deeply...", 548 "in fact, I'm barely conscious. Please fix it and try again."); 549 } 550 succumb(); 551} 552 553 554@ Users occasionally want to interrupt \TeX\ while it's running. 555If the runtime system allows this, one can implement 556a routine that sets the global variable |interrupt| to some nonzero value 557when such an interrupt is signalled. Otherwise there is probably at least 558a way to make |interrupt| nonzero using the debugger. 559@^system dependencies@> 560@^debugging@> 561 562@c 563void check_interrupt(void) 564{ 565 if (interrupt != 0) 566 pause_for_instructions(); 567} 568 569 570 571@ When an interrupt has been detected, the program goes into its 572highest interaction level and lets the user have nearly the full flexibility of 573the |error| routine. \TeX\ checks for interrupts only at times when it is 574safe to do this. 575 576@c 577void pause_for_instructions(void) 578{ 579 if (OK_to_interrupt) { 580 interaction = error_stop_mode; 581 if ((selector == log_only) || (selector == no_print)) 582 incr(selector); 583 print_err("Interruption"); 584 help3("You rang?", 585 "Try to insert some instructions for me (e.g.,`I\\showlists'),", 586 "unless you just want to quit by typing `X'."); 587 deletions_allowed = false; 588 error(); 589 deletions_allowed = true; 590 interrupt = 0; 591 } 592} 593 594@ @c 595void tex_error(const char *msg, const char **hlp) 596{ 597 print_err(msg); 598 if (hlp != NULL) { 599 int i; 600 for (i = 0; (hlp[i] != NULL && i <= 5); i++) { 601 help_line[i] = hlp[i]; 602 } 603 help_line[i] = NULL; 604 } else { 605 help_line[0] = NULL; 606 } 607 error(); 608} 609 610@ The |back_error| routine is used when we want to replace an offending token 611just before issuing an error message. This routine, like |back_input|, 612requires that |cur_tok| has been set. We disable interrupts during the 613call of |back_input| so that the help message won't be lost. 614 615@c 616void back_error(void) 617{ /* back up one token and call |error| */ 618 OK_to_interrupt = false; 619 back_input(); 620 OK_to_interrupt = true; 621 error(); 622} 623 624@ @c 625void ins_error(void) 626{ /* back up one inserted token and call |error| */ 627 OK_to_interrupt = false; 628 back_input(); 629 token_type = inserted; 630 OK_to_interrupt = true; 631 error(); 632} 633 634 635 636@ When \TeX\ wants to typeset a character that doesn't exist, the 637character node is not created; thus the output routine can assume 638that characters exist when it sees them. The following procedure 639prints a warning message unless the user has suppressed it. 640 641@c 642void char_warning(internal_font_number f, int c) 643{ 644 int old_setting; /* saved value of |tracing_online| */ 645 int k; /* index to current digit; we assume that $0\L n<16^{22}$ */ 646 if (int_par(tracing_lost_chars_code) > 0) { 647 old_setting = int_par(tracing_online_code); 648 if (int_par(tracing_lost_chars_code) > 1) 649 int_par(tracing_online_code) = 1; 650 begin_diagnostic(); 651 tprint_nl("Missing character: There is no "); 652 print(c); 653 tprint(" (U+"); 654 k = 0; 655 if (c < 16) 656 print_char('0'); 657 if (c < 256) 658 print_char('0'); 659 if (c < 4096) 660 print_char('0'); 661 do { 662 dig[k] = c % 16; 663 c = c / 16; 664 incr(k); 665 } while (c != 0); 666 print_the_digs((eight_bits) k); 667 tprint(") in font "); 668 print_font_name(f); 669 print_char('!'); 670 end_diagnostic(false); 671 int_par(tracing_online_code) = old_setting; 672 } 673} 674