1
4
5# include "luametatex.h"
6
7
79
80save_state_info lmt_save_state = {
81 .save_stack = NULL,
82 .save_stack_data = {
83 .minimum = min_save_size,
84 .maximum = max_save_size,
85 .size = siz_save_size,
86 .step = stp_save_size,
87 .allocated = 0,
88 .itemsize = sizeof(save_record),
89 .top = 0,
90 .ptr = 0,
91 .initial = memory_data_unset,
92 .offset = 0,
93 .extra = 0,
94 },
95 .current_level = 0,
96 .current_group = 0,
97 .current_boundary = 0,
98
99};
100
101
108
109static void tex_aux_show_eqtb(halfword n);
110
111static void tex_aux_diagnostic_trace(halfword p, const char *s)
112{
113 tex_begin_diagnostic();
114 tex_print_format("{%s ", s);
115 tex_aux_show_eqtb(p);
116 tex_print_char('}');
117 tex_end_diagnostic();
118}
119
120
178
179
180
181
182void tex_initialize_levels(void)
183{
184 cur_level = level_one;
185 cur_group = bottom_level_group;
186 cur_boundary = 0;
187 lmt_scanner_state.last_cs_name = null_cs;
188}
189
190void tex_initialize_undefined_cs(void)
191{
192 set_eq_type(undefined_control_sequence, undefined_cs_cmd);
193 set_eq_flag(undefined_control_sequence, 0);
194 set_eq_value(undefined_control_sequence, null);
195 set_eq_level(undefined_control_sequence, level_zero);
196}
197
198
208
209# define pack_them 1
210
211static void tex_dump_equivalents_mem_hash(dumpstream f)
212{
213 int index = null_cs;
214 int n_of_undefined = 0;
215 int n_of_defined = 0;
216 do {
217 unsigned char undefined = 0;
218 unsigned char defined = 0;
219# if (pack_them)
220 while (index < first_register_base && undefined < 0xE) {
221# else
222 while (index < first_register_base && undefined < 0xFE) {
223# endif
224 if (equal_eqtb_entries(index, undefined_control_sequence)) {
225 ++undefined;
226 ++index;
227 } else {
228 break;
229 }
230 }
231# if (pack_them)
232 while (index < first_register_base && defined < 0xF) {
233# else
234 while (index < first_register_base && defined < 0xFE) {
235# endif
236 if (! equal_eqtb_entries(index, undefined_control_sequence)) {
237 ++defined;
238 ++index;
239 } else {
240 break;
241 }
242 }
243# if (pack_them)
244 dump_via_uchar(f, (undefined << 4) + defined);
245# else
246 dump_uchar(f, undefined);
247 dump_uchar(f, defined);
248# endif
249 if (defined) {
250 dump_things(f, lmt_hash_state.eqtb[index-defined], defined);
251 }
252 n_of_defined += defined;
253 n_of_undefined += undefined;
254 } while (index < first_register_base);
255# if (pack_them)
256 dump_via_uchar(f, 0xFF);
257# else
258 dump_via_uchar(f, 0xFF);
259 dump_via_uchar(f, 0xFF);
260# endif
261 dump_int(f, n_of_undefined);
262 dump_int(f, n_of_defined);
263}
264
265static void tex_dump_equivalents_mem_registers(dumpstream f)
266{
267 int index = first_register_base;
268 int n_of_different = 0;
269 int n_of_equivalent = 0;
270 do {
271 unsigned char different = 1;
272 unsigned short equivalent = 0;
273 int j = index;
274 while (j < (eqtb_size - 1) && different < 0xFF) {
275 if (equal_eqtb_entries(j, j + 1)) {
276 ++equivalent;
277 goto FOUND1;
278 } else {
279 ++different;
280 }
281 ++j;
282 }
283 goto DONE1;
284 FOUND1:
285 j++;
286 while (j < (eqtb_size - 1) && equivalent < 0xFFFF) {
287 if (equal_eqtb_entries(j, j + 1)) {
288 ++equivalent;
289 } else {
290 goto DONE1;
291 }
292 ++j;
293 }
294 DONE1:
295 dump_uchar(f, different);
296 dump_ushort(f, equivalent);
297 if (different) {
298 dump_things(f, lmt_hash_state.eqtb[index], different);
299 }
300 index = index + different + equivalent;
301 n_of_different += different;
302 n_of_equivalent += equivalent;
303 } while (index <= eqtb_size);
304 dump_int(f, n_of_different);
305 dump_int(f, n_of_equivalent);
306}
307
308static void tex_dump_equivalents_mem_extra(dumpstream f)
309{
310 dump_int(f, lmt_hash_state.hash_data.ptr);
311 if (lmt_hash_state.hash_data.ptr > 0) {
312
313 dump_things(f, lmt_hash_state.eqtb[eqtb_size + 1], lmt_hash_state.hash_data.ptr);
314 }
315}
316
317static void tex_dump_equivalents_mem_specials(dumpstream f)
318{
319 dump_int(f, lmt_token_state.par_loc);
320
321 dump_int(f, lmt_token_state.empty);
322}
323
324void tex_dump_equivalents_mem(dumpstream f)
325{
326 tex_dump_equivalents_mem_hash(f);
327 tex_dump_equivalents_mem_registers(f);
328 tex_dump_equivalents_mem_extra(f);
329 tex_dump_equivalents_mem_specials(f);
330}
331
332static void tex_undump_equivalents_mem_hash(dumpstream f)
333{
334 int index = null_cs;
335 memoryword undef = lmt_hash_state.eqtb[undefined_control_sequence];
336 int n_of_undefined = 0;
337 int n_of_defined = 0;
338 while (1) {
339 unsigned char undefined = 0;
340 unsigned char defined = 0;
341# if (pack_them)
342 undump_uchar(f, defined);
343 if (defined == 0xFF) {
344# else
345 undump_uchar(f, undefined);
346 undump_uchar(f, defined);
347 if (undefined == 0xFF && defined == 0xFF) {
348# endif
349 break;
350 } else {
351# if (pack_them)
352 undefined = (defined >> 4) & 0xF;
353 defined = defined & 0xF;
354# endif
355 if (undefined) {
356 for (int i = 1; i <= undefined; i++) {
357 lmt_hash_state.eqtb[index++] = undef;
358 }
359 }
360 if (defined) {
361 undump_things(f, lmt_hash_state.eqtb[index], defined);
362 index += defined;
363 }
364 n_of_defined += defined;
365 n_of_undefined += undefined;
366 }
367 }
368 {
369 int u, d;
370 undump_int(f, u);
371 undump_int(f, d);
372 if (u != n_of_undefined || d != n_of_defined) {
373 tex_fatal_undump_error("eqtb count mismatch");
374 }
375 }
376}
377
378static void tex_undump_equivalents_mem_registers(dumpstream f)
379{
380 int index = first_register_base;
381 int n_of_different = 0;
382 int n_of_equivalent = 0;
383 do {
384 unsigned char different;
385 unsigned short equivalent;
386 undump_uchar(f, different);
387 undump_ushort(f, equivalent);
388 if (different) {
389 undump_things(f, lmt_hash_state.eqtb[index], different);
390 }
391 if (equivalent > 0) {
392 int last = index + different - 1;
393 for (int i = 1; i <= equivalent; i++) {
394 lmt_hash_state.eqtb[last + i] = lmt_hash_state.eqtb[last];
395 }
396 }
397 index = index + different + equivalent;
398 n_of_different += different;
399 n_of_equivalent += equivalent;
400 } while (index <= eqtb_size);
401 {
402 int d, e;
403 undump_int(f, d);
404 undump_int(f, e);
405 if (d != n_of_different || e != n_of_equivalent) {
406 tex_fatal_undump_error("eqtb register mismatch");
407 }
408 }
409}
410
411static void tex_undump_equivalents_mem_extra(dumpstream f)
412{
413 undump_int(f, lmt_hash_state.hash_data.ptr);
414 if (lmt_hash_state.hash_data.ptr > 0) {
415
416 undump_things(f, lmt_hash_state.eqtb[eqtb_size + 1], lmt_hash_state.hash_data.ptr);
417 }
418}
419
420static void tex_undump_equivalents_mem_specials(dumpstream f)
421{
422 undump_int(f, lmt_token_state.par_loc);
423 if (lmt_token_state.par_loc >= hash_base && lmt_token_state.par_loc <= lmt_hash_state.hash_data.top) {
424 lmt_token_state.par_token = cs_token_flag + lmt_token_state.par_loc;
425 } else {
426 tex_fatal_undump_error("parloc");
427 }
428
429
430
431
432
433
434 undump_int(f, lmt_token_state.empty);
435}
436
437void tex_undump_equivalents_mem(dumpstream f)
438{
439 tex_undump_equivalents_mem_hash(f);
440 tex_undump_equivalents_mem_registers(f);
441 tex_undump_equivalents_mem_extra(f);
442 tex_undump_equivalents_mem_specials(f);
443}
444
445
460
461# define reserved_save_stack_slots 32
462
463void tex_initialize_save_stack(void)
464{
465 int size = lmt_save_state.save_stack_data.minimum;
466 lmt_save_state.save_stack = aux_allocate_clear_array(sizeof(save_record), lmt_save_state.save_stack_data.step, reserved_save_stack_slots);
467 if (lmt_save_state.save_stack) {
468 lmt_save_state.save_stack_data.allocated = lmt_save_state.save_stack_data.step;
469 } else {
470 tex_overflow_error("save", size);
471 }
472}
473
474static int tex_room_on_save_stack(void)
475{
476 int top = lmt_save_state.save_stack_data.ptr;
477 if (top > lmt_save_state.save_stack_data.top) {
478 lmt_save_state.save_stack_data.top = top;
479 if (top > lmt_save_state.save_stack_data.allocated) {
480 save_record *tmp = NULL;
481 top = lmt_save_state.save_stack_data.allocated + lmt_save_state.save_stack_data.step;
482 if (top > lmt_save_state.save_stack_data.size) {
483 top = lmt_save_state.save_stack_data.size;
484 }
485 if (top > lmt_save_state.save_stack_data.allocated) {
486 top = lmt_save_state.save_stack_data.allocated + lmt_save_state.save_stack_data.step;
487 tmp = aux_reallocate_array(lmt_save_state.save_stack, sizeof(save_record), top, reserved_save_stack_slots);
488 lmt_save_state.save_stack = tmp;
489 }
490 lmt_run_memory_callback("save", tmp ? 1 : 0);
491 if (! tmp) {
492 tex_overflow_error("save", top);
493 return 0;
494 }
495
496 lmt_save_state.save_stack_data.allocated = top;
497 }
498 }
499 return 1;
500}
501
502void tex_save_halfword_on_stack(quarterword t, halfword v)
503{
504 if (tex_room_on_save_stack()) {
505 saved_type(0) = t;
506 saved_record(0) = 0;
507 saved_value_1(0) = v;
508 ++lmt_save_state.save_stack_data.ptr;
509 }
510}
511
512
527
528static void tex_aux_group_trace(int g)
529{
530 tex_begin_diagnostic();
531 tex_print_format(g ? "{leaving %G}" : "{entering %G}", g);
532 tex_end_diagnostic();
533}
534
535
567
568static void tex_aux_group_warning(void)
569{
570
571 bool warning = false;
572
573 int index = lmt_input_state.in_stack_data.ptr;
574 lmt_input_state.base_ptr = lmt_input_state.input_stack_data.ptr;
575
576 lmt_input_state.input_stack[lmt_input_state.base_ptr] = lmt_input_state.cur_input;
577 while ((lmt_input_state.in_stack[index].group == cur_boundary) && (index > 0)) {
578
584 if (tracing_nesting_par > 0) {
585 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)) {
586 --lmt_input_state.base_ptr;
587 }
588 if (lmt_input_state.input_stack[lmt_input_state.base_ptr].name > 17) {
589
590 warning = true;
591 }
592 }
593 lmt_input_state.in_stack[index].group = save_value(lmt_save_state.save_stack_data.ptr);
594 --index;
595 }
596 if (warning) {
597 tex_begin_diagnostic();
598 tex_print_format("[warning: end of %G of a different file]", 1);
599 tex_end_diagnostic();
600 if (tracing_nesting_par > 1) {
601 tex_show_context();
602 }
603 if (lmt_error_state.history == spotless) {
604 lmt_error_state.history = warning_issued;
605 }
606 }
607}
608
609
616
617typedef enum saved_group_entries {
618 saved_group_group_entry = 0,
619 saved_group_boundary_entry = 0,
620 saved_group_attribute_state_entry = 0,
621 saved_group_input_line_entry = 0,
622 saved_group_n_records = 1,
623} saved_group_entries;
624
625# define saved_group_group saved_group(saved_group_group_entry)
626# define saved_group_boundary saved_value_1(saved_group_boundary_entry)
627# define saved_group_attribute_state saved_value_2(saved_group_attribute_state_entry)
628# define saved_group_input_line saved_value_3(saved_group_input_line_entry)
629
630static inline void saved_group_initialize(void)
631{
632 saved_type(0) = level_boundary_save_type;
633
634}
635
636void tex_new_save_level(quarterword group)
637{
638
639 if (tex_room_on_save_stack()) {
640 add_attribute_reference(current_attribute_state);
641 saved_group_initialize();
642 saved_group_group = cur_group;
643 saved_group_boundary = cur_boundary;
644 saved_group_attribute_state = current_attribute_state;
645 saved_group_input_line = lmt_input_state.input_line;
646 if (cur_level == max_quarterword) {
647
648 tex_overflow_error("grouping levels", max_quarterword - min_quarterword);
649 }
650 cur_boundary = lmt_save_state.save_stack_data.ptr;
651 cur_group = group;
652 if (tracing_groups_par > 0) {
653 tex_aux_group_trace(0);
654 }
655 ++cur_level;
656 lmt_save_state.save_stack_data.ptr += saved_group_n_records;
657 if (end_of_group_par) {
658 update_tex_end_of_group(null);
659 }
660 }
661}
662
663int tex_saved_line_at_level(void)
664{
665 return lmt_save_state.save_stack_data.ptr > 0 ? (saved_group_input_line > 0 ? saved_group_input_line : 0) : 0;
666}
667
668
683
684void tex_show_save_groups(void)
685{
686 int pointer = lmt_nest_state.nest_data.ptr;
687 int saved_pointer = lmt_save_state.save_stack_data.ptr;
688 quarterword saved_level = cur_level;
689 quarterword saved_group = cur_group;
690 halfword saved_tracing = tracing_levels_par;
691 int alignmentstate = 1;
692 const char *package = NULL;
693 lmt_save_state.save_stack_data.ptr = cur_boundary;
694 --cur_level;
695 tracing_levels_par |= tracing_levels_group;
696 while (1) {
697 int mode;
698 tex_print_levels();
699 tex_print_group(1);
700 if (cur_group == bottom_level_group) {
701 goto DONE;
702 }
703 do {
704 mode = lmt_nest_state.nest[pointer].mode;
705 if (pointer > 0) {
706 --pointer;
707 } else {
708 mode = vmode;
709 }
710 } while (mode == hmode);
711 tex_print_str(": ");
712 switch (cur_group) {
713 case simple_group:
714 ++pointer;
715 goto FOUND2;
716 case hbox_group:
717 case adjusted_hbox_group:
718 package = "hbox";
719 break;
720 case vbox_group:
721 package = "vbox";
722 break;
723 case vtop_group:
724 package = "vtop";
725 break;
726 case dbox_group:
727 package = "dbox";
728 break;
729 case align_group:
730 if (alignmentstate == 0) {
731 package = (mode == internal_vmode) ? "halign" : "valign";
732 alignmentstate = 1;
733 goto FOUND1;
734 } else {
735 if (alignmentstate == 1) {
736 tex_print_str("align entry");
737 } else {
738 tex_print_str_esc("cr");
739 }
740 if (pointer >= alignmentstate) {
741 pointer -= alignmentstate;
742 }
743 alignmentstate = 0;
744 goto FOUND2;
745 }
746 case no_align_group:
747 ++pointer;
748 alignmentstate = -1;
749 tex_print_str_esc("noalign");
750 goto FOUND2;
751 case output_group:
752 tex_print_str_esc("output");
753 goto FOUND2;
754
755
756
757
758
759
760
761 case math_group:
762 tex_print_str_esc("mathsubformula");
763 goto FOUND2;
764 case math_component_group:
765 tex_print_str_esc("mathcomponent");
766 goto FOUND2;
767 case math_stack_group:
768 tex_print_str_esc("mathstack");
769 goto FOUND2;
770 case discretionary_group:
771 tex_show_discretionary_group();
772 goto FOUND2;
773 case math_fraction_group:
774 tex_show_math_fraction_group();
775 goto FOUND2;
776 case math_radical_group:
777 tex_show_math_radical_group();
778 goto FOUND2;
779 case math_operator_group:
780 tex_show_math_operator_group();
781 goto FOUND2;
782 case math_choice_group:
783 tex_show_math_choice_group();
784 goto FOUND2;
785 case insert_group:
786 tex_show_insert_group();
787 goto FOUND2;
788 case vadjust_group:
789 tex_show_adjust_group();
790 goto FOUND2;
791 case vcenter_group:
792 package = "vcenter";
793 goto FOUND1;
794 case also_simple_group:
795 case semi_simple_group:
796 ++pointer;
797 tex_print_str_esc("begingroup");
798 goto FOUND2;
799
800
801
802
803 case math_inline_group:
804 tex_print_char('$');
805 case math_display_group:
806 tex_print_char('$');
807 goto FOUND2;
808 case math_number_group:
809 tex_show_math_number_group();
810 goto FOUND2;
811 case math_fence_group:
812
813 tex_print_str_esc((node_subtype(lmt_nest_state.nest[pointer + 1].delimiter) == left_fence_side) ? "left" : "middle");
814 goto FOUND2;
815 default:
816 tex_confusion("show groups");
817 break;
818 }
819
824 switch (tex_get_packaging_context()) {
825 case direct_box_flag:
826 {
827 scaled shift = tex_get_packaging_shift();
828 if (shift != null_flag) {
829
830 singleword cmd = is_v_mode(lmt_nest_state.nest[pointer].mode) ? hmove_cmd : vmove_cmd;
831 tex_print_cmd_chr(cmd, (shift > 0) ? move_forward_code : move_backward_code);
832 tex_print_dimension(abs(shift), pt_unit);
833 }
834 }
835 break;
836 case global_box_flag:
837 tex_print_str_esc("global");
838 case box_flag:
839 {
840 tex_print_str_esc("setbox");
841 tex_print_int(tex_get_packaging_context());
842 tex_print_char('=');
843 }
844 break;
845 case a_leaders_flag:
846 tex_print_cmd_chr(leader_cmd, a_leaders);
847 break;
848 case c_leaders_flag:
849 tex_print_cmd_chr(leader_cmd, c_leaders);
850 break;
851 case x_leaders_flag:
852 tex_print_cmd_chr(leader_cmd, x_leaders);
853 break;
854 case g_leaders_flag:
855 tex_print_cmd_chr(leader_cmd, g_leaders);
856 break;
857 case u_leaders_flag:
858 tex_print_cmd_chr(leader_cmd, u_leaders);
859 break;
860 }
861 FOUND1:
862 tex_show_packaging_group(package);
863 FOUND2:
864 --cur_level;
865 cur_group = saved_group_group;
866 lmt_save_state.save_stack_data.ptr = saved_group_boundary;
867 }
868 DONE:
869 lmt_save_state.save_stack_data.ptr = saved_pointer;
870 cur_level = saved_level;
871 cur_group = saved_group;
872 tracing_levels_par = saved_tracing;
873}
874
875void tex_show_save_stack(void)
876{
877 halfword savedptr = lmt_save_state.save_stack_data.ptr;
878 tex_print_format("%l[savestack size %i]\n", lmt_save_state.save_stack_data.ptr);
879 while (lmt_save_state.save_stack_data.ptr) {
880 --lmt_save_state.save_stack_data.ptr;
881 tex_print_nlp();
882 tex_print_levels();
883 tex_print_format("[%i: ", lmt_save_state.save_stack_data.ptr);
884 if (save_type(lmt_save_state.save_stack_data.ptr) >= saved_record_0 && save_type(lmt_save_state.save_stack_data.ptr) <= saved_record_9) {
885 tex_print_format("save record %i, ", save_type(lmt_save_state.save_stack_data.ptr) - saved_record_0 + 1, save_record(lmt_save_state.save_stack_data.ptr));
886
887 switch (save_record(lmt_save_state.save_stack_data.ptr)) {
888 case unknown_save_type:
889 break;
890 case box_save_type:
891 if (tex_show_packaging_record()) {
892 break;
893 } else {
894 goto INVALID_TYPE;
895 }
896 case local_box_save_type:
897 if (tex_show_localbox_record()) {
898 break;
899 } else {
900 goto INVALID_TYPE;
901 }
902 case alignment_save_type:
903 if (tex_show_alignment_record()) {
904 break;
905 } else {
906 goto INVALID_TYPE;
907 }
908 case adjust_save_type:
909 if (tex_show_adjust_record()) {
910 break;
911 } else {
912 goto INVALID_TYPE;
913 }
914 case math_save_type:
915 if (tex_show_math_record()) {
916 break;
917 } else {
918 goto INVALID_TYPE;
919 }
920 case fraction_save_type:
921 if (tex_show_math_fraction_record()) {
922 break;
923 } else {
924 goto INVALID_TYPE;
925 }
926 case radical_save_type:
927 if (tex_show_math_radical_record()) {
928 break;
929 } else {
930 goto INVALID_TYPE;
931 }
932 case operator_save_type:
933 if (tex_show_math_operator_record()) {
934 break;
935 } else {
936 goto INVALID_TYPE;
937 }
938 case math_group_save_type:
939 if (tex_show_math_group_record()) {
940 break;
941 } else {
942 goto INVALID_TYPE;
943 }
944 case choice_save_type:
945 if (tex_show_math_choice_record()) {
946 break;
947 } else {
948 goto INVALID_TYPE;
949 }
950 case number_save_type:
951 if (tex_show_math_number_record()) {
952 break;
953 } else {
954 goto INVALID_TYPE;
955 }
956 case insert_save_type:
957 if (tex_show_insert_record()) {
958 break;
959 } else {
960 goto INVALID_TYPE;
961 }
962 case discretionary_save_type:
963 if (tex_show_discretionary_record()) {
964 break;
965 } else {
966 goto INVALID_TYPE;
967 }
968 default:
969 goto INVALID_RECORD;
970 }
971 } else {
972 switch (save_type(lmt_save_state.save_stack_data.ptr)) {
973 case level_boundary_save_type:
974 tex_print_format("boundary, group '%s', boundary %i, attrlist %i, line %i", lmt_interface.group_code_values[saved_group_group].name, saved_group_boundary, saved_group_attribute_state, tex_saved_line_at_level());
975 break;
976 case restore_old_value_save_type:
977 tex_print_format("restore, level %i, cs ", save_level(lmt_save_state.save_stack_data.ptr));
978 tex_aux_show_eqtb(save_value(lmt_save_state.save_stack_data.ptr));
979 break;
980 case insert_tokens_save_type:
981 tex_print_format("insert, pointer %i", save_value(lmt_save_state.save_stack_data.ptr));
982 break;
983 case restore_lua_save_type:
984 tex_print_format("restore lua, level %i, function %i", save_level(lmt_save_state.save_stack_data.ptr), save_value(lmt_save_state.save_stack_data.ptr));
985 break;
986 case restore_zero_save_type:
987 tex_print_format("restore zero, level %i, cs ", save_level(lmt_save_state.save_stack_data.ptr));
988 tex_aux_show_eqtb(save_value(lmt_save_state.save_stack_data.ptr));
989 break;
990 default:
991 goto INVALID_TYPE;
992 }
993 }
994 goto DONE;
995 INVALID_RECORD:
996 tex_print_format("invalid record %i", save_record(lmt_save_state.save_stack_data.ptr));
997 goto DONE;
998 INVALID_TYPE:
999 tex_print_format("invalid type %i", save_type(lmt_save_state.save_stack_data.ptr));
1000 goto DONE;
1001 DONE:
1002 tex_print_char(']');
1003 tex_print_nlp();
1004 }
1005 tex_print_format("%l[savestack bottom]\n");
1006 lmt_save_state.save_stack_data.ptr = savedptr;
1007}
1008
1009
1031
1032static void tex_aux_handle_overload(const char *s, halfword cs, int overload, int error_type)
1033{
1034 int callback_id = lmt_callback_defined(handle_overload_callback);
1035 if (callback_id > 0) {
1036 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "bdsd->", error_type == normal_error_type, overload, cs_text(cs), eq_flag(cs));
1037 } else {
1038 tex_handle_error(
1039 error_type,
1040 "You can't redefine %s %S.",
1041 s, cs,
1042 NULL
1043 );
1044 }
1045}
1046
1047static int tex_aux_report_overload(halfword cs, int overload)
1048{
1049 int error_type = overload & 1 ? warning_error_type : normal_error_type;
1050 if (has_eq_flag_bits(cs, immutable_flag_bit)) {
1051 tex_aux_handle_overload("immutable", cs, overload, error_type);
1052 } else if (has_eq_flag_bits(cs, primitive_flag_bit)) {
1053 tex_aux_handle_overload("primitive", cs, overload, error_type);
1054 } else if (has_eq_flag_bits(cs, permanent_flag_bit)) {
1055 tex_aux_handle_overload("permanent", cs, overload, error_type);
1056 } else if (has_eq_flag_bits(cs, frozen_flag_bit)) {
1057 tex_aux_handle_overload("frozen", cs, overload, error_type);
1058 } else if (has_eq_flag_bits(cs, instance_flag_bit)) {
1059 tex_aux_handle_overload("instance", cs, overload, warning_error_type);
1060 return 1;
1061 }
1062 return error_type == warning_error_type;
1063}
1064
1065# define overload_error_type(overload) (overload & 1 ? warning_error_type : normal_error_type)
1066
1067int tex_define_permitted(halfword cs, halfword prefixes)
1068{
1069 halfword overload = overload_mode_par;
1070 if (! cs || ! overload || has_eq_flag_bits(cs, mutable_flag_bit)) {
1071 return 1;
1072 } else if (is_overloaded(prefixes)) {
1073 if (overload > 2 && has_eq_flag_bits(cs, immutable_flag_bit | permanent_flag_bit | primitive_flag_bit)) {
1074 return tex_aux_report_overload(cs, overload);
1075 }
1076 } else if (overload > 4) {
1077 if (has_eq_flag_bits(cs, immutable_flag_bit | permanent_flag_bit | primitive_flag_bit | frozen_flag_bit | instance_flag_bit)) {
1078 return tex_aux_report_overload(cs, overload);
1079 }
1080 } else if (overload > 2) {
1081 if (has_eq_flag_bits(cs, immutable_flag_bit | permanent_flag_bit | primitive_flag_bit | frozen_flag_bit)) {
1082 return tex_aux_report_overload(cs, overload);
1083 }
1084 } else if (has_eq_flag_bits(cs, immutable_flag_bit)) {
1085 return tex_aux_report_overload(cs, overload);
1086 }
1087 return 1;
1088}
1089
1090static int tex_aux_mutation_permitted(halfword cs)
1091{
1092 halfword overload = overload_mode_par;
1093 if (cs && overload && has_eq_flag_bits(cs, immutable_flag_bit)) {
1094 return tex_aux_report_overload(cs, overload);
1095 } else {
1096 return 1;
1097 }
1098}
1099
1100
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150static inline void tex_aux_eq_destroy(memoryword w)
1151{
1152 halfword p = eq_value_field(w);
1153 if (p) {
1154 switch (lmt_hash_state.destructors[eq_type_field(w)]) {
1155 case eq_token_list:
1156 tex_delete_token_reference(p);
1157 break;
1158 case eq_node:
1159 tex_flush_node(p);
1160 break;
1161 case eq_node_list:
1162 tex_flush_node_list(p);
1163 break;
1164 }
1165 }
1166}
1167
1168
1175
1176static void tex_aux_eq_save(halfword p, quarterword l)
1177{
1178 if (tex_room_on_save_stack()) {
1179 if (l == level_zero) {
1180 save_type(lmt_save_state.save_stack_data.ptr) = restore_zero_save_type;
1181 } else {
1182 save_type(lmt_save_state.save_stack_data.ptr) = restore_old_value_save_type;
1183 save_word(lmt_save_state.save_stack_data.ptr) = lmt_hash_state.eqtb[p];
1184 }
1185 save_level(lmt_save_state.save_stack_data.ptr) = l;
1186 save_value(lmt_save_state.save_stack_data.ptr) = p;
1187 ++lmt_save_state.save_stack_data.ptr;
1188 }
1189}
1190
1191
1208
1209static inline int tex_aux_equal_eq(halfword p, singleword cmd, singleword flag, halfword chr)
1210{
1211
1212 if (eq_flag(p) == flag) {
1213
1214 switch (eq_type(p)) {
1215 case internal_glue_reference_cmd:
1216 case register_glue_reference_cmd:
1217 case internal_muglue_reference_cmd:
1218 case register_muglue_reference_cmd:
1219 case gluespec_cmd:
1220 case mugluespec_cmd:
1221
1222 if (tex_same_glue(eq_value(p), chr)) {
1223 if (chr) {
1224 tex_flush_node(chr);
1225 }
1226 return 1;
1227 } else {
1228 return 0;
1229 }
1230 case mathspec_cmd:
1231
1232 if (tex_same_mathspec(eq_value(p), chr)) {
1233 if (chr) {
1234 tex_flush_node(chr);
1235 }
1236 return 1;
1237 } else {
1238 return 0;
1239 }
1240 case fontspec_cmd:
1241
1242 if (tex_same_fontspec(eq_value(p), chr)) {
1243 if (chr) {
1244 tex_flush_node(chr);
1245 }
1246 return 1;
1247 } else {
1248 return 0;
1249 }
1250
1258 case call_cmd:
1259 case protected_call_cmd:
1260 case semi_protected_call_cmd:
1261 case constant_call_cmd:
1262 case tolerant_call_cmd:
1263 case tolerant_protected_call_cmd:
1264 case tolerant_semi_protected_call_cmd:
1265
1266
1267 if (eq_value(p) == chr && eq_level(p) == cur_level) {
1268 tex_delete_token_reference(eq_value(p));
1269 return 1;
1270 } else {
1271 return 0;
1272 }
1273 case specification_reference_cmd:
1274 case unit_reference_cmd:
1275 case internal_box_reference_cmd:
1276 case register_box_reference_cmd:
1277
1278
1279
1280
1281
1282 if (eq_type(p) == cmd && eq_value(p) == chr && ! chr) {
1283
1284 return 1;
1285 } else {
1286
1287 return 0;
1288 }
1289 case internal_toks_reference_cmd:
1290 case register_toks_reference_cmd:
1291
1292 if (p && chr && eq_value(p) == chr) {
1293 tex_delete_token_reference(eq_value(p));
1294 return 1;
1295 } else {
1296 return 0;
1297 }
1298 case internal_toks_cmd:
1299 case register_toks_cmd:
1300
1301 if (eq_value(p) == chr) {
1302
1303 return 1;
1304 } else {
1305 return 0;
1306 }
1307 case integer_cmd:
1308 case index_cmd:
1309 case dimension_cmd:
1310 case posit_cmd:
1311 if (eq_type(p) == cmd && eq_value(p) == chr) {
1312
1313 return 1;
1314 } else {
1315 return 0;
1316 }
1317 default:
1318
1323 if (eq_type(p) == cmd && eq_value(p) == chr) {
1324
1325 return 1;
1326 } else {
1327 return 0;
1328 }
1329 }
1330 } else {
1331 return 0;
1332 }
1333}
1334
1335
1336
1337void tex_eq_define(halfword p, singleword cmd, halfword chr)
1338{
1339 bool trace = tracing_assigns_par > 0;
1340 if (tex_aux_equal_eq(p, cmd, 0, chr)) {
1341 if (trace) {
1342 tex_aux_diagnostic_trace(p, "reassigning");
1343 }
1344 } else {
1345 if (trace) {
1346 tex_aux_diagnostic_trace(p, "changing");
1347 }
1348 if (eq_level(p) == cur_level) {
1349 tex_aux_eq_destroy(lmt_hash_state.eqtb[p]);
1350 } else if (cur_level > level_one) {
1351 tex_aux_eq_save(p, eq_level(p));
1352 }
1353 set_eq_level(p, cur_level);
1354 set_eq_type(p, cmd);
1355 set_eq_flag(p, 0);
1356 set_eq_value(p, chr);
1357 if (trace) {
1358 tex_aux_diagnostic_trace(p, "into");
1359 }
1360 }
1361}
1362
1363
1370
1371void tex_eq_word_define(halfword p, int w)
1372{
1373 bool trace = tracing_assigns_par > 0;
1374 if (eq_value(p) == w) {
1375 if (trace) {
1376 tex_aux_diagnostic_trace(p, "reassigning");
1377 }
1378 } else {
1379 if (trace) {
1380 tex_aux_diagnostic_trace(p, "changing");
1381 }
1382 if (eq_level(p) != cur_level) {
1383 tex_aux_eq_save(p, eq_level(p));
1384 set_eq_level(p, cur_level);
1385 }
1386 eq_value(p) = w;
1387 if (trace) {
1388 tex_aux_diagnostic_trace(p, "into");
1389 }
1390 }
1391}
1392
1393
1400
1401void tex_geq_define(halfword p, singleword cmd, halfword chr)
1402{
1403 bool trace = tracing_assigns_par > 0;
1404 if (trace) {
1405 tex_aux_diagnostic_trace(p, "globally changing");
1406 }
1407 tex_aux_eq_destroy(lmt_hash_state.eqtb[p]);
1408 set_eq_level(p, level_one);
1409 set_eq_type(p, cmd);
1410 set_eq_flag(p, 0);
1411 set_eq_value(p, chr);
1412 if (trace) {
1413 tex_aux_diagnostic_trace(p, "into");
1414 }
1415}
1416
1417void tex_geq_word_define(halfword p, int w)
1418{
1419 bool trace = tracing_assigns_par > 0;
1420 if (trace) {
1421 tex_aux_diagnostic_trace(p, "globally changing");
1422 }
1423 eq_value(p) = w;
1424 set_eq_level(p, level_one);
1425 if (trace) {
1426 tex_aux_diagnostic_trace(p, "into");
1427 }
1428}
1429
1430
1436
1437static inline void tex_aux_set_eq_data(halfword p, singleword t, halfword e, singleword f, quarterword l)
1438{
1439 singleword flag = eq_flag(p);
1440 set_eq_level(p, l);
1441 set_eq_type(p, t);
1442 set_eq_value(p, e);
1443 if (is_mutable(f) || is_mutable(flag)) {
1444 set_eq_flag(p, (f | flag) & ~(noaligned_flag_bit | permanent_flag_bit | primitive_flag_bit | immutable_flag_bit));
1445 } else {
1446 set_eq_flag(p, f);
1447 }
1448}
1449
1450void tex_define(int g, halfword p, singleword t, halfword e)
1451{
1452 bool trace = tracing_assigns_par > 0;
1453 singleword f = make_eq_flag_bits(g);
1454 if (is_global(g)) {
1455
1456 if (trace) {
1457 tex_aux_diagnostic_trace(p, "globally changing");
1458 }
1459
1460
1461
1462 tex_aux_eq_destroy(lmt_hash_state.eqtb[p]);
1463 tex_aux_set_eq_data(p, t, e, f, level_one);
1464 } else if (! is_constrained(g) && tex_aux_equal_eq(p, t, f, e)) {
1465
1466 if (trace) {
1467 tex_aux_diagnostic_trace(p, "reassigning");
1468 return;
1469 }
1470 } else {
1471 if (trace) {
1472 tex_aux_diagnostic_trace(p, "changing");
1473 }
1474 if (eq_level(p) == cur_level) {
1475 tex_aux_eq_destroy(lmt_hash_state.eqtb[p]);
1476 } else if (is_retained(g)) {
1477
1478 } else if (cur_level > level_one) {
1479 tex_aux_eq_save(p, eq_level(p));
1480 }
1481 tex_aux_set_eq_data(p, t, e, f, cur_level);
1482 }
1483 if (trace) {
1484 tex_aux_diagnostic_trace(p, "into");
1485 }
1486}
1487
1488
1492
1493void tex_define_again(int g, halfword p, singleword t, halfword e)
1494{
1495 if (tracing_assigns_par > 0) {
1496 singleword f = make_eq_flag_bits(g);
1497 if (is_global(g)) {
1498
1499 tex_aux_diagnostic_trace(p, "globally changing");
1500
1501
1502
1503 tex_aux_eq_destroy(lmt_hash_state.eqtb[p]);
1504 tex_aux_set_eq_data(p, t, e, f, level_one);
1505 } else if (! is_constrained(g) && tex_aux_equal_eq(p, t, f, e)) {
1506
1507 tex_aux_diagnostic_trace(p, "reassigning");
1508 } else {
1509 tex_aux_diagnostic_trace(p, is_retained(g) ? "retained changing": "changing");
1510 if (eq_level(p) == cur_level) {
1511 tex_aux_eq_destroy(lmt_hash_state.eqtb[p]);
1512 } else if (is_retained(g)) {
1513
1514 } else if (cur_level > level_one) {
1515 tex_aux_eq_save(p, eq_level(p));
1516 }
1517 tex_aux_set_eq_data(p, t, e, f, cur_level);
1518 }
1519 tex_aux_diagnostic_trace(p, "into");
1520 } else {
1521 set_eq_type(p, t);
1522 set_eq_value(p, e);
1523 }
1524}
1525
1526
1529
1530void tex_define_inherit(int g, halfword p, singleword f, singleword t, halfword e)
1531{
1532 bool trace = tracing_assigns_par > 0;
1533 if (is_global(g)) {
1534
1535 if (trace) {
1536 tex_aux_diagnostic_trace(p, "globally changing");
1537 }
1538
1539
1540
1541 tex_aux_eq_destroy(lmt_hash_state.eqtb[p]);
1542 tex_aux_set_eq_data(p, t, e, f, level_one);
1543 } else if (! is_constrained(g) && tex_aux_equal_eq(p, t, f, e)) {
1544 if (trace) {
1545 tex_aux_diagnostic_trace(p, "reassigning");
1546 return;
1547 }
1548 } else {
1549 if (trace) {
1550 tex_aux_diagnostic_trace(p, is_retained(g) ? "retained changing" : "changing");
1551 }
1552 if (eq_level(p) == cur_level) {
1553 tex_aux_eq_destroy(lmt_hash_state.eqtb[p]);
1554 } else if (is_retained(g)) {
1555
1556 } else if (cur_level > level_one) {
1557 tex_aux_eq_save(p, eq_level(p));
1558 }
1559 tex_aux_set_eq_data(p, t, e, f, cur_level);
1560 }
1561 if (trace) {
1562 tex_aux_diagnostic_trace(p, "into");
1563 }
1564}
1565
1566
1570
1571static void tex_aux_just_define(int g, halfword p, halfword e)
1572{
1573 bool trace = tracing_assigns_par > 0;
1574 if (is_global(g)) {
1575 if (trace) {
1576 tex_aux_diagnostic_trace(p, "globally changing");
1577 }
1578 tex_aux_eq_destroy(lmt_hash_state.eqtb[p]);
1579 } else {
1580 if (trace) {
1581 tex_aux_diagnostic_trace(p, "changing");
1582 }
1583 if (eq_level(p) == cur_level) {
1584 tex_aux_eq_destroy(lmt_hash_state.eqtb[p]);
1585 } else if (cur_level > level_one) {
1586 tex_aux_eq_save(p, eq_level(p));
1587 }
1588 set_eq_level(p, cur_level);
1589 }
1590 set_eq_value(p, e);
1591 if (trace) {
1592 tex_aux_diagnostic_trace(p, "into");
1593 }
1594}
1595
1596
1597
1598void tex_define_swapped(int g, halfword p1, halfword p2, int force)
1599{
1600 halfword t1 = eq_type(p1);
1601 halfword t2 = eq_type(p2);
1602 halfword l1 = eq_level(p1);
1603 halfword l2 = eq_level(p2);
1604 singleword f1 = eq_flag(p1);
1605 singleword f2 = eq_flag(p2);
1606 halfword v1 = eq_value(p1);
1607 halfword v2 = eq_value(p2);
1608 if (t1 == t2 && l1 == l2) {
1609 halfword overload = force ? 0 : overload_mode_par;
1610 if (overload) {
1611 if (f1 != f2) {
1612 goto NOTDONE;
1613 } else if (is_immutable(f1)) {
1614 goto NOTDONE;
1615 }
1616 }
1617 if (v1 == v2) {
1618 return;
1619 } else {
1620 switch (t1) {
1621 case register_posit_cmd:
1622 case register_integer_cmd:
1623 case register_attribute_cmd:
1624 case register_dimension_cmd:
1625 case register_glue_cmd:
1626 case register_muglue_cmd:
1627 case internal_muglue_cmd:
1628 case integer_cmd:
1629 case index_cmd:
1630 case dimension_cmd:
1631 case posit_cmd:
1632 tex_aux_just_define(g, p1, v2);
1633 tex_aux_just_define(g, p2, v1);
1634 return;
1635 case register_toks_cmd:
1636 case internal_toks_cmd:
1637 if (v1) tex_add_token_reference(v1);
1638 if (v2) tex_add_token_reference(v2);
1639 tex_aux_just_define(g, p1, v2);
1640 tex_aux_just_define(g, p2, v1);
1641 if (v1) tex_delete_token_reference(v1);
1642 if (v2) tex_delete_token_reference(v2);
1643 return;
1644 case internal_integer_cmd:
1645 tex_assign_internal_integer_value(g, p1, v2);
1646 tex_assign_internal_integer_value(g, p2, v1);
1647 return;
1648 case internal_attribute_cmd:
1649 tex_assign_internal_attribute_value(g, p1, v2);
1650 tex_assign_internal_attribute_value(g, p2, v1);
1651 return;
1652 case internal_posit_cmd:
1653 tex_assign_internal_posit_value(g, p1, v2);
1654 tex_assign_internal_posit_value(g, p2, v1);
1655 return;
1656 case internal_dimension_cmd:
1657 tex_assign_internal_dimension_value(g, p1, v2);
1658 tex_assign_internal_dimension_value(g, p2, v1);
1659 return;
1660 case internal_glue_cmd:
1661
1662 tex_assign_internal_skip_value(g, p1, v2);
1663 tex_assign_internal_skip_value(g, p2, v1);
1664 return;
1665 default:
1666 if (overload > 2) {
1667 if (has_flag_bits(f1, immutable_flag_bit | permanent_flag_bit | primitive_flag_bit)) {
1668 if (overload > 3) {
1669 goto NOTDONE;
1670 }
1671 }
1672 }
1673 if (is_call_cmd(t1)) {
1674 if (v1) tex_add_token_reference(v1);
1675 if (v2) tex_add_token_reference(v2);
1676 tex_aux_just_define(g, p1, v2);
1677 tex_aux_just_define(g, p2, v1);
1678
1679 } else {
1680 tex_handle_error(
1681 normal_error_type,
1682 "\\swapcsvalues not (yet) implemented for commands (%C, %C)",
1683 t1, v1, t2, v2, NULL
1684 );
1685
1686 }
1687 return;
1688 }
1689 }
1690 }
1691 NOTDONE:
1692 tex_handle_error(
1693 normal_error_type,
1694 "\\swapcsvalues requires equal commands (%C, %C), levels (%i, %i) and flags (%i, %i)",
1695 t1, v1, t2, v2, l1, l2, f1, f2, NULL
1696 );
1697}
1698
1699
1702
1703void tex_forced_define(int g, halfword p, singleword f, singleword t, halfword e)
1704{
1705 bool trace = tracing_assigns_par > 0;
1706 if (is_global(g)) {
1707 if (trace) {
1708 tex_aux_diagnostic_trace(p, "globally changing");
1709 }
1710 tex_aux_eq_destroy(lmt_hash_state.eqtb[p]);
1711 set_eq_level(p, level_one);
1712 } else {
1713 if (trace) {
1714 tex_aux_diagnostic_trace(p, "changing");
1715 }
1716 if (eq_level(p) == cur_level) {
1717 tex_aux_eq_destroy(lmt_hash_state.eqtb[p]);
1718 } else if (cur_level > level_one) {
1719 tex_aux_eq_save(p, eq_level(p));
1720 }
1721 set_eq_level(p, cur_level);
1722 }
1723 set_eq_type(p, t);
1724 set_eq_flag(p, f);
1725 set_eq_value(p, e);
1726 if (trace) {
1727 tex_aux_diagnostic_trace(p, "into");
1728 }
1729}
1730
1731
1734
1735void tex_word_define(int g, halfword p, halfword w)
1736{
1737 if (tex_aux_mutation_permitted(p)) {
1738 bool trace = tracing_assigns_par > 0;
1739 if (is_global(g)) {
1740 if (trace) {
1741 tex_aux_diagnostic_trace(p, "globally changing");
1742 }
1743 eq_value(p) = w;
1744 set_eq_level(p, level_one);
1745 } else if (! is_constrained(g) && eq_value(p) == w) {
1746 if (trace) {
1747 tex_aux_diagnostic_trace(p, "reassigning");
1748 return;
1749 }
1750 } else if (is_retained(g)) {
1751 if (trace) {
1752 tex_aux_diagnostic_trace(p, "retained changing");
1753 set_eq_level(p, cur_level);
1754 }
1755 eq_value(p) = w;
1756 } else {
1757 if (trace) {
1758 tex_aux_diagnostic_trace(p, "changing");
1759 }
1760 if (eq_level(p) != cur_level) {
1761 tex_aux_eq_save(p, eq_level(p));
1762 set_eq_level(p, cur_level);
1763 }
1764 eq_value(p) = w;
1765 }
1766 if (trace) {
1767 tex_aux_diagnostic_trace(p, "into");
1768 }
1769 if (is_immutable(g)) {
1770 eq_flag(p) |= immutable_flag_bit;
1771 } else if (is_mutable(g)) {
1772 eq_flag(p) |= mutable_flag_bit;
1773 }
1774 }
1775}
1776
1777
1815
1816
1821
1822void tex_save_for_after_group(halfword t)
1823{
1824 if (t && cur_level > level_one && tex_room_on_save_stack()) {
1825 save_type(lmt_save_state.save_stack_data.ptr) = insert_tokens_save_type;
1826 save_level(lmt_save_state.save_stack_data.ptr) = level_zero;
1827 save_value(lmt_save_state.save_stack_data.ptr) = t;
1828 ++lmt_save_state.save_stack_data.ptr;
1829 }
1830}
1831
1832
1863
1864void tex_unsave(void)
1865{
1866 if (end_of_group_par) {
1867
1871 tex_begin_inserted_list(tex_get_available_token(token_val(end_local_cmd, 0)));
1872 tex_begin_token_list(end_of_group_par, end_of_group_text);
1873 if (tracing_nesting_par > 2) {
1874 tex_local_control_message("entering token scanner via endgroup");
1875 }
1876 tex_local_control(1);
1877
1878 }
1879 delete_attribute_reference(current_attribute_state);
1880 tex_unsave_math_codes(cur_level);
1881 tex_unsave_cat_codes(cat_code_table_par, cur_level);
1882 tex_unsave_text_codes(cur_level);
1883 tex_unsave_math_data(cur_level);
1884 if (cur_level > level_one) {
1885
1889 bool append = false;
1890 bool trace = tracing_restores_par > 0;
1891 --cur_level;
1892
1893 while (1) {
1894 --lmt_save_state.save_stack_data.ptr;
1895 switch (save_type(lmt_save_state.save_stack_data.ptr)) {
1896 case level_boundary_save_type:
1897 goto DONE;
1898 case restore_old_value_save_type:
1899 {
1900 halfword p = save_value(lmt_save_state.save_stack_data.ptr);
1901
1908
1909 if (p < internal_integer_base || p >= internal_specification_base) {
1910 if (eq_level(p) == level_one) {
1911 tex_aux_eq_destroy(save_word(lmt_save_state.save_stack_data.ptr));
1912 if (trace) {
1913 tex_aux_diagnostic_trace(p, "retaining");
1914 }
1915 } else {
1916 tex_aux_eq_destroy(lmt_hash_state.eqtb[p]);
1917 lmt_hash_state.eqtb[p] = save_word(lmt_save_state.save_stack_data.ptr);
1918 if (trace) {
1919 tex_aux_diagnostic_trace(p, "restoring");
1920 }
1921 }
1922 } else if (eq_level(p) == level_one) {
1923 if (trace) {
1924 tex_aux_diagnostic_trace(p, "retaining");
1925 }
1926 } else {
1927 lmt_hash_state.eqtb[p] = save_word(lmt_save_state.save_stack_data.ptr);
1928 if (trace) {
1929 tex_aux_diagnostic_trace(p, "restoring");
1930 }
1931 }
1932 break;
1933 }
1934 case insert_tokens_save_type:
1935 {
1936
1937 halfword p = save_value(lmt_save_state.save_stack_data.ptr);
1938 if (append) {
1939
1940 tex_append_input(p);
1941 } else {
1942 tex_insert_input(p);
1943 append = true;
1944 }
1945 break;
1946 }
1947 case restore_lua_save_type:
1948 {
1949
1950 halfword p = save_value(lmt_save_state.save_stack_data.ptr);
1951 if (p > 0) {
1952 strnumber u = tex_save_cur_string();
1953 lmt_token_state.luacstrings = 0;
1954 lmt_function_call(p, 0);
1955 tex_restore_cur_string(u);
1956 if (lmt_token_state.luacstrings > 0) {
1957 tex_lua_string_start();
1958 }
1959 } else {
1960 tex_normal_error("lua restore", "invalid number");
1961 }
1962 append = true;
1963 break;
1964 }
1965 case restore_zero_save_type:
1966 {
1967 halfword p = save_value(lmt_save_state.save_stack_data.ptr);
1968 if (eq_level(p) == level_one) {
1969 if (trace) {
1970 tex_aux_diagnostic_trace(p, "retaining");
1971 }
1972 } else {
1973 if (p < internal_integer_base || p > eqtb_size) {
1974 tex_aux_eq_destroy(lmt_hash_state.eqtb[p]);
1975 }
1976 lmt_hash_state.eqtb[p] = lmt_hash_state.eqtb[undefined_control_sequence];
1977 if (trace) {
1978 tex_aux_diagnostic_trace(p, "restoring");
1979 }
1980 }
1981 break;
1982 }
1983 default:
1984
1985 tex_formatted_error("tex unsave", "bad save type case %d, probably a stack pointer issue", save_type(lmt_save_state.save_stack_data.ptr));
1986 break;
1987 }
1988 }
1989 DONE:
1990 if (tracing_groups_par > 0) {
1991 tex_aux_group_trace(1);
1992 }
1993 if (lmt_input_state.in_stack[lmt_input_state.in_stack_data.ptr].group == cur_boundary) {
1994
1995 tex_aux_group_warning();
1996 }
1997 cur_group = saved_group_group;
1998 cur_boundary = saved_group_boundary;
1999 set_current_attribute_state(saved_group_attribute_state);
2000 } else {
2001
2002 tex_confusion("current level");
2003 }
2004}
2005
2006
2070
2071void tex_show_cmd_chr(halfword cmd, halfword chr)
2072{
2073 tex_begin_diagnostic();
2074 if (cur_list.mode != lmt_nest_state.shown_mode) {
2075 if (tracing_commands_par >= 4) {
2076
2077 tex_print_format("[mode: entering %M]", cur_list.mode);
2078 tex_print_nlp();
2079 tex_print_levels();
2080 tex_print_str("{");
2081 } else {
2082 tex_print_format("{%M: ", cur_list.mode);
2083 }
2084 lmt_nest_state.shown_mode = cur_list.mode;
2085 } else {
2086 tex_print_str("{");
2087 }
2088 tex_print_cmd_chr((singleword) cmd, chr);
2089 if (cmd == if_test_cmd && tracing_ifs_par > 0) {
2090 halfword p;
2091 int n, l;
2092 if (tracing_commands_par >= 4) {
2093 tex_print_str(": ");
2094 } else {
2095 tex_print_char(' ');
2096 }
2097 if (cur_chr >= first_real_if_test_code || cur_chr == or_else_code || cur_chr == or_unless_code) {
2098 n = 1;
2099 l = lmt_input_state.input_line;
2100 } else {
2101 tex_print_cmd_chr(if_test_cmd, lmt_condition_state.cur_if);
2102 tex_print_char(' ');
2103 n = 0;
2104 l = lmt_condition_state.if_line;
2105 }
2106
2110 p = lmt_condition_state.cond_ptr;
2111 while (p) {
2112 ++n;
2113 p = node_next(p);
2114 }
2115 if (l) {
2116 if (tracing_commands_par >= 4) {
2117 tex_print_format("(level %i, line %i, nesting %i)", n, l, lmt_condition_state.if_nesting);
2118 } else {
2119
2120 tex_print_format("(level %i, line %i)", n, l);
2121 }
2122 } else {
2123 tex_print_format("(level %i)", n);
2124 }
2125 }
2126 tex_print_char('}');
2127 tex_end_diagnostic();
2128}
2129
2130
2156
2157void tex_aux_show_eqtb(halfword n)
2158{
2159 if (n < null_cs) {
2160 tex_print_format("bad token %i, case 1", n);
2161 } else if (eqtb_indirect_range(n)) {
2162 tex_print_cs(n);
2163 tex_print_char('=');
2164 tex_print_cmd_chr(eq_type(n), eq_value(n));
2165 if (eq_type(n) >= call_cmd) {
2166 tex_print_char(':');
2167 tex_token_show(eq_value(n));
2168 }
2169 } else {
2170 switch (eq_type(n)) {
2171 case internal_toks_reference_cmd:
2172 tex_print_cmd_chr(internal_toks_cmd, n);
2173 goto TOKS;
2174 case register_toks_reference_cmd:
2175 tex_print_str_esc("toks");
2176 tex_print_int(register_toks_number(n));
2177 TOKS:
2178 tex_print_char('=');
2179 tex_token_show(eq_value(n));
2180 break;
2181 case internal_box_reference_cmd:
2182 tex_print_cmd_chr(eq_type(n), n);
2183 goto BOX;
2184 case register_box_reference_cmd:
2185 tex_print_str_esc("box");
2186 tex_print_int(register_box_number(n));
2187 BOX:
2188 tex_print_char('=');
2189 if (eq_value(n)) {
2190 tex_show_node_list(eq_value(n), 0, 1);
2191 tex_print_levels();
2192 } else {
2193 tex_print_str("void");
2194 }
2195 break;
2196 case internal_glue_reference_cmd:
2197 tex_print_cmd_chr(internal_glue_cmd, n);
2198 goto SKIP;
2199 case register_glue_reference_cmd:
2200 tex_print_str_esc("skip");
2201 tex_print_int(register_glue_number(n));
2202 SKIP:
2203 tex_print_char('=');
2204 if (tracing_nodes_par > 2) {
2205 tex_print_format("<%i>", eq_value(n));
2206 }
2207 tex_print_spec(eq_value(n), pt_unit);
2208 break;
2209 case internal_muglue_reference_cmd:
2210 tex_print_cmd_chr(internal_muglue_cmd, n);
2211 goto MUSKIP;
2212 case register_muglue_reference_cmd:
2213 tex_print_str_esc("muskip");
2214 tex_print_int(register_muglue_number(n));
2215 MUSKIP:
2216 if (tracing_nodes_par > 2) {
2217 tex_print_format("<%i>", eq_value(n));
2218 }
2219 tex_print_char('=');
2220 tex_print_spec(eq_value(n), mu_unit);
2221 break;
2222 case internal_integer_reference_cmd:
2223 tex_print_cmd_chr(internal_integer_cmd, n);
2224 goto COUNT;
2225 case register_integer_reference_cmd:
2226 tex_print_str_esc("count");
2227 tex_print_int(register_integer_number(n));
2228 COUNT:
2229 tex_print_char('=');
2230 tex_print_int(eq_value(n));
2231 break;
2232 case internal_attribute_reference_cmd:
2233 tex_print_cmd_chr(internal_attribute_cmd, n);
2234 goto ATTRIBUTE;
2235 case register_attribute_reference_cmd:
2236 tex_print_str_esc("attribute");
2237 tex_print_int(register_attribute_number(n));
2238 ATTRIBUTE:
2239 tex_print_char('=');
2240 tex_print_int(eq_value(n));
2241 break;
2242 case internal_posit_reference_cmd:
2243 tex_print_cmd_chr(internal_posit_cmd, n);
2244 goto POSIT;
2245 case register_posit_reference_cmd:
2246 tex_print_str_esc("posit");
2247 tex_print_int(register_posit_number(n));
2248 POSIT:
2249 tex_print_char('=');
2250 tex_print_posit(eq_value(n));
2251 break;
2252 case internal_dimension_reference_cmd:
2253 tex_print_cmd_chr(internal_dimension_cmd, n);
2254 goto DIMEN;
2255 case register_dimension_reference_cmd:
2256 tex_print_str_esc("dimen");
2257 tex_print_int(register_dimension_number(n));
2258 DIMEN:
2259 tex_print_char('=');
2260 tex_print_dimension(eq_value(n), pt_unit);
2261 break;
2262 case specification_reference_cmd:
2263 tex_print_cmd_chr(specification_cmd, n);
2264 tex_print_char('=');
2265 if (eq_value(n)) {
2266
2267
2268
2269 tex_print_int(specification_count(eq_value(n)));
2270 } else {
2271 tex_print_char('0');
2272 }
2273 break;
2274 case unit_reference_cmd:
2275 tex_print_cmd_chr(association_cmd, n);
2276 tex_print_char('=');
2277 if (eq_value(n)) {
2278 tex_print_str("todo");
2279 } else {
2280 tex_print_char('0');
2281 }
2282 break;
2283 default:
2284 tex_print_format("bad token %i, case 2", n);
2285 break;
2286 }
2287 }
2288}
2289
2290
2297
2298halfword tex_automatic_disc_penalty(halfword mode)
2299{
2300 return hyphenation_permitted(mode, automatic_penalty_hyphenation_mode) ? automatic_hyphen_penalty_par : ex_hyphen_penalty_par;
2301}
2302
2303halfword tex_explicit_disc_penalty(halfword mode)
2304{
2305 return hyphenation_permitted(mode, explicit_penalty_hyphenation_mode) ? explicit_hyphen_penalty_par : ex_hyphen_penalty_par;
2306}
2307
2308
2317
2318static inline void tex_aux_set_eq(halfword base, quarterword level, singleword cmd, halfword value, halfword count)
2319{
2320 if (count > 0) {
2321 set_eq_level(base, level);
2322 set_eq_type(base, cmd);
2323 set_eq_flag(base, 0);
2324 set_eq_value(base, value);
2325 for (int k = base + 1; k <= base + count; k++){
2326 copy_eqtb_entry(k, base);
2327 }
2328 }
2329}
2330
2331void tex_synchronize_equivalents(void)
2332{
2333 tex_aux_set_eq(null_cs, level_zero, undefined_cs_cmd, null, lmt_hash_state.hash_data.top - 1);
2334}
2335
2336void tex_initialize_equivalents(void)
2337{
2338
2339 tex_aux_set_eq(null_cs, level_zero, undefined_cs_cmd, null, lmt_hash_state.hash_data.top - 1);
2340 tex_aux_set_eq(internal_glue_base, level_one, internal_glue_reference_cmd, zero_glue, number_glue_pars);
2341 tex_aux_set_eq(register_glue_base, level_one, register_glue_reference_cmd, zero_glue, max_glue_register_index);
2342 tex_aux_set_eq(internal_muglue_base, level_one, internal_muglue_reference_cmd, zero_glue, number_muglue_pars);
2343 tex_aux_set_eq(register_muglue_base, level_one, register_muglue_reference_cmd, zero_glue, max_muglue_register_index);
2344 tex_aux_set_eq(internal_toks_base, level_one, internal_toks_reference_cmd, null, number_tok_pars);
2345 tex_aux_set_eq(register_toks_base, level_one, register_toks_reference_cmd, null, max_toks_register_index);
2346 tex_aux_set_eq(internal_box_base, level_one, internal_box_reference_cmd, null, number_box_pars);
2347 tex_aux_set_eq(register_box_base, level_one, register_box_reference_cmd, null, max_box_register_index);
2348 tex_aux_set_eq(internal_integer_base, level_one, internal_integer_reference_cmd, 0, number_integer_pars);
2349 tex_aux_set_eq(register_integer_base, level_one, register_integer_reference_cmd, 0, max_integer_register_index);
2350 tex_aux_set_eq(internal_attribute_base, level_one, internal_attribute_reference_cmd, unused_attribute_value, number_attribute_pars);
2351 tex_aux_set_eq(register_attribute_base, level_one, register_attribute_reference_cmd, unused_attribute_value, max_attribute_register_index);
2352 tex_aux_set_eq(internal_posit_base, level_one, internal_posit_reference_cmd, 0, number_posit_pars);
2353 tex_aux_set_eq(register_posit_base, level_one, register_posit_reference_cmd, 0, max_posit_register_index);
2354 tex_aux_set_eq(internal_dimension_base, level_one, internal_dimension_reference_cmd, 0, number_dimension_pars);
2355 tex_aux_set_eq(register_dimension_base, level_one, register_dimension_reference_cmd, 0, max_dimension_register_index);
2356 tex_aux_set_eq(internal_specification_base, level_one, specification_reference_cmd, null, number_specification_pars);
2357 tex_aux_set_eq(internal_unit_base, level_one, unit_reference_cmd, unset_unit_class, max_unit_register_index);
2358 tex_aux_set_eq(undefined_control_sequence, level_zero, undefined_cs_cmd, null, 0);
2359
2360 cat_code_table_par = 0;
2361}
2362
2363void tex_initialize_destructors(void)
2364{
2365 lmt_hash_state.destructors[call_cmd] = eq_token_list;
2366 lmt_hash_state.destructors[protected_call_cmd] = eq_token_list;
2367 lmt_hash_state.destructors[semi_protected_call_cmd] = eq_token_list;
2368 lmt_hash_state.destructors[constant_call_cmd] = eq_token_list;
2369 lmt_hash_state.destructors[tolerant_call_cmd] = eq_token_list;
2370 lmt_hash_state.destructors[tolerant_protected_call_cmd] = eq_token_list;
2371 lmt_hash_state.destructors[tolerant_semi_protected_call_cmd] = eq_token_list;
2372 lmt_hash_state.destructors[register_toks_reference_cmd] = eq_token_list;
2373 lmt_hash_state.destructors[internal_toks_reference_cmd] = eq_token_list;
2374 lmt_hash_state.destructors[internal_glue_reference_cmd] = eq_node;
2375 lmt_hash_state.destructors[register_glue_reference_cmd] = eq_node;
2376 lmt_hash_state.destructors[internal_muglue_reference_cmd] = eq_node;
2377 lmt_hash_state.destructors[register_muglue_reference_cmd] = eq_node;
2378 lmt_hash_state.destructors[gluespec_cmd] = eq_node;
2379 lmt_hash_state.destructors[mugluespec_cmd] = eq_node;
2380 lmt_hash_state.destructors[mathspec_cmd] = eq_node;
2381 lmt_hash_state.destructors[fontspec_cmd] = eq_node;
2382 lmt_hash_state.destructors[specificationspec_cmd] = eq_node;
2383 lmt_hash_state.destructors[specification_reference_cmd] = eq_node;
2384 lmt_hash_state.destructors[internal_box_reference_cmd] = eq_node_list;
2385 lmt_hash_state.destructors[register_box_reference_cmd] = eq_node_list;
2386}
2387
2388int tex_located_save_value(int id)
2389{
2390 int i = lmt_save_state.save_stack_data.ptr - 1;
2391 while (save_type(i) != level_boundary_save_type) {
2392 i--;
2393 }
2394 while (i < lmt_save_state.save_stack_data.ptr) {
2395 if (save_type(i) == restore_old_value_save_type && save_value(i) == id) {
2396
2401 return save_value(i - 1);
2402 }
2403 i++;
2404 }
2405 return 0;
2406}
2407
2408int tex_cs_state(halfword p)
2409{
2410 if (p == null_cs) {
2411 return cs_null_error;
2412 } else if (p < hash_base) {
2413 return cs_below_base_error;
2414 } else if (p == undefined_control_sequence) {
2415 return cs_undefined_error;
2416 } else if (eqtb_out_of_range(p)) {
2417 return cs_out_of_range_error;
2418 } else {
2419 return cs_no_error;
2420 }
2421}
2422
2423void tex_save_stack_catch_up(void)
2424{
2425
2426 halfword saved_stack_ptr = lmt_save_state.save_stack_data.ptr;
2427 quarterword saved_group = cur_group;
2428 quarterword saved_level = cur_level;
2429 lmt_save_state.save_stack_data.ptr = cur_boundary;
2430 while (lmt_input_state.in_stack[lmt_input_state.in_stack_data.ptr].group != lmt_save_state.save_stack_data.ptr) {
2431 --cur_level;
2432 tex_print_nlp();
2433 tex_print_format("Warning: end of file when %G is incomplete", 1);
2434 cur_group = save_level(lmt_save_state.save_stack_data.ptr);
2435 lmt_save_state.save_stack_data.ptr = save_value(lmt_save_state.save_stack_data.ptr);
2436 }
2437
2438 lmt_save_state.save_stack_data.ptr = saved_stack_ptr;
2439 cur_level = saved_level;
2440 cur_group = saved_group;
2441}
2442 |