3 % Copyright
2009-2010 Taco Hoekwater
<taco@@luatex.org
>
5 % This file is part of LuaTeX.
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.
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.
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
/>.
20 @ TODO
: we need to use a formatted normal_error in
:
27 #define edit_var
"TEXEDIT"
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
36 A two-line help message would be given using |help2|
, etc.
; these informal
37 helps should use simple vocabulary that complements the words used in the
38 official error message that was printed.
(Outside the U.S.A.
, the help
39 messages should preferably be translated into the local vernacular. Each
40 line of help is at most
60 characters long
, in the present implementation
,
41 so that |max_print_line| will not be exceeded.
)
43 The |print_err| procedure supplies a `\.
!' before the official message
,
44 and makes sure that the terminal is awake if a stop is going to occur.
45 The |error| procedure supplies a `\..' after the official message
, then it
46 shows the location of the error
; and if |interaction
=error_stop_mode|
,
47 it also enters into a dialog with the user
, during which time the help
48 message may be printed.
49 @^system dependencies@
>
52 int interaction
; /* current level of interaction
*/
53 int interactionoption
; /* set from command line
*/
55 /* ls-hh
: so
, new code only kicks in when we have a callback defined
*/
57 char
*last_error
= NULL;
58 char
*last_lua_error
= NULL;
59 char
*last_warning_tag
= NULL;
60 char
*last_warning_str
= NULL;
61 char
*last_error_context
= NULL;
63 int err_old_setting
= 0 ;
66 void set_last_error_context
(void
)
70 int saved_new_line_char
;
71 int saved_new_string_line
;
72 selector
= new_string
;
73 saved_new_line_char
= new_line_char_par
;
74 saved_new_string_line
= new_string_line
;
75 new_line_char_par
= 10;
78 xfree
(last_error_context
);
80 last_error_context
= makecstring
(str
);
83 new_line_char_par
= saved_new_line_char
;
84 new_string_line
= saved_new_string_line
;
94 selector
= err_old_setting
;
96 s_error
= make_string
();
97 s
= makecstring
(s_error
);
99 if
(interaction
== error_stop_mode
) {
103 last_error
= (string
) xmalloc
((unsigned
) (strlen
(s
) + 1));
104 strcpy
(last_error
,s
);
105 callback_id
= callback_defined
(show_error_message_callback
);
106 if
(callback_id
> 0) {
107 run_callback
(callback_id
, "->");
115 void print_err
(const char
*s
)
117 int callback_id
= callback_defined
(show_error_message_callback
);
118 if
(interaction
== error_stop_mode
) {
121 if
(callback_id
> 0) {
122 err_old_setting
= selector
;
123 selector
= new_string
;
126 if
(filelineerrorstylep
) {
132 if
(callback_id
<= 0) {
134 last_error
= (string
) xmalloc
((unsigned
) (strlen
(s
) + 1));
135 strcpy
(last_error
,s
);
139 @ \TeX\ is careful not to call |error| when the print |selector| setting
140 might be unusual. The only possible values of |selector| at the time of
144 \hang|no_print|
(when |interaction
=batch_mode| and |log_file| not yet open
);
146 \hang|term_only|
(when |interaction
>batch_mode| and |log_file| not yet open
);
148 \hang|log_only|
(when |interaction
=batch_mode| and |log_file| is open
);
150 \hang|term_and_log|
(when |interaction
>batch_mode| and |log_file| is open
).
153 void fixup_selector
(boolean logopened
)
155 if
(interaction
== batch_mode
)
158 selector
= term_only
;
160 selector
= selector
+ 2;
163 @ A global variable |deletions_allowed| is set |false| if the |get_next|
164 routine is active when |error| is called
; this ensures that |get_next|
165 and related routines like |get_token| will never be called recursively.
166 A similar interlock is provided by |set_box_allowed|.
169 The global variable |history| records the worst level of error that
170 has been detected. It has four possible values
: |spotless|
, |warning_issued|
,
171 |error_message_issued|
, and |fatal_error_stop|.
173 Another global variable
, |error_count|
, is increased by one when an
174 |error| occurs without an interactive dialog
, and it is reset to zero at
175 the end of every paragraph. If |error_count| reaches
100, \TeX\ decides
176 that there is no point in continuing further.
179 boolean deletions_allowed
; /* is it safe for |error| to call |get_token|?
*/
180 boolean set_box_allowed
; /* is it safe to do a \.
{\\setbox
} assignment?
*/
181 int history
; /* has the source input been clean so far?
*/
182 int error_count
; /* the number of scrolled errors since the last paragraph ended
*/
183 int interrupt
; /* should \TeX\ pause for instructions?
*/
184 boolean OK_to_interrupt
; /* should interrupts be observed?
*/
186 @ The value of |history| is initially |fatal_error_stop|
, but it will
187 be changed to |spotless| if \TeX\ survives the initialization process.
190 void initialize_errors
(void
)
192 if
(interactionoption
== unspecified_mode
)
193 interaction
= error_stop_mode
;
195 interaction
= interactionoption
;
196 deletions_allowed
= true
;
197 set_box_allowed
= true
;
198 OK_to_interrupt
= true
;
199 /* |history| is initialized elsewhere
*/
202 @ It is possible for |error| to be called recursively if some error arises
203 when |get_token| is being used to delete a token
, and
/or if some fatal error
204 occurs while \TeX\ is trying to fix a non-fatal one. But such recursion
206 is never more than two levels deep.
208 @ Individual lines of help are recorded in the array |help_line|.
211 const char
*help_line
[7]; /* helps for the next |error|
*/
212 boolean use_err_help
; /* should the |err_help| list be shown?
*/
214 @ The |jump_out| procedure just cuts across all active procedure levels and
215 exits the program. It is used when there is no recovery from a particular error.
218 __attribute__
((noreturn
))
219 void do_final_end
(void
)
223 lua_close
(Luas
); /* new per
0.99 */
224 if
((history
!= spotless
) && (history != warning_issued))
230 __attribute__
((noreturn
))
233 close_files_and_terminate
();
236 @ Here is the function that calls the editor
, if one is defined. This
237 is loosely based on a similar function in kpathsea
, but the calling
238 convention is quite different.
241 static const_string edit_value
= EDITOR;
247 return
(c
== ' ' || c
== '\t'
);
251 __attribute__
((noreturn
))
252 static void luatex_calledit
(int baseptr
, int linenumber
)
254 char
*temp
, *command
, *fullcmd
;
257 char
*filename
= makecstring
(input_stack
[base_ptr
].name_field
);
258 int fnlength
= strlen
(filename
);
261 char
*fp
, *ffp
, *env
, editorname
[256], buffer
[256];
268 /* Close any open input files
, since we're going to kill the job.
*/
269 close_files_and_terminate
();
271 /* Replace the default with the value of the appropriate environment
272 variable or config file value
, if it's set.
*/
273 temp
= kpse_var_value
(edit_var
);
277 /* Construct the command string. The `
11' is the maximum length an
279 command
= xmalloc
(strlen
(edit_value
) + fnlength
+ 11);
281 /* So we can construct it as we go.
*/
286 if
((isalpha
(*edit_value
) && *(edit_value + 1) == ':'
287 && IS_DIR_SEP (*(edit_value + 2)))
288 ||
(*edit_value
== '
"' && isalpha(*(edit_value + 1))
289 && *(edit_value + 2) == ':'
290 && IS_DIR_SEP (*(edit_value + 3)))
295 while ((c = *edit_value++) != 0)
299 switch (c = *edit_value++)
303 FATAL1 ("call_edit
: `
%%d' appears twice in editor command
: `
%s'
", edit_value);
304 sprintf (temp, "%ld
", (long int)linenumber);
305 while (*temp != '\0')
312 FATAL1 ("call_edit
: `
%%s' appears twice in editor command
: `
%s'
", edit_value);
313 for (i =0; i < fnlength; i++)
314 *temp++ = filename[i];
320 /* Back up to the null to force termination. */
334 else { if(Isspace(c) && cnt == 0) {
339 } else if(!Isspace(c) && cnt == 0) {
354 if (dontchange == 0) {
355 if(editorname[0] == '.' ||
356 editorname[0] == '/' ||
357 editorname[0] == '\\') {
358 fprintf(stderr, "%s is not allowed to execute.\n
", editorname);
361 env = (char *)getenv("PATH
");
362 if(SearchPath(env, editorname, ".exe
", 256, buffer, &ffp)==0) {
363 if(SearchPath(env, editorname, ".bat
", 256, buffer, &ffp)==0) {
364 fprintf(stderr, "I cannot find
%s in the PATH.\n
", editorname);
368 fullcmd = (char *)xmalloc(strlen(buffer)+strlen(command)+5);
369 strcpy(fullcmd, "\
"");
370 strcat
(fullcmd
, buffer
);
371 strcat
(fullcmd
, "\"");
372 strcat(fullcmd, command);
377 /* Execute the command. */
378 if (system (fullcmd) != 0)
379 fprintf (stderr, "! Trouble executing `
%s'.\n
", command);
381 /* Quit, since we found an error. */
388 { /* completes the job of error reporting */
389 ASCII_code c; /* what the user types */
391 int s1, s2, s3, s4; /* used to save global variables when deleting tokens */
393 flush_err(); /* hh-ls */
394 if (history < error_message_issued)
395 history = error_message_issued;
396 callback_id = callback_defined(show_error_hook_callback);
397 if (callback_id > 0) {
398 set_last_error_context();
399 run_callback(callback_id, "->");
405 history = fatal_error_stop;
408 if (interaction == error_stop_mode) {
409 /* Get user's advice and |return| */
412 clear_for_error_prompt();
418 c = c + 'A' - 'a'; /* convert to uppercase */
419 /* Interpret code |c| and |return| if done */
421 /* It is desirable to provide an `\.E' option here that gives the user
422 an easy way to return from \TeX\ to the system editor, with the offending
423 line ready to be edited. But such an extension requires some system
424 wizardry, so the present implementation simply types out the name of the
425 file that should be edited and the relevant line number.
427 There is a secret `\.D' option available when the debugging routines haven't
428 been commented~out. */
441 if (deletions_allowed) {
442 /* Delete |c-"0"| tokens and |goto continue| */
443 /* We allow deletion of up to 99 tokens at a time */
448 align_state = 1000000;
449 OK_to_interrupt = false;
450 if ((last > first + 1) && (buffer[first + 1] >= '0')
451 && (buffer[first + 1] <= '9'))
452 c = c * 10 + buffer[first + 1] - '0' * 11;
456 get_token(); /* one-level recursive call of |error| is possible */
463 OK_to_interrupt = true;
464 help2("I have just deleted some text
, as you asked.
",
465 "You can now delete more
, or insert
, or whatever.
");
478 int callback_id = callback_defined(call_edit_callback);
480 (void)run_callback(callback_id, "Sd-
>", makecstring(input_stack[base_ptr].name_field), line);
481 jump_out(); /* should not be reached */
483 tprint_nl("You want to edit file
");
484 print(input_stack[base_ptr].name_field);
487 interaction = scroll_mode;
489 luatex_calledit(base_ptr, line);
491 tprint_nl("There is no valid callback defined.
");
492 jump_out(); /* should not be reached */
498 /* Print the help information and |goto continue| */
502 if (help_line[0] == NULL) {
504 ("Sorry
, I don't know how to help in this situation.
",
505 "Maybe you should try asking a human?
");
508 while (help_line[i] != NULL)
509 tprint_nl(help_line[i++]);
510 help4("Sorry
, I already gave what help I could...
",
511 "Maybe you should try asking a human?
",
512 "An error might have occurred before I noticed any problems.
",
513 "``If all else fails
, read the instructions.''
");
518 /* Introduce new material from the terminal and |return| */
519 /* When the following code is executed, |buffer[(first+1)..(last-1)]| may
520 contain the material inserted by the user; otherwise another prompt will
521 be given. In order to understand this part of the program fully, you need
522 to be familiar with \TeX's input stacks. */
524 begin_file_reading(); /* enter a new syntactic level for terminal input */
525 /* now |state=mid_line|, so an initial blank space will count as a blank */
526 if (last > first + 1) {
530 prompt_input("insert
>");
534 ilimit = last - 1; /* no |end_line_char| ends this line */
540 /* Change the interaction level and |return| */
541 /* Here the author of \TeX\ apologizes for making use of the numerical
542 relation between |"Q
"|, |"R
"|, |"S
"|, and the desired interaction settings
543 |batch_mode|, |nonstop_mode|, |scroll_mode|. */
545 interaction = batch_mode + c - 'Q';
546 tprint("OK, entering
");
549 tprint_esc("batchmode
");
553 tprint_esc("nonstopmode
");
556 tprint_esc("scrollmode
");
565 interaction = scroll_mode;
572 /* Print the menu of available options */
573 tprint("Type
<return
> to proceed
, S to scroll future error messages
,");
574 tprint_nl("R to run without stopping
, Q to run quietly
,");
575 tprint_nl("I to insert something
, ");
577 tprint("E to edit your file
,");
578 if (deletions_allowed)
579 tprint_nl("1 or ... or
9 to ignore the next
1 to
9 tokens of input
,");
580 tprint_nl("H for help
, X to quit.
");
582 use_err_help = false;
587 if (error_count == 100) {
588 tprint_nl("(That makes
100 errors
; please try again.
)");
589 history = fatal_error_stop;
592 /* Put help message on the transcript file */
593 if (interaction > batch_mode)
594 decr(selector); /* avoid terminal output */
600 while (help_line[i1] != NULL)
601 tprint_nl(help_line[i1++]);
604 if (interaction > batch_mode)
605 incr(selector); /* re-enable terminal output */
609 @ A dozen or so error messages end with a parenthesized integer, so we
610 save a teeny bit of program space by declaring the following procedure:
613 void int_error(int n)
621 @ In anomalous cases, the print selector might be in an unknown state;
622 the following subroutine is called to fix things just enough to keep
623 running a bit longer.
626 void normalize_selector(void)
628 if (log_opened_global)
629 selector = term_and_log;
631 selector = term_only;
634 if (interaction == batch_mode)
638 @ The following procedure prints \TeX's last words before dying
642 if (interaction == error_stop_mode)
643 interaction = scroll_mode; /* no more interaction */
644 if (log_opened_global)
647 if (interaction > batch_mode)
650 history = fatal_error_stop;
651 jump_out(); /* irrecoverable error */
655 void fatal_error(const char *s)
656 { /* prints |s|, and that's it */
657 normalize_selector();
658 print_err("Emergency stop
");
663 @ Here is the most dreaded error message
665 void overflow(const char *s, unsigned int n)
666 { /* stop due to finiteness */
667 normalize_selector();
668 print_err("TeX capacity exceeded
, sorry
[");
673 if (varmem == NULL) {
674 print_err("Sorry
, I ran out of memory.
");
678 help2("If you really absolutely need more capacity
,",
679 "you can ask a wizard to enlarge me.
");
683 @ The program might sometime run completely amok, at which point there is
684 no choice but to stop. If no previous error has been detected, that's bad
685 news; a message is printed that is really intended for the \TeX\
686 maintenance person instead of the user (unless the user has been
687 particularly diabolical). The index entries for `this can't happen' may
688 help to pinpoint the problem.
692 void confusion(const char *s)
693 { /* consistency check violated; |s| tells where */
694 normalize_selector();
695 if (history < error_message_issued) {
696 print_err("This can't happen
(");
699 help1("I'm broken. Please show this to someone who can fix can fix
");
701 print_err("I can't go on meeting you like this
");
702 help2("One of your faux pas seems to have wounded me deeply...
",
703 "in fact
, I'm barely conscious. Please fix it and try again.
");
708 @ Users occasionally want to interrupt \TeX\ while it's running.
709 If the runtime system allows this, one can implement
710 a routine that sets the global variable |interrupt| to some nonzero value
711 when such an interrupt is signalled. Otherwise there is probably at least
712 a way to make |interrupt| nonzero using the debugger.
713 @^system dependencies@>
717 void check_interrupt(void)
720 pause_for_instructions();
723 @ When an interrupt has been detected, the program goes into its
724 highest interaction level and lets the user have nearly the full flexibility of
725 the |error| routine. \TeX\ checks for interrupts only at times when it is
729 void pause_for_instructions(void)
731 if (OK_to_interrupt) {
732 interaction = error_stop_mode;
733 if ((selector == log_only) || (selector == no_print))
735 print_err("Interruption
");
737 "Try to insert some instructions for me
(e.g.
,`I\\showlists'
),",
738 "unless you just want to quit by typing `
X'.
");
739 deletions_allowed = false;
741 deletions_allowed = true;
747 void tex_error(const char *msg, const char **hlp)
752 for (i = 0; (hlp[i] != NULL && i <= 5); i++) {
753 help_line[i] = hlp[i];
762 @ The |back_error| routine is used when we want to replace an offending token
763 just before issuing an error message. This routine, like |back_input|,
764 requires that |cur_tok| has been set. We disable interrupts during the
765 call of |back_input| so that the help message won't be lost.
768 void back_error(void)
769 { /* back up one token and call |error| */
770 OK_to_interrupt = false;
772 OK_to_interrupt = true;
778 { /* back up one inserted token and call |error| */
779 OK_to_interrupt = false;
781 token_type = inserted;
782 OK_to_interrupt = true;
786 @ When \TeX\ wants to typeset a character that doesn't exist, the
787 character node is not created; thus the output routine can assume
788 that characters exist when it sees them. The following procedure
789 prints a warning message unless the user has suppressed it.
792 void char_warning(internal_font_number f, int c)
794 int old_setting; /* saved value of |tracing_online| */
795 int k; /* index to current digit; we assume that $0\L n<16^{22}$ */
796 if (tracing_lost_chars_par > 0) {
797 old_setting = tracing_online_par;
798 if (tracing_lost_chars_par > 1)
799 tracing_online_par = 1;
801 tprint_nl("Missing character
: There is no
");
816 print_the_digs((eight_bits) k);
817 tprint(") in font
");
820 end_diagnostic(false);
821 tracing_online_par = old_setting;
827 void wrapup_backend(void) {
828 ensure_output_state(static_pdf, ST_OMODE_FIX);
829 switch (output_mode_used) {
831 print_err(" ==> Fatal error occurred
, no FMT file produced
!");
834 if (history == fatal_error_stop) {
835 remove_pdffile(static_pdf); /* will become remove_output_file */
836 print_err(" ==> Fatal error occurred
, no output PDF file produced
!");
838 finish_pdf_file(static_pdf, luatex_version, get_luatexrevision());
842 if (history == fatal_error_stop) {
843 print_err(" ==> Fatal error occurred
, bad output DVI file produced
!");
844 finish_dvi_file(static_pdf, luatex_version, get_luatexrevision());
846 finish_dvi_file(static_pdf, luatex_version, get_luatexrevision());
852 void normal_error(const char *t, const char *p)
854 normalize_selector();
855 if (interaction == error_stop_mode) {
858 if (filelineerrorstylep) {
866 tprint(cur_file_name);
877 history = fatal_error_stop;
883 void normal_error(const char *t, const char *p)
885 normalize_selector();
886 if (interaction == error_stop_mode) {
892 history = fatal_error_stop;
899 void normal_warning(const char *t, const char *p)
902 if (strcmp(t,"lua
") == 0) {
903 int saved_new_line_char;
904 saved_new_line_char = new_line_char_par;
905 new_line_char_par = 10;
906 report_id = callback_defined(show_lua_error_hook_callback);
907 if (report_id == 0) {
909 help2("The lua interpreter ran into a problem
, so the
",
910 "remainder of this lua chunk will be ignored.
");
912 (void) run_callback(report_id, "->");
915 new_line_char_par = saved_new_line_char;
917 report_id = callback_defined(show_warning_message_callback);
920 xfree(last_warning_str);
921 xfree(last_warning_tag);
922 last_warning_str = (string) xmalloc(strlen(p) + 1);
923 last_warning_tag = (string) xmalloc(strlen(t) + 1);
924 strcpy(last_warning_str,p);
925 strcpy(last_warning_tag,t);
926 run_callback(report_id, "->");
932 tprint(cur_file_name);
945 if (history == spotless)
946 history = warning_issued;
951 static char print_buf[PRINTF_BUF_SIZE];
952 __attribute__ ((format(printf, 2,3)))
953 void formatted_error(const char *t, const char *fmt, ...)
957 vsnprintf(print_buf, PRINTF_BUF_SIZE, fmt, args);
958 normal_error(t,print_buf);
962 __attribute__ ((format(printf, 2,3)))
963 void formatted_warning(const char *t, const char *fmt, ...)
967 vsnprintf(print_buf, PRINTF_BUF_SIZE, fmt, args);
968 normal_warning(t,print_buf);