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