1
4
5# include "luametatex.h"
6
7
16
17
41
42condition_state_info lmt_condition_state = {
43 .cond_ptr = null,
44 .cur_if = 0,
45 .if_limit = 0,
46 .cur_unless = 0,
47 .if_unless = 0,
48 .if_step = 0,
49 .unused = 0,
50 .if_line = 0,
51 .if_nesting = 0,
52 .skip_line = 0,
53 .chk_integer = 0,
54 .chk_dimension = 0,
55};
56
57
67
68static void tex_aux_pass_text(void)
69{
70 int level = 0;
71 int status = lmt_input_state.scanner_status;
72 lmt_input_state.scanner_status = scanner_is_skipping;
73 lmt_condition_state.skip_line = lmt_input_state.input_line;
74 while (1) {
75 tex_get_next();
76 if (cur_cmd == if_test_cmd) {
77 switch (cur_chr) {
78 case fi_code:
79 if (level == 0) {
80 lmt_input_state.scanner_status = status;
81 return;
82 } else {
83 --level;
84 break;
85 }
86 case else_code:
87 case or_code:
88 if (level == 0) {
89 lmt_input_state.scanner_status = status;
90 return;
91 } else {
92 break;
93 }
94 case or_else_code:
95 case or_unless_code:
96 tex_get_next_non_spacer();
97
98 break;
99 default:
100 ++level;
101 break;
102 }
103 }
104 }
105}
106
107
111
112static int tex_aux_pass_text_x(int tracing_ifs, int tracing_commands)
113{
114 int level = 0;
115 int status = lmt_input_state.scanner_status;
116 lmt_input_state.scanner_status = scanner_is_skipping;
117 lmt_condition_state.skip_line = lmt_input_state.input_line;
118 while (1) {
119 tex_get_next();
120 if (cur_cmd == if_test_cmd) {
121 switch (cur_chr) {
122 case if_code:
123 ++level;
124 break;
125 case fi_code:
126 if (level == 0) {
127 lmt_input_state.scanner_status = status;
128 return 0;
129 } else {
130 --level;
131 break;
132 }
133 case else_code:
134 case or_code:
135 if (level == 0) {
136 lmt_input_state.scanner_status = status;
137 return 0;
138 } else {
139 break;
140 }
141 case or_else_code:
142 case or_unless_code:
143 if (level == 0) {
144 int unless = cur_chr == or_unless_code;
145 if (tracing_commands > 1) {
146 tex_begin_diagnostic();
147 tex_print_str(unless ? "{orunless}" : "{orelse}");
148 tex_end_diagnostic();
149 } else if (tracing_ifs) {
150 tex_show_cmd_chr(cur_cmd, cur_chr);
151 }
152 tex_get_next_non_spacer();
153 if (lmt_condition_state.if_limit == if_code) {
154 if (cur_cmd == if_test_cmd && cur_chr >= first_real_if_test_code) {
155
156 } else {
157 tex_handle_error(
158 normal_error_type,
159 unless ? "No condition after \\orunless" : "No condition after \\orelse",
160 "I'd expected a proper if test command."
161 );
162 }
163 lmt_input_state.scanner_status = status;
164 return unless;
165 }
166 } else {
167 --level;
168 }
169 break;
170 default:
171 ++level;
172 break;
173 }
174 }
175 }
176}
177
178
190
191static void tex_aux_if_warning(void)
192{
193
194 bool warning = false;
195 int index = lmt_input_state.in_stack_data.ptr;
196 lmt_input_state.base_ptr = lmt_input_state.input_stack_data.ptr;
197
198 lmt_input_state.input_stack[lmt_input_state.base_ptr] = lmt_input_state.cur_input;
199 while (lmt_input_state.in_stack[index].if_ptr == lmt_condition_state.cond_ptr) {
200
201 if (tracing_nesting_par > 0) {
202 while ((lmt_input_state.input_stack[lmt_input_state.base_ptr].state == token_list_state) || (lmt_input_state.input_stack[lmt_input_state.base_ptr].index > index)) {
203 --lmt_input_state.base_ptr;
204 }
205 if (lmt_input_state.input_stack[lmt_input_state.base_ptr].name > 17) {
206 warning = true;
207 }
208 }
209 lmt_input_state.in_stack[index].if_ptr = node_next(lmt_condition_state.cond_ptr);
210 --index;
211 }
212 if (warning) {
213 tex_begin_diagnostic();
214 tex_print_format("[conditional: end of %C%L of a different file]", if_test_cmd, lmt_condition_state.cur_if, lmt_condition_state.if_line);
215 tex_end_diagnostic();
216 if (tracing_nesting_par > 1) {
217 tex_show_context();
218 }
219 if (lmt_error_state.history == spotless) {
220 lmt_error_state.history = warning_issued;
221 }
222 }
223}
224
225
229
230static void tex_aux_push_condition_stack(int code, int unless)
231{
232 halfword p = tex_get_node(if_node_size);
233 node_type(p) = if_node;
234 node_subtype(p) = 0;
235 node_next(p) = lmt_condition_state.cond_ptr;
236 if_limit_type(p) = (quarterword) lmt_condition_state.if_limit;
237 if_limit_subtype(p) = (quarterword) lmt_condition_state.cur_if;
238 if_limit_step(p) = (singleword) lmt_condition_state.cur_unless;
239 if_limit_unless(p) = (singleword) lmt_condition_state.if_unless;
240 if_limit_stepunless(p) = (singleword) lmt_condition_state.if_unless;
241 if_limit_line(p) = lmt_condition_state.if_line;
242 lmt_condition_state.cond_ptr = p;
243 lmt_condition_state.cur_if = cur_chr;
244 lmt_condition_state.cur_unless = unless;
245 lmt_condition_state.if_step = code;
246 lmt_condition_state.if_limit = if_code;
247 lmt_condition_state.if_line = lmt_input_state.input_line;
248 ++lmt_condition_state.if_nesting;
249}
250
251static void tex_aux_pop_condition_stack(void)
252{
253 halfword p;
254 if (lmt_input_state.in_stack[lmt_input_state.in_stack_data.ptr].if_ptr == lmt_condition_state.cond_ptr) {
255
259 tex_aux_if_warning();
260 }
261 p = lmt_condition_state.cond_ptr;
262 --lmt_condition_state.if_nesting;
263 lmt_condition_state.if_line = if_limit_line(p);
264 lmt_condition_state.cur_if = if_limit_subtype(p);
265 lmt_condition_state.cur_unless = if_limit_unless(p);
266 lmt_condition_state.if_step = if_limit_step(p);
267 lmt_condition_state.if_unless = if_limit_stepunless(p);
268 lmt_condition_state.if_limit = if_limit_type(p);
269 lmt_condition_state.cond_ptr = node_next(p);
270 tex_free_node(p, if_node_size);
271}
272
273
279
280
284
285static inline void tex_aux_change_if_limit(int l, halfword p)
286{
287 if (p == lmt_condition_state.cond_ptr) {
288 lmt_condition_state.if_limit = l;
289 } else {
290 halfword q = lmt_condition_state.cond_ptr;
291 while (q) {
292 if (node_next(q) == p) {
293 if_limit_type(q) = (quarterword) l;
294 return;
295 } else {
296 q = node_next(q);
297 }
298 }
299 tex_confusion("if");
300 }
301}
302
303
314
315
316
317
323
324static void tex_aux_get_x_token_or_active_char(void)
325{
326 tex_get_x_token();
327
328 if (cur_cmd == relax_cmd && cur_chr == no_expand_relax_code && tex_is_active_cs(cs_text(cur_cs))) {
329 cur_cmd = active_char_cmd;
330 cur_chr = active_cs_value(cs_text(cur_tok - cs_token_flag));
331 }
332}
333
334
340
341static void tex_aux_missing_equal_error(int code)
342{
343 tex_handle_error(back_error_type, "Missing = inserted for %C", if_test_cmd, code,
344 "I was expecting to see '<', '=', or '>'. Didn't."
345 );
346}
347
348
363
364static void tex_aux_show_if_state(halfword code, halfword case_value)
365{
366 tex_begin_diagnostic();
367 switch (code) {
368 case if_chk_int_code : tex_print_format("{chknum %i}", case_value); break;
369 case if_chk_integer_code : tex_print_format("{chknumber %i}", case_value); break;
370 case if_val_int_code : tex_print_format("{numval %i}", case_value); break;
371 case if_cmp_int_code : tex_print_format("{cmpnum %i}", case_value); break;
372 case if_chk_dim_code : tex_print_format("{chkdim %i}", case_value); break;
373 case if_chk_dimension_code : tex_print_format("{chkdimension %i}", case_value); break;
374 case if_val_dim_code : tex_print_format("{dimval %i}", case_value); break;
375 case if_cmp_dim_code : tex_print_format("{cmpdim %i}", case_value); break;
376 case if_case_code : tex_print_format("{case %i}", case_value); break;
377 case if_math_parameter_code: tex_print_format("{mathparameter %i}", case_value); break;
378 case if_math_style_code : tex_print_format("{mathstyle %i}", case_value); break;
379 case if_arguments_code : tex_print_format("{arguments %i}", case_value); break;
380 case if_parameter_code : tex_print_format("{parameter %i}", case_value); break;
381 case if_parameters_code : tex_print_format("{parameters %i}", case_value); break;
382 default : tex_print_format("{todo %i}", case_value); break;
383 }
384 tex_end_diagnostic();
385}
386
387
388
389static inline halfword tex_aux_grab_toks(int expand, int expandlist, int *head)
390{
391 halfword p = null;
392 if (expand) {
393 do {
394 tex_get_x_token();
395 } while (cur_cmd == spacer_cmd || cur_cmd == relax_cmd);
396 } else {
397 do {
398 tex_get_token();
399 } while (cur_cmd == spacer_cmd || cur_cmd == relax_cmd);
400 }
401 switch (cur_cmd) {
402 case left_brace_cmd:
403 p = expandlist ? tex_scan_toks_expand(1, NULL, 0, 0) : tex_scan_toks_normal(1, NULL);
404 *head = p;
405 break;
406 case internal_toks_cmd:
407 case register_toks_cmd:
408 p = eq_value(cur_chr);
409 break;
410 case register_cmd:
411
412 if (cur_chr == token_val_level) {
413 halfword n = tex_scan_toks_register_number();
414 p = eq_value(register_toks_location(n));
415 break;
416 } else {
417 goto DEFAULT;
418 }
419 case cs_name_cmd:
420 if (cur_chr == last_named_cs_code) {
421 if (lmt_scanner_state.last_cs_name != null_cs) {
422 p = eq_value(lmt_scanner_state.last_cs_name);
423 }
424 break;
425 } else {
426
427 }
428 case call_cmd:
429 case protected_call_cmd:
430 case semi_protected_call_cmd:
431 case constant_call_cmd:
432 case tolerant_call_cmd:
433 case tolerant_protected_call_cmd:
434 case tolerant_semi_protected_call_cmd:
435 p = eq_value(cur_cs);
436 break;
437 default:
438 DEFAULT:
439 {
440 halfword n;
441 tex_back_input(cur_tok);
442 n = tex_scan_toks_register_number();
443 p = eq_value(register_toks_location(n));
444 break;
445 }
446 }
447
448 return p ? token_link(p) : null;
449}
450
451
464
465static halfword tex_aux_count_tok(int once)
466{
467 halfword qq = null;
468 halfword p, q;
469 halfword result = 0;
470 int save_scanner_status = lmt_input_state.scanner_status;
471 lmt_input_state.scanner_status = scanner_is_normal;
472 p = tex_get_token();
473 q = tex_aux_grab_toks(0, 0, &qq);
474 if (p == q) {
475 result = 1;
476 } else {
477 while (q) {
478 if (p == token_info(q)) {
479 result += 1;
480 if (once) {
481 break;
482 }
483 } else {
484 q = token_link(q);
485 }
486 }
487 }
488 if (qq) {
489 tex_flush_token_list(qq);
490 }
491 lmt_input_state.scanner_status = save_scanner_status;
492 return result;
493}
494
495static halfword tex_aux_count_toks(int once, int expand)
496{
497 halfword pp = null;
498 halfword p;
499 halfword result = 0;
500 int save_scanner_status = lmt_input_state.scanner_status;
501 lmt_input_state.scanner_status = scanner_is_normal;
502 p = tex_aux_grab_toks(expand, expand, &pp);
503 if (p) {
504 halfword qq = null;
505 halfword q = tex_aux_grab_toks(expand, expand, &qq);
506 if (p == q) {
507 result = 1;
508 } else {
509 int qh = q;
510 int ph = p;
511 while (p && q) {
512 halfword pt = token_info(p);
513 halfword qt = token_info(q);
514 AGAIN:
515 if (pt == qt) {
516 p = token_link(p);
517 q = token_link(q);
518 } else if (token_cmd(pt) == ignore_cmd && token_cmd(qt) >= ignore_cmd && token_cmd(qt) <= other_char_cmd) {
519 p = token_link(p);
520 if (token_chr(pt) == token_chr(qt)) {
521 q = token_link(q);
522 } else {
523 pt = token_info(p);
524 goto AGAIN;
525 }
526 } else {
527 p = ph;
528 q = token_link(qh);
529 qh = q;
530 }
531 if (! p) {
532 result += 1;
533 if (once) {
534 break;
535 }
536 }
537 }
538 }
539 if (qq) {
540 tex_flush_token_list(qq);
541 }
542 }
543 if (pp) {
544 tex_flush_token_list(pp);
545 }
546 lmt_input_state.scanner_status = save_scanner_status;
547 return result;
548}
549
550static halfword tex_aux_count_char(int once)
551{
552 halfword tok;
553 halfword qq = null;
554 halfword q;
555 halfword result = 0;
556 int save_scanner_status = lmt_input_state.scanner_status;
557 lmt_input_state.scanner_status = scanner_is_normal;
558 tok = tex_get_token();
559 q = tex_aux_grab_toks(0, 0, &qq);
560 if (q) {
561 int nesting = 0;
562 while (q) {
563 if (! nesting && token_info(q) == tok) {
564 result += 1;
565 if (once) {
566 break;
567 }
568 } else if (token_cmd(token_info(q)) == left_brace_cmd) {
569 nesting += 1;
570 } else if (token_cmd(token_info(q)) == right_brace_cmd) {
571 nesting -= 1;
572 }
573 q = token_link(q);
574 }
575 }
576 if (qq) {
577 tex_flush_token_list(qq);
578 }
579 lmt_input_state.scanner_status = save_scanner_status;
580 return result;
581}
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611typedef enum comparisons {
612
613 comparison_equal = 0,
614 comparison_less = 1,
615 comparison_greater = 2,
616 comparison_not_equal = 3,
617 comparison_not_less = 4,
618 comparison_not_greater = 5,
619 comparison_element = 6,
620 comparison_not_element = 7,
621} comparisons;
622
623typedef enum values {
624
625 value_less = 1,
626 value_equal = 2,
627 value_greater = 3,
628 value_error = 4,
629} values;
630
631typedef enum checks {
632
633 check_okay = 1,
634 check_error = 2,
635} checks;
636
637typedef enum parameterstates {
638 parameter_zero = 0,
639 parameter_set = 1,
640 parameter_unset = 2,
641} parameterstates;
642
643static inline halfword tex_aux_scan_comparison(int code)
644{
645 bool negate = false;
646 while (1) {
647 tex_get_x_token();
648 switch (cur_cmd) {
649 case letter_cmd:
650 case other_char_cmd:
651 switch (cur_chr) {
652
653 case '=' : return negate ? comparison_not_equal : comparison_equal;
654 case '<' : return negate ? comparison_not_less : comparison_less;
655 case '>' : return negate ? comparison_not_greater : comparison_greater;
656
657 case '&' : return negate ? comparison_not_element : comparison_element;
658
659 case '!' : negate = ! negate ; continue;
660
661 case 0x2208: return negate ? comparison_not_element : comparison_element;
662 case 0x2209: return negate ? comparison_element : comparison_not_element;
663 case 0x2260: return negate ? comparison_equal : comparison_not_equal;
664 case 0x2264: return negate ? comparison_greater : comparison_not_greater;
665 case 0x2265: return negate ? comparison_less : comparison_not_less;
666 case 0x2270: return negate ? comparison_greater : comparison_not_greater;
667 case 0x2271: return negate ? comparison_less : comparison_not_less;
668 }
669 case spacer_cmd:
670 continue;
671 default:
672 tex_aux_missing_equal_error(code);
673 return 0;
674 }
675 }
676}
677
678static inline void tex_aux_check_strict(int *result)
679{
680 tex_get_x_token();
681 switch (cur_cmd) {
682 case relax_cmd:
683 case spacer_cmd:
684 case if_test_cmd:
685 break;
686 default:
687 *result = check_error;
688 break;
689 }
690 tex_back_input(cur_tok);
691}
692
693void tex_conditional_if(halfword code, int unless)
694{
695
696 int result = 0;
697
698 halfword save_cond_ptr;
699
700 int tracing_ifs = tracing_ifs_par > 0;
701 int tracing_commands = tracing_commands_par;
702 int tracing_both = tracing_ifs && (tracing_commands <= 1);
703 if (tracing_both) {
704 tex_show_cmd_chr(cur_cmd, cur_chr);
705 }
706 tex_aux_push_condition_stack(code, unless);
707 save_cond_ptr = lmt_condition_state.cond_ptr;
708
709 HERE:
710
711 lmt_condition_state.if_step = code;
712 lmt_condition_state.if_unless = unless;
713 switch (code) {
714 case if_char_code:
715 case if_cat_code:
716
717 {
718 halfword n, m;
719 tex_aux_get_x_token_or_active_char();
720 if ((cur_cmd > active_char_cmd) || (cur_chr > max_character_code)) {
721
722 m = relax_cmd;
723 n = relax_code;
724 } else {
725 m = cur_cmd;
726 n = cur_chr;
727 }
728 tex_aux_get_x_token_or_active_char();
729 if ((cur_cmd > active_char_cmd) || (cur_chr > max_character_code)) {
730 cur_cmd = relax_cmd;
731 cur_chr = relax_code;
732 }
733 result = code == if_char_code ? (n == cur_chr) : (m == cur_cmd);
734 }
735 goto RESULT;
736 case if_int_code:
737 case if_abs_int_code:
738 {
739 halfword n1 = tex_scan_integer(0, NULL, NULL);
740 halfword cp = tex_aux_scan_comparison(code);
741 halfword n2 = tex_scan_integer(0, NULL, NULL);
742 if (code == if_abs_int_code) {
743 if (n1 < 0) {
744 n1 = -n1;
745 }
746 if (n2 < 0) {
747 n2 = -n2;
748 }
749 }
750 switch (cp) {
751 case comparison_equal : result = (n1 == n2); break;
752 case comparison_less : result = (n1 < n2); break;
753 case comparison_greater : result = (n1 > n2); break;
754 case comparison_not_equal : result = (n1 != n2); break;
755 case comparison_not_less : result = (n1 >= n2); break;
756 case comparison_not_greater: result = (n1 <= n2); break;
757 case comparison_element : result = (n1 & n2) == n1; break;
758 case comparison_not_element: result = (n1 & n2) != n1; break;
759 }
760 }
761 goto RESULT;
762 case if_zero_int_code:
763 result = tex_scan_integer(0, NULL, NULL) == 0;
764 goto RESULT;
765 case if_interval_int_code:
766 {
767 scaled n0 = tex_scan_integer(0, NULL, NULL);
768 scaled n1 = tex_scan_integer(0, NULL, NULL);
769 scaled n2 = tex_scan_integer(0, NULL, NULL);
770 result = n1 - n2;
771 result = result == 0 ? 1 : (result > 0 ? result <= n0 : -result <= n0);
772 }
773 goto RESULT;
774 case if_posit_code:
775 case if_abs_posit_code:
776 {
777 halfword n1 = tex_scan_posit(0);
778 halfword cp = tex_aux_scan_comparison(code);
779 halfword n2 = tex_scan_posit(0);
780 if (code == if_abs_posit_code) {
781 tex_posit zero = tex_integer_to_posit(0);
782 if (tex_posit_lt(n1,zero.v)) {
783 n1 = tex_posit_neg(n1);
784 }
785 if (tex_posit_lt(n2,zero.v)) {
786 n2 = tex_posit_neg(n2);
787 }
788 }
789 switch (cp) {
790 case comparison_equal : result = tex_posit_eq(n1,n2); break;
791 case comparison_less : result = tex_posit_lt(n1,n2); break;
792 case comparison_greater : result = tex_posit_gt(n1,n2); break;
793 case comparison_not_equal : result = tex_posit_ne(n1,n2); break;
794 case comparison_not_less : result = tex_posit_gt(n1,n2); break;
795 case comparison_not_greater: result = tex_posit_lt(n1,n2); break;
796 case comparison_element : result = tex_posit_eq(tex_integer_to_posit(tex_posit_to_integer(n1) & tex_posit_to_integer(n2)).v,n1); break;
797 case comparison_not_element: result = tex_posit_ne(tex_integer_to_posit(tex_posit_to_integer(n1) & tex_posit_to_integer(n2)).v,n1); break;
798 }
799 }
800 goto RESULT;
801 case if_zero_posit_code:
802 result = tex_posit_eq_zero(tex_scan_posit(0));
803 goto RESULT;
804 case if_interval_posit_code:
805 {
806 halfword n0 = tex_scan_posit(0);
807 halfword n1 = tex_scan_posit(0);
808 halfword n2 = tex_scan_posit(0);
809 result = tex_posit_sub(n1, n2);
810 result = tex_posit_eq_zero(result) ? 1 : (tex_posit_gt_zero(result) ? tex_posit_le(result, n0) : tex_posit_le(tex_posit_neg(result), n0));
811 }
812 goto RESULT;
813 case if_dim_code:
814 case if_abs_dim_code:
815 {
816 scaled n1 = tex_scan_dimension(0, 0, 0, 0, NULL, NULL);
817 halfword cp = tex_aux_scan_comparison(code);
818 scaled n2 = tex_scan_dimension(0, 0, 0, 0, NULL, NULL);
819 if (code == if_abs_dim_code) {
820 if (n1 < 0) {
821 n1 = -n1;
822 }
823 if (n2 < 0) {
824 n2 = -n2;
825 }
826 }
827 switch (cp) {
828 case comparison_equal : result = (n1 == n2); break;
829 case comparison_less : result = (n1 < n2); break;
830 case comparison_greater : result = (n1 > n2); break;
831 case comparison_not_equal : result = (n1 != n2); break;
832 case comparison_not_less : result = (n1 >= n2); break;
833 case comparison_not_greater: result = (n1 <= n2); break;
834 case comparison_element : result = (n1/65536 & n2/65536) == n1/65536; break;
835 case comparison_not_element: result = (n1/65536 & n2/65536) != n1/65536; break;
836 }
837 }
838 goto RESULT;
839 case if_zero_dim_code:
840 result = tex_scan_dimension(0, 0, 0, 0, NULL, NULL) == 0;
841 goto RESULT;
842 case if_interval_dim_code:
843 {
844 scaled n0 = tex_scan_dimension(0, 0, 0, 0, NULL, NULL);
845 scaled n1 = tex_scan_dimension(0, 0, 0, 0, NULL, NULL);
846 scaled n2 = tex_scan_dimension(0, 0, 0, 0, NULL, NULL);
847 result = n1 - n2;
848 result = result == 0 ? 1 : (result > 0 ? result <= n0 : -result <= n0);
849 }
850 goto RESULT;
851 case if_odd_code:
852 result = odd(tex_scan_integer(0, NULL, NULL));
853 goto RESULT;
854 case if_vmode_code:
855 result = is_v_mode(cur_list.mode);
856 goto RESULT;
857 case if_hmode_code:
858 result = is_h_mode(cur_list.mode);
859 goto RESULT;
860 case if_mmode_code:
861 result = is_m_mode(cur_list.mode);
862 goto RESULT;
863 case if_inner_code:
864 result = cur_list.mode < nomode;
865 goto RESULT;
866 case if_void_code:
867 {
868 halfword n = tex_scan_box_register_number();
869 result = box_register(n) == null;
870 }
871 goto RESULT;
872 case if_hbox_code:
873 {
874 halfword n = tex_scan_box_register_number();
875 halfword p = box_register(n);
876 result = p && (node_type(p) == hlist_node);
877 }
878 goto RESULT;
879 case if_vbox_code:
880 {
881 halfword n = tex_scan_box_register_number();
882 halfword p = box_register(n);
883 result = p && (node_type(p) == vlist_node);
884 }
885 goto RESULT;
886 case if_tok_code:
887 case if_cstok_code:
888 {
889 halfword pp = null;
890 halfword qq = null;
891 halfword p, q;
892 int expand = code == if_tok_code;
893 int save_scanner_status = lmt_input_state.scanner_status;
894 lmt_input_state.scanner_status = scanner_is_normal;
895 p = tex_aux_grab_toks(expand, 1, &pp);
896 q = tex_aux_grab_toks(expand, 1, &qq);
897 if (p == q) {
898
899 result = 1;
900 } else {
901 while (p && q) {
902 if (token_info(p) != token_info(q)) {
903
904
905 result = 0;
906 goto IFTOKDONE;
907 } else {
908 p = token_link(p);
909 q = token_link(q);
910 }
911 }
912 result = (! p) && (! q);
913 }
914 IFTOKDONE:
915 if (pp) {
916 tex_flush_token_list(pp);
917 }
918 if (qq) {
919 tex_flush_token_list(qq);
920 }
921 lmt_input_state.scanner_status = save_scanner_status;
922 }
923 goto RESULT;
924 case if_last_named_cs_code:
925 case if_x_code:
926 {
927
938
939 halfword p, q;
940 int save_scanner_status = lmt_input_state.scanner_status;
941 lmt_input_state.scanner_status = scanner_is_normal;
942 if (code == if_x_code) {
943 tex_get_next();
944
945 p = cur_cmd;
946 q = cur_chr;
947 } else {
948
949 p = eq_type(lmt_scanner_state.last_cs_name);
950 q = eq_value(lmt_scanner_state.last_cs_name);
951 }
952 tex_get_next();
953 if ((p == constant_call_cmd && cur_cmd == call_cmd) || (p == call_cmd && cur_cmd == constant_call_cmd)) {
954
955 goto SOMECALLCMD;
956 } else if (cur_cmd != p) {
957 result = 0;
958 } else if (cur_cmd < call_cmd) {
959 result = cur_chr == q;
960 } else {
961 SOMECALLCMD:
962
974 p = token_link(cur_chr);
975
976
977 q = token_link(q);
978 if (p == q) {
979 result = 1;
980
984 } else {
985 while (p && q) {
986 if (token_info(p) != token_info(q)) {
987
988
989 result = 0;
990 goto IFXDONE;
991 } else {
992 p = token_link(p);
993 q = token_link(q);
994 }
995 }
996 result = (! p) && (! q);
997 }
998 }
999 IFXDONE:
1000 lmt_input_state.scanner_status = save_scanner_status;
1001 }
1002 goto RESULT;
1003 case if_true_code:
1004 result = 1;
1005 goto RESULT;
1006 case if_false_code:
1007 result = 0;
1008 goto RESULT;
1009 case if_chk_int_code:
1010 {
1011 lmt_error_state.intercept = 1;
1012 lmt_error_state.last_intercept = 0;
1013 lmt_condition_state.chk_integer = 0;
1014 tex_scan_integer_validate();
1015 result = lmt_error_state.last_intercept ? check_error : check_okay;
1016 lmt_error_state.intercept = 0;
1017 lmt_error_state.last_intercept = 0;
1018
1019 goto CASECHECK;
1020 }
1021 case if_chk_integer_code:
1022 {
1023 lmt_error_state.intercept = 1;
1024 lmt_error_state.last_intercept = 0;
1025 lmt_condition_state.chk_integer = tex_scan_integer(0, NULL, NULL);
1026 result = lmt_error_state.last_intercept ? check_error : check_okay;
1027 if (result == check_okay) {
1028 tex_aux_check_strict(&result);
1029 }
1030 lmt_error_state.intercept = 0;
1031 lmt_error_state.last_intercept = 0;
1032
1033 goto CASECHECK;
1034 }
1035 case if_chk_intexpr_code:
1036 lmt_error_state.intercept = 1;
1037 lmt_error_state.last_intercept = 0;
1038 lmt_condition_state.chk_integer = tex_scan_expr(integer_val_level);
1039 result = lmt_error_state.last_intercept ? check_error : check_okay;
1040 if (result == check_okay) {
1041 tex_aux_check_strict(&result);
1042 }
1043 lmt_error_state.intercept = 0;
1044 lmt_error_state.last_intercept = 0;
1045 goto CASECHECK;
1046 case if_val_int_code:
1047 {
1048 lmt_error_state.intercept = 1;
1049 lmt_error_state.last_intercept = 0;
1050 lmt_condition_state.chk_integer = tex_scan_integer(0, NULL, NULL);
1051 result = lmt_error_state.last_intercept ? value_error : (lmt_condition_state.chk_integer < 0) ? value_less : (lmt_condition_state.chk_integer > 0) ? value_greater : value_equal;
1052 lmt_error_state.intercept = 0;
1053 lmt_error_state.last_intercept = 0;
1054 goto CASE;
1055 }
1056 case if_cmp_int_code:
1057 {
1058 halfword n1 = tex_scan_integer(0, NULL, NULL);
1059 halfword n2 = tex_scan_integer(0, NULL, NULL);
1060 result = (n1 < n2) ? 0 : (n1 > n2) ? 2 : 1;
1061 goto CASE;
1062 }
1063 case if_chk_dim_code:
1064 {
1065 lmt_error_state.intercept = 1;
1066 lmt_error_state.last_intercept = 0;
1067 lmt_condition_state.chk_dimension = 0;
1068 tex_scan_dimension_validate();
1069 result = lmt_error_state.last_intercept ? check_error : check_okay;
1070 lmt_error_state.intercept = 0;
1071 lmt_error_state.last_intercept = 0;
1072
1073 goto CASECHECK;
1074 }
1075 case if_chk_dimension_code:
1076 {
1077 lmt_error_state.intercept = 1;
1078 lmt_error_state.last_intercept = 0;
1079 lmt_condition_state.chk_dimension = tex_scan_dimension(0, 0, 0, 0, NULL, NULL);
1080 result = lmt_error_state.last_intercept ? check_error : check_okay;
1081 if (result == check_okay) {
1082 tex_aux_check_strict(&result);
1083 }
1084 lmt_error_state.intercept = 0;
1085 lmt_error_state.last_intercept = 0;
1086
1087 goto CASECHECK;
1088 }
1089 case if_chk_dimexpr_code:
1090 lmt_error_state.intercept = 1;
1091 lmt_error_state.last_intercept = 0;
1092 lmt_condition_state.chk_dimension = tex_scan_expr(dimension_val_level);
1093 result = lmt_error_state.last_intercept ? check_error : check_okay;
1094 if (result == check_okay) {
1095 tex_aux_check_strict(&result);
1096 }
1097 lmt_error_state.intercept = 0;
1098 lmt_error_state.last_intercept = 0;
1099 goto CASECHECK;
1100 case if_val_dim_code:
1101 {
1102 lmt_error_state.intercept = 1;
1103 lmt_error_state.last_intercept = 0;
1104 lmt_condition_state.chk_dimension = tex_scan_dimension(0, 0, 0, 0, NULL, NULL);
1105 result = lmt_error_state.last_intercept ? value_error : (lmt_condition_state.chk_dimension < 0) ? value_less : (lmt_condition_state.chk_dimension > 0) ? value_greater : value_equal;
1106 lmt_error_state.intercept = 0;
1107 lmt_error_state.last_intercept = 0;
1108 goto CASE;
1109 }
1110 case if_cmp_dim_code:
1111 {
1112 scaled n1 = tex_scan_dimension(0, 0, 0, 0, NULL, NULL);
1113 scaled n2 = tex_scan_dimension(0, 0, 0, 0, NULL, NULL);
1114 result = (n1 < n2) ? 0 : (n1 > n2) ? 2 : 1;
1115 goto CASE;
1116 }
1117 case if_case_code:
1118
1123 result = tex_scan_integer(0, NULL, NULL);
1124 goto CASE;
1125 case if_defined_code:
1126
1131 {
1132 int save_scanner_status = lmt_input_state.scanner_status;
1133 lmt_input_state.scanner_status = scanner_is_normal;
1134 tex_get_next();
1135 result = cur_cmd != undefined_cs_cmd;
1136 lmt_input_state.scanner_status = save_scanner_status;
1137 goto RESULT;
1138 }
1139 case if_csname_code:
1140 result = tex_is_valid_csname();
1141 goto RESULT;
1142 case if_in_csname_code:
1143
1144 result = lmt_expand_state.cs_name_level;
1145 goto RESULT;
1146 case if_font_char_code:
1147
1148 {
1149 halfword fnt = tex_scan_font_identifier(NULL);
1150 halfword chr = tex_scan_char_number(0);
1151 result = tex_char_exists(fnt, chr);
1152 }
1153 goto RESULT;
1154 case if_condition_code:
1155
1156 goto RESULT;
1157 case if_flags_code:
1158 {
1159 halfword cs;
1160 singleword flag;
1161 tex_get_r_token();
1162 cs = cur_cs;
1163 flag = eq_flag(cs);
1164
1165 tex_get_token();
1166 if (cur_cmd == prefix_cmd) {
1167
1168 switch (cur_chr) {
1169
1170 case frozen_code : result = is_frozen (flag); break;
1171 case permanent_code : result = is_permanent(flag); break;
1172 case immutable_code : result = is_immutable(flag); break;
1173
1174 case mutable_code : result = is_mutable (flag); break;
1175 case noaligned_code : result = is_noaligned(flag); break;
1176 case instance_code : result = is_instance (flag); break;
1177 case untraced_code : result = is_untraced (flag); break;
1178
1179 case global_code : result = eq_level(cs) == level_one; break;
1180 case tolerant_code : result = is_tolerant_cmd(eq_type(cs)); break;
1181 case protected_code : result = is_protected_cmd(eq_type(cs)); break;
1182
1183
1184
1185
1186
1187
1188 case semiprotected_code : result = is_semi_protected_cmd(eq_type(cs)); break;
1189
1190
1191
1192 case constant_code : result = is_constant_cmd(eq_type(cs)); break;
1193
1194
1195 }
1196 } else {
1197 int fl;
1198 tex_back_input(cur_tok);
1199 fl = tex_scan_integer(1, NULL, NULL);
1200 result = (flag & fl) == fl;
1201 if (! result) {
1202 if (is_protected(fl)) {
1203 result = is_protected_cmd(eq_type(cs));
1204 } else if (is_semiprotected(fl)) {
1205 result = is_semi_protected_cmd(eq_type(cs));
1206 } else if (is_tolerant(fl)) {
1207 result = is_tolerant_cmd(eq_type(cs));
1208 } else if (is_global(fl)) {
1209 result = eq_level(cs) == level_one;
1210 }
1211 }
1212 }
1213 goto RESULT;
1214 }
1215 case if_empty_code:
1216 {
1217 tex_get_token();
1218 EMPTY_CHECK_AGAIN:
1219 switch (cur_cmd) {
1220 case call_cmd:
1221 case constant_call_cmd:
1222 result = ! token_link(cur_chr);
1223 break;
1224 case internal_toks_reference_cmd:
1225 case register_toks_reference_cmd:
1226 result = ! token_link(cur_chr);
1227 break;
1228 case register_cmd:
1229
1230 if (cur_chr == token_val_level) {
1231 halfword n = tex_scan_toks_register_number();
1232 halfword p = eq_value(register_toks_location(n));
1233 result = ! p || ! token_link(p);
1234 } else {
1235 result = 0;
1236 }
1237 break;
1238 case internal_toks_cmd:
1239 case register_toks_cmd:
1240 {
1241 halfword p = eq_value(cur_chr);
1242 result = ! p || ! token_link(p);
1243 }
1244 break;
1245 case left_brace_cmd:
1246 {
1247 halfword h = tex_scan_toks_expand(1, NULL, 0, 0);
1248 result = token_link(h) == null;
1249 tex_flush_token_list(h);
1250 }
1251 break;
1252 case cs_name_cmd:
1253 if (cur_chr == last_named_cs_code && lmt_scanner_state.last_cs_name != null_cs) {
1254 cur_cmd = eq_type(lmt_scanner_state.last_cs_name);
1255 cur_chr = eq_value(lmt_scanner_state.last_cs_name);
1256 goto EMPTY_CHECK_AGAIN;
1257 }
1258
1259 default:
1260 result = 0;
1261 }
1262 goto RESULT;
1263 }
1264 case if_relax_code:
1265 {
1266 tex_get_token();
1267 result = cur_cmd == relax_cmd;
1268 goto RESULT;
1269 }
1270 case if_boolean_code:
1271 result = tex_scan_integer(0, NULL, NULL) ? 1 : 0;
1272 goto RESULT;
1273 case if_numexpression_code:
1274 result = tex_scanned_expression(integer_val_level) ? 1 : 0;
1275 goto RESULT;
1276 case if_dimexpression_code:
1277 result = tex_scanned_expression(dimension_val_level) ? 1 : 0;
1278 goto RESULT;
1279 case if_math_parameter_code:
1280
1284 {
1285 do {
1286 tex_get_x_token();
1287 } while (cur_cmd == spacer_cmd);
1288 if (cur_cmd == math_parameter_cmd) {
1289 int code = cur_chr;
1290 int style = tex_scan_math_style_identifier(0, 0);
1291 result = tex_get_math_parameter(style, code, NULL);
1292 if (result == max_dimension) {
1293 result = parameter_unset;
1294 } else if (result) {
1295 result = parameter_set;
1296 } else {
1297 result = parameter_zero;
1298 }
1299 } else {
1300 tex_normal_error("mathparameter", "a valid parameter expected");
1301 result = parameter_zero;
1302 }
1303 goto CASE;
1304 }
1305 case if_math_style_code:
1306 result = tex_current_math_style();
1307 goto CASE;
1308 case if_arguments_code:
1309 result = lmt_expand_state.arguments;
1310 goto CASE;
1311 case if_parameters_code:
1312
1316 result = tex_get_parameter_count();
1317 goto CASE;
1318 case if_parameter_code:
1319 {
1320
1325 if (lmt_input_state.cur_input.loc) {
1326 halfword t = token_info(lmt_input_state.cur_input.loc);
1327 if (t < cs_token_flag && token_cmd(t) == parameter_reference_cmd) {
1328 lmt_input_state.cur_input.loc = token_link(lmt_input_state.cur_input.loc);
1329 result = lmt_input_state.parameter_stack[lmt_input_state.cur_input.parameter_start + token_chr(t) - 1] != null ? 1 : 2;
1330 } else {
1331
1335 tex_get_token();
1336 switch (cur_cmd) {
1337 case if_test_cmd:
1338 result = 2;
1339 break;
1340 case index_cmd:
1341 if (cur_chr >= 0 && cur_chr < lmt_input_state.parameter_stack_data.ptr) {
1342 result = lmt_input_state.parameter_stack[cur_chr] != null ? 1 : 2;
1343 }
1344 break;
1345 default:
1346 result = 1;
1347 break;
1348 }
1349 }
1350
1351
1352
1353
1354
1355 goto CASECHECK;
1356 } else {
1357 goto CASE;
1358 }
1359 }
1360 case if_has_tok_code:
1361 result = tex_aux_count_tok(1);
1362 goto RESULT;
1363 case if_has_toks_code:
1364 case if_has_xtoks_code:
1365 result = tex_aux_count_toks(1, code == if_has_xtoks_code);
1366 goto RESULT;
1367 case if_has_char_code:
1368 result = tex_aux_count_char(1);
1369 goto RESULT;
1370 case if_insert_code:
1371
1372 result = ! tex_insert_is_void(tex_scan_integer(0, NULL, NULL));
1373 goto RESULT;
1374 case if_in_alignment_code:
1375 result = tex_in_alignment();
1376 goto RESULT;
1377 case if_cramped_code:
1378 result = tex_is_cramped_style(tex_scan_math_style_identifier(0, 0));
1379 goto RESULT;
1380 case if_list_code:
1381 {
1382 halfword n = tex_scan_box_register_number();
1383 result = box_register(n) != null && box_list(box_register(n)) != null;
1384 }
1385 goto RESULT;
1386
1387
1388
1389
1390
1391
1392
1393 default:
1394 {
1395 int category;
1396 strnumber u = tex_save_cur_string();
1397 int save_scanner_status = lmt_input_state.scanner_status;
1398 lmt_input_state.scanner_status = scanner_is_normal;
1399 lmt_token_state.luacstrings = 0;
1400 category = lmt_function_call_by_category(code - last_if_test_code, 0, &result);
1401 tex_restore_cur_string(u);
1402 lmt_input_state.scanner_status = save_scanner_status;
1403 if (lmt_token_state.luacstrings > 0) {
1404 tex_lua_string_start();
1405 }
1406 switch (category) {
1407 case lua_value_integer_code:
1408 case lua_value_cardinal_code:
1409 case lua_value_dimension_code:
1410
1411 goto CASE;
1412 case lua_value_boolean_code:
1413 goto RESULT;
1414 case lua_value_conditional_code:
1415
1416 tex_back_input(token_val(if_test_cmd, if_condition_code));
1417 tex_aux_pop_condition_stack();
1418 return;
1419 default:
1420 result = 0;
1421 goto RESULT;
1422 }
1423 }
1424 }
1425 CASECHECK:
1426 if (unless) {
1427 result = result == check_okay ? check_error : check_okay;
1428 goto CASEWITHUNLESS;
1429 } else {
1430 goto CASE;
1431 }
1432 CASE:
1433
1437 if (unless) {
1438
1439 halfword online = tracing_online_par;
1440 tracing_online_par = 1;
1441 tex_begin_diagnostic();
1442 tex_print_format( "ignoring \\unless in %C test", if_test_cmd, code);
1443 tex_end_diagnostic();
1444 tracing_online_par = online;
1445 }
1446 CASEWITHUNLESS:
1447 if (tracing_commands > 1) {
1448 tex_aux_show_if_state(code, result);
1449 }
1450 while (result) {
1451 unless = tex_aux_pass_text_x(tracing_ifs, tracing_commands);
1452 if (tracing_both) {
1453 tex_show_cmd_chr(cur_cmd, cur_chr);
1454 }
1455 if (lmt_condition_state.cond_ptr == save_cond_ptr) {
1456 if (cur_chr >= first_real_if_test_code) {
1457
1462 if (cur_chr == if_condition_code) {
1463
1464 tex_aux_pop_condition_stack();
1465 return;
1466 } else {
1467 code = cur_chr;
1468 goto HERE;
1469 }
1470 } else if (cur_chr == or_code) {
1471 --result;
1472 } else {
1473 goto COMMON_ENDING;
1474 }
1475 } else if (cur_chr == fi_code) {
1476 tex_aux_pop_condition_stack();
1477 }
1478 }
1479 tex_aux_change_if_limit(or_code, save_cond_ptr);
1480
1481 return;
1482 RESULT:
1483 if (unless) {
1484 result = ! result;
1485 }
1486 if (tracing_commands > 1) {
1487
1488 tex_begin_diagnostic();
1489 tex_print_str(result ? "{true}" : "{false}");
1490 tex_end_diagnostic();
1491 }
1492 if (result) {
1493 tex_aux_change_if_limit(else_code, save_cond_ptr);
1494
1495 return;
1496 } else {
1497
1502 while (1) {
1503 unless = tex_aux_pass_text_x(tracing_ifs, tracing_commands);
1504 if (tracing_both) {
1505 tex_show_cmd_chr(cur_cmd, cur_chr);
1506 }
1507 if (lmt_condition_state.cond_ptr == save_cond_ptr) {
1508
1509 if (cur_chr >= first_real_if_test_code) {
1510 if (cur_chr == if_condition_code) {
1511
1512 tex_aux_pop_condition_stack();
1513 return;
1514 } else {
1515 code = cur_chr;
1516 goto HERE;
1517 }
1518 } else if (cur_chr != or_code) {
1519 goto COMMON_ENDING;
1520 } else {
1521 tex_handle_error(
1522 normal_error_type,
1523 "Extra \\or",
1524 "I'm ignoring this; it doesn't match any \\if."
1525 );
1526 }
1527 } else if (cur_chr == fi_code) {
1528 tex_aux_pop_condition_stack();
1529 }
1530 }
1531 }
1532 COMMON_ENDING:
1533 if (cur_chr == fi_code) {
1534 tex_aux_pop_condition_stack();
1535 } else {
1536
1537
1538 lmt_condition_state.if_limit = fi_code;
1539 }
1540}
1541
1542
1547
1548void tex_conditional_fi_or_else(void)
1549{
1550 int tracing_ifs = tracing_ifs_par > 0;
1551 if (tracing_ifs && tracing_commands_par <= 1) {
1552 tex_show_cmd_chr(if_test_cmd, cur_chr);
1553 }
1554 if (cur_chr == or_else_code || cur_chr == or_unless_code) {
1555 tex_get_next_non_spacer();
1556 } else if (cur_chr > lmt_condition_state.if_limit) {
1557 if (lmt_condition_state.if_limit == if_code) {
1558
1559 tex_insert_relax_and_cur_cs();
1560 } else {
1561 tex_handle_error(normal_error_type,
1562 "Extra %C",
1563 if_test_cmd, cur_chr,
1564 "I'm ignoring this; it doesn't match any \\if."
1565 );
1566 }
1567
1568 return;
1569 }
1570
1571 while (! (cur_cmd == if_test_cmd && cur_chr == fi_code)) {
1572 tex_aux_pass_text();
1573 if (tracing_ifs) {
1574 tex_show_cmd_chr(cur_cmd, cur_chr);
1575 }
1576 }
1577 tex_aux_pop_condition_stack();
1578}
1579
1580
1587
1588void tex_conditional_unless(void)
1589{
1590 tex_get_token();
1591 if (cur_cmd == if_test_cmd) {
1592 if (tracing_commands_par > 1) {
1593 tex_show_cmd_chr(cur_cmd, cur_chr);
1594 }
1595 if (cur_chr != if_condition_code) {;
1596 tex_conditional_if(cur_chr, 1);
1597 }
1598 } else {
1599 tex_handle_error(back_error_type,
1600 "You can't use '\\unless' before '%C'",
1601 cur_cmd, cur_chr,
1602 "Continue, and I'll forget that it ever happened."
1603 );
1604 }
1605}
1606
1607void tex_show_ifs(void)
1608{
1609 if (lmt_condition_state.cond_ptr) {
1610
1611 int n = 0;
1612 {
1613
1614 halfword p = lmt_condition_state.cond_ptr;
1615 do {
1616 ++n;
1617 p = node_next(p);
1618 } while (p);
1619 }
1620
1621 {
1622 halfword cond_ptr = lmt_condition_state.cond_ptr;
1623 int cur_if = lmt_condition_state.cur_if;
1624 int cur_unless = lmt_condition_state.cur_unless;
1625 int if_step = lmt_condition_state.if_step;
1626 int if_unless = lmt_condition_state.if_unless;
1627 int if_line = lmt_condition_state.if_line;
1628 int if_limit = lmt_condition_state.if_limit;
1629 do {
1630 if (cur_unless) {
1631 if (if_line) {
1632 tex_print_format("[conditional: level %i, current %C %C, limit %C, %sstep %C, line %i]",
1633 n,
1634 expand_after_cmd, expand_unless_code,
1635 if_test_cmd, cur_if,
1636 if_test_cmd, if_limit,
1637 if_unless ? "unless " : "",
1638 if_test_cmd, if_step,
1639 if_line
1640 );
1641 } else {
1642 tex_print_format("[conditional: level %i, current %C %C, limit %C, %sstep %C]",
1643 n,
1644 expand_after_cmd, expand_unless_code,
1645 if_test_cmd, cur_if,
1646 if_test_cmd, if_limit,
1647 if_unless ? "unless " : "",
1648 if_test_cmd, if_step
1649 );
1650 }
1651 } else {
1652 if (if_line) {
1653 tex_print_format("[conditional: level %i, current %C, limit %C, %sstep %C, line %i]",
1654 n,
1655 if_test_cmd, cur_if,
1656 if_test_cmd, if_limit,
1657 if_unless ? "unless " : "",
1658 if_test_cmd, if_step,
1659 if_line
1660 );
1661 } else {
1662 tex_print_format("[conditional: level %i, current %C, limit %C, %sstep %C]",
1663 n,
1664 if_test_cmd, cur_if,
1665 if_test_cmd, if_limit,
1666 if_unless ? "unless " : "",
1667 if_test_cmd, if_step
1668 );
1669 }
1670 }
1671 --n;
1672 cur_if = if_limit_subtype(cond_ptr);
1673 cur_unless = if_limit_unless(cond_ptr);;
1674 if_step = if_limit_step(cond_ptr);;
1675 if_unless = if_limit_stepunless(cond_ptr);;
1676 if_line = if_limit_line(cond_ptr);;
1677 if_limit = if_limit_type(cond_ptr);;
1678 cond_ptr = node_next(cond_ptr);
1679 if (cond_ptr) {
1680 tex_print_levels();
1681 }
1682 } while (cond_ptr);
1683 }
1684 } else {
1685 tex_print_str("[conditional: none active]");
1686 }
1687}
1688
1689void tex_conditional_catch_up(void)
1690{
1691 condition_state_info saved_condition_state = lmt_condition_state;
1692 while (lmt_input_state.in_stack[lmt_input_state.in_stack_data.ptr].if_ptr != lmt_condition_state.cond_ptr) {
1693
1694 tex_print_nlp();
1695 tex_print_format("Warning: end of file when %C", if_test_cmd, lmt_condition_state.cur_if);
1696 if (lmt_condition_state.if_limit == fi_code) {
1697 tex_print_str_esc("else");
1698 }
1699 if (lmt_condition_state.if_line) {
1700 tex_print_format(" entered on line %i", lmt_condition_state.if_line);
1701 }
1702 tex_print_str(" is incomplete");
1703 lmt_condition_state.cur_if = if_limit_subtype(lmt_condition_state.cond_ptr);
1704 lmt_condition_state.cur_unless = if_limit_unless(lmt_condition_state.cond_ptr);
1705 lmt_condition_state.if_step = if_limit_step(lmt_condition_state.cond_ptr);
1706 lmt_condition_state.if_unless = if_limit_stepunless(lmt_condition_state.cond_ptr);
1707 lmt_condition_state.if_limit = if_limit_type(lmt_condition_state.cond_ptr);
1708 lmt_condition_state.if_line = if_limit_line(lmt_condition_state.cond_ptr);
1709 lmt_condition_state.cond_ptr = node_next(lmt_condition_state.cond_ptr);
1710 }
1711 lmt_condition_state = saved_condition_state;
1712}
1713
1714
1719
1720
1738 |