1
4
5# include "luametatex.h"
6
7# include <string.h>
8
9
37
38error_state_info lmt_error_state = {
39 .last_error = NULL,
40 .last_lua_error = NULL,
41 .last_warning_tag = NULL,
42 .last_warning = NULL,
43 .last_error_context = NULL,
44 .help_text = NULL,
45
46 .intercept = 0,
47 .last_intercept = 0,
48 .interaction = 0,
49 .default_exit_code = 0,
50 .set_box_allowed = 0,
51 .history = 0,
52 .error_count = 0,
53 .saved_selector = 0,
54 .in_error = 0,
55 .long_help_seen = 0,
56 .context_indent = 4,
57 .padding = 0,
58 .line_limits = {
59 .maximum = max_error_line,
60 .minimum = min_error_line,
61 .size = min_error_line,
62 .top = 0,
63 },
64 .half_line_limits = {
65 .maximum = max_half_error_line,
66 .minimum = min_half_error_line,
67 .size = min_half_error_line,
68 .top = 0,
69 },
70} ;
71
72
76
77inline static void tex_aux_update_help_text(const char* str)
78{
79 if (lmt_error_state.help_text) {
80 lmt_memory_free(lmt_error_state.help_text);
81 lmt_error_state.help_text = NULL;
82 }
83 if (str) {
84 lmt_error_state.help_text = lmt_memory_strdup(str);
85 }
86}
87
88
99
100static void tex_aux_set_last_error_context(void)
101{
102 int saved_selector = lmt_print_state.selector;
103 int saved_new_line_char = new_line_char_par;
104 int saved_new_string_line = lmt_print_state.new_string_line;
105 lmt_print_state.selector = new_string_selector_code;
106 new_line_char_par = 10;
107 lmt_print_state.new_string_line = 10;
108 tex_show_validity();
109 tex_show_context();
110 lmt_memory_free(lmt_error_state.last_error_context);
111 lmt_error_state.last_error_context = tex_take_string(NULL);
112 lmt_print_state.selector = saved_selector;
113 new_line_char_par = saved_new_line_char;
114 lmt_print_state.new_string_line = saved_new_string_line;
115}
116
117static void tex_aux_flush_error(void)
118{
119 if (lmt_error_state.in_error) {
120 lmt_print_state.selector = lmt_error_state.saved_selector;
121 lmt_memory_free(lmt_error_state.last_error);
122 lmt_error_state.last_error = tex_take_string(NULL);
123 if (lmt_error_state.last_error) {
124 int callback_id = lmt_callback_defined(show_error_message_callback);
125 if (callback_id > 0) {
126 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "->");
127 } else {
128 tex_print_str(lmt_error_state.last_error);
129 }
130 }
131 lmt_error_state.in_error = 0;
132 }
133}
134
135static int tex_aux_error_callback_set(void)
136{
137 int callback_id = lmt_callback_defined(show_error_message_callback);
138 return lmt_lua_state.lua_instance && callback_id > 0 ? callback_id : 0;
139}
140
141static void tex_aux_start_error(void)
142{
143 if (tex_aux_error_callback_set()) {
144 lmt_error_state.saved_selector = lmt_print_state.selector;
145 lmt_print_state.selector = new_string_selector_code;
146 lmt_error_state.in_error = 1 ;
147 lmt_memory_free(lmt_error_state.last_error);
148 lmt_error_state.last_error = NULL;
149 } else {
150 tex_print_nlp();
151 tex_print_str("! ");
152 }
153}
154
155
168
169void tex_fixup_selector(int logopened)
170{
171 if (lmt_error_state.interaction == batch_mode) {
172 lmt_print_state.selector = logopened ? logfile_selector_code : no_print_selector_code ;
173 } else {
174 lmt_print_state.selector = logopened ? terminal_and_logfile_selector_code : terminal_selector_code;
175 }
176}
177
178
191
192void tex_initialize_errors(void)
193{
194 lmt_error_state.interaction = error_stop_mode;
195 lmt_error_state.set_box_allowed = 1;
196 if (lmt_error_state.half_line_limits.size > lmt_error_state.line_limits.size) {
197 lmt_error_state.half_line_limits.size = lmt_error_state.line_limits.size/2;
198 }
199 if (lmt_error_state.half_line_limits.size <= 30) {
200 lmt_error_state.half_line_limits.size = 31;
201 } else if (lmt_error_state.half_line_limits.size >= (lmt_error_state.line_limits.size - 15)) {
202 lmt_error_state.half_line_limits.size = lmt_error_state.line_limits.size - 16;
203 }
204}
205
206
222
223static int tex_aux_final_exit(int code)
224{
225 exit(code);
226 return 0;
227}
228
229int tex_normal_exit(void)
230{
231 tex_terminal_update();
232
233 lmt_main_state.ready_already = output_disabled_state;
234 if (lmt_error_state.history != spotless && lmt_error_state.history != warning_issued) {
235 return tex_aux_final_exit(EXIT_FAILURE);
236 } else {
237 return tex_aux_final_exit(lmt_error_state.default_exit_code);
238 }
239}
240
241static void tex_aux_jump_out(void)
242{
243 tex_close_files_and_terminate(1);
244 tex_normal_exit();
245}
246
247
254
255static void tex_aux_error(int type)
256{
257 int callback_id = lmt_callback_defined(intercept_tex_error_callback);
258 tex_aux_flush_error();
259 if (lmt_error_state.history < error_message_issued && type != warning_error_type) {
260 lmt_error_state.history = error_message_issued;
261 }
262 if (lmt_lua_state.lua_instance && callback_id > 0) {
263 tex_aux_set_last_error_context();
264 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "dd->d", lmt_error_state.interaction, type, &lmt_error_state.interaction);
265 lmt_error_state.error_count = 0;
266 tex_terminal_update();
267 switch (lmt_error_state.interaction) {
268 case batch_mode:
269 --lmt_print_state.selector;
270 return;
271 case nonstop_mode:
272 return;
273 case scroll_mode:
274 return;
275 case error_stop_mode:
276 break;
277 default:
278 lmt_error_state.interaction = scroll_mode;
279 if (type != warning_error_type) {
280 tex_aux_jump_out();
281 }
282 break;
283 }
284 } else {
285 tex_print_char('.');
286 tex_show_context();
287 }
288 if (type != warning_error_type) {
289 ++lmt_error_state.error_count;
290 if (lmt_error_state.error_count == 100) {
291 tex_print_message("That makes 100 errors; please try again.");
292 lmt_error_state.history = fatal_error_stop;
293 tex_aux_jump_out();
294 }
295 }
296
300 if (callback_id == 0) {
301 if (lmt_error_state.interaction > batch_mode) {
302
303 --lmt_print_state.selector;
304 }
305 tex_print_nlp();
306 if (lmt_error_state.help_text) {
307 tex_print_str(lmt_error_state.help_text);
308 tex_print_nlp();
309 }
310 if (lmt_error_state.interaction > batch_mode) {
311
312 ++lmt_print_state.selector;
313 }
314 }
315 tex_print_ln();
316}
317
318
324
325static void tex_aux_normalize_selector(void)
326{
327 if (lmt_fileio_state.log_opened) {
328 lmt_print_state.selector = terminal_and_logfile_selector_code;
329 } else {
330 lmt_print_state.selector = terminal_selector_code;
331 }
332 if (! lmt_fileio_state.job_name) {
333 tex_open_log_file();
334 }
335 if (lmt_error_state.interaction == batch_mode) {
336
337 --lmt_print_state.selector;
338 }
339}
340
341
342
343static void tex_aux_succumb_error(void)
344{
345 if (lmt_error_state.interaction == error_stop_mode) {
346
347 lmt_error_state.interaction = scroll_mode;
348 }
349 if (lmt_fileio_state.log_opened) {
350 tex_aux_error(succumb_error_type);
351 }
352 lmt_error_state.history = fatal_error_stop;
353
354 tex_aux_jump_out();
355}
356
357
358
359void tex_fatal_error(const char *helpinfo)
360{
361 tex_aux_normalize_selector();
362 tex_handle_error(
363 succumb_error_type,
364 "Emergency stop",
365 helpinfo
366 );
367}
368
369
370
371void tex_overflow_error(const char *s, int n)
372{
373 tex_aux_normalize_selector();
374 tex_handle_error(
375 succumb_error_type,
376 "TeX capacity exceeded, sorry [%s=%i]",
377 s, n,
378 "If you really absolutely need more capacity, you can ask a wizard to enlarge me."
379 );
380}
381
382
391
392int tex_confusion(const char *s)
393{
394
395 tex_aux_normalize_selector();
396 if (lmt_error_state.history < error_message_issued) {
397 tex_handle_error(
398 succumb_error_type,
399 "This can't happen (%s)",
400 s,
401 "I'm broken. Please show this to someone who can fix me."
402 );
403 } else {
404 tex_handle_error(
405 succumb_error_type,
406 "I can't go on meeting you like this",
407 "One of your faux pas seems to have wounded me deeply ... in fact, I'm barely\n"
408 "conscious. Please fix it and try again."
409 );
410 }
411 return 0;
412}
413
414
419
420void aux_quit_the_program(void)
421{
422 tex_handle_error(
423 succumb_error_type,
424 "Forced stop",
425 NULL
426 );
427}
428
429
436
437static void tex_aux_back_error(void)
438{
439 tex_back_input(cur_tok);
440 tex_aux_error(back_error_type);
441}
442
443
444
445static void tex_aux_insert_error(void)
446{
447 tex_back_input(cur_tok);
448 lmt_input_state.cur_input.token_type = inserted_text;
449 tex_aux_error(insert_error_type);
450}
451
452int tex_normal_error(const char *t, const char *p)
453{
454 if (lmt_engine_state.lua_only) {
455
456 tex_emergency_message(t, p);
457 } else {
458 tex_aux_normalize_selector();
459 if (! tex_aux_error_callback_set()) {
460 tex_print_nlp();
461 tex_print_str("! ");
462 }
463 tex_print_str("error");
464 if (t) {
465 tex_print_format(" (%s)", t);
466 }
467 tex_print_str(": ");
468 if (p) {
469 tex_print_str(p);
470 }
471 lmt_error_state.history = fatal_error_stop;
472 tex_print_str("\n");
473 }
474 return tex_aux_final_exit(EXIT_FAILURE);
475}
476
477void tex_normal_warning(const char *t, const char *p)
478{
479 if (lmt_engine_state.lua_only) {
480
481 tex_emergency_message(t, p);
482 } else if (strcmp(t, "lua") == 0) {
483 int callback_id = lmt_callback_defined(intercept_lua_error_callback);
484 int saved_new_line_char = new_line_char_par;
485 new_line_char_par = 10;
486 if (lmt_lua_state.lua_instance && callback_id) {
487 (void) lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "->");
488
489 } else {
490 tex_handle_error(
491 normal_error_type,
492 p ? p : "unspecified lua error",
493 "The lua interpreter ran into a problem, so the remainder of this lua chunk will\n"
494 "be ignored."
495 );
496 }
497 new_line_char_par = saved_new_line_char;
498 } else {
499 int callback_id = lmt_callback_defined(show_warning_message_callback);
500 if (callback_id > 0) {
501
502 lmt_memory_free(lmt_error_state.last_warning);
503 lmt_memory_free(lmt_error_state.last_warning_tag);
504 lmt_error_state.last_warning = lmt_memory_strdup(p);
505 lmt_error_state.last_warning_tag = lmt_memory_strdup(t);
506 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "->");
507 } else {
508 tex_print_ln();
509 tex_print_str("warning");
510 if (t) {
511 tex_print_format(" (%s)", t);
512 }
513 tex_print_str(": ");
514 if (p) {
515 tex_print_str(p);
516 }
517 tex_print_ln();
518 }
519 if (lmt_error_state.history == spotless) {
520 lmt_error_state.history = warning_issued;
521 }
522 }
523}
524
525int tex_formatted_error(const char *t, const char *fmt, ...)
526{
527 char print_buffer[print_buffer_size];
528 va_list args;
529 va_start(args, fmt);
530 vsnprintf(print_buffer, print_buffer_size, fmt, args);
531 return tex_normal_error(t, print_buffer);
532
536}
537
538void tex_formatted_warning(const char *t, const char *fmt, ...)
539{
540 char print_buffer[print_buffer_size];
541 va_list args;
542 va_start(args, fmt);
543 vsnprintf(print_buffer, print_buffer_size, fmt, args);
544 tex_normal_warning(t, print_buffer);
545 va_end(args);
546}
547
548void tex_emergency_message(const char *t, const char *fmt, ...)
549{
550 char print_buffer[print_buffer_size];
551 va_list args;
552 va_start(args, fmt);
553 vsnprintf(print_buffer, print_buffer_size, fmt, args);
554 fprintf(stdout,"%s : %s\n", t, print_buffer);
555 va_end(args);
556}
557
558int tex_emergency_exit(void)
559{
560 return tex_aux_final_exit(EXIT_FAILURE);
561}
562
563
564
565static void tex_aux_do_handle_error_type(
566 int type
567) {
568 switch (type) {
569 case normal_error_type:
570 case eof_error_type:
571 case condition_error_type:
572 case runaway_error_type:
573 case warning_error_type:
574 tex_aux_error(type);
575 break;
576 case back_error_type:
577 tex_aux_back_error();
578 break;
579 case insert_error_type:
580 tex_aux_insert_error();
581 break;
582 case succumb_error_type:
583 tex_aux_succumb_error();
584 break;
585 }
586}
587
588void tex_handle_error_message_only(
589 const char *message
590)
591{
592 tex_aux_start_error();
593 tex_print_str(message);
594 if (tex_aux_error_callback_set()) {
595 lmt_error_state.in_error = 0;
596 lmt_memory_free(lmt_error_state.last_error);
597 lmt_error_state.last_error = lmt_memory_strdup(message);
598 }
599}
600
601
612
613extern void tex_handle_error(error_types type, const char *format, ...)
614{
615 const char *str = NULL;
616 va_list args;
617 va_start(args, format);
618 tex_aux_start_error();
619 str = tex_print_format_args(format, args);
620 tex_aux_update_help_text(str);
621 tex_aux_do_handle_error_type(type);
622 va_end(args);
623}
624 |