~ubuntu-branches/ubuntu/maverick/luatex/maverick

« back to all changes in this revision

Viewing changes to source/texk/web2c/luatexdir/tex/errors.c

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Preining
  • Date: 2009-12-25 09:47:05 UTC
  • mfrom: (1.1.9 upstream) (4.2.3 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091225094705-y33rpflo8t4u9nag
Tags: 0.50.0-1
* new upstream release
* disable fix-hurd-ftbfs patch, included upstream
* disable upstram-fixes, included upstream
* disable ubuntu_libpoppler-0.11, not needed anymore

Show diffs side-by-side

added added

removed removed

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