1
4
5# include "luametatex.h"
6
7
55
56main_control_state_info lmt_main_control_state = {
57 .control_state = goto_next_state,
58 .local_level = 0,
59 .after_token = null,
60 .after_tokens = null,
61 .last_par_trigger = 0,
62 .last_par_context = 0,
63 .loop_iterator = 0,
64 .loop_nesting = 0,
65 .loop_stack_head = null,
66 .loop_stack_tail = null,
67 .quit_loop = 0,
68 .padding = 0,
69};
70
71inline static void tex_aux_big_switch (int mode, int cmd);
72static void tex_run_prefixed_command (void);
73
74
78
79static void tex_aux_fixup_directions_and_unsave(void)
80{
81 int saved_par_state = internal_par_state_par;
82 int saved_dir_state = internal_dir_state_par;
83 int saved_direction = text_direction_par;
84 tex_pop_text_dir_ptr();
85 tex_unsave();
86 if (cur_mode == hmode) {
87 if (saved_dir_state) {
88
89 tex_tail_append(tex_new_dir(cancel_dir_subtype, text_direction_par));
90 dir_direction(cur_list.tail) = saved_direction;
91 }
92 if (saved_par_state) {
93
94 tex_tail_append(tex_new_par_node(parameter_par_subtype));
95 }
96 }
97}
98
99static void tex_aux_fixup_directions_only(void)
100{
101 int saved_dir_state = internal_dir_state_par;
102 int saved_direction = text_direction_par;
103 tex_pop_text_dir_ptr();
104 if (saved_dir_state) {
105
106 tex_tail_append(tex_new_dir(cancel_dir_subtype, saved_direction));
107 }
108}
109
110static void tex_aux_fixup_math_and_unsave(void)
111{
112 int saved_math_style = internal_math_style_par;
113 int saved_math_scale = internal_math_scale_par;
114 tex_unsave();
115 if (cur_mode == mmode) {
116 if (saved_math_style >= 0 && saved_math_style != cur_list.math_style) {
117 halfword noad = tex_new_node(style_node, (quarterword) saved_math_style);
118 cur_list.math_style = saved_math_style;
119 tex_tail_append(noad);
120 }
121 if (saved_math_scale != cur_list.math_scale) {
122 halfword noad = tex_new_node(style_node, scaled_math_style);
123 style_scale(noad) = saved_math_scale;
124 cur_list.math_scale = saved_math_scale;
125 tex_tail_append(noad);
126 }
127 }
128}
129
130
139
140static void tex_aux_adjust_space_factor(halfword chr)
141{
142 halfword s = tex_get_sf_code(chr);
143 if (s == default_space_factor) {
144 cur_list.space_factor = default_space_factor;
145 } else if (s < default_space_factor) {
146 if (s > 0) {
147 cur_list.space_factor = s;
148 } else {
149
150 }
151 } else if (cur_list.space_factor < default_space_factor) {
152 cur_list.space_factor = default_space_factor;
153 } else {
154 cur_list.space_factor = s;
155 }
156}
157
158static void tex_aux_run_text_char_number(void)
159{
160 switch (cur_chr) {
161 case char_number_code:
162 {
163 halfword chr = tex_scan_char_number(0);
164 tex_aux_adjust_space_factor(chr);
165 tex_tail_append(tex_new_char_node(glyph_unset_subtype, cur_font_par, chr, 1));
166 break;
167 }
168 case glyph_number_code:
169 {
170 scaled xoffset = glyph_x_offset_par;
171 scaled yoffset = glyph_y_offset_par;
172 halfword xscale = glyph_x_scale_par;
173 halfword yscale = glyph_y_scale_par;
174 halfword scale = glyph_scale_par;
175 halfword slant = glyph_slant_par;
176 halfword weight = glyph_weight_par;
177 halfword options = glyph_options_par;
178 halfword font = cur_font_par;
179 scaled left = 0;
180 scaled right = 0;
181 scaled raise = 0;
182 halfword chr = 0;
183 halfword glyph;
184 while (1) {
185 switch (tex_scan_character("xyofislrwXYOFISLRW", 0, 1, 0)) {
186 case 0:
187 goto DONE;
188 case 'x': case 'X':
189 switch (tex_scan_character("osOS", 0, 0, 0)) {
190 case 'o': case 'O':
191 if (tex_scan_mandate_keyword("xoffset", 2)) {
192 xoffset = tex_scan_dimension(0, 0, 0, 0, NULL);
193 }
194 break;
195 case 's': case 'S':
196 if (tex_scan_mandate_keyword("xscale", 2)) {
197 xscale = tex_scan_integer(0, NULL);
198 }
199 break;
200 default:
201 tex_aux_show_keyword_error("xoffset|xscale");
202 goto DONE;
203 }
204 break;
205 case 'y': case 'Y':
206 switch (tex_scan_character("osOS", 0, 0, 0)) {
207 case 'o': case 'O':
208 if (tex_scan_mandate_keyword("yoffset", 2)) {
209 yoffset = tex_scan_dimension(0, 0, 0, 0, NULL);
210 }
211 break;
212 case 's': case 'S':
213 if (tex_scan_mandate_keyword("yscale", 2)) {
214 yscale = tex_scan_integer(0, NULL);
215 }
216 break;
217 default:
218 tex_aux_show_keyword_error("yoffset|yscale");
219 goto DONE;
220 }
221 break;
222 case 'o': case 'O':
223 if (tex_scan_mandate_keyword("options", 1)) {
224 options = tex_scan_integer(0, NULL) & glyph_option_valid;
225 }
226 break;
227 case 'f': case 'F':
228 if (tex_scan_mandate_keyword("font", 1)) {
229 font = tex_scan_font_identifier(NULL);
230 }
231 break;
232 case 'i': case 'I':
233 if (tex_scan_mandate_keyword("id", 1)) {
234 halfword f = tex_scan_integer(0, NULL);
235 if (f > 0 && tex_is_valid_font(f)) {
236 font = f;
237 }
238 }
239 break;
240 case 's': case 'S':
241 switch (tex_scan_character("clCL", 0, 0, 0)) {
242 case 'c': case 'C':
243 if (tex_scan_mandate_keyword("scale", 2)) {
244 scale = tex_scan_integer(0, NULL);
245 }
246 break;
247 case 'l': case 'L':
248 if (tex_scan_mandate_keyword("slant", 2)) {
249 slant = tex_scan_integer(0, NULL);
250 }
251 break;
252 default:
253 tex_aux_show_keyword_error("scale|slant");
254 goto DONE;
255 }
256 break;
257 case 'l': case 'L':
258 if (tex_scan_mandate_keyword("left", 1)) {
259 left = tex_scan_dimension(0, 0, 0, 0, NULL);
260 }
261 break;
262 case 'r': case 'R':
263 switch (tex_scan_character("aiAI", 0, 0, 0)) {
264 case 'i': case 'I':
265 if (tex_scan_mandate_keyword("right", 2)) {
266 right = tex_scan_dimension(0, 0, 0, 0, NULL);
267 }
268 break;
269 case 'a': case 'A':
270 if (tex_scan_mandate_keyword("raise", 2)) {
271 raise = tex_scan_dimension(0, 0, 0, 0, NULL);
272 }
273 break;
274 default:
275 tex_aux_show_keyword_error("right|raise");
276 goto DONE;
277 }
278 break;
279 case 'w': case 'W':
280 if (tex_scan_mandate_keyword("weight", 1)) {
281 weight = tex_scan_integer(0, NULL);
282 }
283 break;
284 default:
285 goto DONE;
286 }
287 }
288 DONE:
289 chr = tex_scan_char_number(0);
290 tex_aux_adjust_space_factor(chr);
291 glyph = tex_new_char_node(glyph_unset_subtype, font, chr, 1);
292 set_glyph_x_offset(glyph, xoffset);
293 set_glyph_y_offset(glyph, yoffset);
294 set_glyph_scale(glyph, scale);
295 set_glyph_x_scale(glyph, xscale);
296 set_glyph_y_scale(glyph, yscale);
297 set_glyph_slant(glyph, slant);
298 set_glyph_weight(glyph, weight);
299 set_glyph_left(glyph, left);
300 set_glyph_right(glyph, right);
301 set_glyph_raise(glyph, raise);
302 set_glyph_options(glyph, options);
303 tex_tail_append(glyph);
304 break;
305 }
306 }
307}
308
309static void tex_aux_run_text_letter(void) {
310 tex_aux_adjust_space_factor(cur_chr);
311 tex_tail_append(tex_new_char_node(glyph_unset_subtype, cur_font_par, cur_chr, 1));
312}
313
314
321
322static void tex_aux_run_node(void) {
323 halfword n = cur_chr;
324 if (node_token_flagged(n)) {
325 tex_get_token();
326 n = node_token_sum(n,cur_chr);
327 }
328 if (copy_lua_input_nodes_par) {
329 n = tex_copy_node_list(n, null);
330 }
331 tex_tail_append(n);
332 if (tex_nodetype_has_attributes(node_type(n)) && ! node_attr(n)) {
333 attach_current_attribute_list(n);
334 }
335 while (node_next(n)) {
336 n = node_next(n);
337 tex_tail_append(n);
338 if (tex_nodetype_has_attributes(node_type(n)) && ! node_attr(n)) {
339 attach_current_attribute_list(n);
340 }
341 }
342}
343
344
345
346inline static void lmt_bytecode_run(int index)
347{
348 strnumber u = tex_save_cur_string();
349 lmt_token_state.luacstrings = 0;
350 lmt_bytecode_call(index);
351 tex_restore_cur_string(u);
352 if (lmt_token_state.luacstrings > 0) {
353 tex_lua_string_start();
354 }
355}
356
357inline static void lmt_lua_run(int reference, int prefix)
358{
359 strnumber u = tex_save_cur_string();
360 lmt_token_state.luacstrings = 0;
361 lmt_function_call(reference, prefix);
362 tex_restore_cur_string(u);
363 if (lmt_token_state.luacstrings > 0) {
364 tex_lua_string_start();
365 }
366}
367
368static void tex_aux_run_lua_protected_call(void) {
369 if (cur_chr > 0) {
370 lmt_lua_run(cur_chr, 0);
371 } else {
372 tex_normal_error("luacall", "invalid number in protected call");
373 }
374}
375
376void tex_aux_lua_call(halfword cmd, halfword chr) {
377 (void) cmd;
378 if (chr > 0) {
379 lmt_lua_run(chr, 0);
380 } else {
381 tex_normal_error("luacall", "invalid number in unprotected call");
382 }
383}
384
385static void tex_aux_set_lua_value(int a) {
386 if (cur_chr > 0) {
387 lmt_lua_run(cur_chr, a);
388 } else {
389 tex_normal_error("luavalue", "invalid number");
390 }
391}
392
393
407
408static void tex_aux_run_math_space(void) {
409 if (! no_spaces_par && node_type(cur_list.tail) == simple_noad) {
410 noad_options(cur_list.tail) |= noad_option_followed_by_space;
411 }
412}
413
414static void tex_aux_run_space(void) {
415 switch (no_spaces_par) {
416 case 1:
417
418 return;
419 case 2:
420
421 tex_tail_append(tex_new_glue_node(zero_glue, zero_space_skip_glue));
422 glue_font(cur_list.tail) = cur_font_par;
423 break;
424 default:
425
429 {
430 halfword p;
431 if (cur_mode == hmode && cur_cmd == spacer_cmd && cur_list.space_factor != default_space_factor) {
432 if ((cur_list.space_factor >= space_factor_threshold) && (! tex_glue_is_zero(xspace_skip_par))) {
433 p = tex_get_scaled_parameter_glue(xspace_skip_code, xspace_skip_glue);
434 } else {
435 halfword font = cur_font_par;
436 if (tex_glue_is_zero(space_skip_par)) {
437 p = tex_get_scaled_glue(font);
438 } else {
439 p = tex_get_parameter_glue(space_skip_code, space_skip_glue);
440 }
441
442 if (cur_list.space_factor >= space_factor_threshold) {
443 glue_amount(p) += tex_get_scaled_extra_space(font);
444 }
445 glue_options(p) |= glue_option_has_factor;
446 if (space_factor_stretch_limit_par >= scaling_factor && cur_list.space_factor > scaling_factor) {
447 glue_options(p) |= glue_option_is_limited;
448 glue_stretch(p) = tex_xn_over_d(glue_stretch(p), space_factor_stretch_limit_par, scaling_factor);
449 } else {
450 glue_stretch(p) = tex_xn_over_d(glue_stretch(p), cur_list.space_factor, scaling_factor);
451 }
452 if (space_factor_shrink_limit_par >= scaling_factor && cur_list.space_factor > scaling_factor) {
453 glue_options(p) |= glue_option_is_limited;
454 switch (space_factor_mode_par) {
455 case 1:
456 glue_shrink(p) = tex_xn_over_d(glue_shrink(p), space_factor_shrink_limit_par, scaling_factor);
457 break;
458 case 2 :
459 glue_shrink(p) = tex_xn_over_d(glue_shrink(p), 2*scaling_factor, space_factor_shrink_limit_par);
460 break;
461 default:
462 glue_shrink(p) = tex_xn_over_d(glue_shrink(p), scaling_factor, space_factor_shrink_limit_par);
463 break;
464 }
465 } else {
466 switch (space_factor_mode_par) {
467 case 1:
468 glue_shrink(p) = tex_xn_over_d(glue_shrink(p), cur_list.space_factor, scaling_factor);
469 break;
470 case 2 :
471 glue_shrink(p) = tex_xn_over_d(glue_shrink(p), 2*scaling_factor, cur_list.space_factor);
472 break;
473 default:
474 glue_shrink(p) = tex_xn_over_d(glue_shrink(p), scaling_factor, cur_list.space_factor);
475 break;
476 }
477 }
478 }
479 } else if (tex_glue_is_zero(space_skip_par)) {
480
481 p = tex_get_scaled_glue(cur_font_par);
482 } else {
483
484 p = tex_get_parameter_glue(space_skip_code, space_skip_glue);
485 }
486 glue_font(p) = cur_font_par;
487 tex_tail_append(p);
488 }
489 break;
490 }
491}
492
493
494
495static void tex_aux_run_relax(void) {
496 return;
497}
498
499static void tex_aux_run_active(void) {
500
501
502
503
504
505
506 if ((cur_mode == mmode || lmt_nest_state.math_mode) && tex_check_active_math_char(cur_chr)) {
507
508 tex_back_input(cur_tok);
509 } else {
510 cur_cs = tex_active_to_cs(cur_chr, ! lmt_hash_state.no_new_cs);
511 cur_cmd = eq_type(cur_cs);
512 cur_chr = eq_value(cur_cs);
513 tex_x_token();
514 tex_back_input(cur_tok);
515 }
516}
517
518
524
525static void tex_aux_run_ignore_something(void) {
526 switch (cur_chr) {
527 case ignore_space_code:
528
529 do {
530 tex_get_x_token();
531 } while (cur_cmd == spacer_cmd);
532 lmt_main_control_state.control_state = goto_skip_token_state;
533 break;
534 case ignore_par_code:
535
536 do {
537 tex_get_x_token();
538 } while (cur_cmd == spacer_cmd || cur_cmd == end_paragraph_cmd);
539 lmt_main_control_state.control_state = goto_skip_token_state;
540 break;
541 case ignore_argument_code:
542
543 break;
544 case ignore_upto_code:
545 {
546 halfword token = tex_get_token();
547 do {
548 tex_get_token();
549 } while (cur_tok != token);
550 break;
551 }
552 case ignore_nested_upto_code:
553 {
554 halfword starttoken = tex_get_token();
555 halfword stoptoken = tex_get_token();
556 int level = 1;
557 do {
558 tex_get_token();
559 if (cur_tok == starttoken) {
560 ++level;
561 } else if (cur_tok == stoptoken) {
562 --level;
563 }
564 } while (level);
565 break;
566 }
567 case ignore_rest_code:
568 tex_quit_token_list();
569 break;
570 default:
571 break;
572 }
573}
574
575
576
577static void tex_aux_run_math_non_math(void) {
578 if (tracing_commands_par >= 4) {
579 tex_begin_diagnostic();
580 tex_print_format("[math: pushing back %C]", cur_cmd, cur_chr);
581 tex_end_diagnostic();
582 }
583 tex_back_input(cur_tok);
584 tex_begin_paragraph(1, math_char_par_trigger);
585}
586
587
619
620
621
642
643static void tex_aux_run_left_brace(void) {
644 tex_new_save_level(simple_group);
645 update_tex_internal_par_state(0);
646 update_tex_internal_dir_state(0);
647}
648
649
662
663static void tex_aux_run_begin_group(void) {
664 switch (cur_chr) {
665 case semi_simple_group_code:
666 case also_simple_group_code:
667 tex_new_save_level(cur_chr ? also_simple_group : semi_simple_group);
668 update_tex_internal_par_state(0);
669 update_tex_internal_dir_state(0);
670 break;
671 case math_simple_group_code:
672 tex_new_save_level(math_simple_group);
673 update_tex_internal_math_style(cur_mode == mmode ? cur_list.math_style : -1);
674 update_tex_internal_math_scale(cur_mode == mmode ? cur_list.math_scale : 0);
675 break;
676 }
677}
678
679static void tex_aux_run_end_group(void) {
680
681
682
683
684
685
686 switch (cur_group) {
687 case semi_simple_group:
688 case also_simple_group:
689 tex_aux_fixup_directions_and_unsave();
690 break;
691 case math_simple_group:
692 tex_aux_fixup_math_and_unsave();
693 break;
694 default:
695 tex_off_save();
696 break;
697 }
698}
699
700
711
712static void tex_aux_scan_box(int boxcontext, int optional_equal, scaled shift, halfword slot, halfword callback)
713{
714
715 while (1) {
716 tex_get_x_token();
717 if (cur_cmd == spacer_cmd) {
718
719 } else if (cur_cmd == relax_cmd) {
720 optional_equal = 0;
721 } else if (optional_equal && cur_tok == equal_token) {
722 optional_equal = 0;
723 } else {
724 break;
725 }
726 }
727 switch (cur_cmd) {
728 case make_box_cmd:
729 {
730 tex_begin_box(boxcontext, shift, slot, callback);
731 return;
732 }
733 case vcenter_cmd:
734 {
735 tex_run_vcenter();
736 return;
737 }
738 case lua_call_cmd:
739 case lua_protected_call_cmd:
740 case lua_semi_protected_call_cmd:
741 {
742 if (box_leaders_flag(boxcontext)) {
743 tex_aux_run_lua_protected_call();
744 tex_get_next();
745 if (cur_cmd == node_cmd) {
746
747 halfword boxnode = null;
748 tex_aux_run_node();
749 boxnode = tex_pop_tail();
750 if (boxnode) {
751 switch (node_type(boxnode)) {
752 case hlist_node:
753 case vlist_node:
754 case rule_node:
755 case glyph_node:
756 tex_box_end(boxcontext, boxnode, shift, unset_noad_class, slot, callback);
757 return;
758 }
759 }
760 }
761 tex_formatted_error("lua", "invalid function call, proper leader content expected");
762 return;
763 } else {
764 break;
765 }
766 }
767 case lua_value_cmd:
768 {
769 halfword v = tex_scan_lua_value(cur_chr);
770 switch (v) {
771 case no_val_level:
772 tex_box_end(boxcontext, null, shift, unset_noad_class, slot, callback);
773 return;
774 case list_val_level:
775 if (box_leaders_flag(boxcontext)) {
776 switch (node_type(cur_val)) {
777 case hlist_node:
778 case vlist_node:
779 case rule_node:
780
781 tex_box_end(boxcontext, cur_val, shift, unset_noad_class, slot, callback);
782 return;
783 }
784 } else {
785 switch (node_type(cur_val)) {
786 case hlist_node:
787 case vlist_node:
788 tex_box_end(boxcontext, cur_val, shift, unset_noad_class, slot, callback);
789 return;
790 }
791 }
792 }
793 tex_formatted_error("lua", "invalid function call, return type %i instead of %i", v, list_val_level);
794 return;
795 }
796 case hrule_cmd:
797 case vrule_cmd:
798 {
799 if (box_leaders_flag(boxcontext)) {
800 halfword rulenode = tex_aux_scan_rule_spec(cur_cmd == hrule_cmd ? h_rule_type : (cur_cmd == vrule_cmd ? v_rule_type : m_rule_type), cur_chr);
801 tex_box_end(boxcontext, rulenode, shift, unset_noad_class, slot, callback);
802 return;
803 } else {
804 break;
805 }
806 }
807 case char_number_cmd:
808 {
809 if (cur_mode == hmode && box_leaders_flag(boxcontext)) {
810
811 halfword boxnode = null;
812 tex_aux_run_text_char_number();
813 boxnode = tex_pop_tail();
814 tex_box_end(boxcontext, boxnode, shift, unset_noad_class, slot, callback);
815 return;
816 } else {
817 break;
818 }
819 }
820 }
821 tex_handle_error(
822 back_error_type,
823 "A <box> was supposed to be here",
824 "I was expecting to see \\hbox or \\vbox or \\copy or \\box or something like\n"
825 "that. So you might find something missing in your output. But keep trying; you\n"
826 "can fix this later."
827 );
828 if (boxcontext == lua_scan_flag) {
829 tex_box_end(boxcontext, null, shift, unset_noad_class, slot, callback);
830 }
831}
832
833
839
840static void tex_aux_run_move(void) {
841 int code = cur_chr;
842 halfword val = tex_scan_dimension(0, 0, 0, 0, NULL);
843 tex_aux_scan_box(direct_box_flag, 0, code == move_forward_code ? val : - val, -1, 0);
844}
845
846static int leader_flags[] = {
847 a_leaders_flag,
848 c_leaders_flag,
849 x_leaders_flag,
850 g_leaders_flag,
851 u_leaders_flag,
852};
853
854static void tex_aux_run_leader(void) {
855 int code = cur_chr;
856 int callback = (code == u_leaders_code && tex_scan_keyword("callback")) ? tex_scan_integer(0, NULL) : 0;
857 tex_aux_scan_box(leader_flags[code], 0, null_flag, -1, callback);
858}
859
860static void tex_aux_run_legacy(void) {
861 switch (cur_chr) {
862 case shipout_code:
863 tex_aux_scan_box(shipout_flag, 0, null_flag, -1, 0);
864 break;
865 default:
866
867 break;
868 }
869}
870
871static void tex_aux_run_local_box(void) {
872 tex_aux_scan_local_box(cur_chr);
873}
874
875static void tex_aux_run_make_box(void) {
876 tex_begin_box(direct_box_flag, null_flag, -1, 0);
877}
878
879
892
893static void tex_aux_insert_parindent(int indented)
894{
895 if (normalize_line_mode_permitted(normalize_line_mode_par, parindent_skip_mode)) {
896
897 halfword glue = tex_new_glue_node(zero_glue, indent_skip_glue);
898 if (indented) {
899 glue_amount(glue) = par_indent_par;
900 }
901 tex_tail_append(glue);
902 } else if (indented) {
903 halfword box = tex_new_null_box_node(hlist_node, indent_list);
904 box_dir(box) = (singleword) par_direction_par;
905 box_width(box) = par_indent_par;
906 tex_tail_append(box);
907 }
908}
909
910static void tex_aux_remove_parindent(void)
911{
912 halfword tail = cur_list.tail;
913 switch (node_type(tail)) {
914 case glue_node:
915 if (tex_is_par_init_glue(tail)) {
916 glue_amount(tail) = 0;
917 }
918 break;
919 case hlist_node:
920 if (node_subtype(tail) == indent_list) {
921 box_width(tail) = 0;
922 }
923 break;
924 }
925}
926
927static void tex_aux_run_begin_paragraph_vmode(void) {
928 switch (cur_chr) {
929 case noindent_par_code:
930 tex_begin_paragraph(0, no_indent_par_trigger);
931 break;
932 case indent_par_code:
933 tex_begin_paragraph(1, indent_par_trigger);
934 break;
935 case quitvmode_par_code:
936 tex_begin_paragraph(1, force_par_trigger);
937 break;
938 case snapshot_par_code:
939
940 tex_scan_integer(0, NULL);
941 break;
942 case attribute_par_code:
943
944 tex_scan_attribute_register_number();
945 tex_scan_integer(1, NULL);
946 break;
947 case wrapup_par_code:
948 tex_you_cant_error(NULL);
949 break;
950 }
951}
952
953static bool tex_aux_scan_more_toks(halfword *h)
954{
955 int reverse = tex_scan_optional_keyword("reverse");
956 do {
957 tex_get_x_token();
958 } while (cur_cmd == spacer_cmd);
959 if (cur_cmd == left_brace_cmd) {
960 halfword source = tex_scan_toks_normal(1, NULL);
961 if (source) {
962 if (! *h) {
963 *h = source;
964 } else if (reverse) {
965 token_link(tex_tail_of_token_list(*h)) = token_link(source);
966 tex_put_available_token(source);
967 } else {
968 token_link(tex_tail_of_token_list(source)) = token_link(*h);
969 tex_put_available_token(*h);
970 *h = source;
971 }
972 }
973 return true;
974 } else {
975 return false;
976 }
977}
978
979static void tex_aux_run_begin_paragraph_hmode(void) {
980 switch (cur_chr) {
981 case noindent_par_code:
982
983 break;
984 case indent_par_code:
985
986 tex_aux_insert_parindent(1);
987 break;
988 case undent_par_code:
989 tex_aux_remove_parindent();
990 break;
991 case snapshot_par_code:
992 {
993 halfword tag = tex_scan_integer(0, NULL);
994 halfword par = tex_find_par_par(cur_list.head);
995 if (par) {
996 tex_snapshot_par(par, tag);
997 }
998 break;
999 }
1000 case attribute_par_code:
1001 {
1002 halfword att = tex_scan_attribute_register_number();
1003 halfword val = tex_scan_integer(1, NULL);
1004 halfword par = tex_find_par_par(cur_list.head);
1005 if (par) {
1006 if (val == unused_attribute_value) {
1007 tex_unset_attribute(par, att, val);
1008 } else {
1009 tex_set_attribute(par, att, val);
1010 }
1011 }
1012 break;
1013 }
1014 case wrapup_par_code:
1015 {
1016 halfword par = tex_find_par_par(cur_list.head);
1017 if (par) {
1018 halfword h = par_end_par_tokens(par);
1019 if (tex_aux_scan_more_toks(&h)) {
1020 par_end_par_tokens(par) = h;
1021 } else {
1022 tex_handle_error(
1023 normal_error_type,
1024 "I expected a {",
1025 "The '\\wrapuppar' command only accepts an explicit token list."
1026 );
1027 }
1028 }
1029 break;
1030 }
1031 }
1032}
1033
1034static void tex_aux_run_begin_paragraph_mmode(void) {
1035 switch (cur_chr) {
1036 case indent_par_code:
1037 {
1038
1039 halfword p = tex_new_null_box_node(hlist_node, indent_list);
1040 box_width(p) = par_indent_par;
1041 p = tex_new_sub_box(p);
1042 tex_tail_append(p);
1043 break;
1044 }
1045 case snapshot_par_code:
1046
1047 tex_scan_integer(0, NULL);
1048 break;
1049 case attribute_par_code:
1050
1051 tex_scan_attribute_register_number();
1052 tex_scan_integer(1, NULL);
1053 break;
1054 case wrapup_par_code:
1055 tex_you_cant_error(NULL);
1056 break;
1057 }
1058}
1059
1060static void tex_aux_run_new_paragraph(void) {
1061 int context;
1062 switch (cur_cmd) {
1063 case char_given_cmd:
1064 case other_char_cmd:
1065 case letter_cmd:
1066 case accent_cmd:
1067 case char_number_cmd:
1068 case discretionary_cmd:
1069 context = char_par_trigger;
1070 break;
1071 case boundary_cmd:
1072 context = boundary_par_trigger;
1073 break;
1074 case explicit_space_cmd:
1075 context = space_par_trigger;
1076 break;
1077 case math_shift_cmd:
1078 case math_shift_cs_cmd:
1079 context = math_par_trigger;
1080 break;
1081 case hskip_cmd:
1082 context = hskip_par_trigger;
1083 break;
1084 case kern_cmd:
1085 context = kern_par_trigger;
1086 break;
1087 case un_hbox_cmd:
1088 context = un_hbox_char_par_trigger;
1089 break;
1090 case valign_cmd:
1091 context = valign_char_par_trigger;
1092 break;
1093 case vrule_cmd:
1094 context = vrule_char_par_trigger;
1095 break;
1096 default:
1097 context = normal_par_trigger;
1098 break;
1099 }
1100 if (tracing_commands_par >= 4) {
1101 tex_begin_diagnostic();
1102 tex_print_format("[text: pushing back %C]", cur_cmd, cur_chr);
1103 tex_end_diagnostic();
1104 }
1105 tex_back_input(cur_tok);
1106 tex_begin_paragraph(1, context);
1107}
1108
1109
1121
1122void tex_page_boundary_message(const char *s, halfword n)
1123{
1124 if (tracing_pages_par > 0) {
1125 tex_begin_diagnostic();
1126 tex_print_format("[page: boundary, %s, trigger %i]", s, n);
1127 tex_end_diagnostic();
1128 }
1129}
1130
1131static void tex_aux_run_par_boundary(void) {
1132 switch (cur_chr) {
1133 case page_boundary:
1134 {
1135 halfword n = tex_scan_integer(0, NULL);
1136 if (lmt_nest_state.nest_data.ptr == 0 && ! lmt_page_builder_state.output_active) {
1137 halfword boundary = tex_new_node(boundary_node, page_boundary);
1138 boundary_data(boundary) = n;
1139 tex_tail_append(boundary);
1140 if (cur_list.mode == vmode) {
1141 tex_page_boundary_message("build triggered", n);
1142 tex_build_page(boundary_page_context, n);
1143 } else {
1144 tex_page_boundary_message("appended", n);
1145 }
1146 } else {
1147 tex_page_boundary_message("ignored", n);
1148 }
1149 break;
1150 }
1151
1160 default:
1161
1162 tex_aux_run_new_paragraph();
1163 break;
1164 }
1165}
1166
1167static void tex_aux_run_text_boundary(void) {
1168 halfword boundary = tex_new_node(boundary_node, (quarterword) cur_chr);
1169 switch (cur_chr) {
1170 case user_boundary:
1171 case protrusion_boundary:
1172 case optional_boundary:
1173 boundary_data(boundary) = tex_scan_integer(0, NULL);
1174 break;
1175 case page_boundary:
1176
1177 tex_scan_integer(0, NULL);
1178 break;
1179 default:
1180 break;
1181 }
1182 tex_tail_append(boundary);
1183}
1184
1185static void tex_aux_run_math_boundary(void) {
1186 switch (cur_chr) {
1187 case user_boundary:
1188 {
1189 halfword n = tex_new_node(boundary_node, (quarterword) cur_chr);
1190 boundary_data(n) = tex_scan_integer(0, NULL);
1191 tex_tail_append(n);
1192 break;
1193 }
1194 case math_boundary:
1195 {
1196 halfword n = tex_new_node(boundary_node, (quarterword) cur_chr);
1197 boundary_data(n) = tex_scan_integer(0, NULL);
1198 switch (boundary_data(n)) {
1199 case 0: case 1:
1200
1201 break;
1202 case 2: case 3:
1203
1204 boundary_reserved(n) = tex_scan_integer(0, NULL);
1205 break;
1206 }
1207 tex_tail_append(n);
1208 break;
1209 }
1210 case protrusion_boundary:
1211 case page_boundary:
1212
1213 tex_scan_integer(0, NULL);
1214 break;
1215 }
1216}
1217
1218
1224
1225static void tex_aux_run_paragraph_end_vmode(void) {
1226
1227 tex_normal_paragraph(vmode_par_context);
1228 if (cur_list.mode > nomode) {
1229 tex_build_page(vmode_par_page_context, 0);
1230 }
1231}
1232
1233
1234
1235int tex_wrapped_up_paragraph(int context, int final) {
1236 halfword par = tex_find_par_par(cur_list.head);
1237 lmt_main_control_state.last_par_context = context;
1238 if (par) {
1239 int done = 0;
1240 if (par_end_par_tokens(par)) {
1241 halfword eop = par_end_par_tokens(par);
1242 par_end_par_tokens(par) = null;
1243 tex_back_input(cur_tok);
1244
1245 tex_begin_token_list(eop, end_paragraph_text);
1246
1247 tex_delete_token_reference(eop);
1248 done = 1;
1249 }
1250 if (final && end_of_group_par) {
1251 if (! done) {
1252 tex_back_input(cur_tok);
1253 }
1254 tex_begin_token_list(end_of_group_par, end_paragraph_text);
1255 update_tex_end_of_group(null);
1256 done = 1;
1257 }
1258 return done;
1259 } else {
1260 return 0;
1261 }
1262}
1263
1264static void tex_aux_run_paragraph_end_hmode(void) {
1265 if (! tex_wrapped_up_paragraph(normal_par_context, 0)) {
1266 if (lmt_input_state.align_state < 0) {
1267
1268 tex_off_save();
1269 }
1270
1271 tex_end_paragraph(bottom_level_group, normal_par_context);
1272 if (cur_list.mode == vmode) {
1273 tex_build_page(hmode_par_page_context, 0);
1274 }
1275 }
1276}
1277
1278
1279
1280static void tex_aux_run_halign_mmode(void) {
1281 switch (cur_group) {
1282 case math_inline_group:
1283 case math_display_group:
1284 tex_run_alignment_initialize();
1285 break;
1286 default:
1287 tex_off_save();
1288 break;
1289 }
1290}
1291
1292
1299
1300static void tex_aux_run_after_something(void) {
1301 switch (cur_chr) {
1302 case after_group_code:
1303 {
1304 halfword t = tex_get_token();
1305 t = tex_get_available_token(t);
1306 tex_save_for_after_group(t);
1307 break;
1308 }
1309 case after_grouped_code:
1310 {
1311 do {
1312 tex_get_x_token();
1313 } while (cur_cmd == spacer_cmd);
1314 if (cur_cmd == left_brace_cmd) {
1315 halfword source = tex_scan_toks_normal(1, NULL);
1316 if (source) {
1317 if (token_link(source)) {
1318 tex_save_for_after_group(token_link(source));
1319 token_link(source) = null;
1320 }
1321 tex_put_available_token(source);
1322 }
1323 } else {
1324 tex_handle_error(
1325 normal_error_type,
1326 "I expected a {",
1327 "The '\\aftergrouped' command only accepts an explicit token list."
1328 );
1329 }
1330 break;
1331 }
1332 case after_assignment_code:
1333 {
1334 lmt_main_control_state.after_token = tex_get_token();
1335 break;
1336 }
1337 case after_assigned_code:
1338 {
1339 do {
1340 tex_get_x_token();
1341 } while (cur_cmd == spacer_cmd);
1342 if (cur_cmd == left_brace_cmd) {
1343 halfword source = tex_scan_toks_normal(1, NULL);
1344 if (source) {
1345
1346 lmt_main_control_state.after_tokens = token_link(source);
1347 token_link(source) = null;
1348 tex_put_available_token(source);
1349 }
1350 } else {
1351 tex_handle_error(
1352 normal_error_type,
1353 "I expected a {",
1354 "The '\\afterassigned' command only accepts an explicit token list."
1355 );
1356 }
1357 break;
1358 }
1359 case at_end_of_group_code:
1360 {
1361 halfword t = tex_get_token();
1362 halfword r = tex_get_available_token(t);
1363 if (end_of_group_par) {
1364 halfword p = tex_tail_of_token_list(end_of_group_par);
1365 token_link(p) = r;
1366 } else {
1367 halfword p = tex_get_available_token(null);
1368 token_link(p) = r;
1369 update_tex_end_of_group(p);
1370 }
1371 break;
1372 }
1373 case at_end_of_grouped_code:
1374 {
1375 do {
1376 tex_get_x_token();
1377 } while (cur_cmd == spacer_cmd);
1378 if (cur_cmd == left_brace_cmd) {
1379 halfword source = tex_scan_toks_normal(1, NULL);
1380 if (source) {
1381 if (end_of_group_par) {
1382 halfword p = tex_tail_of_token_list(end_of_group_par);
1383 token_link(p) = token_link(source);
1384 token_link(source) = null;
1385 tex_put_available_token(source);
1386 } else {
1387 update_tex_end_of_group(source);
1388 }
1389 }
1390 } else {
1391 tex_handle_error(
1392 normal_error_type,
1393 "I expected a {",
1394 "The '\\endofgrouped' command only accepts an explicit token list."
1395 );
1396 }
1397 break;
1398 }
1399 case at_end_of_file_code:
1400 {
1401 halfword t = tex_get_token();
1402 halfword r = tex_get_available_token(t);
1403 halfword h = tex_get_at_end_of_file();
1404 h = h ? tex_tail_of_token_list(h) : tex_get_available_token(null);
1405 token_link(h) = r;
1406 tex_set_at_end_of_file(h);
1407 break;
1408 }
1409 case at_end_of_filed_code:
1410 {
1411 halfword h = tex_get_at_end_of_file();
1412 if (tex_aux_scan_more_toks(&h)) {
1413 tex_set_at_end_of_file(h);
1414 } else {
1415 tex_handle_error(
1416 normal_error_type,
1417 "I expected a {",
1418 "The '\\endoffiled' command only accepts an explicit token list."
1419 );
1420 }
1421 break;
1422 }
1423 }
1424}
1425
1426inline static void tex_aux_finish_after_assignment(void)
1427{
1428 if (lmt_main_control_state.after_token) {
1429 tex_back_input(lmt_main_control_state.after_token);
1430 lmt_main_control_state.after_token = null;
1431 }
1432 if (lmt_main_control_state.after_tokens) {
1433 tex_begin_inserted_list(lmt_main_control_state.after_tokens);
1434 lmt_main_control_state.after_tokens = null;
1435 }
1436}
1437
1438static void tex_aux_invalid_catcode_table_error(void) {
1439 tex_handle_error(
1440 normal_error_type,
1441 "Invalid \\catcode table",
1442 "All \\catcode table ids must be between 0 and " LMT_TOSTRING(max_n_of_catcode_tables - 1)
1443 );
1444}
1445
1446static void tex_aux_overwrite_catcode_table_error(void) {
1447 tex_handle_error(
1448 normal_error_type,
1449 "Invalid \\catcode table",
1450 "You cannot overwrite the current \\catcode table"
1451 );
1452}
1453
1454static void tex_aux_run_catcode_table(void) {
1455 switch (cur_chr) {
1456 case save_cat_code_table_code:
1457 {
1458 halfword v = tex_scan_integer(0, NULL);
1459 if ((v < 0) || (v >= max_n_of_catcode_tables)) {
1460 tex_aux_invalid_catcode_table_error();
1461 } else if (v == cat_code_table_par) {
1462 tex_aux_overwrite_catcode_table_error();
1463 } else {
1464 tex_copy_cat_codes(cat_code_table_par, v);
1465 }
1466 break;
1467 }
1468 case init_cat_code_table_code:
1469 {
1470 halfword v = tex_scan_integer(0, NULL);
1471 if ((v < 0) || (v >= max_n_of_catcode_tables)) {
1472 tex_aux_invalid_catcode_table_error();
1473 } else if (v == cat_code_table_par) {
1474 tex_aux_overwrite_catcode_table_error();
1475 } else {
1476 tex_initialize_cat_codes(v);
1477 }
1478 break;
1479 }
1480
1492 default:
1493 break;
1494 }
1495}
1496
1497static void tex_aux_run_end_local(void)
1498{
1499 if (tracing_nesting_par > 2) {
1500 tex_local_control_message("leaving token scanner due to local end token");
1501 }
1502 tex_end_local_control();
1503}
1504
1505static void tex_aux_run_lua_function_call(void)
1506{
1507 switch (cur_chr) {
1508 case lua_function_call_code:
1509 {
1510 halfword v = tex_scan_function_reference(0);
1511 lmt_lua_run(v, 0);
1512 break;
1513 }
1514 case lua_bytecode_call_code:
1515 {
1516 halfword v = tex_scan_bytecode_reference(0);
1517 lmt_bytecode_run(v);
1518 break;
1519 }
1520 default:
1521 break;
1522 }
1523}
1524
1525
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567int tex_main_control(void)
1568{
1569 lmt_main_control_state.control_state = goto_next_state;
1570 if (every_job_par) {
1571 tex_begin_token_list(every_job_par, every_job_text);
1572 }
1573 while (1) {
1574 switch (lmt_main_control_state.control_state) {
1575 case goto_next_state:
1576 tex_get_x_token();
1577 break;
1578 case goto_skip_token_state:
1579 lmt_main_control_state.control_state = goto_next_state;
1580 break;
1581 case goto_return_state:
1582 return lmt_main_state.run_state == initializing_state && cur_chr == dump_code;
1583 }
1584
1588 if (tracing_commands_par > 0) {
1589 tex_show_cmd_chr(cur_cmd, cur_chr);
1590 }
1591
1592 tex_aux_big_switch(cur_mode, cur_cmd);
1593 }
1594 return 0;
1595}
1596
1597
1602
1603void tex_local_control_message(const char *s)
1604{
1605 tex_begin_diagnostic();
1606 tex_print_format("[local control: level %i, %s]", lmt_main_control_state.local_level, s);
1607 tex_end_diagnostic();
1608}
1609
1610
1623
1624void tex_local_control(int obeymode)
1625{
1626 full_scanner_status saved_full_status = tex_save_full_scanner_status();
1627 int old_mode = cur_list.mode;
1628 int at_level = lmt_main_control_state.local_level;
1629 lmt_main_control_state.local_level += 1;
1630 lmt_main_control_state.control_state = goto_next_state;
1631 if (! obeymode) {
1632 cur_list.mode = restricted_hmode;
1633 }
1634 while (1) {
1635 if (lmt_main_control_state.control_state == goto_skip_token_state) {
1636 lmt_main_control_state.control_state = goto_next_state;
1637 } else {
1638 tex_get_x_token();
1639 }
1640 if (tracing_commands_par > 0) {
1641 tex_show_cmd_chr(cur_cmd, cur_chr);
1642 }
1643 tex_aux_big_switch(cur_mode, cur_cmd);
1644 if (lmt_main_control_state.local_level <= at_level) {
1645 lmt_main_control_state.control_state = goto_next_state;
1646 if (tracing_nesting_par > 2) {
1647
1648 tex_local_control_message("leaving local control due to level change");
1649 }
1650 break;
1651 } else if (lmt_main_control_state.control_state == goto_return_state) {
1652 if (tracing_nesting_par > 2) {
1653 tex_local_control_message("leaving local control due to triggering");
1654 }
1655 break;
1656 }
1657 }
1658 if (! obeymode) {
1659 cur_list.mode = old_mode;
1660 }
1661 tex_unsave_full_scanner_status(saved_full_status);
1662}
1663
1664inline static int tex_aux_is_iterator_value(halfword tokeninfo)
1665{
1666 if (tokeninfo >= cs_token_flag) {
1667 halfword cs = tokeninfo - cs_token_flag;
1668 return eq_type(cs) == some_item_cmd && eq_value(cs) == last_loop_iterator_code;
1669 } else {
1670 return 0;
1671 }
1672}
1673
1674inline static void tex_push_stack_entry(void)
1675{
1676 halfword state = tex_get_node(loop_state_node_size);
1677 node_type(state) = loop_state_node;
1678 loop_state_count(state) = 0;
1679 if (lmt_main_control_state.loop_stack_head) {
1680 node_prev(lmt_main_control_state.loop_stack_head) = state;
1681 node_next(state) = lmt_main_control_state.loop_stack_head;
1682 } else {
1683 lmt_main_control_state.loop_stack_tail = state;
1684 }
1685 lmt_main_control_state.loop_stack_head = state;
1686}
1687
1688inline static void tex_pop_stack_entry(void)
1689{
1690 halfword state = lmt_main_control_state.loop_stack_head;
1691 lmt_main_control_state.loop_stack_head = node_next(state);
1692 if (! lmt_main_control_state.loop_stack_head) {
1693 lmt_main_control_state.loop_stack_tail = null;
1694 }
1695 tex_free_node(state, loop_state_node_size);
1696}
1697
1698halfword tex_nested_loop_iterator(void)
1699{
1700 halfword delta = tex_scan_integer(0, NULL);
1701 halfword state = lmt_main_control_state.loop_stack_tail;
1702 while (delta-- > 0 && state) {
1703 state = node_prev(state);
1704 }
1705 return state ? loop_state_count(state) : 0;
1706}
1707
1708halfword tex_previous_loop_iterator(void)
1709{
1710 halfword delta = tex_scan_integer(0, NULL);
1711 halfword state = lmt_main_control_state.loop_stack_head;
1712 while (delta-- && state) {
1713 state = node_next(state);
1714 }
1715 return state ? loop_state_count(state) : 0;
1716}
1717
1718inline static halfword tex_previous_loop_iterator_delta(int delta)
1719{
1720 halfword state = lmt_main_control_state.loop_stack_head;
1721 while (delta-- && state) {
1722 state = node_next(state);
1723 }
1724 return state ? loop_state_count(state) : 0;
1725}
1726
1727inline static void tex_update_stack_entry(halfword count)
1728{
1729 loop_state_count(lmt_main_control_state.loop_stack_head) = count;
1730}
1731
1732void tex_begin_local_control(void)
1733{
1734 halfword code = cur_chr;
1735 if (tracing_nesting_par > 2) {
1736 tex_local_control_message("entering token scanner via primitive");
1737 }
1738 switch (code) {
1739 case local_control_list_code:
1740 {
1741 halfword t;
1742 halfword h = tex_scan_toks_normal(0, &t);
1743 halfword r = tex_get_available_token(token_val(end_local_cmd, 0));
1744 tex_begin_inserted_list(r);
1745 tex_begin_token_list(h, local_text);
1746 break;
1747 }
1748 case local_control_token_code:
1749 {
1750 halfword t = tex_get_token();
1751 halfword h = get_reference_token();
1752 halfword r = tex_get_available_token(token_val(end_local_cmd, 0));
1753 tex_store_new_token(h, t);
1754 tex_begin_inserted_list(r);
1755 tex_begin_token_list(h, local_text);
1756 break;
1757 }
1758
1773 case local_control_loop_code:
1774 case expanded_loop_code:
1775 case unexpanded_loop_code:
1776 case local_control_repeat_code:
1777 case expanded_repeat_code:
1778 case unexpanded_repeat_code:
1779 case local_control_endless_code:
1780 case expanded_endless_code:
1781 case unexpanded_endless_code:
1782 {
1783 halfword tail;
1784 int looping = code >= local_control_loop_code && code <= unexpanded_loop_code;
1785 int endless = code >= local_control_endless_code && code <= unexpanded_endless_code;
1786 halfword first = looping ? tex_scan_integer(1, NULL) : 1;
1787 halfword last = endless ? max_integer : tex_scan_integer(1, NULL);
1788 halfword step = looping ? tex_scan_integer(1, NULL) : 1;
1789 halfword head = tex_scan_toks_normal(0, &tail);
1790 if (token_link(head) && step) {
1791 int savedloop = lmt_main_control_state.loop_iterator;
1792 int savedquit = lmt_main_control_state.quit_loop;
1793 lmt_main_control_state.loop_iterator = 0;
1794 lmt_main_control_state.quit_loop = 0;
1795 ++lmt_main_control_state.loop_nesting;
1796 tex_push_stack_entry();
1797 switch (code) {
1798 case local_control_loop_code:
1799 case local_control_repeat_code:
1800 case local_control_endless_code:
1801 {
1802
1807
1808 LOCALCONTROL:
1809 for (halfword i = first; step > 0 ? i <= last : i >= last; i += step) {
1810 lmt_main_control_state.loop_iterator = i;
1811 tex_update_stack_entry(i);
1812 lmt_main_control_state.quit_loop = 0;
1813
1814 tex_begin_inserted_list(tex_get_available_token(token_val(end_local_cmd, 0)));
1815
1816 tex_begin_token_list(head, local_loop_text);
1817 tex_local_control(1);
1818
1819 tex_cleanup_input_state();
1820 if (lmt_main_control_state.quit_loop) {
1821 break;
1822 } else if (endless && i >= last) {
1823 goto LOCALCONTROL;
1824 }
1825 }
1826 tex_flush_token_list(head);
1827 break;
1828 }
1829 case expanded_loop_code:
1830 case expanded_repeat_code:
1831 case expanded_endless_code:
1832 {
1833 halfword h = null;
1834 halfword t = null;
1835 full_scanner_status saved_full_status = tex_save_full_scanner_status();
1836 strnumber u = tex_save_cur_string();
1837 tex_store_new_token(tail, right_brace_token + '}');
1838 EXPANDED:
1839 for (halfword i = first; step > 0 ? i <= last : i >= last; i += step) {
1840 halfword lt = null;
1841 halfword lh = null;
1842 ++lmt_input_state.align_state;
1843 lmt_main_control_state.loop_iterator = i;
1844 tex_update_stack_entry(i);
1845 tex_begin_token_list(head, loop_text);
1846 lh = tex_scan_toks_expand(1, <, 0, 0);
1847 if (token_link(lh)) {
1848 if (h) {
1849 token_link(t) = token_link(lh);
1850 } else {
1851 h = token_link(lh);
1852 }
1853 t = lt;
1854 }
1855 tex_put_available_token(lh);
1856 tex_cleanup_input_state();
1857 if (lmt_main_control_state.quit_loop) {
1858 break;
1859 } else if (endless && i >= last) {
1860 goto EXPANDED;
1861 }
1862 }
1863 tex_unsave_full_scanner_status(saved_full_status);
1864 tex_restore_cur_string(u);
1865 tex_flush_token_list(head);
1866 tex_begin_inserted_list(h);
1867 break;
1868 }
1869 case unexpanded_loop_code:
1870 case unexpanded_repeat_code:
1871 case unexpanded_endless_code:
1872 {
1873
1879
1880 halfword h = token_link(head);
1881 halfword tt = null;
1882 halfword t = h;
1883 halfword b = 0;
1884 while (token_link(t)) {
1885 t = token_link(t);
1886 if (! b && tex_aux_is_iterator_value(token_info(t))) {
1887 b = 1;
1888 }
1889 }
1890 tt = t;
1891 UNEXPANDED:
1892 for (halfword i = first + step; step > 0 ? i <= last : i >= last; i += step) {
1893 halfword hh = h;
1894 while (1) {
1895 t = tex_store_new_token(t, token_info(hh));
1896 if (b && tex_aux_is_iterator_value(token_info(t))) {
1897 halfword v = (i < min_iterator_value) ? min_iterator_value : (i > max_iterator_value ? max_iterator_value : i);
1898 token_info(t) = token_val(iterator_value_cmd, v < 0 ? 0x100000 - v : v);
1899 }
1900 if (hh == tt) {
1901 break;
1902 } else {
1903 hh = token_link(hh);
1904 }
1905 }
1906 if (endless && i >= last) {
1907 goto UNEXPANDED;
1908 }
1909 }
1910 if (b) {
1911 halfword hh = h;
1912 while (1) {
1913 if (tex_aux_is_iterator_value(token_info(hh))) {
1914 halfword v = (first < min_iterator_value) ? min_iterator_value : (first > max_iterator_value ? max_iterator_value : first);
1915 token_info(hh) = token_val(iterator_value_cmd, v < 0 ? 0x100000 - v : v);
1916 }
1917 if (hh == tt) {
1918 break;
1919 } else {
1920 hh = token_link(hh);
1921 }
1922 }
1923 }
1924 tex_put_available_token(head);
1925 tex_begin_inserted_list(h);
1926 break;
1927 }
1928 }
1929 tex_pop_stack_entry();
1930 --lmt_main_control_state.loop_nesting;
1931 lmt_main_control_state.quit_loop = savedquit;
1932 lmt_main_control_state.loop_iterator = savedloop;
1933 return;
1934 } else {
1935 tex_flush_token_list(head);
1936 }
1937 return;
1938 }
1939 }
1940 tex_local_control(1);
1941
1942}
1943
1944void tex_end_local_control(void )
1945{
1946 if (lmt_main_control_state.local_level > 0) {
1947 lmt_main_control_state.local_level -= 1;
1948 } else {
1949 tex_local_control_message("redundant end local control");
1950 }
1951}
1952
1953
1969
1970halfword tex_local_scan_box(void)
1971{
1972 int old_mode = cur_list.mode;
1973 int old_level = lmt_main_control_state.local_level;
1974 cur_list.mode = restricted_hmode;
1975 tex_aux_scan_box(lua_scan_flag, 0, null_flag, -1, 0);
1976 if (lmt_main_control_state.local_level == old_level) {
1977
1978 if (tracing_nesting_par > 2) {
1979 tex_local_control_message("entering at end of box scanning");
1980 }
1981 tex_local_control(1);
1982 } else {
1983
1984
1989 lmt_main_control_state.local_level = old_level;
1990 }
1991 cur_list.mode = old_mode;
1992 return cur_box;
1993}
1994
1995
2002
2003static void tex_aux_wrapup_local_scan_box(void)
2004{
2005
2010 lmt_main_control_state.local_level -= 1;
2011}
2012
2013static void tex_aux_run_insert_dollar_sign(void)
2014{
2015 tex_back_input(cur_tok);
2016 cur_tok = dollar_token_m;
2017 tex_handle_error(
2018 insert_error_type,
2019 "Missing $ inserted",
2020 "I've inserted a begin-math/end-math symbol since I think you left one out.\n"
2021 "Proceed, with fingers crossed."
2022 );
2023}
2024
2025
2031
2032void tex_you_cant_error(const char *helpinfo)
2033{
2034 tex_handle_error(
2035 normal_error_type,
2036 "You can't use '%C' in %M", cur_cmd, cur_chr, cur_list.mode,
2037 helpinfo
2038 );
2039}
2040
2041
2051
2052static void tex_aux_run_illegal_case(void)
2053{
2054 tex_you_cant_error(
2055 "Sorry, but I'm not programmed to handle this case;\n"
2056 "I'll just pretend that you didn''t ask for it.\n"
2057 "If you're in the wrong mode, you might be able to\n"
2058 "return to the right one by typing 'I}' or 'I$' or 'I\\par'."
2059 );
2060}
2061
2062
2069
2070int tex_in_privileged_mode(void)
2071{
2072 if (cur_list.mode > nomode) {
2073 return 1;
2074 } else {
2075 tex_aux_run_illegal_case();
2076 return 0;
2077 }
2078}
2079
2080
2091
2092static void tex_aux_run_end_job(void) {
2093 if (tex_in_privileged_mode()) {
2094 if ((page_head == lmt_page_builder_state.page_tail)
2095 && (cur_list.head == cur_list.tail)
2096 && (lmt_page_builder_state.dead_cycles == 0)) {
2097
2098 lmt_main_control_state.control_state = goto_return_state;
2099 } else {
2100
2104 tex_back_input(cur_tok);
2105 tex_tail_append(tex_new_null_box_node(hlist_node, unknown_list));
2106 box_width(cur_list.tail) = hsize_par;
2107 tex_tail_append(tex_new_glue_node(fi_ll_glue, user_skip_glue));
2108 tex_tail_append(tex_new_penalty_node(final_penalty, final_penalty_subtype));
2109 tex_build_page(end_page_context, 0);
2110 }
2111 }
2112}
2113
2114
2128
2129static const int glue_filler_codes[] = {
2130 fi_l_glue,
2131 fi_ll_glue,
2132 fi_ss_glue,
2133 fi_l_neg_glue,
2134};
2135
2136static void tex_aux_run_glue(void)
2137{
2138 halfword code = cur_chr;
2139 switch (code) {
2140 case fi_l_code:
2141 case fi_ll_code:
2142 case fi_ss_code:
2143 case fi_l_neg_code:
2144 tex_tail_append(tex_new_glue_node(glue_filler_codes[code], user_skip_glue));
2145 break;
2146 case skip_code:
2147 {
2148 halfword v = tex_scan_glue(glue_val_level, 0, 1);
2149 halfword g = tex_new_glue_node(v, user_skip_glue);
2150
2151 if (cur_mode == mmode) {
2152
2153 glue_options(g) |= glue_option_no_auto_break;
2154 }
2155 tex_tail_append(g);
2156 tex_flush_node(v);
2157 break;
2158 }
2159 default:
2160 break;
2161 }
2162}
2163
2164static void tex_aux_run_mglue(void)
2165{
2166 switch (cur_chr) {
2167 case normal_mskip_code:
2168 {
2169 halfword v = tex_scan_glue(muglue_val_level, 0, 0);
2170 tex_tail_append(tex_new_glue_node(v, mu_glue));
2171 tex_flush_node(v);
2172 break;
2173 }
2174 case atom_mskip_code:
2175 {
2176 halfword left = tex_scan_math_class_number(0);
2177 halfword right = tex_scan_math_class_number(0);
2178 halfword style = tex_scan_math_style_identifier(0, 0);
2179 halfword node = tex_math_spacing_glue(left, right, style);
2180 if (node) {
2181 tex_tail_append(node);
2182 } else {
2183
2184 tex_tail_append(tex_new_glue_node(zero_glue, mu_glue));
2185 }
2186 break;
2187 }
2188 }
2189}
2190
2191
2202
2203void tex_off_save(void)
2204{
2205 if (cur_group == bottom_level_group) {
2206
2207 tex_handle_error(normal_error_type, "Extra %C", cur_cmd, cur_chr,
2208 "Things are pretty mixed up, but I think the worst is over."
2209 );
2210 } else {
2211 const char * helpinfo =
2212 "I've inserted something that you may have forgotten. (See the <inserted text>\n"
2213 "above.) With luck, this will get me unwedged.";
2214 halfword h = tex_get_available_token(null);
2215 tex_back_input(cur_tok);
2216
2220 switch (cur_group) {
2221 case also_simple_group:
2222 case semi_simple_group:
2223 case math_simple_group:
2224 {
2225 set_token_info(h, deep_frozen_end_group_token);
2226 tex_handle_error(
2227 normal_error_type,
2228 "Missing \\endgroup inserted",
2229 helpinfo
2230 );
2231 break;
2232 }
2233 case math_inline_group:
2234 case math_display_group:
2235 case math_number_group:
2236 {
2237 set_token_info(h, math_shift_token + '$');
2238 tex_handle_error(
2239 normal_error_type,
2240 "Missing $ inserted",
2241 helpinfo
2242 );
2243 break;
2244 }
2245 case math_fence_group:
2246 {
2247
2248 halfword q = tex_get_available_token(period_token);
2249 halfword f = node_next(cur_list.head);
2250 set_token_info(h, deep_frozen_right_token);
2251 set_token_link(h, q);
2252 if (! (f && node_type(f) == fence_noad && has_noad_option_nocheck(f))) {
2253 tex_handle_error(
2254 normal_error_type,
2255 "Missing \\right. inserted",
2256 helpinfo
2257 );
2258 }
2259 break;
2260 }
2261 default:
2262 {
2263 set_token_info(h, right_brace_token + '}');
2264 tex_handle_error(
2265 normal_error_type,
2266 "Missing } inserted",
2267 helpinfo
2268 );
2269 break;
2270 }
2271 }
2272 tex_begin_inserted_list(h);
2273 }
2274}
2275
2276
2285
2286
2287
2288typedef enum saved_discretionary_entries {
2289 saved_discretionary_component_entry = 0,
2290 saved_discretionary_n_of_records = 1,
2291} saved_discretionary_entries;
2292
2293# define saved_discretionary_component saved_value_1(saved_discretionary_component_entry)
2294
2295inline static void saved_discretionary_initialize(void)
2296{
2297 saved_type(0) = saved_record_0;
2298 saved_record(0) = discretionary_save_type;
2299}
2300
2301inline static int saved_discretionary_current_component(void)
2302{
2303 return saved_type(saved_discretionary_component_entry - saved_discretionary_n_of_records) == saved_record_0
2304 ? saved_value_1(saved_discretionary_component_entry - saved_discretionary_n_of_records) : -1 ;
2305}
2306
2307inline static void saved_discretionary_update_component(void)
2308{
2309 saved_value_1(saved_discretionary_component_entry - saved_discretionary_n_of_records) += 1;
2310}
2311
2312void tex_show_discretionary_group(void)
2313{
2314 tex_print_str_esc("discretionary");
2315 tex_aux_show_group_count(saved_discretionary_component);
2316}
2317
2318int tex_show_discretionary_record(void)
2319{
2320 tex_print_str("discretionary ");
2321 switch (save_type(lmt_save_state.save_stack_data.ptr)) {
2322 case saved_record_0:
2323 tex_print_format("component %i", saved_discretionary_component);
2324 break;
2325 default:
2326 return 0;
2327 }
2328 return 1;
2329}
2330
2331static void tex_aux_run_discretionary(void)
2332{
2333 switch (cur_chr) {
2334 case normal_discretionary_code:
2335
2336 {
2337 halfword d = tex_new_disc_node(normal_discretionary_code);
2338 tex_tail_append(d);
2339 while (1) {
2340 switch (tex_scan_character("pocbnPOCBN", 0, 1, 0)) {
2341 case 0:
2342 goto DONE;
2343 case 'p': case 'P':
2344 switch (tex_scan_character("eorEOR", 0, 0, 0)) {
2345 case 'e': case 'E':
2346 if (tex_scan_mandate_keyword("penalty", 2)) {
2347 set_disc_penalty(d, tex_scan_integer(0, NULL));
2348 }
2349 break;
2350 case 'o': case 'O':
2351 if (tex_scan_mandate_keyword("postword", 2)) {
2352 set_disc_option(d, disc_option_post_word);
2353 }
2354 break;
2355 case 'r': case 'R':
2356 if (tex_scan_mandate_keyword("preword", 2)) {
2357 set_disc_option(d, disc_option_pre_word);
2358 }
2359 break;
2360 default:
2361 tex_aux_show_keyword_error("penalty|postword|preword");
2362 goto DONE;
2363 }
2364 break;
2365 case 'b': case 'B':
2366 if (tex_scan_mandate_keyword("break", 1)) {
2367 set_disc_option(d, disc_option_prefer_break);
2368 }
2369 break;
2370 case 'n': case 'N':
2371 if (tex_scan_mandate_keyword("nobreak", 1)) {
2372 set_disc_option(d, disc_option_prefer_nobreak);
2373 }
2374 break;
2375 case 'o': case 'O':
2376 if (tex_scan_mandate_keyword("options", 1)) {
2377 set_disc_options(d, tex_scan_integer(0, NULL));
2378 }
2379 break;
2380 case 'c': case 'C':
2381 if (tex_scan_mandate_keyword("class", 1)) {
2382 set_disc_class(d, tex_scan_math_class_number(0));
2383 }
2384 break;
2385 default:
2386 goto DONE;
2387 }
2388 }
2389 DONE:
2390 saved_discretionary_initialize();
2391 saved_discretionary_component = 0;
2392 lmt_save_state.save_stack_data.ptr += saved_discretionary_n_of_records;
2393 tex_new_save_level(discretionary_group);
2394 tex_scan_left_brace();
2395 tex_push_nest();
2396 cur_list.mode = restricted_hmode;
2397 cur_list.space_factor = default_space_factor;
2398 }
2399 break;
2400 case explicit_discretionary_code:
2401
2402 if (hyphenation_permitted(hyphenation_mode_par, explicit_hyphenation_mode)) {
2403 int c = tex_get_pre_hyphen_char(cur_lang_par);
2404 halfword d = tex_new_disc_node(explicit_discretionary_code);
2405 tex_tail_append(d);
2406 if (c > 0) {
2407 tex_set_disc_field(d, pre_break_code, tex_new_char_node(glyph_unset_subtype, cur_font_par, c, 1));
2408 }
2409 c = tex_get_post_hyphen_char(cur_lang_par);
2410 if (c > 0) {
2411 tex_set_disc_field(d, post_break_code, tex_new_char_node(glyph_unset_subtype, cur_font_par, c, 1));
2412 }
2413 disc_penalty(d) = tex_explicit_disc_penalty(hyphenation_mode_par);
2414 }
2415 break;
2416 case automatic_discretionary_code:
2417 case mathematics_discretionary_code:
2418
2419 if (hyphenation_permitted(hyphenation_mode_par, automatic_hyphenation_mode)) {
2420 halfword c = tex_get_pre_exhyphen_char(cur_lang_par);
2421 halfword d = tex_new_disc_node(automatic_discretionary_code);
2422 tex_tail_append(d);
2423
2424 if (c <= 0) {
2425 c = ex_hyphen_char_par;
2426 }
2427 if (c > 0) {
2428 tex_set_disc_field(d, pre_break_code, tex_new_char_node(glyph_unset_subtype, cur_font_par, c, 1));
2429 }
2430 c = tex_get_post_exhyphen_char(cur_lang_par);
2431 if (c > 0) {
2432 tex_set_disc_field(d, post_break_code, tex_new_char_node(glyph_unset_subtype, cur_font_par, c, 1));
2433 }
2434 c = ex_hyphen_char_par;
2435 if (c > 0) {
2436 tex_set_disc_field(d, no_break_code, tex_new_char_node(glyph_unset_subtype, cur_font_par, c, 1));
2437 }
2438 disc_penalty(d) = tex_automatic_disc_penalty(hyphenation_mode_par);
2439 } else {
2440 halfword c = ex_hyphen_char_par;
2441 if (c > 0) {
2442 c = tex_new_char_node(glyph_unset_subtype, cur_font_par, c, 1);
2443 set_glyph_discpart(c, glyph_discpart_always);
2444 tex_tail_append(c);
2445 }
2446 }
2447 break;
2448 }
2449}
2450
2451
2457
2458static void tex_aux_finish_discretionary(void)
2459{
2460 halfword current, next;
2461 int length = 0;
2462 tex_unsave();
2463
2469 current = cur_list.head;
2470 next = node_next(current);
2471 while (next) {
2472 switch (node_type(next)) {
2473 case glyph_node:
2474 case hlist_node:
2475 case vlist_node:
2476 case rule_node:
2477 case kern_node:
2478 break;
2479 case glue_node:
2480 if (hyphenation_permitted(hyphenation_mode_par, permit_glue_hyphenation_mode)) {
2481 if (glue_stretch_order(next)) {
2482 glue_stretch(next) = 0;
2483 glue_stretch_order(next) = 0;
2484 }
2485 if (glue_shrink_order(next)) {
2486 glue_shrink(next) = 0;
2487 glue_shrink_order(next) = 0;
2488 }
2489 break;
2490 } else {
2491
2492 }
2493 default:
2494 if (hyphenation_permitted(hyphenation_mode_par, permit_all_hyphenation_mode)) {
2495 break;
2496 } else {
2497 tex_handle_error(
2498 normal_error_type,
2499 "Improper discretionary list",
2500 "Discretionary lists must contain only glyphs, boxes, rules and kerns."
2501 );
2502 tex_begin_diagnostic();
2503 tex_print_str("The following discretionary sublist has been deleted:");
2504 tex_print_levels();
2505 tex_show_box(next);
2506 tex_end_diagnostic();
2507 tex_flush_node_list(next);
2508 node_next(current) = null;
2509 goto DONE;
2510 }
2511 }
2512 node_prev(next) = current;
2513 current = next;
2514 next = node_next(current);
2515 ++length;
2516 }
2517 DONE:
2518 next = node_next(cur_list.head);
2519 tex_pop_nest();
2520 {
2521 halfword discnode = cur_list.tail;
2522 switch (saved_discretionary_current_component()) {
2523 case 0:
2524 if (length > 0) {
2525 tex_set_disc_field(discnode, pre_break_code, next);
2526 }
2527 break;
2528 case 1:
2529 if (length > 0) {
2530 tex_set_disc_field(discnode, post_break_code, next);
2531 }
2532 break;
2533 case 2:
2534
2538 if (length > 0) {
2539 if (cur_mode == mmode && ! hyphenation_permitted(hyphenation_mode_par, permit_math_replace_hyphenation_mode)) {
2540 tex_handle_error(
2541 normal_error_type,
2542 "Illegal math \\discretionary",
2543 "Sorry: The third part of a discretionary break must be empty, in math formulas. I\n"
2544 "had to delete your third part."
2545 );
2546 tex_flush_node_list(next);
2547 } else {
2548 tex_set_disc_field(discnode, no_break_code, next);
2549 }
2550 }
2551 if (! hyphenation_permitted(hyphenation_mode_par, normal_hyphenation_mode)) {
2552 halfword replace = disc_no_break_head(discnode);
2553 cur_list.tail = node_prev(cur_list.tail);
2554 node_next(cur_list.tail) = null;
2555 if (replace) {
2556 tex_tail_append(replace);
2557 cur_list.tail = disc_no_break_tail(discnode);
2558 tex_set_disc_field(discnode, no_break_code, null);
2559 tex_set_discpart(discnode, replace, disc_no_break_tail(discnode), glyph_discpart_replace);
2560 }
2561 tex_flush_node(discnode);
2562 } else if (cur_mode == mmode && disc_class(discnode) != unset_disc_class) {
2563 halfword noad = null;
2564 cur_list.tail = node_prev(discnode);
2565 node_prev(discnode ) = null;
2566 node_next(discnode ) = null;
2567 noad = tex_math_make_disc(discnode);
2568 tex_tail_append(noad);
2569 }
2570
2571 lmt_save_state.save_stack_data.ptr -= saved_discretionary_n_of_records;
2572 return;
2573 default:
2574 tex_confusion("finish discretionary");
2575 return;
2576 }
2577 saved_discretionary_update_component();
2578 tex_new_save_level(discretionary_group);
2579 tex_scan_left_brace();
2580 tex_push_nest();
2581 cur_list.mode = restricted_hmode;
2582 cur_list.space_factor = default_space_factor;
2583 }
2584}
2585
2586
2597
2598static void tex_aux_extra_right_brace_error(void)
2599{
2600 const char *helpinfo =
2601 "I've deleted a group-closing symbol because it seems to be spurious, as in\n"
2602 "'$x}$'. But perhaps the } is legitimate and you forgot something else, as in\n"
2603 "'\\hbox{$x}'.";
2604 switch (cur_group) {
2605 case also_simple_group:
2606 case semi_simple_group:
2607 tex_handle_error(
2608 normal_error_type,
2609 "Extra }, or forgotten %eendgroup",
2610 helpinfo
2611 );
2612 break;
2613 case math_simple_group:
2614 tex_handle_error(
2615 normal_error_type,
2616 "Extra }, or forgotten %eendmathgroup",
2617 helpinfo
2618 );
2619 break;
2620 case math_inline_group:
2621 case math_display_group:
2622 case math_number_group:
2623 tex_handle_error(
2624 normal_error_type,
2625 "Extra }, or forgotten $",
2626 helpinfo
2627 );
2628 break;
2629 case math_fence_group:
2630 tex_handle_error(
2631 normal_error_type,
2632 "Extra }, or forgotten %eright",
2633 helpinfo
2634 );
2635 break;
2636 }
2637 ++lmt_input_state.align_state;
2638}
2639
2640inline static void tex_aux_finish_hbox(void)
2641{
2642 tex_aux_fixup_directions_only();
2643 tex_package(hbox_code);
2644}
2645
2646inline static void tex_aux_finish_adjusted_hbox(void)
2647{
2648 lmt_packaging_state.post_adjust_tail = post_adjust_head;
2649 lmt_packaging_state.pre_adjust_tail = pre_adjust_head;
2650 lmt_packaging_state.post_migrate_tail = post_migrate_head;
2651 lmt_packaging_state.pre_migrate_tail = pre_migrate_head;
2652 tex_package(hbox_code);
2653}
2654
2655inline static void tex_aux_finish_vbox(void)
2656{
2657
2658 if (! tex_wrapped_up_paragraph(vbox_par_context, 1)) {
2659 tex_end_paragraph(vbox_group, vbox_par_context);
2660 tex_package(vbox_code);
2661 }
2662}
2663
2664inline static void tex_aux_finish_vtop(void)
2665{
2666 if (! tex_wrapped_up_paragraph(vtop_par_context, 1)) {
2667 tex_end_paragraph(vtop_group, vtop_par_context);
2668 tex_package(vtop_code);
2669 }
2670}
2671
2672inline static void tex_aux_finish_dbox(void)
2673{
2674 if (! tex_wrapped_up_paragraph(dbox_par_context, 1)) {
2675 tex_end_paragraph(dbox_group, dbox_par_context);
2676 tex_package(dbox_code);
2677 }
2678}
2679
2680inline static void tex_aux_finish_simple_group(void)
2681{
2682 tex_aux_fixup_directions_and_unsave();
2683}
2684
2685static void tex_aux_finish_bottom_level_group(void)
2686{
2687 tex_handle_error(
2688 normal_error_type,
2689 "Too many }'s",
2690 "You've closed more groups than you opened. Such booboos are generally harmless,\n"
2691 "so keep going."
2692 );
2693}
2694
2695inline static void tex_aux_finish_output(void)
2696{
2697 tex_pop_text_dir_ptr();
2698 tex_resume_after_output();
2699}
2700
2701static void tex_aux_run_right_brace(void)
2702{
2703 switch (cur_group) {
2704 case bottom_level_group:
2705 tex_aux_finish_bottom_level_group();
2706 break;
2707 case simple_group:
2708 tex_aux_finish_simple_group();
2709 break;
2710 case hbox_group:
2711 tex_aux_finish_hbox();
2712 break;
2713 case adjusted_hbox_group:
2714 tex_aux_finish_adjusted_hbox();
2715 break;
2716 case vbox_group:
2717 tex_aux_finish_vbox();
2718 break;
2719 case vtop_group:
2720 tex_aux_finish_vtop();
2721 break;
2722 case dbox_group:
2723 tex_aux_finish_dbox();
2724 break;
2725 case align_group:
2726 tex_finish_alignment_group();
2727 break;
2728 case no_align_group:
2729 tex_finish_no_alignment_group();
2730 break;
2731 case output_group:
2732 tex_aux_finish_output();
2733 break;
2734 case math_group:
2735 case math_component_group:
2736 case math_stack_group:
2737 tex_finish_math_group();
2738 break;
2739 case discretionary_group:
2740 tex_aux_finish_discretionary();
2741 break;
2742 case insert_group:
2743 tex_finish_insert_group();
2744 break;
2745 case vadjust_group:
2746 tex_finish_vadjust_group();
2747 break;
2748 case vcenter_group:
2749 tex_finish_vcenter_group();
2750 break;
2751 case math_fraction_group:
2752 tex_finish_math_fraction();
2753 break;
2754 case math_radical_group:
2755 tex_finish_math_radical();
2756 break;
2757 case math_operator_group:
2758 tex_finish_math_operator();
2759 break;
2760 case math_choice_group:
2761 tex_finish_math_choice();
2762 break;
2763 case also_simple_group:
2764 case math_simple_group:
2765
2766 tex_aux_run_end_group();
2767 break;
2768 case semi_simple_group:
2769 case math_inline_group:
2770 case math_display_group:
2771 case math_number_group:
2772 case math_fence_group:
2773 tex_aux_extra_right_brace_error();
2774 break;
2775 case local_box_group:
2776 tex_aux_finish_local_box();
2777 break;
2778 default:
2779 tex_confusion("right brace");
2780 break;
2781 }
2782}
2783
2784
2790
2791void tex_normal_paragraph(int context)
2792{
2793 int ignore = 0;
2794 lmt_main_control_state.last_par_context = context;
2795 lmt_paragraph_context_callback(context, &ignore);
2796 if (! ignore) {
2797 if (looseness_par) {
2798 update_tex_looseness(0);
2799 }
2800 if (hang_indent_par) {
2801 update_tex_hang_indent(0);
2802 }
2803 if (hang_after_par != 1) {
2804 update_tex_hang_after(1);
2805 }
2806 if (par_shape_par) {
2807 update_tex_par_shape(null);
2808 }
2809 if (inter_line_penalties_par) {
2810 update_tex_inter_line_penalties(null);
2811 }
2812 if (emergency_left_skip_par) {
2813 update_tex_emergency_left_skip(null);
2814 }
2815 if (emergency_right_skip_par) {
2816 update_tex_emergency_right_skip(null);
2817 }
2818 if (local_interline_penalty_par) {
2819 update_tex_local_interline_penalty(0);
2820 }
2821 if (local_broken_penalty_par) {
2822 update_tex_local_broken_penalty(0);
2823 }
2824 if (local_tolerance_par) {
2825 update_tex_local_tolerance(0);
2826 }
2827 if (local_pre_tolerance_par) {
2828 update_tex_local_pre_tolerance(0);
2829 }
2830 if (single_line_penalty_par) {
2831 update_tex_single_line_penalty(0);
2832 }
2833 }
2834}
2835
2836
2847
2848static void tex_aux_wrapup_leader_box(halfword boxcontext, halfword boxnode, halfword callback)
2849{
2850
2851 do {
2852 tex_get_x_token();
2853 } while (cur_cmd == spacer_cmd || cur_cmd == relax_cmd);
2854 if ((cur_cmd == hskip_cmd && cur_mode != vmode) || (cur_cmd == vskip_cmd && cur_mode == vmode)) {
2855 tex_aux_run_glue();
2856 switch (boxcontext) {
2857 case a_leaders_flag:
2858 node_subtype(cur_list.tail) = a_leaders;
2859 break;
2860 case c_leaders_flag:
2861 node_subtype(cur_list.tail) = c_leaders;
2862 break;
2863 case x_leaders_flag:
2864 node_subtype(cur_list.tail) = x_leaders;
2865 break;
2866 case g_leaders_flag:
2867 node_subtype(cur_list.tail) = g_leaders;
2868 break;
2869 case u_leaders_flag:
2870 switch (node_type(boxnode)) {
2871 case hlist_node:
2872 if (cur_mode != vmode) {
2873 node_subtype(cur_list.tail) = u_leaders;
2874 glue_amount(cur_list.tail) += box_width(boxnode);
2875 glue_callback(cur_list.tail) = callback;
2876 } else {
2877 node_subtype(cur_list.tail) = a_leaders;
2878 }
2879 break;
2880 case vlist_node:
2881 if (cur_mode == vmode) {
2882 node_subtype(cur_list.tail) = u_leaders;
2883 glue_amount(cur_list.tail) += box_total(boxnode);
2884 glue_callback(cur_list.tail) = callback;
2885 } else {
2886 node_subtype(cur_list.tail) = a_leaders;
2887 }
2888 break;
2889 default:
2890
2891 node_subtype(cur_list.tail) = a_leaders;
2892 break;
2893 }
2894 break;
2895 }
2896 glue_leader_ptr(cur_list.tail) = boxnode;
2897 } else {
2898 tex_handle_error(
2899 back_error_type,
2900 "Leaders not followed by proper glue",
2901 "You should say '\\leaders <box or rule><hskip or vskip>'. I found the <box or\n"
2902 "rule>, but there's no suitable <hskip or vskip>, so I'm ignoring these leaders."
2903 );
2904 tex_flush_node_list(boxnode);
2905 }
2906}
2907
2908void tex_box_end(int boxcontext, halfword boxnode, scaled shift, halfword mainclass, halfword slot, halfword callback)
2909{
2910 cur_box = boxnode;
2911 switch (boxcontext) {
2912 case direct_box_flag:
2913
2923 if (boxnode) {
2924 if (shift != null_flag) {
2925 box_shift_amount(boxnode) = shift;
2926 }
2927 switch (cur_mode) {
2928 case vmode:
2929 if (lmt_packaging_state.pre_adjust_tail) {
2930 if (pre_adjust_head != lmt_packaging_state.pre_adjust_tail) {
2931 tex_inject_adjust_list(pre_adjust_head, 1, boxnode, NULL);
2932 }
2933 lmt_packaging_state.pre_adjust_tail = null;
2934 }
2935 if (lmt_packaging_state.pre_migrate_tail) {
2936 if (pre_migrate_head != lmt_packaging_state.pre_migrate_tail) {
2937 tex_append_list(pre_migrate_head, lmt_packaging_state.pre_migrate_tail);
2938 }
2939 lmt_packaging_state.pre_migrate_tail = null;
2940 }
2941 tex_append_to_vlist(boxnode, lua_key_index(box), NULL);
2942 if (lmt_packaging_state.post_migrate_tail) {
2943 if (post_migrate_head != lmt_packaging_state.post_migrate_tail) {
2944 tex_append_list(post_migrate_head, lmt_packaging_state.post_migrate_tail);
2945 }
2946 lmt_packaging_state.post_migrate_tail = null;
2947 }
2948 if (lmt_packaging_state.post_adjust_tail) {
2949 if (post_adjust_head != lmt_packaging_state.post_adjust_tail) {
2950 tex_inject_adjust_list(post_adjust_head, 1, null, NULL);
2951 }
2952 lmt_packaging_state.post_adjust_tail = null;
2953 }
2954 if (cur_list.mode > nomode) {
2955 tex_build_page(box_page_context, 0);
2956 }
2957 break;
2958 case hmode:
2959 cur_list.space_factor = default_space_factor;
2960 tex_couple_nodes(cur_list.tail, boxnode);
2961 cur_list.tail = boxnode;
2962 break;
2963
2964 default:
2965 boxnode = tex_new_sub_box(boxnode);
2966 tex_couple_nodes(cur_list.tail, boxnode);
2967 cur_list.tail = boxnode;
2968 if (mainclass != unset_noad_class) {
2969 set_noad_classes(boxnode, mainclass);
2970 }
2971 break;
2972 }
2973 } else {
2974
2975 }
2976 break;
2977 case box_flag:
2978
2979 update_tex_box_local(slot, boxnode);
2980 break;
2981 case global_box_flag:
2982
2983 update_tex_box_global(slot, boxnode);
2984 break;
2985 case shipout_flag:
2986
2987 if (boxnode) {
2988
2989 tex_begin_diagnostic();
2990 tex_show_node_list(boxnode, max_integer, max_integer);
2991 tex_end_diagnostic();
2992
2993 if (box_register(boxnode)) {
2994 tex_flush_node_list(boxnode);
2995 box_register(boxnode) = null;
2996 }
2997
2998 }
2999 break;
3000 case left_box_flag:
3001 case right_box_flag:
3002 case middle_box_flag:
3003
3004 tex_aux_finish_local_box();
3005 break;
3006 case lua_scan_flag:
3007
3008 tex_aux_wrapup_local_scan_box();
3009 cur_box = boxnode;
3010 break;
3011 case a_leaders_flag:
3012 case c_leaders_flag:
3013 case x_leaders_flag:
3014 case g_leaders_flag:
3015 case u_leaders_flag:
3016 tex_aux_wrapup_leader_box(boxcontext, boxnode, callback);
3017 break;
3018 default:
3019
3020 break;
3021 }
3022}
3023
3024
3033
3034void tex_begin_paragraph(int doindent, int context)
3035{
3036 int indented = doindent;
3037 int isvmode = cur_list.mode == vmode;
3038 lmt_main_control_state.last_par_trigger = context;
3039 if (isvmode || cur_list.head != cur_list.tail) {
3040
3046 if (every_before_par_par) {
3047 tex_begin_inserted_list(tex_get_available_token(token_val(end_local_cmd, 0)));
3048 tex_begin_token_list(every_before_par_par, every_before_par_text);
3049 if (tracing_nesting_par > 2) {
3050 tex_local_control_message("entering local control via \\everybeforepar");
3051 }
3052 tex_local_control(1);
3053 }
3054 tex_tail_append(tex_new_param_glue_node(par_skip_code, par_skip_glue));
3055 }
3056 lmt_begin_paragraph_callback(isvmode, &indented, context);
3057
3058 {
3059 halfword prev_graf = cur_list.prev_graf;
3060 cur_list.prev_graf = 0;
3061 tex_push_nest();
3062 cur_list.mode = hmode;
3063 cur_list.space_factor = default_space_factor;
3064
3065 tex_tail_append(tex_new_par_node(vmode_par_par_subtype));
3066 par_prev_graf(cur_list.tail) = prev_graf;
3067
3068 tex_append_dir_state();
3069 }
3070 tex_aux_insert_parindent(indented);
3071 if (tracing_paragraph_lists) {
3072 tex_begin_diagnostic();
3073 tex_print_format("[paragraph: start, context %i]", context);
3074 tex_show_box(node_next(cur_list.head));
3075 tex_end_diagnostic();
3076 }
3077
3078 if (every_par_par) {
3079 tex_begin_token_list(every_par_par, every_par_text);
3080 }
3081 if (lmt_nest_state.nest_data.ptr == 1) {
3082
3083 tex_build_page(begin_paragraph_page_context, 0);
3084 }
3085}
3086
3087void tex_insert_paragraph_token(void)
3088{
3089 if (auto_paragraph_mode_par > 0) {
3090 cur_tok = token_val(end_paragraph_cmd, inserted_end_paragraph_code);
3091
3092
3093 } else {
3094 cur_tok = lmt_token_state.par_token;
3095 }
3096}
3097
3098static void tex_aux_run_head_for_vmode(void)
3099{
3100 if (cur_list.mode >= nomode) {
3101 tex_back_input(cur_tok);
3102
3110 tex_insert_paragraph_token();
3111
3115 tex_back_input(cur_tok);
3116 lmt_input_state.cur_input.token_type = inserted_text;
3117
3120 } else if (cur_cmd != hrule_cmd) {
3121 tex_off_save();
3122 } else {
3123 tex_handle_error(
3124 normal_error_type,
3125 "You can't use '\\hrule' here except with leaders",
3126 "To put a horizontal rule in an hbox or an alignment, you should use \\leaders or\n"
3127 "\\hrulefill (see The TeXbook)."
3128 );
3129 }
3130}
3131
3132
3141
3142
3149
3150static void tex_aux_run_kern(void)
3151{
3152 halfword code = cur_chr;
3153 switch (code) {
3154
3155 case h_kern_code:
3156 if (cur_mode == vmode) {
3157 tex_back_input(token_val(kern_cmd, normal_kern_code));
3158 tex_back_input(token_val(begin_paragraph_cmd, quitvmode_par_code));
3159 return;
3160 } else {
3161 break;
3162 }
3163 case v_kern_code:
3164 if (cur_mode == hmode) {
3165 tex_back_input(token_val(kern_cmd, normal_kern_code));
3166 tex_back_input(token_val(end_paragraph_cmd, normal_end_paragraph_code));
3167 return;
3168 } else {
3169 break;
3170 }
3171 }
3172 {
3173 scaled val = tex_scan_dimension(0, 0, 0, 0, NULL);
3174 if (code == non_zero_width_kern_code && ! val) {
3175 return;
3176 } else {
3177 tex_tail_append(tex_new_kern_node(val, explicit_kern_subtype));
3178 }
3179 }
3180}
3181
3182static void tex_aux_run_mkern(void)
3183{
3184 halfword val = tex_scan_dimension(1, 0, 0, 0, NULL);
3185 tex_tail_append(tex_new_kern_node(val, explicit_math_kern_subtype));
3186}
3187
3188
3195
3196static int tex_aux_only_dirs(halfword n)
3197{
3198 while (n) {
3199 switch (node_type(n)) {
3200 case par_node:
3201 case dir_node:
3202 n = node_next(n);
3203 break;
3204
3209 case glue_node:
3210 if (tex_is_par_init_glue(n)) {
3211 n = node_next(n);
3212 break;
3213 }
3214 default:
3215 return 0;
3216 }
3217 }
3218 return 1;
3219}
3220
3221void tex_end_paragraph(int group, int context)
3222{
3223 if (cur_list.mode == hmode) {
3224 if (cur_list.head == cur_list.tail) {
3225
3226 tex_pop_nest();
3227 } else if (tex_aux_only_dirs(node_next(cur_list.head))) {
3228 tex_flush_node_list(node_next(cur_list.head));
3229
3230 tex_pop_nest();
3231
3232
3233
3234
3235
3236
3237 } else {
3238 tex_line_break(0, group);
3239 }
3240 if (cur_list.direction_stack) {
3241 tex_flush_node_list(cur_list.direction_stack);
3242 cur_list.direction_stack = null;
3243 }
3244 tex_normal_paragraph(context);
3245 lmt_error_state.error_count = 0;
3246 }
3247}
3248
3249static void tex_aux_run_penalty(void)
3250{
3251 halfword code = cur_chr;
3252 switch (code) {
3253
3254 case h_penalty_code:
3255 if (cur_mode == vmode) {
3256 tex_back_input(token_val(penalty_cmd, normal_penalty_code));
3257 tex_back_input(token_val(begin_paragraph_cmd, quitvmode_par_code));
3258 return;
3259 } else {
3260 break;
3261 }
3262 case v_penalty_code:
3263 if (cur_mode == hmode) {
3264 tex_back_input(token_val(penalty_cmd, normal_penalty_code));
3265 tex_back_input(token_val(end_paragraph_cmd, normal_end_paragraph_code));
3266 return;
3267 } else {
3268 break;
3269 }
3270 }
3271 {
3272 halfword value = tex_scan_integer(0, NULL);
3273 tex_tail_append(tex_new_penalty_node(value, user_penalty_subtype));
3274 if (cur_list.mode == vmode) {
3275 tex_build_page(penalty_page_context, 0);
3276 }
3277 }
3278}
3279
3280
3289
3290static void tex_aux_run_remove_item(void)
3291{
3292 halfword code = cur_chr;
3293 halfword head = cur_list.head;
3294 halfword tail = cur_list.tail;
3295 if (cur_list.mode == vmode && tail == head) {
3296
3300 if ((code != skip_item_code) || (lmt_page_builder_state.last_glue != max_halfword)) {
3301 switch (code) {
3302 case kern_item_code:
3303 tex_you_cant_error(
3304 "Sorry...I usually can't take things from the current page.\n"
3305 "Try '\\kern-\\lastkern' instead."
3306 );
3307 break;
3308 case penalty_item_code:
3309 case boundary_item_code:
3310 tex_you_cant_error(
3311 "Sorry...I usually can't take things from the current page.\n"
3312 "Perhaps you can make the output routine do it."
3313 );
3314 break;
3315 case skip_item_code:
3316 tex_you_cant_error(
3317 "Sorry...I usually can't take things from the current page.\n"
3318 "Try '\\vskip-\\lastskip' instead."
3319 );
3320 break;
3321 }
3322 }
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351 } else {
3352
3357 switch (node_type(tail)) {
3358 case kern_node :
3359 if (code == kern_item_code) {
3360 break;
3361 } else {
3362 return;
3363 }
3364 case penalty_node :
3365 if (code == penalty_item_code) {
3366 break;
3367 } else {
3368 return;
3369 }
3370 case glue_node :
3371 if (code == skip_item_code) {
3372 break;
3373 } else {
3374 return;
3375 }
3376 case boundary_node :
3377 if (node_subtype(tail) == user_boundary && code == boundary_item_code) {
3378 break;
3379 } else {
3380 return;
3381 }
3382 default:
3383 return;
3384 }
3385 {
3386
3390 halfword p;
3391 do {
3392 p = head;
3393 if (p == tail && node_type(head) == disc_node) {
3394 return;
3395 } else {
3396 head = node_next(p);
3397 }
3398 } while (head != tail);
3399 node_next(p) = null;
3400 tex_flush_node_list(tail);
3401 cur_list.tail = p;
3402 }
3403 }
3404
3405}
3406
3407
3417
3418static void tex_aux_run_text_italic_correction(void)
3419{
3420 halfword tail = cur_list.tail;
3421 scaled kern = 0;
3422 quarterword subtype = 0;
3423 switch (cur_chr) {
3424 case italic_correction_code:
3425 if (tail == cur_list.head) {
3426 return;
3427 } else {
3428 subtype = italic_kern_subtype;
3429 break;
3430 }
3431 case left_correction_code:
3432 subtype = left_correction_kern_subtype;
3433 break;
3434 case right_correction_code:
3435 subtype = right_correction_kern_subtype;
3436 break;
3437 default:
3438 return;
3439 }
3440 if (subtype == italic_kern_subtype) {
3441 switch (node_type(tail)) {
3442 case glyph_node:
3443 kern = tex_char_italic_from_glyph(tail);
3444 if (cur_mode == mmode) {
3445
3449 break;
3450 } else if (tex_has_glyph_option(tail, glyph_option_no_italic_correction)) {
3451 break;
3452 } else {
3453
3457 kern = lmt_italic_correction_callback(tail, kern, subtype);
3458 if (kern || ! tex_has_glyph_option(tail, glyph_option_no_zero_italic_correction)) {
3459 break;
3460 } else {
3461 return;
3462 }
3463 }
3464 case disc_node:
3465
3469 kern = lmt_italic_correction_callback(tail, 0, subtype);
3470 if (kern) {
3471 break;
3472 } else {
3473 return;
3474 }
3475 default:
3476 return;
3477 }
3478 }
3479
3483 tex_tail_append(tex_new_kern_node(kern, subtype));
3484
3489 if (subtype != italic_kern_subtype) {
3490 lmt_italic_correction_callback(cur_list.tail, kern, subtype);
3491 }
3492}
3493
3494
3508
3509static void tex_aux_run_text_accent(void)
3510{
3511 halfword fnt = cur_font_par;
3512 halfword accent = null;
3513 halfword base = null;
3514 scaled xoffset = 0;
3515 scaled yoffset = 0;
3516 while (1) {
3517 switch (tex_scan_character("xyXY", 0, 1, 0)) {
3518 case 'x': case 'X':
3519 if (tex_scan_mandate_keyword("xoffset", 1)) {
3520 xoffset = tex_scan_dimension(0, 0, 0, 0, NULL);
3521 }
3522 break;
3523 case 'y': case 'Y':
3524 if (tex_scan_mandate_keyword("yoffset", 1)) {
3525 yoffset = tex_scan_dimension(0, 0, 0, 0, NULL);
3526 }
3527 break;
3528 default:
3529 goto DONE;
3530 }
3531 }
3532 DONE:
3533 accent = tex_new_char_node(glyph_unset_subtype, fnt, tex_scan_char_number(0), 1);
3534 if (accent) {
3535
3539 scaled x = tex_get_scaled_ex_height(fnt);
3540 double s = (double) (tex_get_font_slant(fnt)) / (double) (65536);
3541 scaled a = tex_glyph_width(accent);
3542
3550
3551 fnt = cur_font_par;
3552 PICKUP:
3553 switch (cur_cmd) {
3554 case spacer_cmd:
3555 case relax_cmd:
3556 tex_get_x_token();
3557 goto PICKUP;
3558 case letter_cmd:
3559 case other_char_cmd:
3560 case char_given_cmd:
3561 base = tex_new_glyph_node(glyph_unset_subtype, fnt, cur_chr, accent);
3562 break;
3563 case char_number_cmd:
3564
3565 base = tex_new_glyph_node(glyph_unset_subtype, fnt, tex_scan_char_number(0), accent);
3566 break;
3567 default:
3568
3569 if (cur_cmd <= max_non_prefixed_cmd) {
3570 tex_back_input(cur_tok);
3571 break;
3572 } else {
3573 lmt_error_state.set_box_allowed = 0;
3574 tex_run_prefixed_command();
3575 lmt_error_state.set_box_allowed = 0;
3576 goto PICKUP;
3577 }
3578 }
3579 if (base) {
3580
3591 double t = (double) (tex_get_font_slant(fnt)) / (double) (65536);
3592 scaled w = tex_glyph_width(base);
3593 scaled h = tex_glyph_height(base);
3594 scaled delta = glueround((double) (w - a) / (double) (2) + h * t - x * s);
3595 halfword left = tex_new_kern_node(delta, accent_kern_subtype);
3596 halfword right = tex_new_kern_node(- a - delta, accent_kern_subtype);
3597 glyph_x_offset(accent) = xoffset;
3598 glyph_y_offset(accent) = yoffset;
3599 if (h != x) {
3600
3601
3602
3603 glyph_y_offset(accent) += x - h;
3604 }
3605 tex_couple_nodes(cur_list.tail, left);
3606 tex_couple_nodes(left, accent);
3607 tex_couple_nodes(accent, right);
3608 tex_couple_nodes(right,base);
3609 cur_list.tail = base;
3610 } else {
3611 tex_couple_nodes(cur_list.tail, accent);
3612 cur_list.tail = accent;
3613 }
3614 cur_list.space_factor = default_space_factor;
3615 }
3616}
3617
3618
3619
3620static void tex_aux_run_cs_error(void)
3621{
3622 tex_handle_error(
3623 normal_error_type,
3624 "Extra \\endcsname",
3625 "I'm ignoring this, since I wasn't doing a \\csname."
3626 );
3627}
3628
3629
3643
3644void tex_inject_text_or_line_dir(int val, int check_glue)
3645{
3646 if (cur_mode == hmode && internal_dir_state_par > 0) {
3647
3648 halfword dirn = tex_new_dir(cancel_dir_subtype, text_direction_par);
3649 halfword tail = cur_list.tail;
3650 if (check_glue && tail && node_type(tail) == glue_node) {
3651 halfword prev = node_prev(tail);
3652 tex_couple_nodes(prev, dirn);
3653 tex_couple_nodes(dirn, tail);
3654 } else {
3655 tex_tail_append(dirn);
3656 }
3657 }
3658 tex_push_text_dir_ptr(val);
3659 if (cur_mode == hmode) {
3660 halfword dir = tex_new_dir(normal_dir_subtype, val);
3661 dir_level(dir) = cur_level;
3662 tex_tail_append(dir);
3663 }
3664}
3665
3666static void tex_aux_show_frozen_error(halfword cs)
3667{
3668 if (cs) {
3669 tex_handle_error(
3670 normal_error_type,
3671 "You can't redefine the frozen macro %S.", cs,
3672 NULL
3673 );
3674 } else {
3675 tex_handle_error(
3676 normal_error_type,
3677 "You can't redefine a frozen macro.",
3678 NULL
3679 );
3680
3681 }
3682}
3683
3684
3692
3693inline static halfword tex_aux_get_register_index(int level)
3694{
3695 switch (level) {
3696 case integer_val_level:
3697 {
3698 halfword index = tex_scan_integer_register_number();
3699 return register_integer_location(index);
3700 }
3701 case dimension_val_level:
3702 {
3703 halfword index = tex_scan_dimension_register_number();
3704 return register_dimension_location(index);
3705 }
3706 case attribute_val_level:
3707 {
3708 halfword index = tex_scan_attribute_register_number();
3709 return register_attribute_location(index);
3710 }
3711 case posit_val_level:
3712 {
3713 halfword index = tex_scan_posit_register_number();
3714 return register_posit_location(index);
3715 }
3716 case glue_val_level:
3717 {
3718 halfword index = tex_scan_glue_register_number();
3719 return register_glue_location(index);
3720 }
3721 case muglue_val_level:
3722 {
3723 halfword index = tex_scan_muglue_register_number();
3724 return register_muglue_location(index);
3725 }
3726 case token_val_level:
3727 {
3728 halfword index = tex_scan_toks_register_number();
3729 return register_toks_location(index);
3730 }
3731 default:
3732 return 0;
3733 }
3734}
3735
3736inline static halfword tex_aux_get_register_value(int level, int optionalequal)
3737{
3738 switch (level) {
3739 case integer_val_level:
3740 case attribute_val_level:
3741 return tex_scan_integer(optionalequal, NULL);
3742 case posit_val_level:
3743 return tex_scan_posit(optionalequal);
3744 case dimension_val_level:
3745 return tex_scan_dimension(0, 0, 0, optionalequal, NULL);
3746 default:
3747 return tex_scan_glue(level, optionalequal, 1);
3748 }
3749}
3750
3751static int tex_aux_valid_arithmic(int cmd, int *index, int *level, int *varcmd, int *simple, int *original)
3752{
3753
3754 tex_get_x_token();
3755 *varcmd = cur_cmd;
3756
3757 switch (cur_cmd) {
3758 case register_integer_cmd:
3759 case internal_integer_cmd:
3760 *index = cur_chr;
3761 *level = integer_val_level;
3762 *original = eq_value(*index);
3763 return 1;
3764 case register_attribute_cmd:
3765 case internal_attribute_cmd:
3766 *index = cur_chr;
3767 *level = attribute_val_level;
3768 *original = eq_value(*index);
3769 return 1;
3770 case register_posit_cmd:
3771 case internal_posit_cmd:
3772 *index = cur_chr;
3773 *level = posit_val_level;
3774 *original = eq_value(*index);
3775 return 1;
3776 case register_dimension_cmd:
3777 case internal_dimension_cmd:
3778 *index = cur_chr;
3779 *level = dimension_val_level;
3780 *original = eq_value(*index);
3781 return 1;
3782 case register_glue_cmd:
3783 case internal_glue_cmd:
3784 *index = cur_chr;
3785 *level = glue_val_level;
3786 *original = eq_value(*index);
3787 return 1;
3788 case register_muglue_cmd:
3789 case internal_muglue_cmd:
3790 *index = cur_chr;
3791 *level = muglue_val_level;
3792 *original = eq_value(*index);
3793 return 1;
3794 case register_cmd:
3795 *level = cur_chr;
3796 *index = tex_aux_get_register_index(cur_chr);
3797 *original = eq_value(*index);
3798 return 1;
3799 case integer_cmd:
3800 *index = cur_cs;
3801 *level = integer_val_level;
3802 *original = cur_chr;
3803 *simple = integer_cmd;
3804 return 1;
3805
3806
3807
3808
3809
3810
3811 case dimension_cmd:
3812 *index = cur_cs;
3813 *level = dimension_val_level;
3814 *original = cur_chr;
3815 *simple = dimension_cmd;
3816 return 1;
3817 case posit_cmd:
3818 *index = cur_cs;
3819 *level = posit_val_level;
3820 *original = cur_chr;
3821 *simple = posit_cmd;
3822 return 1;
3823 case gluespec_cmd:
3824 *index = cur_cs;
3825 *level = glue_val_level;
3826 *original = cur_chr;
3827 *simple = gluespec_cmd;
3828 return 1;
3829 case mugluespec_cmd:
3830 *index = cur_cs;
3831 *level = muglue_val_level;
3832 *original = cur_chr;
3833 *simple = mugluespec_cmd;
3834 return 1;
3835 default:
3836 tex_handle_error(
3837 normal_error_type,
3838 "You can't use '%C' after %C",
3839 cur_cmd, cur_chr, cmd, 0,
3840 "I'm forgetting what you said and not changing anything."
3841 );
3842 return 0;
3843 }
3844}
3845
3846static void tex_aux_arithmic_overflow_error(int level, halfword value)
3847{
3848 if (level >= glue_val_level) {
3849 tex_flush_node(value);
3850 }
3851 tex_handle_error(
3852 normal_error_type,
3853 "Arithmetic overflow",
3854 "I can't carry out that multiplication or division, since the result is out of\n"
3855 "range."
3856 );
3857}
3858
3859inline static void tex_aux_update_register(int a, int level, halfword index, halfword value, halfword cmd)
3860{
3861 switch (level) {
3862 case integer_val_level:
3863 tex_word_define(a, index, value);
3864 if (is_frozen(a) && cmd == internal_integer_cmd && cur_mode == hmode) {
3865 tex_update_par_par(internal_integer_cmd, index - lmt_primitive_state.prim_data[cmd].offset);
3866 }
3867 break;
3868 case attribute_val_level:
3869 if ((register_attribute_number(index)) > lmt_node_memory_state.max_used_attribute) {
3870 lmt_node_memory_state.max_used_attribute = register_attribute_number(index);
3871 }
3872 tex_change_attribute_register(a, index, value);
3873 tex_word_define(a, index, value);
3874 break;
3875 case posit_val_level:
3876 tex_word_define(a, index, value);
3877 if (is_frozen(a) && cmd == internal_posit_cmd && cur_mode == hmode) {
3878 tex_update_par_par(internal_posit_cmd, index - lmt_primitive_state.prim_data[cmd].offset);
3879 }
3880 break;
3881 case dimension_val_level:
3882 tex_word_define(a, index, value);
3883 if (is_frozen(a) && cmd == internal_dimension_cmd && cur_mode == hmode) {
3884 tex_update_par_par(internal_dimension_cmd, index - lmt_primitive_state.prim_data[cmd].offset);
3885 }
3886 break;
3887 case glue_val_level:
3888 tex_define(a, index, cmd == internal_glue_cmd ? internal_glue_reference_cmd : register_glue_reference_cmd, value);
3889 if (is_frozen(a) && cmd == internal_glue_cmd && cur_mode == hmode) {
3890 tex_update_par_par(internal_glue_cmd, index - lmt_primitive_state.prim_data[cmd].offset);
3891 }
3892 break;
3893 case muglue_val_level:
3894 tex_define(a, index, cmd == internal_glue_cmd ? internal_muglue_reference_cmd : register_muglue_reference_cmd, value);
3895 break;
3896 default:
3897
3898 tex_word_define(a, index, value);
3899 break;
3900 }
3901}
3902
3903inline static void tex_aux_set_register(int a)
3904{
3905 halfword level = cur_chr;
3906 halfword varcmd = cur_cmd;
3907 halfword index = tex_aux_get_register_index(level);
3908 halfword value = tex_aux_get_register_value(level, 1);
3909 tex_aux_update_register(a, level, index, value, varcmd);
3910}
3911
3912
3918
3919static void tex_aux_arithmic_register(int a, int code)
3920{
3921 halfword cmd = cur_cmd;
3922 halfword level = cur_chr;
3923 halfword index = 0;
3924 halfword varcmd = 0;
3925 halfword simple = 0;
3926 halfword original = 0;
3927 if (tex_aux_valid_arithmic(cmd, &index, &level, &varcmd, &simple, &original)) {
3928 halfword value = null;
3929
3930 switch (code) {
3931 case advance_code:
3932 tex_scan_optional_keyword("by");
3933 case advance_by_code:
3934 {
3935 halfword amount = tex_aux_get_register_value(level, 0);
3936 switch (level) {
3937 case integer_val_level:
3938 case attribute_val_level:
3939 case dimension_val_level:
3940 if (amount) {
3941 value = original + amount;
3942 break;
3943 } else {
3944 return;
3945 }
3946 case posit_val_level:
3947 if (tex_posit_eq_zero(amount)) {
3948 return;
3949 } else {
3950 value = tex_posit_add(original, amount);
3951 break;
3952 }
3953 case glue_val_level:
3954 case muglue_val_level:
3955 if (tex_glue_is_zero(amount)) {
3956 return;
3957 } else {
3958
3959 halfword newvalue = tex_new_glue_spec_node(amount);
3960 tex_flush_node(value);
3961 glue_amount(newvalue) += glue_amount(original);
3962 if (glue_stretch(newvalue) == 0) {
3963 glue_stretch_order(newvalue) = normal_glue_order;
3964 }
3965 if (glue_stretch_order(newvalue) == glue_stretch_order(original)) {
3966 glue_stretch(newvalue) += glue_stretch(original);
3967 } else if ((glue_stretch_order(newvalue) < glue_stretch_order(original)) && (glue_stretch(original))) {
3968 glue_stretch(newvalue) = glue_stretch(original);
3969 glue_stretch_order(newvalue) = glue_stretch_order(original);
3970 }
3971 if (glue_shrink(newvalue) == 0) {
3972 glue_shrink_order(newvalue) = normal_glue_order;
3973 }
3974 if (glue_shrink_order(newvalue) == glue_shrink_order(original)) {
3975 glue_shrink(newvalue) += glue_shrink(original);
3976 } else if ((glue_shrink_order(newvalue) < glue_shrink_order(original)) && (glue_shrink(original))) {
3977 glue_shrink(newvalue) = glue_shrink(original);
3978 glue_shrink_order(newvalue) = glue_shrink_order(original);
3979 }
3980 value = newvalue;
3981 break;
3982 }
3983 default:
3984
3985 break;
3986 }
3987
3988 if (simple) {
3989 tex_define(a, index, (singleword) simple, value);
3990 } else {
3991 tex_aux_update_register(a, level, index, value, varcmd);
3992 }
3993 break;
3994 }
3995 case multiply_code:
3996 tex_scan_optional_keyword("by");
3997 case multiply_by_code:
3998 {
3999 halfword amount = tex_scan_integer(0, NULL);
4000 halfword value = 0;
4001 if (amount == 1) {
4002 return;
4003 } else {
4004 lmt_scanner_state.arithmic_error = 0;
4005 switch (level) {
4006 case integer_val_level:
4007 case attribute_val_level:
4008 value = tex_multiply_integers(original, amount);
4009 break;
4010 case posit_val_level:
4011 value = tex_posit_mul_by(original, amount);
4012 break;
4013 case dimension_val_level:
4014 value = tex_nx_plus_y(original, amount, 0);
4015 break;
4016 case glue_val_level:
4017 case muglue_val_level:
4018 {
4019 halfword newvalue = tex_new_glue_spec_node(original);
4020 glue_amount(newvalue) = tex_nx_plus_y(glue_amount(original), amount, 0);
4021 glue_stretch(newvalue) = tex_nx_plus_y(glue_stretch(original), amount, 0);
4022 glue_shrink(newvalue) = tex_nx_plus_y(glue_shrink(original), amount, 0);
4023 value = newvalue;
4024 break;
4025 }
4026 default:
4027
4028 break;
4029 }
4030 if (lmt_scanner_state.arithmic_error) {
4031 tex_aux_arithmic_overflow_error(level, value);
4032 } else if (simple) {
4033 tex_define(a, index, (singleword) simple, value);
4034 } else {
4035 tex_aux_update_register(a, level, index, value, varcmd);
4036 }
4037 break;
4038 }
4039 }
4040 case divide_code:
4041 case r_divide_code:
4042 case e_divide_code:
4043 tex_scan_optional_keyword("by");
4044 case divide_by_code:
4045 case r_divide_by_code:
4046 case e_divide_by_code:
4047 {
4048 halfword amount = tex_scan_integer(0, NULL);
4049 if (amount == 1) {
4050 return;
4051 } else {
4052 bool rounded = code == r_divide_code || code == r_divide_by_code;
4053 lmt_scanner_state.arithmic_error = 0;
4054 switch (level) {
4055 case dimension_val_level:
4056 if (rounded) {
4057 value = tex_quotient(original >> 16, amount, 1) << 16;
4058 break;
4059 }
4060 case integer_val_level:
4061 case attribute_val_level:
4062 {
4063 bool asexpr = code == e_divide_code || code == e_divide_by_code;
4064 value = tex_quotient(original, amount, asexpr || rounded);
4065 break;
4066 }
4067 case posit_val_level:
4068 value = tex_posit_div_by(original, amount);
4069 break;
4070 case glue_val_level:
4071 case muglue_val_level:
4072 {
4073 halfword newvalue = tex_new_glue_spec_node(original);
4074
4075 if (rounded) {
4076 glue_amount(newvalue) = tex_quotient(glue_amount(original) >> 16, amount, 1) << 16;
4077 glue_stretch(newvalue) = tex_quotient(glue_stretch(original) >> 16, amount, 1) << 16;
4078 glue_shrink(newvalue) = tex_quotient(glue_shrink(original) >> 16, amount, 1) << 16;
4079 } else {
4080 bool asexpr = code == e_divide_code || code == e_divide_by_code;
4081 glue_amount(newvalue) = tex_quotient(glue_amount(original), amount, asexpr);
4082 glue_stretch(newvalue) = tex_quotient(glue_stretch(original), amount, asexpr);
4083 glue_shrink(newvalue) = tex_quotient(glue_shrink(original), amount, asexpr);
4084 }
4085 value = newvalue;
4086 break;
4087 }
4088 default:
4089
4090 break;
4091 }
4092 if (lmt_scanner_state.arithmic_error) {
4093 tex_aux_arithmic_overflow_error(level, value);
4094 } else if (simple) {
4095 tex_define(a, index, (singleword) simple, value);
4096 } else {
4097 tex_aux_update_register(a, level, index, value, varcmd);
4098 }
4099 break;
4100 }
4101 }
4102
4120 }
4121 }
4122}
4123
4124
4143
4144inline static void tex_aux_set_interaction(halfword mode)
4145{
4146 tex_print_ln();
4147 if (mode < batch_mode) {
4148 lmt_error_state.interaction = batch_mode;
4149 } else if (mode > error_stop_mode) {
4150 lmt_error_state.interaction = error_stop_mode;
4151 } else {
4152 lmt_error_state.interaction = mode;
4153 }
4154 tex_fixup_selector(lmt_fileio_state.log_opened);
4155}
4156
4157static void tex_aux_set_page_property(void)
4158{
4159 switch (cur_chr) {
4160 case page_goal_code:
4161 lmt_page_builder_state.goal = tex_scan_dimension(0, 0, 0, 1, NULL);
4162 break;
4163 case page_vsize_code:
4164 lmt_page_builder_state.vsize = tex_scan_dimension(0, 0, 0, 1, NULL);
4165 break;
4166 case page_total_code:
4167 lmt_page_builder_state.total = tex_scan_dimension(0, 0, 0, 1, NULL);
4168
4169 lmt_page_builder_state.last_height = lmt_page_builder_state.total;
4170
4171 lmt_page_builder_state.last_depth = 0;
4172 break;
4173 case page_excess_code:
4174 lmt_page_builder_state.excess = tex_scan_dimension(0, 0, 0, 1, NULL);
4175 break;
4176 case page_depth_code:
4177 lmt_page_builder_state.depth = tex_scan_dimension(0, 0, 0, 1, NULL);
4178
4179 lmt_page_builder_state.last_depth = lmt_page_builder_state.depth;
4180 break;
4181 case page_last_height_code:
4182 lmt_page_builder_state.last_height = tex_scan_dimension(0, 0, 0, 1, NULL);
4183 break;
4184 case page_last_depth_code:
4185 lmt_page_builder_state.last_depth = tex_scan_dimension(0, 0, 0, 1, NULL);
4186 break;
4187 case dead_cycles_code:
4188 lmt_page_builder_state.dead_cycles = tex_scan_integer(1, NULL);
4189 break;
4190 case insert_penalties_code:
4191 lmt_page_builder_state.insert_penalties = tex_scan_integer(1, NULL);
4192 break;
4193 case insert_heights_code:
4194 lmt_page_builder_state.insert_heights = tex_scan_dimension(0, 0, 0, 1, NULL);
4195 break;
4196 case insert_storing_code:
4197 lmt_insert_state.storing = tex_scan_integer(1, NULL);
4198 break;
4199 case insert_distance_code:
4200 {
4201
4205 int index = tex_scan_integer(0, NULL);
4206 tex_set_insert_distance(index, tex_scan_glue(glue_val_level, 1, 1));
4207 }
4208 break;
4209 case insert_multiplier_code:
4210 {
4211 int index = tex_scan_integer(0, NULL);
4212 tex_set_insert_multiplier(index, tex_scan_integer(1, NULL));
4213 }
4214 break;
4215 case insert_limit_code:
4216 {
4217 int index = tex_scan_integer(0, NULL);
4218 tex_set_insert_limit(index, tex_scan_dimension(0, 0, 0, 1, NULL));
4219 }
4220 break;
4221 case insert_storage_code:
4222 {
4223 int index = tex_scan_integer(0, NULL);
4224 tex_set_insert_storage(index, tex_scan_integer(1, NULL));
4225 }
4226 break;
4227 case insert_penalty_code:
4228 {
4229 int index = tex_scan_integer(0, NULL);
4230 tex_set_insert_penalty(index, tex_scan_integer(1, NULL));
4231 }
4232 break;
4233 case insert_maxdepth_code:
4234 {
4235 int index = tex_scan_integer(0, NULL);
4236 tex_set_insert_maxdepth(index, tex_scan_dimension(0, 0, 0, 1, NULL));
4237 }
4238 break;
4239 case insert_height_code:
4240 {
4241 int index = tex_scan_integer(0, NULL);
4242 tex_set_insert_height(index, tex_scan_dimension(0, 0, 0, 1, NULL));
4243 }
4244 break;
4245 case insert_depth_code:
4246 {
4247 int index = tex_scan_integer(0, NULL);
4248 tex_set_insert_depth(index, tex_scan_dimension(0, 0, 0, 1, NULL));
4249 }
4250 break;
4251 case insert_width_code:
4252 {
4253 int index = tex_scan_integer(0, NULL);
4254 tex_set_insert_width(index, tex_scan_dimension(0, 0, 0, 1, NULL));
4255 }
4256 break;
4257
4258
4259
4260 case page_stretch_code:
4261 lmt_page_builder_state.stretch = tex_scan_dimension(0, 0, 0, 1, NULL);
4262 break;
4263 case page_fistretch_code:
4264 lmt_page_builder_state.fistretch = tex_scan_dimension(0, 0, 0, 1, NULL);
4265 break;
4266 case page_filstretch_code:
4267 lmt_page_builder_state.filstretch = tex_scan_dimension(0, 0, 0, 1, NULL);
4268 break;
4269 case page_fillstretch_code:
4270 lmt_page_builder_state.fillstretch = tex_scan_dimension(0, 0, 0, 1, NULL);
4271 break;
4272 case page_filllstretch_code:
4273 lmt_page_builder_state.filllstretch = tex_scan_dimension(0, 0, 0, 1, NULL);
4274 break;
4275 case page_shrink_code:
4276 lmt_page_builder_state.shrink = tex_scan_dimension(0, 0, 0, 1, NULL);
4277 break;
4278 default:
4279 tex_confusion("page property");
4280 break;
4281 }
4282}
4283
4284
4289
4290static void tex_aux_set_auxiliary(int a)
4291{
4292 (void) a;
4293 switch (cur_chr) {
4294 case space_factor_code:
4295 if (cur_mode == hmode) {
4296 cur_list.space_factor = tex_scan_space_factor(1);
4297 } else {
4298 tex_aux_run_illegal_case();
4299 }
4300 break;
4301 case prev_depth_code:
4302 if (cur_mode == vmode) {
4303 cur_list.prev_depth = tex_scan_dimension(0, 0, 0, 1, NULL);
4304 } else {
4305 tex_aux_run_illegal_case();
4306 }
4307 break;
4308 case prev_graf_code:
4309 {
4310 lmt_nest_state.nest[tex_vmode_nest_index()].prev_graf = tex_scan_positive_number(1);
4311 break;
4312 }
4313 case interaction_mode_code:
4314 {
4315 tex_aux_set_interaction(tex_scan_integer(1, NULL));
4316 break;
4317 }
4318 case insert_mode_code:
4319 {
4320 tex_set_insert_mode(tex_scan_integer(1, NULL));
4321 break;
4322 }
4323 }
4324}
4325
4326
4330
4331static void tex_aux_set_box_property(void)
4332{
4333 halfword code = cur_chr;
4334 halfword n = tex_scan_box_register_number();
4335 halfword b = box_register(n);
4336 switch (code) {
4337 case box_width_code:
4338 {
4339 scaled v = tex_scan_dimension(0, 0, 0, 1, NULL);
4340 if (b) {
4341 box_width(b) = v;
4342 }
4343 break;
4344 }
4345 case box_height_code:
4346 {
4347 scaled v = tex_scan_dimension(0, 0, 0, 1, NULL);
4348 if (b) {
4349 box_height(b) = v;
4350 }
4351 break;
4352 }
4353 case box_depth_code:
4354 {
4355 scaled v = tex_scan_dimension(0, 0, 0, 1, NULL);
4356 if (b) {
4357 box_depth(b) = v;
4358 }
4359 break;
4360 }
4361 case box_direction_code:
4362 {
4363 halfword v = tex_scan_direction(1);
4364 if (b) {
4365 tex_set_box_direction(b, v);
4366 }
4367 break;
4368 }
4369 case box_geometry_code:
4370 {
4371 halfword v = tex_scan_geometry(1);
4372 if (b) {
4373 box_geometry(b) = (singleword) v;
4374 }
4375 break;
4376 }
4377 case box_orientation_code:
4378 {
4379 halfword v = tex_scan_orientation(1);
4380 if (b) {
4381 box_orientation(b) = v;
4382 tex_set_box_geometry(b, orientation_geometry);
4383 }
4384 break;
4385 }
4386 case box_anchor_code:
4387 case box_anchors_code:
4388 {
4389 halfword v = code == box_anchor_code ? tex_scan_anchor(1) : tex_scan_anchors(1);
4390 if (b) {
4391 box_anchor(b) = v;
4392 tex_set_box_geometry(b, anchor_geometry);
4393 }
4394 break;
4395 }
4396 case box_source_code:
4397 {
4398 halfword v = tex_scan_integer(1, NULL);
4399 if (b) {
4400 box_source_anchor(b) = v;
4401 tex_set_box_geometry(b, anchor_geometry);
4402 }
4403 break;
4404 }
4405 case box_target_code:
4406 {
4407 halfword v = tex_scan_integer(1, NULL);
4408 if (b) {
4409 box_target_anchor(b) = v;
4410 tex_set_box_geometry(b, anchor_geometry);
4411 }
4412 break;
4413 }
4414 case box_xoffset_code:
4415 {
4416 scaled v = tex_scan_dimension(0, 0, 0, 1, NULL);
4417 if (b) {
4418 box_x_offset(b) = v;
4419 tex_set_box_geometry(b, offset_geometry);
4420 }
4421 break;
4422 }
4423 case box_yoffset_code:
4424 {
4425 scaled v = tex_scan_dimension(0, 0, 0, 1, NULL);
4426 if (b) {
4427 box_y_offset(b) = v;
4428 tex_set_box_geometry(b, offset_geometry);
4429 }
4430 break;
4431 }
4432 case box_xmove_code:
4433 {
4434 scaled v = tex_scan_dimension(0, 0, 0, 1, NULL);
4435 if (b) {
4436 box_x_offset(b) = tex_aux_checked_dimension1(box_x_offset(b) + v);
4437 box_width(b) = tex_aux_checked_dimension2(box_width(b) + v);
4438 tex_set_box_geometry(b, offset_geometry);
4439 }
4440 break;
4441 }
4442 case box_ymove_code:
4443 {
4444 scaled v = tex_scan_dimension(0, 0, 0, 1, NULL);
4445 if (b) {
4446 box_y_offset(b) = tex_aux_checked_dimension1(box_y_offset(b) + v);
4447 box_height(b) = tex_aux_checked_dimension2(box_height(b) + v);
4448 box_depth(b) = tex_aux_checked_dimension2(box_depth(b) - v);
4449 tex_set_box_geometry(b, offset_geometry);
4450 }
4451 break;
4452 }
4453 case box_total_code:
4454 {
4455 scaled v = tex_scan_dimension(0, 0, 0, 1, NULL);
4456 if (b) {
4457 box_height(b) = v / 2;
4458 box_depth(b) = v - (v / 2);
4459 }
4460 }
4461 break;
4462 case box_shift_code:
4463 {
4464 scaled v = tex_scan_dimension(0, 0, 0, 1, NULL);
4465 if (b) {
4466 box_shift_amount(b) = v;
4467 }
4468 }
4469 break;
4470 case box_adapt_code:
4471 {
4472 scaled v = tex_scan_limited_scale(1);
4473 if (b) {
4474 tex_repack(b, v, packing_adapted);
4475 }
4476 }
4477 break;
4478 case box_repack_code:
4479 {
4480 scaled v = tex_scan_dimension(0, 0, 0, 1, NULL);
4481 if (b) {
4482 tex_repack(b, v, packing_additional);
4483 }
4484 }
4485 break;
4486 case box_freeze_code:
4487 {
4488 halfword recurse = tex_scan_integer(1, NULL);
4489 if (b) {
4490 tex_freeze(b, recurse, -1, 0);
4491 }
4492 }
4493 break;
4494 case box_limitate_code:
4495 {
4496 halfword recurse = tex_scan_integer(1, NULL);
4497 if (b) {
4498 tex_freeze(b, recurse, node_type(b), 0);
4499 }
4500 }
4501 break;
4502 case box_finalize_code:
4503 {
4504 halfword factor = tex_scan_integer(0, NULL);
4505 if (b) {
4506 tex_freeze(b, 0, -1, factor);
4507 }
4508 }
4509 break;
4510 case box_limit_code:
4511 {
4512 if (b && box_list(b)) {
4513 tex_limit(b);
4514 }
4515 }
4516 break;
4517 case box_attribute_code:
4518 {
4519 halfword att = tex_scan_attribute_register_number();
4520 halfword val = tex_scan_integer(1, NULL);
4521 if (b) {
4522 if (val == unused_attribute_value) {
4523 tex_unset_attribute(b, att, val);
4524 } else {
4525 tex_set_attribute(b, att, val);
4526 }
4527 }
4528 }
4529 break;
4530 case box_vadjust_code:
4531 if (b) {
4532 tex_set_vadjust(b);
4533 } else {
4534 tex_run_vadjust();
4535 }
4536 break;
4537 case box_stretch_code:
4538 case box_shrink_code:
4539
4540 break;
4541 default:
4542 break;
4543 }
4544}
4545
4546
4550
4551static void tex_aux_set_box(int a)
4552{
4553 halfword slot = tex_scan_box_register_number();
4554 if (lmt_error_state.set_box_allowed) {
4555 tex_aux_scan_box(is_global(a) ? global_box_flag : box_flag, 1, null_flag, slot, 0);
4556 } else {
4557 tex_handle_error(
4558 normal_error_type,
4559 "Improper \\setbox",
4560 "Sorry, \\setbox is not allowed after \\halign in a display, between \\accent and\n"
4561 "an accented character, or in immediate assignments."
4562 );
4563 }
4564}
4565
4566
4572
4573static void tex_aux_set_shorthand_def(int a, int force)
4574{
4575 halfword code = cur_chr;
4576
4587 tex_get_r_token();
4588 if (force || tex_define_permitted(cur_cs, a)) {
4589
4590 halfword p = cur_cs;
4591 tex_define(a, p, relax_cmd, relax_code);
4592 tex_scan_optional_equals();
4593 switch (code) {
4594 case char_def_code:
4595 {
4596 halfword chr = tex_scan_char_number(0);
4597 tex_define_again(a, p, char_given_cmd, chr);
4598 break;
4599 }
4600 case math_char_def_code:
4601 {
4602 mathcodeval mval = tex_scan_mathchar(tex_mathcode);
4603 tex_define_again(a, p, mathspec_cmd, tex_new_math_spec(mval, tex_mathcode));
4604 break;
4605 }
4606 case math_dchar_def_code:
4607 {
4608 mathdictval dval = tex_scan_mathdict();
4609 mathcodeval mval = tex_scan_mathchar(umath_mathcode);
4610 tex_define_again(a, p, mathspec_cmd, tex_new_math_dict_spec(dval, mval, umath_mathcode));
4611 break;
4612 }
4613 case math_uchar_def_code:
4614 {
4615 mathcodeval mval = tex_scan_mathchar(umath_mathcode);
4616 tex_define_again(a, p, mathspec_cmd, tex_new_math_spec(mval, umath_mathcode));
4617 break;
4618 }
4619 case count_def_code:
4620 {
4621 halfword n = tex_scan_integer_register_number();
4622 tex_define_again(a, p, register_integer_cmd, register_integer_location(n));
4623 break;
4624 }
4625 case attribute_def_code:
4626 {
4627 halfword n = tex_scan_attribute_register_number();
4628 tex_define_again(a, p, register_attribute_cmd, register_attribute_location(n));
4629 break;
4630 }
4631 case float_def_code:
4632 {
4633 scaled n = tex_scan_posit_register_number();
4634 tex_define_again(a, p, register_posit_cmd, register_posit_location(n));
4635 break;
4636 }
4637 case dimen_def_code:
4638 {
4639 scaled n = tex_scan_dimension_register_number();
4640 tex_define_again(a, p, register_dimension_cmd, register_dimension_location(n));
4641 break;
4642 }
4643 case skip_def_code:
4644 {
4645 halfword n = tex_scan_glue_register_number();
4646 tex_define_again(a, p, register_glue_cmd, register_glue_location(n));
4647 break;
4648 }
4649 case muskip_def_code:
4650 {
4651 halfword n = tex_scan_muglue_register_number();
4652 tex_define_again(a, p, register_muglue_cmd, register_muglue_location(n));
4653 break;
4654 }
4655 case toks_def_code:
4656 {
4657 halfword n = tex_scan_toks_register_number();
4658 tex_define_again(a, p, register_toks_cmd, register_toks_location(n));
4659 break;
4660 }
4661 case lua_def_code:
4662 {
4663 halfword v = tex_scan_function_reference(1);
4664 tex_define_again(a, p, is_protected(a) ? lua_protected_call_cmd : (is_semiprotected(a) ? lua_semi_protected_call_cmd : lua_call_cmd), v);
4665 break;
4666 }
4667 case integer_def_code:
4668
4669 {
4670 halfword v = tex_scan_integer(1, NULL);
4671 tex_define_again(a, p, integer_cmd, v);
4672 break;
4673 }
4674 case parameter_def_code:
4675
4676 {
4677 halfword v = tex_get_parameter_index(tex_scan_parameter_index());
4678 tex_define_again(a, p, index_cmd, v);
4679 break;
4680 }
4681 case dimension_def_code:
4682
4683 {
4684 scaled v = tex_scan_dimension(0, 0, 0, 1, NULL);
4685 tex_define_again(a, p, dimension_cmd, v);
4686 break;
4687 }
4688 case posit_def_code:
4689
4690 {
4691 scaled v = tex_scan_posit(1);
4692 tex_define_again(a, p, posit_cmd, v);
4693 break;
4694 }
4695 case gluespec_def_code:
4696 {
4697 halfword v = tex_scan_glue(glue_val_level, 1, 1);
4698 tex_define_again(a, p, gluespec_cmd, v);
4699 break;
4700 }
4701 case mugluespec_def_code:
4702 {
4703 halfword v = tex_scan_glue(muglue_val_level, 1, 0);
4704 tex_define_again(a, p, mugluespec_cmd, v);
4705 break;
4706 }
4707
4715 case fontspec_def_code:
4716 {
4717 halfword v = tex_scan_font(1);
4718 tex_define(a, p, fontspec_cmd, v);
4719 break;
4720 }
4721 default:
4722 tex_confusion("shorthand definition");
4723 break;
4724 }
4725 }
4726}
4727
4728static void tex_aux_set_association(int flags, int force)
4729{
4730 switch (cur_chr) {
4731 case unit_association_code:
4732 {
4733 tex_get_r_token();
4734 if (tex_valid_userunit(cur_cmd, cur_chr, cur_cs)) {
4735 halfword cs = cur_cs;
4736 halfword index = tex_scan_unit_register_number(1);
4737 if (tex_get_unit_class(index)) {
4738 tex_handle_error(
4739 normal_error_type,
4740 "Imvalid \\associateunit, unit %i is already taken", index,
4741 "Units can only be bound once and not overload built-in ones."
4742 );
4743 } else if (force || tex_define_permitted(cs, flags)) {
4744 unit_parameter(index) = cs;
4745 }
4746 } else {
4747 tex_handle_error(
4748 normal_error_type,
4749 "Invalid \\associateunit target",
4750 "Only existing dimension equivalent commands are accepted."
4751 );
4752 }
4753 break;
4754 }
4755 }
4756}
4757
4758
4759
4760static void tex_aux_set_specification(int a)
4761{
4762 halfword loc = cur_chr;
4763 quarterword num = (quarterword) internal_specification_number(loc);
4764 halfword p = null;
4765 halfword options = 0;
4766 halfword count = tex_scan_integer(1, NULL);
4767 if (tex_scan_keyword("options")) {
4768 options = tex_scan_integer(0, NULL);
4769 }
4770 if (count > 0) {
4771 p = tex_new_specification_node(count, num, options);
4772 switch (num) {
4773 case par_shape_code:
4774 {
4775 for (int j = 1; j <= count; j++) {
4776 tex_set_specification_indent(p, j, tex_scan_dimension(0, 0, 0, 0, NULL));
4777 tex_set_specification_width(p, j, tex_scan_dimension(0, 0, 0, 0, NULL));
4778 }
4779 break;
4780 }
4781
4786 case par_passes_code:
4787 {
4788 halfword j = 1;
4789 while (j <= count) {
4790 switch (tex_scan_character("abcdefilnoqstABCDEFILNOQST", 0, 1, 0)) {
4791 case 0:
4792 goto DONE;
4793 case 'a': case 'A':
4794 if (tex_scan_mandate_keyword("adj", 1)) {
4795 switch (tex_scan_character("duDU", 0, 0, 0)) {
4796 case 'd': case 'D' :
4797 if (tex_scan_mandate_keyword("adjdemerits", 4)) {
4798 tex_set_passes_adjdemerits(p, j, tex_scan_integer(0, NULL));
4799 } break;
4800 case 'u': case 'U':
4801 if (tex_scan_mandate_keyword("adjustspacing", 4)) {
4802 if (tex_scan_character("sS", 0, 0, 0)) {
4803 switch (tex_scan_character("thTH", 0, 0, 0)) {
4804 case 't': case 'T':
4805 switch (tex_scan_character("erER", 0, 0, 0)) {
4806 case 'e': case 'E':
4807 if (tex_scan_mandate_keyword("adjustspacingstep", 16)) {
4808 tex_set_passes_adjustspacingstep(p, j, tex_scan_integer(0, NULL));
4809 }
4810 break;
4811 case 'r': case 'R':
4812 if (tex_scan_mandate_keyword("adjustspacingstretch", 16)) {
4813 tex_set_passes_adjustspacingstretch(p, j, tex_scan_integer(0, NULL));
4814 }
4815 break;
4816 default:
4817 tex_aux_show_keyword_error("adjustspacingsstep|adjustspacingstretch");
4818 goto DONE;
4819 }
4820 break;
4821 case 'h': case 'H':
4822 if (tex_scan_mandate_keyword("adjustspacingshrink", 15)) {
4823 tex_set_passes_adjustspacingshrink(p, j, tex_scan_integer(0, NULL));
4824 }
4825 break;
4826 default:
4827 tex_aux_show_keyword_error("adjustspacingsstep|adjustspacingshrink|adjustspacingstretch");
4828 goto DONE;
4829 }
4830 } else {
4831 tex_set_passes_adjustspacing(p, j, tex_scan_integer(0, NULL));
4832 }
4833 }
4834 break;
4835 default:
4836 tex_aux_show_keyword_error("adjdemerits|adjustspacing|adjustspacingstep|adjustspacingshrink|adjustspacingstretch");
4837 goto DONE;
4838 }
4839 }
4840 break;
4841 case 'b': case 'B':
4842 if (tex_scan_mandate_keyword("badness", 1)) {
4843 tex_set_passes_badness(p, j, tex_scan_integer(0, NULL));
4844 }
4845 break;
4846 case 'c': case 'C':
4847 switch (tex_scan_character("alAL", 0, 0, 0)) {
4848 case 'a': case 'A':
4849 if (tex_scan_mandate_keyword("callback", 2)) {
4850 tex_set_passes_callback(p, j, tex_scan_integer(0, NULL));
4851 tex_set_passes_features(p, j, passes_callback_set);
4852 }
4853 break;
4854 case 'l': case 'L':
4855 if (tex_scan_mandate_keyword("classes", 2)) {
4856 tex_set_passes_classes(p, j, tex_scan_integer(0, NULL));
4857 }
4858 break;
4859 default:
4860 tex_aux_show_keyword_error("classes|callback");
4861 goto DONE;
4862 }
4863 break;
4864 case 'd': case 'D':
4865 if (tex_scan_mandate_keyword("double", 1)) {
4866 switch (tex_scan_character("ahAH", 0, 0, 0)) {
4867 case 'a': case 'A':
4868 if (tex_scan_mandate_keyword("doubleadjdemerits", 7)) {
4869 tex_set_passes_doubleadjdemerits(p, j, tex_scan_integer(0, NULL));
4870 }
4871 break;
4872 case 'h': case 'H':
4873 if (tex_scan_mandate_keyword("doublehyphendemerits", 7)) {
4874 tex_set_passes_doublehyphendemerits(p, j, tex_scan_integer(0, NULL));
4875 }
4876 break;
4877 default:
4878 tex_aux_show_keyword_error("doubleadjdemerits|doublehyphendemerits");
4879 goto DONE;
4880 }
4881 }
4882 break;
4883 case 'e': case 'E':
4884 switch (tex_scan_character("mxMX", 0, 0, 0)) {
4885 case 'm': case 'M':
4886 if (tex_scan_mandate_keyword("emergencystretch", 2)) {
4887 tex_set_passes_emergencystretch(p, j, tex_scan_dimension(0, 0, 0, 0, NULL));
4888 }
4889 break;
4890 case 'x': case 'X':
4891 if (tex_scan_mandate_keyword("extrahyphenpenalty", 2)) {
4892 tex_set_passes_extrahyphenpenalty(p, j, tex_scan_integer(0, NULL));
4893 }
4894 break;
4895 default:
4896 tex_aux_show_keyword_error("emergencystretch|extrahyphenpenalty");
4897 goto DONE;
4898 }
4899 break;
4900 case 'f': case 'F':
4901 if (tex_scan_mandate_keyword("finalhyphendemerits", 1)) {
4902 tex_set_passes_finalhyphendemerits(p, j, tex_scan_integer(0, NULL));
4903 }
4904 break;
4905 case 'i': case 'I':
4906 switch (tex_scan_character("dfDF", 0, 0, 0)) {
4907 case 'd': case 'D':
4908 if (tex_scan_mandate_keyword("identifier", 2)) {
4909 tex_set_passes_identifier(p, j, tex_scan_integer(0, NULL));
4910 }
4911 break;
4912 case 'f': case 'F':
4913 if (tex_scan_mandate_keyword("ifadjustspacing", 2)) {
4914 tex_set_passes_features(p, j, passes_if_adjust_spacing);
4915 }
4916 break;
4917 default:
4918 tex_aux_show_keyword_error("identifier|ifadjustspacing");
4919 goto DONE;
4920 }
4921 break;
4922 case 'l': case 'L':
4923 switch (tex_scan_character("ioIO", 0, 0, 0)) {
4924 case 'o': case 'O':
4925 if (tex_scan_mandate_keyword("looseness", 2)) {
4926 tex_set_passes_looseness(p, j, tex_scan_integer(0, NULL));
4927 }
4928 break;
4929 case 'i': case 'I':
4930 if (tex_scan_mandate_keyword("line", 2)) {
4931 switch (tex_scan_character("bpBP", 0, 0, 0)) {
4932 case 'b': case 'B':
4933 if (tex_scan_mandate_keyword("linebreak", 5)) {
4934 switch (tex_scan_character("coCO", 0, 0, 0)) {
4935 case 'c': case 'C':
4936 if (tex_scan_mandate_keyword("linebreakcriterion", 10)) {
4937 tex_set_passes_linebreakcriterion(p, j, tex_scan_integer(0, NULL));
4938 }
4939 break;
4940 case 'o': case 'O':
4941 if (tex_scan_mandate_keyword("linebreakoptional", 10)) {
4942 tex_set_passes_optional(p, j, tex_scan_integer(0, NULL));
4943 tex_set_passes_features(p, j, passes_optional_set);
4944 }
4945 break;
4946 default:
4947 tex_aux_show_keyword_error("linebreakcriterium|linebreakoptional");
4948 goto DONE;
4949 }
4950 }
4951 break;
4952 case 'p': case 'P':
4953 if (tex_scan_mandate_keyword("linepenalty", 5)) {
4954 tex_set_passes_linepenalty(p, j, tex_scan_integer(0, NULL));
4955 }
4956 break;
4957 default:
4958 tex_aux_show_keyword_error("linebreakcriterium|linebreakoptional|linepenalty");
4959 goto DONE;
4960 }
4961 }
4962 break;
4963 }
4964 break;
4965 case 'n': case 'N':
4966 if (tex_scan_mandate_keyword("next", 1)) {
4967 j++;
4968 }
4969 break;
4970 case 'o': case 'O':
4971
4972 if (tex_scan_mandate_keyword("orphanpenalty", 1)) {
4973 tex_set_passes_orphanpenalty(p, j, tex_scan_integer(0, NULL));
4974 tex_set_passes_features(p, j, passes_orphan_penalty_set);
4975 }
4976 break;
4977 case 'q': case 'Q':
4978 if (tex_scan_mandate_keyword("quit", 1)) {
4979 tex_set_passes_features(p, j, passes_quit_pass);
4980 }
4981 break;
4982 case 's': case 'S':
4983
4984 if (tex_scan_mandate_keyword("skip", 1)) {
4985 tex_set_passes_features(p, j, passes_skip_pass);
4986 }
4987 break;
4988 case 't': case 'T':
4989 switch (tex_scan_character("hoHO", 0, 0, 0)) {
4990 case 'h': case 'H':
4991 if (tex_scan_mandate_keyword("threshold", 2)) {
4992 tex_set_passes_threshold(p, j, tex_scan_dimension(0, 0, 0, 0, NULL));
4993 }
4994 break;
4995 case 'o': case 'O':
4996 if (tex_scan_mandate_keyword("tolerance", 2)) {
4997 tex_set_passes_tolerance(p, j, tex_scan_integer(0, NULL));
4998 }
4999 break;
5000 default:
5001 tex_aux_show_keyword_error("threshold|tolerance");
5002 goto DONE;
5003 }
5004 break;
5005 default:
5006 goto DONE;
5007 }
5008 }
5009 DONE:
5010 break;
5011 }
5012 default:
5013 {
5014 for (int j = 1; j <= count; j++) {
5015 tex_set_specification_penalty(p, j, tex_scan_integer(0, NULL));
5016 }
5017 break;
5018 }
5019 }
5020 }
5021 tex_define(a, loc, specification_reference_cmd, p);
5022 if (is_frozen(a) && cur_mode == hmode) {
5023 tex_update_par_par(specification_reference_cmd, num);
5024 }
5025}
5026
5027
5031
5032static void tex_aux_set_hyph_data(void)
5033{
5034 switch (cur_chr) {
5035 case hyphenation_code:
5036 {
5037 halfword result = tex_scan_toks_expand(0, NULL, 0, 0);
5038 tex_load_tex_hyphenation(language_par, result);
5039 tex_flush_token_list(result);
5040 break;
5041 }
5042 case patterns_code:
5043 {
5044 halfword result = tex_scan_toks_expand(0, NULL, 0, 0);
5045 tex_load_tex_patterns(language_par, result);
5046 tex_flush_token_list(result);
5047 break;
5048 }
5049 case prehyphenchar_code:
5050 tex_set_pre_hyphen_char(language_par, tex_scan_integer(1, NULL));
5051 break;
5052 case posthyphenchar_code:
5053 tex_set_post_hyphen_char(language_par, tex_scan_integer(1, NULL));
5054 break;
5055 case preexhyphenchar_code:
5056 tex_set_pre_exhyphen_char(language_par, tex_scan_integer(1, NULL));
5057 break;
5058 case postexhyphenchar_code:
5059 tex_set_post_exhyphen_char(language_par, tex_scan_integer(1, NULL));
5060 break;
5061 case hyphenationmin_code:
5062 tex_set_hyphenation_min(language_par, tex_scan_integer(1, NULL));
5063 break;
5064 case hjcode_code:
5065 {
5066 halfword lan = tex_scan_integer(0, NULL);
5067 halfword val = tex_scan_integer(1, NULL);
5068 tex_set_hj_code(language_par, lan, val, -1);
5069 }
5070 break;
5071 default:
5072 break;
5073 }
5074}
5075
5076
5077
5078static void tex_aux_set_font_property(void)
5079{
5080 halfword code = cur_chr;
5081 switch (code) {
5082 case font_hyphen_code:
5083 {
5084 halfword fnt = tex_scan_font_identifier(NULL);
5085 halfword val = tex_scan_integer(1, NULL);
5086 set_font_hyphen_char(fnt, val);
5087 break;
5088 }
5089 case font_skew_code:
5090 {
5091 halfword fnt = tex_scan_font_identifier(NULL);
5092 halfword val = tex_scan_integer(1, NULL);
5093 set_font_skew_char(fnt, val);
5094 break;
5095 }
5096 case font_lp_code:
5097 {
5098 halfword fnt = tex_scan_font_identifier(NULL);
5099 halfword chr = tex_scan_char_number(0);
5100 halfword val = tex_scan_dimension(0, 0, 0, 1, NULL);
5101 tex_set_lpcode_in_font(fnt, chr, val);
5102 break;
5103 }
5104 case font_rp_code:
5105 {
5106 halfword fnt = tex_scan_font_identifier(NULL);
5107 halfword chr = tex_scan_char_number(0);
5108 halfword val = tex_scan_dimension(0, 0, 0, 1, NULL);
5109 tex_set_rpcode_in_font(fnt, chr, val);
5110 break;
5111 }
5112 case font_ef_code:
5113 {
5114 halfword fnt = tex_scan_font_identifier(NULL);
5115 halfword chr = tex_scan_char_number(0);
5116 halfword val = tex_scan_integer(1, NULL);
5117 tex_set_efcode_in_font(fnt, chr, val);
5118 break;
5119 }
5120 case font_cf_code:
5121 {
5122 halfword fnt = tex_scan_font_identifier(NULL);
5123 halfword chr = tex_scan_char_number(0);
5124 halfword val = tex_scan_integer(1, NULL);
5125 tex_set_cfcode_in_font(fnt, chr, val);
5126 break;
5127 }
5128 case font_dimension_code:
5129 {
5130 tex_set_font_dimension();
5131 break;
5132 }
5133 case scaled_font_dimension_code:
5134 {
5135 tex_set_scaled_font_dimension();
5136 break;
5137 }
5138 default:
5139 break;
5140 }
5141}
5142
5143
5147
5148static void tex_aux_set_font(int a)
5149{
5150 tex_set_cur_font(a, cur_chr);
5151}
5152
5153static void tex_aux_set_define_font(int a)
5154{
5155 if (! tex_tex_def_font(a)) {
5156 tex_aux_show_frozen_error(cur_cs);
5157 }
5158}
5159
5160
5165
5166static void tex_aux_set_def(int flags, int force)
5167{
5168 int expand = 0;
5169 switch (cur_chr) {
5170 case expanded_def_code:
5171 expand = 1;
5172 break;
5173 case def_code:
5174 break;
5175 case global_expanded_def_code:
5176 expand = 1;
5177
5178 case global_def_code:
5179 flags = add_global_flag(flags);
5180 break;
5181 case expanded_def_csname_code:
5182 expand = 1;
5183
5184 case def_csname_code:
5185 cur_cs = tex_create_csname();
5186 goto DONE;
5187 case global_expanded_def_csname_code:
5188 expand = 1;
5189
5190 case global_def_csname_code:
5191 cur_cs = tex_create_csname();
5192 flags = add_global_flag(flags);
5193 goto DONE;
5194 case constant_def_code:
5195 expand = 2;
5196 flags = add_constant_flag(flags);
5197 break;
5198 case constant_def_csname_code:
5199 expand = 2;
5200 cur_cs = tex_create_csname();
5201 flags = add_constant_flag(flags);
5202 goto DONE;
5203 }
5204 tex_get_r_token();
5205 DONE:
5206 if (global_defs_par) {
5207 flags = global_defs_par > 0 ? add_global_flag(flags) : remove_global_flag(flags);
5208 }
5209 if (force || tex_define_permitted(cur_cs, flags)) {
5210 halfword p = cur_cs;
5211 halfword t = expand == 2 ? tex_scan_toks_expand(0, null, 1, 0) : (expand ? tex_scan_macro_expand() : tex_scan_macro_normal());
5212 tex_define(flags, p, tex_flags_to_cmd(flags), t);
5213 }
5214}
5215
5216static void tex_aux_set_let(int flags, int force)
5217{
5218 halfword code = cur_chr;
5219 halfword cs = null;
5220 switch (code) {
5221 case global_let_code:
5222
5223 if (global_defs_par >= 0) {
5224 flags = add_global_flag(flags);
5225 }
5226
5227 case let_code:
5228
5229 tex_get_r_token();
5230 LETINDEED:
5231 if (force || tex_define_permitted(cur_cs, flags)) {
5232 cs = cur_cs;
5233 do {
5234 tex_get_token();
5235 } while (cur_cmd == spacer_cmd);
5236 if (cur_tok == equal_token) {
5237 tex_get_token();
5238 if (cur_cmd == spacer_cmd) {
5239 tex_get_token();
5240 }
5241 }
5242 }
5243 break;
5244 case future_let_code:
5245 case future_def_code:
5246
5247 tex_get_r_token();
5248
5251 if (force || tex_define_permitted(cur_cs, flags)) {
5252 halfword q;
5253 cs = cur_cs;
5254 q = tex_get_token();
5255 tex_back_input(tex_get_token());
5256
5260 tex_back_input(q);
5261 if (code == future_def_code) {
5262 halfword result = get_reference_token();
5263 halfword r = result;
5264 r = tex_store_new_token(r, cur_tok);
5265 cur_cmd = tex_flags_to_cmd(flags);
5266 cur_chr = result;
5267 }
5268 }
5269 break;
5270 case let_charcode_code:
5271
5272 {
5273 halfword character = tex_scan_integer(0, NULL);
5274 if (character > 0) {
5275 cs = tex_active_to_cs(character, 1);
5276 do {
5277 tex_get_token();
5278 } while (cur_cmd == spacer_cmd);
5279 if (cur_tok == equal_token) {
5280 tex_get_token();
5281 if (cur_cmd == spacer_cmd) {
5282 tex_get_token();
5283 }
5284 }
5285 } else {
5286 tex_handle_error(
5287 normal_error_type,
5288 "invalid number for \\letcharcode",
5289 NULL
5290 );
5291 }
5292 break;
5293 }
5294 case swap_cs_values_code:
5295 {
5296
5303 halfword s1, s2;
5304 tex_get_r_token();
5305 s1 = cur_cs;
5306 tex_get_r_token();
5307 s2 = cur_cs;
5308 tex_define_swapped(flags, s1, s2, force);
5309 return;
5310 }
5311 case let_protected_code:
5312 tex_get_r_token();
5313 if (force || tex_define_permitted(cur_cs, flags)) {
5314 switch (cur_cmd) {
5315 case call_cmd:
5316 case semi_protected_call_cmd:
5317 set_eq_type(cur_cs, protected_call_cmd);
5318 break;
5319 case tolerant_call_cmd:
5320 case tolerant_semi_protected_call_cmd:
5321 set_eq_type(cur_cs, tolerant_protected_call_cmd);
5322 break;
5323 }
5324 }
5325 return;
5326 case unlet_protected_code:
5327 tex_get_r_token();
5328 if (force || tex_define_permitted(cur_cs, flags)) {
5329 switch (cur_cmd) {
5330 case protected_call_cmd:
5331 case semi_protected_call_cmd:
5332 set_eq_type(cur_cs, call_cmd);
5333 break;
5334 case tolerant_call_cmd:
5335 case tolerant_semi_protected_call_cmd:
5336 set_eq_type(cur_cs, tolerant_call_cmd);
5337 break;
5338 }
5339 }
5340 return;
5341 case let_frozen_code:
5342 tex_get_r_token();
5343 if (is_call_cmd(cur_cmd) && (force || tex_define_permitted(cur_cs, flags))) {
5344 set_eq_flag(cur_cs, add_frozen_flag(eq_flag(cur_cs)));
5345 }
5346 return;
5347 case unlet_frozen_code:
5348 tex_get_r_token();
5349 if (is_call_cmd(cur_cmd) && (force || tex_define_permitted(cur_cs, flags))) {
5350 set_eq_flag(cur_cs, remove_frozen_flag(eq_flag(cur_cs)));
5351 }
5352 return;
5353 case global_let_csname_code:
5354 if (global_defs_par >= 0) {
5355 flags = add_global_flag(flags);
5356 }
5357
5358 case let_csname_code:
5359 cur_cs = tex_create_csname();
5360 goto LETINDEED;
5361 case global_let_to_nothing_code:
5362 if (global_defs_par >= 0) {
5363 flags = add_global_flag(flags);
5364 }
5365
5366 case let_to_nothing_code:
5367 tex_get_r_token();
5368 LETTONOTHING:
5369 if (force || tex_define_permitted(cur_cs, flags)) {
5370
5371
5372
5373
5374
5375
5376 halfword empty = lmt_token_state.empty;
5377 tex_define(flags, cur_cs, tex_flags_to_cmd(flags), empty);
5378 }
5379 return;
5380 case let_to_last_named_cs_code:
5381
5387 if (lmt_scanner_state.last_cs_name == null_cs) {
5388 tex_get_r_token();
5389 goto LETTONOTHING;
5390 } else {
5391
5396 halfword lastcs = lmt_scanner_state.last_cs_name;
5397 tex_get_r_token();
5398 cs = cur_cs;
5399 cur_cs = lastcs;
5400 cur_cmd = eq_type(lastcs);
5401 cur_chr = eq_value(lastcs);
5402 break;
5403 }
5404 default:
5405
5406 tex_confusion("let");
5407 break;
5408 }
5409 if (is_referenced_cmd(cur_cmd)) {
5410 tex_add_token_reference(cur_chr);
5411 } else if (is_nodebased_cmd(cur_cmd)) {
5412 cur_chr = cur_chr ? tex_copy_node(cur_chr) : null;
5413 }
5414
5415 if (cs && cur_cmd >= 0) {
5416 singleword oldf = eq_flag(cur_cs);
5417 singleword newf = 0;
5418 singleword cmd = (singleword) cur_cmd;
5419 if (is_aliased(flags)) {
5420
5424 newf = oldf;
5425 } else {
5426 oldf = remove_overload_flags(oldf);
5427 newf = oldf | make_eq_flag_bits(flags);
5428 }
5429 if (is_protected(flags)) {
5430 switch (cmd) {
5431 case call_cmd:
5432 cmd = protected_call_cmd;
5433 break;
5434 case tolerant_call_cmd:
5435 cmd = tolerant_protected_call_cmd;
5436 break;
5437 }
5438 }
5439 tex_define_inherit(flags, cs, (singleword) newf, (singleword) cmd, cur_chr);
5440 } else {
5441 tex_define(flags, cs, (singleword) cur_cmd, cur_chr);
5442 }
5443}
5444
5445
5450
5451static void tex_aux_set_assign_toks(int a)
5452{
5453 halfword cs = cur_cs;
5454 halfword cmd = cur_cmd;
5455 halfword chr;
5456 halfword tail;
5457
5458 halfword loc = cmd == register_cmd ? register_toks_location(tex_scan_toks_register_number()) : cur_chr;
5459
5462 {
5463 int n = 1 ;
5464 while (1) {
5465 tex_get_x_token();
5466 if (cur_cmd == spacer_cmd) {
5467
5468 } else if (cur_cmd == relax_cmd) {
5469 n = 0;
5470 } else if (n && cur_tok == equal_token) {
5471 n = 0;
5472 } else {
5473 break;
5474 }
5475 }
5476 }
5477 if (cur_cmd != left_brace_cmd) {
5478
5482 if (cur_cmd == register_cmd && cur_chr == token_val_level) {
5483 chr = eq_value(register_toks_location(tex_scan_toks_register_number()));
5484 if (chr) {
5485 tex_add_token_reference(chr);
5486 }
5487 goto DEFINE;
5488 } else if (cur_cmd == register_toks_cmd || cur_cmd == internal_toks_cmd) {
5489 chr = eq_value(cur_chr);
5490 if (chr) {
5491 tex_add_token_reference(chr);
5492 }
5493 goto DEFINE;
5494 } else {
5495
5496 tex_back_input(cur_tok);
5497 cur_cs = cs;
5498 chr = tex_scan_toks_normal(0, &tail);
5499 }
5500 } else {
5501 cur_cs = cs;
5502 chr = tex_scan_toks_normal(1, &tail);
5503 }
5504 if (! token_link(chr)) {
5505 tex_put_available_token(chr);
5506 chr = null;
5507 } else if (loc == internal_toks_location(output_routine_code)) {
5508 halfword head = token_link(chr);
5509 halfword list = tex_store_new_token(null, left_brace_token + '{');
5510 tex_store_new_token(tail, right_brace_token + '}');
5511 set_token_link(list, head);
5512 set_token_link(chr, list);
5513 }
5514 DEFINE:
5515 tex_define(a, loc, cmd == internal_toks_cmd ? internal_toks_reference_cmd : register_toks_reference_cmd, chr);
5516}
5517
5518
5519
5520static void tex_aux_set_define_char_code(int a)
5521{
5522 switch (cur_chr) {
5523 case catcode_charcode:
5524 {
5525 halfword chr = tex_scan_char_number(0);
5526 halfword val = tex_scan_category_code(1);
5527 tex_set_cat_code(cat_code_table_par, chr, val, global_or_local(a));
5528 }
5529 break;
5530 case lccode_charcode:
5531 {
5532 halfword chr = tex_scan_char_number(0);
5533 halfword val = tex_scan_char_number(1);
5534 tex_set_lc_code(chr, val, global_or_local(a));
5535 }
5536 break;
5537 case uccode_charcode:
5538 {
5539 halfword chr = tex_scan_char_number(0);
5540 halfword val = tex_scan_char_number(1);
5541 tex_set_uc_code(chr, val, global_or_local(a));
5542 }
5543 break;
5544 case sfcode_charcode:
5545 {
5546 halfword chr = tex_scan_char_number(0);
5547 halfword val = tex_scan_space_factor(1);
5548 tex_set_sf_code(chr, val, global_or_local(a));
5549 }
5550 break;
5551 case hccode_charcode:
5552 {
5553 halfword chr = tex_scan_char_number(0);
5554 halfword val = tex_scan_char_number(1);
5555 tex_set_hc_code(chr, val, global_or_local(a));
5556 }
5557 break;
5558 case hmcode_charcode:
5559 {
5560 halfword chr = tex_scan_char_number(0);
5561 halfword val = tex_scan_math_discretionary_number(1);
5562 tex_set_hm_code(chr, val, global_or_local(a));
5563 }
5564 break;
5565 case amcode_charcode:
5566 {
5567 halfword chr = tex_scan_char_number(0);
5568 halfword val = tex_scan_category_code(1);
5569 tex_set_am_code(chr, val, global_or_local(a));
5570 }
5571 break;
5572 case mathcode_charcode:
5573 tex_scan_extdef_math_code(global_or_local(a), tex_mathcode);
5574 break;
5575 case extmathcode_charcode:
5576 tex_scan_extdef_math_code(global_or_local(a), umath_mathcode);
5577 break;
5578 case delcode_charcode:
5579 tex_scan_extdef_del_code(global_or_local(a), tex_mathcode);
5580 break;
5581 case extdelcode_charcode:
5582 tex_scan_extdef_del_code(global_or_local(a), umath_mathcode);
5583 break;
5584 default:
5585 break;
5586 }
5587}
5588
5589static void tex_aux_skip_optional_equal(void)
5590{
5591 do {
5592 tex_get_x_token();
5593 } while (cur_cmd == spacer_cmd);
5594 if (cur_tok == equal_token) {
5595 tex_get_x_token();
5596 }
5597}
5598
5599static void tex_aux_set_math_parameter(int a)
5600{
5601 halfword code = cur_chr;
5602 halfword value = null;
5603 switch (code) {
5604 case math_parameter_reset_spacing:
5605 {
5606 tex_reset_all_styles(global_or_local(a));
5607 return;
5608 }
5609 case math_parameter_set_spacing:
5610 case math_parameter_set_atom_rule:
5611 {
5612 halfword left = tex_scan_math_class_number(0);
5613 halfword right = tex_scan_math_class_number(0);
5614 switch (code) {
5615 case math_parameter_set_spacing:
5616 code = tex_to_math_spacing_parameter(left, right);
5617 break;
5618 case math_parameter_set_atom_rule:
5619 code = tex_to_math_rules_parameter(left, right);
5620 break;
5621 }
5622 if (code < 0) {
5623 tex_handle_error(
5624 normal_error_type,
5625 "Invalid math class pair",
5626 "I'm going to assume ordinary atoms."
5627 );
5628 switch (code) {
5629 case math_parameter_set_spacing:
5630 code = tex_to_math_spacing_parameter(ordinary_noad_subtype, ordinary_noad_subtype);
5631 break;
5632 case math_parameter_set_atom_rule:
5633 code = tex_to_math_rules_parameter(ordinary_noad_subtype, ordinary_noad_subtype);
5634 break;
5635 }
5636 }
5637 break;
5638 }
5639 case math_parameter_let_spacing:
5640 case math_parameter_let_atom_rule:
5641 {
5642 halfword mathclass = tex_scan_math_class_number(0);
5643 halfword display = tex_scan_math_class_number(1);
5644 halfword text = tex_scan_math_class_number(0);
5645 halfword script = tex_scan_math_class_number(0);
5646 halfword scriptscript = tex_scan_math_class_number(0);
5647 if (valid_math_class_code(mathclass)) {
5648 switch (code) {
5649 case math_parameter_let_spacing:
5650 code = internal_integer_location(first_math_class_code + mathclass);
5651 break;
5652 case math_parameter_let_atom_rule:
5653 code = internal_integer_location(first_math_atom_code + mathclass);
5654 break;
5655 }
5656 value = (display << 24) + (text << 16) + (script << 8) + scriptscript;
5657
5658 tex_word_define(a, code, value);
5659 } else {
5660 tex_handle_error(
5661 normal_error_type,
5662 "Invalid math class",
5663 "I'm going to ignore this alias."
5664 );
5665 }
5666 return;
5667 }
5668 case math_parameter_copy_spacing:
5669 case math_parameter_copy_atom_rule:
5670 case math_parameter_copy_parent:
5671 {
5672 halfword mathclass = tex_scan_math_class_number(0);
5673 halfword parent = tex_scan_math_class_number(1);
5674 if (valid_math_class_code(mathclass) && valid_math_class_code(parent)) {
5675 switch (code) {
5676 case math_parameter_copy_spacing:
5677 code = internal_integer_location(first_math_class_code + mathclass);
5678 value = count_parameter(first_math_class_code + parent);
5679 break;
5680 case math_parameter_copy_atom_rule:
5681 code = internal_integer_location(first_math_atom_code + mathclass);
5682 value = count_parameter(first_math_atom_code + parent);
5683 break;
5684 case math_parameter_copy_parent:
5685 code = internal_integer_location(first_math_parent_code + mathclass);
5686 value = count_parameter(first_math_parent_code + parent);
5687 break;
5688 }
5689 tex_word_define(a, code, value);
5690 } else {
5691 tex_handle_error(
5692 normal_error_type,
5693 "Invalid math class",
5694 "I'm going to ignore this alias."
5695 );
5696 }
5697 return;
5698 }
5699 case math_parameter_set_pre_penalty:
5700 case math_parameter_set_post_penalty:
5701 case math_parameter_set_display_pre_penalty:
5702 case math_parameter_set_display_post_penalty:
5703 {
5704 halfword mathclass = tex_scan_math_class_number(0);
5705 halfword penalty = tex_scan_integer(1, NULL);
5706 if (valid_math_class_code(mathclass)) {
5707 switch (code) {
5708 case math_parameter_set_pre_penalty:
5709 code = internal_integer_location(first_math_pre_penalty_code + mathclass);
5710 break;
5711 case math_parameter_set_post_penalty:
5712 code = internal_integer_location(first_math_post_penalty_code + mathclass);
5713 break;
5714 case math_parameter_set_display_pre_penalty:
5715 code = internal_integer_location(first_math_display_pre_penalty_code + mathclass);
5716 break;
5717 case math_parameter_set_display_post_penalty:
5718 code = internal_integer_location(first_math_display_post_penalty_code + mathclass);
5719 break;
5720 }
5721 tex_word_define(a, code, penalty);
5722
5723 } else {
5724 tex_handle_error(
5725 normal_error_type,
5726 "Invalid math class",
5727 "I'm going to ignore this atom penalty."
5728 );
5729 }
5730 return;
5731 }
5732 case math_parameter_let_parent:
5733 {
5734 halfword mathclass = tex_scan_math_class_number(0);
5735 halfword pre = tex_scan_math_class_number(1);
5736 halfword post = tex_scan_math_class_number(0);
5737 halfword options = tex_scan_math_class_number(0);
5738 halfword reserved = tex_scan_math_class_number(0);
5739 if (valid_math_class_code(mathclass)) {
5740 code = internal_integer_location(first_math_parent_code + mathclass);
5741 value = (reserved << 24) + (options << 16) + (pre << 8) + post;
5742 tex_word_define(a, code, value);
5743
5744 } else {
5745 tex_handle_error(
5746 normal_error_type,
5747 "Invalid math class",
5748 "I'm going to ignore this penalty alias."
5749 );
5750 }
5751 return;
5752 }
5753 case math_parameter_ignore:
5754 {
5755 halfword param = tex_scan_math_parameter();
5756 if (param >= 0) {
5757 code = internal_integer_location(first_math_ignore_code + param);
5758 value = tex_scan_integer(1, NULL);
5759 tex_word_define(a, code, value);
5760 }
5761 return;
5762 }
5763 case math_parameter_options:
5764 {
5765 halfword mathclass = tex_scan_math_class_number(0);
5766 if (valid_math_class_code(mathclass)) {
5767 code = internal_integer_location(first_math_options_code + mathclass);
5768 value = tex_scan_integer(1, NULL);
5769 tex_word_define(a, code, value);
5770
5771 } else {
5772 tex_handle_error(
5773 normal_error_type,
5774 "Invalid math class",
5775 "I'm going to ignore these options."
5776 );
5777 }
5778 return;
5779 }
5780 case math_parameter_set_defaults:
5781 tex_set_default_math_codes();
5782 return;
5783 }
5784 {
5785 halfword style = tex_scan_math_style_identifier(0, 1);
5786 halfword indirect = indirect_math_regular;
5787 int freeze = is_frozen(a) && cur_mode == mmode;
5788 if (! freeze && is_inherited(a)) {
5789 tex_aux_skip_optional_equal();
5790
5791 switch (math_parameter_value_type(code)) {
5792 case math_integer_parameter:
5793 switch (cur_cmd) {
5794 case integer_cmd:
5795 value = cur_cs;
5796 indirect = indirect_math_integer;
5797 break;
5798 case register_integer_cmd:
5799 value = cur_chr;
5800 indirect = indirect_math_register_integer;
5801 break;
5802 }
5803 break;
5804 case math_dimension_parameter:
5805 switch (cur_cmd) {
5806 case dimension_cmd:
5807 value = cur_cs;
5808 indirect = indirect_math_dimension;
5809 break;
5810 case register_dimension_cmd:
5811 value = cur_chr;
5812 indirect = indirect_math_register_dimension;
5813 break;
5814 }
5815 break;
5816 case math_muglue_parameter:
5817 switch (cur_cmd) {
5818 case mugluespec_cmd:
5819 value = cur_cs;
5820 indirect = indirect_math_mugluespec;
5821 break;
5822 case register_muglue_cmd:
5823 value = cur_chr;
5824 indirect = indirect_math_register_mugluespec;
5825 break;
5826 case internal_muglue_cmd:
5827 value = cur_chr;
5828 indirect = indirect_math_internal_mugluespec;
5829 break;
5830 case dimension_cmd:
5831 value = cur_cs;
5832 indirect = indirect_math_dimension;
5833 break;
5834 case register_dimension_cmd:
5835 value = cur_chr;
5836 indirect = indirect_math_register_dimension;
5837 break;
5838 case gluespec_cmd:
5839 value = cur_cs;
5840 indirect = indirect_math_gluespec;
5841 break;
5842 case register_glue_cmd:
5843 value = cur_chr;
5844 indirect = indirect_math_register_gluespec;
5845 break;
5846 case internal_glue_cmd:
5847 value = cur_chr;
5848 indirect = indirect_math_internal_gluespec;
5849 break;
5850 }
5851 break;
5852 case math_pair_parameter:
5853 {
5854 halfword left = tex_scan_math_class_number(0);
5855 halfword right = tex_scan_math_class_number(0);
5856 value = (left << 16) + right;
5857 }
5858 break;
5859 }
5860 if (indirect == indirect_math_regular) {
5861 tex_handle_error(
5862 normal_error_type,
5863 "Invalid inherited math parameter type",
5864 "The inheritance type should match the math parameter type"
5865 );
5866 return;
5867 }
5868 } else {
5869 switch (math_parameter_value_type(code)) {
5870 case math_integer_parameter:
5871 value = tex_scan_integer(1, NULL);
5872 break;
5873 case math_dimension_parameter:
5874 value = tex_scan_dimension(0, 0, 0, 1, NULL);
5875 break;
5876 case math_muglue_parameter:
5877 value = tex_scan_glue(muglue_val_level, 1, 0);
5878 break;
5879 case math_style_parameter:
5880 value = tex_scan_integer(1, NULL);
5881 if (value < 0 || value > last_math_style_variant) {
5882
5883 value = math_normal_style_variant;
5884 }
5885 break;
5886 case math_pair_parameter:
5887 {
5888 halfword left = tex_scan_math_class_number(0);
5889 halfword right = tex_scan_math_class_number(0);
5890 value = (left << 16) + right;
5891 }
5892 break;
5893 default:
5894 tex_confusion("math parameter type");
5895 return;
5896 }
5897 }
5898 if (freeze) {
5899 halfword n = tex_new_node(parameter_node, (quarterword) style);
5900 parameter_name(n) = code;
5901 parameter_value(n) = value;
5902 attach_current_attribute_list(n);
5903 tex_tail_append(n);
5904 } else {
5905 switch (style) {
5906 case all_display_styles:
5907 tex_set_display_styles(code, value, global_or_local(a), indirect);
5908 break;
5909 case all_text_styles:
5910 tex_set_text_styles(code, value, global_or_local(a), indirect);
5911 break;
5912 case all_script_styles:
5913 tex_set_script_styles(code, value, global_or_local(a), indirect);
5914 break;
5915 case all_script_script_styles:
5916 tex_set_script_script_styles(code, value, global_or_local(a), indirect);
5917 break;
5918 case all_math_styles:
5919 tex_set_all_styles(code, value, global_or_local(a), indirect);
5920 break;
5921 case all_main_styles:
5922 tex_set_main_styles(code, value, global_or_local(a), indirect);
5923 break;
5924 case all_split_styles:
5925 tex_set_split_styles(code, value, global_or_local(a), indirect);
5926 break;
5927 case all_unsplit_styles:
5928 tex_set_unsplit_styles(code, value, global_or_local(a), indirect);
5929 break;
5930 case all_uncramped_styles:
5931 tex_set_uncramped_styles(code, value, global_or_local(a), indirect);
5932 break;
5933 case all_cramped_styles:
5934 tex_set_cramped_styles(code, value, global_or_local(a), indirect);
5935 break;
5936 default:
5937 tex_def_math_parameter(style, code, value, global_or_local(a), indirect, 0);
5938 break;
5939 }
5940
5941 }
5942 }
5943}
5944
5945
5946
5947static void tex_aux_set_define_family(int a)
5948{
5949 halfword p = cur_chr;
5950 halfword fnt;
5951 halfword fam = tex_scan_math_family_number();
5952 tex_scan_optional_equals();
5953 fnt = tex_scan_font_identifier(NULL);
5954 tex_def_fam_fnt(fam, p, fnt, global_or_local(a));
5955}
5956
5957
5958
5959static void tex_aux_set_internal_integer(int a)
5960{
5961 halfword p = cur_chr;
5962 halfword v = tex_scan_integer(1, NULL);
5963 tex_assign_internal_integer_value(a, p, v);
5964}
5965
5966static void tex_aux_set_register_integer(int a)
5967{
5968 halfword p = cur_chr;
5969 halfword v = tex_scan_integer(1, NULL);
5970 tex_word_define(a, p, v);
5971}
5972
5973static void tex_aux_set_internal_posit(int a)
5974{
5975 halfword p = cur_chr;
5976 scaled v = tex_scan_posit(1);
5977 tex_assign_internal_integer_value(a, p, v);
5978}
5979
5980static void tex_aux_set_register_posit(int a)
5981{
5982 halfword p = cur_chr;
5983 scaled v = tex_scan_posit(1);
5984 tex_word_define(a, p, v);
5985}
5986
5987static void tex_aux_set_internal_attribute(int a)
5988{
5989 halfword p = cur_chr;
5990 halfword v = tex_scan_integer(1, NULL);
5991 if (internal_attribute_number(p) > lmt_node_memory_state.max_used_attribute) {
5992 lmt_node_memory_state.max_used_attribute = internal_attribute_number(p);
5993 }
5994 tex_change_attribute_register(a, p, v);
5995 tex_word_define(a, p, v);
5996}
5997
5998static void tex_aux_set_register_attribute(int a)
5999{
6000 halfword p = cur_chr;
6001 halfword v = tex_scan_integer(1, NULL);
6002 if (register_attribute_number(p) > lmt_node_memory_state.max_used_attribute) {
6003 lmt_node_memory_state.max_used_attribute = register_attribute_number(p);
6004 }
6005 tex_change_attribute_register(a, p, v);
6006 tex_word_define(a, p, v);
6007}
6008
6009static void tex_aux_set_internal_dimension(int a)
6010{
6011 halfword p = cur_chr;
6012 scaled v = tex_scan_dimension(0, 0, 0, 1, NULL);
6013 tex_assign_internal_dimension_value(a, p, v);
6014}
6015
6016static void tex_aux_set_register_dimension(int a)
6017{
6018 halfword p = cur_chr;
6019 scaled v = tex_scan_dimension(0, 0, 0, 1, NULL);
6020 tex_word_define(a, p, v);
6021}
6022
6023static void tex_aux_set_internal_glue(int a)
6024{
6025 halfword p = cur_chr;
6026 halfword v = tex_scan_glue(glue_val_level, 1, 0);
6027
6028 tex_assign_internal_skip_value(a, p, v);
6029}
6030
6031static void tex_aux_set_register_glue(int a)
6032{
6033 halfword p = cur_chr;
6034 halfword v = tex_scan_glue(glue_val_level, 1, 1);
6035 tex_define(a, p, register_glue_reference_cmd, v);
6036}
6037
6038static void tex_aux_set_internal_muglue(int a)
6039{
6040 halfword p = cur_chr;
6041 halfword v = tex_scan_glue(muglue_val_level, 1, 0);
6042 tex_define(a, p, internal_muglue_reference_cmd, v);
6043}
6044
6045static void tex_aux_set_register_muglue(int a)
6046{
6047 halfword p = cur_chr;
6048 halfword v = tex_scan_glue(muglue_val_level, 1, 0);
6049 tex_define(a, p, register_muglue_reference_cmd, v);
6050}
6051
6052
6059
6060static void tex_aux_set_combine_toks(halfword a)
6061{
6062 if (is_global(a)) {
6063 switch (cur_chr) {
6064 case expanded_toks_code: cur_chr = global_expanded_toks_code; break;
6065 case append_toks_code: cur_chr = global_append_toks_code; break;
6066 case append_expanded_toks_code: cur_chr = global_append_expanded_toks_code; break;
6067 case prepend_toks_code: cur_chr = global_prepend_toks_code; break;
6068 case prepend_expanded_toks_code: cur_chr = global_prepend_expanded_toks_code; break;
6069 }
6070 }
6071 tex_run_combine_the_toks();
6072}
6073
6074static int tex_aux_set_some_item(void)
6075{
6076 switch (cur_chr) {
6077 case lastpenalty_code:
6078 lmt_page_builder_state.last_penalty = tex_scan_integer(1, NULL);
6079 return 1;
6080 case lastkern_code:
6081 lmt_page_builder_state.last_kern = tex_scan_integer(1, NULL);
6082 return 1;
6083 case lastskip_code:
6084 lmt_page_builder_state.last_glue = tex_scan_glue(glue_val_level, 1, 0);
6085 return 1;
6086 case lastboundary_code:
6087 lmt_page_builder_state.last_penalty = tex_scan_integer(1, NULL);
6088 return 1;
6089 case last_node_type_code:
6090 lmt_page_builder_state.last_node_type = tex_scan_integer(1, NULL);
6091 return 1;
6092 case last_node_subtype_code:
6093 lmt_page_builder_state.last_node_subtype = tex_scan_integer(1, NULL);
6094 return 1;
6095 case last_left_class_code:
6096 lmt_math_state.last_left = tex_scan_math_class_number(1);
6097 return 1;
6098 case last_right_class_code:
6099 lmt_math_state.last_right = tex_scan_math_class_number(1);
6100 return 1;
6101 case last_atom_class_code:
6102 lmt_math_state.last_atom = tex_scan_math_class_number(1);
6103 return 1;
6104 default:
6105 return 0;
6106 }
6107}
6108
6109static void tex_aux_set_constant_register(halfword cmd, halfword cs, halfword flags)
6110{
6111 halfword v = null;
6112 switch(cmd) {
6113 case integer_cmd:
6114 v = tex_scan_integer(1, NULL);
6115 break;
6116 case dimension_cmd:
6117 v = tex_scan_dimension(0, 0, 0, 1, NULL);
6118 break;
6119 case posit_cmd:
6120 v = tex_scan_posit(1);
6121 break;
6122 case gluespec_cmd:
6123 v = tex_scan_glue(glue_val_level, 1, 1);
6124 break;
6125 case mugluespec_cmd:
6126 v = tex_scan_glue(muglue_val_level, 1, 0);
6127 break;
6128 }
6129 tex_define(flags, cs, (singleword) cmd, v);
6130}
6131
6132static void tex_run_prefixed_command(void)
6133{
6134
6135 int flags = 0;
6136 int force = 0;
6137 halfword lastprefix = -1;
6138 while (cur_cmd == prefix_cmd) {
6139 switch (cur_chr) {
6140 case frozen_code: flags = add_frozen_flag (flags); break;
6141 case tolerant_code: flags = add_tolerant_flag (flags); break;
6142 case protected_code: flags = add_protected_flag (flags); break;
6143 case permanent_code: flags = add_permanent_flag (flags); break;
6144 case immutable_code: flags = add_immutable_flag (flags); break;
6145 case mutable_code: flags = add_mutable_flag (flags); break;
6146 case noaligned_code: flags = add_noaligned_flag (flags); break;
6147 case instance_code: flags = add_instance_flag (flags); break;
6148 case untraced_code: flags = add_untraced_flag (flags); break;
6149 case global_code: flags = add_global_flag (flags); break;
6150 case overloaded_code: flags = add_overloaded_flag (flags); break;
6151 case aliased_code: flags = add_aliased_flag (flags); break;
6152 case immediate_code: flags = add_immediate_flag (flags); break;
6153 case semiprotected_code: flags = add_semiprotected_flag(flags); break;
6154
6155 case always_code: flags = add_aliased_flag (flags); force = 1; break;
6156
6157 case inherited_code: flags = add_inherited_flag (flags); break;
6158 case constant_code: flags = add_constant_flag (flags); break;
6159 case retained_code: flags = add_retained_flag (flags); break;
6160 case constrained_code: flags = add_constrained_flag (flags); break;
6161 default:
6162 goto PICKUP;
6163 }
6164 lastprefix = cur_chr;
6165 PICKUP:
6166
6167 do {
6168 tex_get_x_token();
6169 } while (cur_cmd == spacer_cmd || cur_cmd == relax_cmd);
6170 if (tracing_commands_par > 2) {
6171 tex_show_cmd_chr(cur_cmd, cur_chr);
6172 }
6173 }
6174
6175
6176
6177
6181 if (global_defs_par) {
6182 flags = global_defs_par > 0 ? add_global_flag(flags) : remove_global_flag(flags);
6183 }
6184
6188 switch (cur_cmd) {
6189 case set_font_cmd:
6190 tex_aux_set_font(flags);
6191 break;
6192 case def_cmd:
6193 tex_aux_set_def(flags, force);
6194 break;
6195 case let_cmd:
6196 tex_aux_set_let(flags, force);
6197 break;
6198 case shorthand_def_cmd:
6199 tex_aux_set_shorthand_def(flags, force);
6200 break;
6201 case association_cmd:
6202 tex_aux_set_association(flags, force);
6203 break;
6204 case internal_toks_cmd:
6205 case register_toks_cmd:
6206 tex_aux_set_assign_toks(flags);
6207 break;
6208 case internal_integer_cmd:
6209 tex_aux_set_internal_integer(flags);
6210 break;
6211 case register_integer_cmd:
6212 tex_aux_set_register_integer(flags);
6213 break;
6214 case internal_attribute_cmd:
6215 tex_aux_set_internal_attribute(flags);
6216 break;
6217 case register_attribute_cmd:
6218 tex_aux_set_register_attribute(flags);
6219 break;
6220 case internal_posit_cmd:
6221 tex_aux_set_internal_posit(flags);
6222 break;
6223 case register_posit_cmd:
6224 tex_aux_set_register_posit(flags);
6225 break;
6226 case internal_dimension_cmd:
6227 tex_aux_set_internal_dimension(flags);
6228 break;
6229 case register_dimension_cmd:
6230 tex_aux_set_register_dimension(flags);
6231 break;
6232 case internal_glue_cmd:
6233 tex_aux_set_internal_glue(flags);
6234 break;
6235 case register_glue_cmd:
6236 tex_aux_set_register_glue(flags);
6237 break;
6238 case internal_muglue_cmd:
6239 tex_aux_set_internal_muglue(flags);
6240 break;
6241 case register_muglue_cmd:
6242 tex_aux_set_register_muglue(flags);
6243 break;
6244 case lua_value_cmd:
6245 tex_aux_set_lua_value(flags);
6246 break;
6247 case define_char_code_cmd:
6248 tex_aux_set_define_char_code(flags);
6249 break;
6250 case define_family_cmd:
6251 tex_aux_set_define_family(flags);
6252 break;
6253 case math_parameter_cmd:
6254 tex_aux_set_math_parameter(flags);
6255 break;
6256 case register_cmd:
6257 if (cur_chr == token_val_level) {
6258 tex_aux_set_assign_toks(flags);
6259 } else {
6260 tex_aux_set_register(flags);
6261 }
6262 break;
6263 case arithmic_cmd:
6264 tex_aux_arithmic_register(flags, cur_chr);
6265 break;
6266 case set_box_cmd:
6267 tex_aux_set_box(flags);
6268 break;
6269 case auxiliary_cmd:
6270 tex_aux_set_auxiliary(flags);
6271 break;
6272 case page_property_cmd:
6273 tex_aux_set_page_property();
6274 break;
6275 case box_property_cmd:
6276 tex_aux_set_box_property();
6277 break;
6278 case specification_cmd:
6279 tex_aux_set_specification(flags);
6280 break;
6281 case hyphenation_cmd:
6282 tex_aux_set_hyph_data();
6283 break;
6284 case font_property_cmd:
6285 tex_aux_set_font_property();
6286 break;
6287 case define_font_cmd:
6288 tex_aux_set_define_font(flags);
6289 break;
6290 case interaction_cmd:
6291 tex_aux_set_interaction(cur_chr);
6292 break;
6293 case combine_toks_cmd:
6294 tex_aux_set_combine_toks(flags);
6295 break;
6296 case some_item_cmd:
6297 if (! tex_aux_set_some_item()) {
6298 tex_aux_run_illegal_case();
6299 }
6300 break;
6301 case integer_cmd:
6302 case dimension_cmd:
6303 case posit_cmd:
6304 case gluespec_cmd:
6305 case mugluespec_cmd:
6306 tex_aux_set_constant_register(cur_cmd, cur_cs, flags);
6307 break;
6308
6311 case index_cmd:
6312 tex_inject_parameter(cur_chr);
6313 break;
6314 default:
6315 if (lastprefix < 0) {
6316 tex_confusion("prefixed command");
6317 } else {
6318 tex_handle_error(
6319 normal_error_type,
6320 "You can't use a prefix %C with %C",
6321 prefix_cmd, lastprefix, cur_cmd, cur_chr,
6322 "A prefix should be followed by a quantity that can be assigned to. Intermediate\n"
6323 "spaces and \\relax tokens are gobbled in the process.\n"
6324 );
6325 break;
6326 }
6327 }
6328
6331 tex_aux_finish_after_assignment();
6332}
6333
6334
6341
6342void tex_get_r_token(void)
6343{
6344 RESTART:
6345 do {
6346 tex_get_token();
6347 } while (cur_tok == space_token);
6348 if (eqtb_invalid_cs(cur_cs)) {
6349 if (cur_cmd == active_char_cmd) {
6350 cur_cs = tex_active_to_cs(cur_chr, 1);
6351 cur_cmd = eq_type(cur_cs);
6352 cur_chr = eq_value(cur_cs);
6353
6354
6355 return;
6356
6357 }
6358 if (cur_cs == 0) {
6359 tex_back_input(cur_tok);
6360 }
6361 cur_tok = deep_frozen_protection_token;
6362
6366 tex_handle_error(
6367 insert_error_type,
6368 "Missing control sequence inserted",
6369 "Please don't say '\\def cs{...}', say '\\def\\cs{...}'. I've inserted an\n"
6370 "inaccessible control sequence so that your definition will be completed without\n"
6371 "mixing me up too badly.\n"
6372 );
6373 goto RESTART;
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388 }
6389}
6390
6391
6400
6401void tex_assign_internal_integer_value(int a, halfword p, int val)
6402{
6403 switch (internal_integer_number(p)) {
6404 case par_direction_code:
6405 case math_direction_code:
6406 {
6407 check_direction_value(val);
6408 tex_word_define(a, p, val);
6409 }
6410 break;
6411 case text_direction_code:
6412 {
6413 check_direction_value(val);
6414 tex_inject_text_or_line_dir(val, 0);
6415 tex_word_define(a, p, val);
6416
6417 update_tex_internal_dir_state(internal_dir_state_par + 1);
6418 }
6419 break;
6420 case line_direction_code:
6421 {
6422 check_direction_value(val);
6423 tex_inject_text_or_line_dir(val, 1);
6424 p = internal_integer_location(text_direction_code);
6425 tex_word_define(a, p, val);
6426
6427 update_tex_internal_dir_state(internal_dir_state_par + 1);
6428 }
6429 break;
6430 case cat_code_table_code:
6431 if (tex_valid_catcode_table(val)) {
6432 if (val != cat_code_table_par) {
6433 tex_word_define(a, p, val);
6434 }
6435 } else {
6436 tex_handle_error(
6437 normal_error_type,
6438 "Invalid \\catcode table",
6439 "You can only switch to a \\catcode table that is initialized using\n"
6440 "\\savecatcodetable or \\initcatcodetable, or to table 0"
6441 );
6442 }
6443 break;
6444 case glyph_scale_code:
6445 case glyph_x_scale_code:
6446 case glyph_y_scale_code:
6447
6448 if (val) {
6449 tex_word_define(a, p, val);
6450 } else {
6451
6452 }
6453 break;
6454
6455
6456
6457
6458 case glyph_text_scale_code:
6459 case glyph_script_scale_code:
6460 case glyph_scriptscript_scale_code:
6461
6462 if (val < min_math_style_scale || val > max_math_style_scale) {
6463 tex_handle_error(
6464 normal_error_type,
6465 "Invalid \\glyph..scale",
6466 "The value for \\glyph..scale has to be between " LMT_TOSTRING(min_math_style_scale) " and " LMT_TOSTRING(max_math_style_scale) " where\n"
6467 "a value of zero forces font percentage scaling to be used."
6468 );
6469 val = max_limited_scale;
6470 }
6471 tex_word_define(a, p, val);
6472 break;
6473 case math_begin_class_code:
6474 case math_end_class_code:
6475 case math_left_class_code:
6476 case math_right_class_code:
6477 if (! valid_math_class_code(val)) {
6478 val = unset_noad_class;
6479 }
6480 tex_word_define(a, p, val);
6481 break;
6482 case output_box_code:
6483 if (val < 0 || val > max_box_index) {
6484 tex_handle_error(
6485 normal_error_type,
6486 "Invalid \\outputbox",
6487 "The value for \\outputbox has to be between 0 and " LMT_TOSTRING(max_box_index) "."
6488 );
6489 } else {
6490 tex_word_define(a, p, val);
6491 }
6492 break;
6493 case new_line_char_code:
6494 if (val > max_newline_character) {
6495 tex_handle_error(
6496 normal_error_type,
6497 "Invalid \\newlinechar",
6498 "The value for \\newlinechar has to be no higher than " LMT_TOSTRING(max_newline_character) ".\n"
6499 "Your invalid assignment will be ignored."
6500 );
6501 }
6502 else {
6503 tex_word_define(a, p, val);
6504 }
6505 break;
6506 case end_line_char_code:
6507 if (val > max_endline_character) {
6508 tex_handle_error(
6509 normal_error_type,
6510 "Invalid \\endlinechar",
6511 "The value for \\endlinechar has to be no higher than " LMT_TOSTRING(max_endline_character) "."
6512 );
6513 }
6514 else {
6515 tex_word_define(a, p, val);
6516 }
6517 break;
6518 case language_code:
6519
6520 if (val < 0) {
6521 val = 0;
6522 }
6523 if (tex_is_valid_language(val)) {
6524 update_tex_language(a, val);
6525 }
6526 else {
6527 tex_handle_error(
6528 normal_error_type,
6529 "Invalid \\language",
6530 "The value for \\language has to be defined and in the range 0 .. " LMT_TOSTRING(max_n_of_languages) "."
6531 );
6532 }
6533 break;
6534 case font_code:
6535 if (val < 0) {
6536 val = 0;
6537 }
6538 if (tex_is_valid_font(val)) {
6539 tex_set_cur_font(a, val);
6540 }
6541 else {
6542 tex_handle_error(
6543 normal_error_type,
6544 "Invalid \\fontid",
6545 "The value for \\fontid has to be defined and in the range 0 .. " LMT_TOSTRING(max_n_of_fonts) "."
6546 );
6547 }
6548 break;
6549 case hyphenation_mode_code:
6550 if (val < 0) {
6551 val = 0;
6552 }
6553
6554 tex_word_define(a, p, val);
6555 break;
6556 case uc_hyph_code:
6557
6558 tex_word_define(a, p, val);
6559
6560 val = val ? set_hyphenation_mode(hyphenation_mode_par, uppercase_hyphenation_mode) : unset_hyphenation_mode(hyphenation_mode_par, uppercase_hyphenation_mode);
6561 tex_word_define(a, internal_integer_location(hyphenation_mode_code), val);
6562 break;
6563 case local_interline_penalty_code:
6564 case local_broken_penalty_code:
6565 case local_tolerance_code:
6566 case local_pre_tolerance_code:
6567
6573 if (cur_mode == hmode) {
6574 tex_word_define(a, p, val);
6575 tex_tail_append(tex_new_par_node(parameter_par_subtype));
6576 update_tex_internal_par_state(internal_par_state_par + 1);
6577 } else {
6578
6579 }
6580 break;
6581 case adjust_spacing_code:
6582 if (val < adjust_spacing_off) {
6583 val = adjust_spacing_off;
6584 }
6585 else if (val > adjust_spacing_font) {
6586 val = adjust_spacing_font;
6587 }
6588 goto DEFINE;
6589 case protrude_chars_code:
6590 if (val < protrude_chars_off) {
6591 val = protrude_chars_off;
6592 }
6593 else if (val > protrude_chars_advanced) {
6594 val = protrude_chars_advanced;
6595 }
6596 goto DEFINE;
6597 case glyph_options_code:
6598 val &= glyph_option_valid;
6599 tex_word_define(a, p, val);
6600 break;
6601 case discretionary_options_code:
6602 val &= disc_option_valid;
6603 tex_word_define(a, p, val);
6604 break;
6605 case overload_mode_code:
6606
6607 tex_word_define(a, p, val);
6608
6609 break;
6610
6611 case post_binary_penalty_code:
6612 tex_word_define(a, internal_integer_location(first_math_post_penalty_code + binary_noad_subtype), val);
6613 tex_word_define(a, internal_integer_location(first_math_display_post_penalty_code + binary_noad_subtype), val);
6614 break;
6615 case post_relation_penalty_code:
6616 tex_word_define(a, internal_integer_location(first_math_post_penalty_code + relation_noad_subtype), val);
6617 tex_word_define(a, internal_integer_location(first_math_display_post_penalty_code + relation_noad_subtype), val);
6618 break;
6619 case pre_binary_penalty_code:
6620 tex_word_define(a, internal_integer_location(first_math_pre_penalty_code + binary_noad_subtype), val);
6621 tex_word_define(a, internal_integer_location(first_math_display_pre_penalty_code + binary_noad_subtype), val);
6622 break;
6623 case pre_relation_penalty_code:
6624 tex_word_define(a, internal_integer_location(first_math_pre_penalty_code + relation_noad_subtype), val);
6625 tex_word_define(a, internal_integer_location(first_math_display_pre_penalty_code + relation_noad_subtype), val);
6626 break;
6627
6636 case eu_factor_code:
6637 if (val < eu_min_factor) {
6638 val = eu_min_factor;
6639 } else if (val > eu_max_factor) {
6640 val = eu_max_factor;
6641 }
6642 tex_word_define(a, p, val);
6643 break;
6644 default:
6645 DEFINE:
6646 tex_word_define(a, p, val);
6647 if (is_frozen(a) && cur_mode == hmode) {
6648 tex_update_par_par(internal_integer_cmd, internal_integer_number(p));
6649 }
6650 }
6651}
6652
6653void tex_assign_internal_attribute_value(int a, halfword p, int val)
6654{
6655 if (register_attribute_number(p) > lmt_node_memory_state.max_used_attribute) {
6656 lmt_node_memory_state.max_used_attribute = register_attribute_number(p);
6657 }
6658 tex_change_attribute_register(a, p, val);
6659 tex_word_define(a, p, val);
6660}
6661
6662void tex_assign_internal_posit_value(int a, halfword p, int val)
6663{
6664 tex_word_define(a, p, val);
6665
6666
6667
6668}
6669
6670void tex_assign_internal_dimension_value(int a, halfword p, int val)
6671{
6672 tex_word_define(a, p, val);
6673 if (is_frozen(a) && cur_mode == hmode) {
6674 tex_update_par_par(internal_dimension_cmd, internal_dimension_number(p));
6675 }
6676}
6677
6678void tex_assign_internal_skip_value(int a, halfword p, int val)
6679{
6680 switch (internal_glue_number(p)) {
6681 case additional_page_skip_code:
6682 tex_define(a & global_flag_bit, p, internal_glue_reference_cmd, val);
6683 if (cur_mode == vmode) {
6684 tex_additional_page_skip();
6685 }
6686 break;
6687 default:
6688 tex_define(a, p, internal_glue_reference_cmd, val);
6689 break;
6690 }
6691 if (is_frozen(a) && cur_mode == hmode) {
6692 tex_update_par_par(internal_glue_cmd, internal_glue_number(p));
6693 }
6694}
6695
6696
6703
6704void tex_handle_assignments(void)
6705{
6706 while (1) {
6707 do {
6708 tex_get_x_token();
6709 } while (cur_cmd == spacer_cmd || cur_cmd == relax_cmd);
6710 if (cur_cmd <= max_non_prefixed_cmd) {
6711 return;
6712 } else {
6713 lmt_error_state.set_box_allowed = 0;
6714 tex_run_prefixed_command();
6715 lmt_error_state.set_box_allowed = 1;
6716 }
6717 }
6718}
6719
6720
6721
6722static strnumber tex_aux_scan_string(void)
6723{
6724 int saved_selector = lmt_print_state.selector;
6725 halfword result = tex_scan_toks_expand(0, NULL, 0, 0);
6726
6727 lmt_print_state.selector = new_string_selector_code;
6728 tex_token_show(result);
6729 tex_flush_token_list(result);
6730 lmt_print_state.selector = saved_selector;
6731 return tex_make_string();
6732}
6733
6734static void tex_aux_run_message(void)
6735{
6736 switch (cur_chr) {
6737 case message_code:
6738 {
6739
6740 strnumber s = tex_aux_scan_string();
6741 if ((lmt_print_state.terminal_offset > 0) || (lmt_print_state.logfile_offset > 0)) {
6742 tex_print_char(' ');
6743 }
6744 tex_print_tex_str(s);
6745 tex_terminal_update();
6746 tex_flush_str(s);
6747 break;
6748 }
6749 case error_message_code:
6750 {
6751
6757 strnumber s = tex_aux_scan_string();
6758 if (error_help_par) {
6759 strnumber helpinfo = tex_tokens_to_string(error_help_par);
6760 const char *h = tex_to_cstring(helpinfo);
6761 tex_handle_error(
6762 normal_error_type,
6763 "%T",
6764 s,
6765 h
6766 );
6767 tex_flush_str(helpinfo);
6768 } else if (lmt_error_state.long_help_seen) {
6769 tex_handle_error(
6770 normal_error_type,
6771 "%T",
6772 s,
6773 "(That was another \\errmessage.)"
6774 );
6775 } else {
6776 if (lmt_error_state.interaction < error_stop_mode) {
6777 lmt_error_state.long_help_seen = 1;
6778 }
6779 tex_handle_error(
6780 normal_error_type,
6781 "%T",
6782 s,
6783 "This error message was generated by an \\errmessage command, so I can't give any\n"
6784 "explicit help. Pretend that you're Hercule Poirot: Examine all clues, and deduce\n"
6785 "the truth by order and method."
6786 );
6787 }
6788 tex_flush_str(s);
6789 break;
6790 }
6791 }
6792}
6793
6794
6804
6805static void tex_aux_run_case_shift(void)
6806{
6807 tex_run_case_shift(cur_chr);
6808}
6809
6810
6816
6817static void tex_aux_run_show_whatever(void)
6818{
6819 int justshow = 1;
6820 switch (cur_chr) {
6821 case show_code:
6822
6823 {
6824 tex_get_token();
6825 tex_print_nlp();
6826 tex_print_str("> ");
6827 if (cur_cs != 0) {
6828 tex_print_cs(cur_cs);
6829 tex_print_char('=');
6830 }
6831 tex_print_meaning(meaning_full_code);
6832 goto COMMON_ENDING;
6833 }
6834 case show_box_code:
6835
6836 {
6837 int nolevels = 0;
6838 int diagnose = 0;
6839 int content = 0;
6840 int online = 0;
6841 int max = 0;
6842 while (1) {
6843 switch (tex_scan_character("ocdnaOCDNA", 0, 1, 0)) {
6844 case 'a': case 'A':
6845 if (tex_scan_mandate_keyword("all", 1)) {
6846 max = 1;
6847 }
6848 break;
6849 case 'c': case 'C':
6850 if (tex_scan_mandate_keyword("content", 1)) {
6851 content = 1;
6852 }
6853 break;
6854 case 'd': case 'D':
6855 if (tex_scan_mandate_keyword("diagnose", 1)) {
6856 diagnose = 1;
6857 }
6858 break;
6859 case 'n': case 'N':
6860 if (tex_scan_mandate_keyword("nolevels", 1)) {
6861 nolevels = 1;
6862 }
6863 break;
6864 case 'o': case 'O':
6865 if (tex_scan_mandate_keyword("online", 1)) {
6866 online = 1;
6867 }
6868 break;
6869 default:
6870 goto DONE;
6871 }
6872 }
6873 DONE:
6874
6875 {
6876 halfword n = tex_scan_box_register_number();
6877 halfword r = box_register(n);
6878 halfword l = tracing_levels_par;
6879 halfword o = tracing_online_par;
6880 halfword d = show_box_depth_par;
6881 halfword b = show_box_breadth_par;
6882 if (nolevels) {
6883 tracing_levels_par = 0;
6884 }
6885 if (online) {
6886 tracing_online_par = 2;
6887 }
6888 if (max) {
6889 show_box_depth_par = max_integer;
6890 show_box_breadth_par = max_integer;
6891 }
6892 if (diagnose) {
6893 tex_begin_diagnostic();
6894 }
6895 if (! content) {
6896 tex_print_format("> \\box%i=",n);
6897 }
6898 if (r) {
6899 tex_show_box(r);
6900 } else {
6901 tex_print_str("void");
6902 }
6903 if (diagnose) {
6904 tex_end_diagnostic();
6905 }
6906 tracing_levels_par = l;
6907 tracing_online_par = o;
6908 show_box_depth_par = d;
6909 show_box_breadth_par = b;
6910 }
6911 break;
6912 }
6913 case show_the_code:
6914 {
6915 halfword head = tex_the_value_toks(the_code, NULL, 0);
6916 tex_print_nlp();
6917 tex_print_str("> ");
6918 tex_show_token_list(head, 0, 0);
6919 tex_flush_token_list(head);
6920 goto COMMON_ENDING;
6921 }
6922 case show_lists_code:
6923 {
6924 tex_begin_diagnostic();
6925 tex_show_activities();
6926 tex_end_diagnostic();
6927 break;
6928 }
6929 case show_groups_code:
6930 {
6931 tex_begin_diagnostic();
6932 tex_show_save_groups();
6933 tex_end_diagnostic();
6934 break;
6935 }
6936 case show_stack_code:
6937 {
6938 tex_begin_diagnostic();
6939 tex_show_save_stack();
6940 tex_end_diagnostic();
6941 break;
6942 }
6943 case show_tokens_code:
6944 {
6945 halfword head = tex_the_detokenized_toks(NULL, 0, 0);
6946 tex_print_nlp();
6947 tex_print_str("> ");
6948 tex_show_token_list(head, 0, 0);
6949 tex_flush_token_list(head);
6950 goto COMMON_ENDING;
6951 }
6952 case show_ifs_code:
6953 {
6954
6955 tex_begin_diagnostic();
6956
6957 tex_show_ifs();
6958
6959 tex_end_diagnostic();
6960
6961 break;
6962 }
6963 default:
6964
6965 break;
6966 }
6967 if (justshow) {
6968 return;
6969 } else {
6970
6971 }
6972
6973 tex_handle_error_message_only("OK");
6974 if (lmt_print_state.selector == terminal_and_logfile_selector_code && tracing_online_par <= 0) {
6975 lmt_print_state.selector = terminal_selector_code;
6976 tex_print_str(" (see the transcript file)");
6977 lmt_print_state.selector = terminal_and_logfile_selector_code;
6978 }
6979 COMMON_ENDING:
6980 if (justshow) {
6981 return;
6982 } else if (lmt_error_state.interaction < error_stop_mode) {
6983 tex_handle_error(
6984 normal_error_type,
6985 NULL,
6986 NULL
6987 );
6988 --lmt_error_state.error_count;
6989
6990 } else {
6991 tex_handle_error(
6992 normal_error_type,
6993 NULL,
6994 "This isn't an error message; I'm just \\showing something.\n"
6995 );
6996 }
6997}
6998
6999
7000
7001static inline halfword tex_aux_expand_escaped(halfword tok, halfword *tail)
7002{
7003 halfword value = tex_get_available_token(tok);
7004 if (tail) {
7005 *tail = value;
7006 }
7007 return value;
7008}
7009
7010
7011
7012halfword tex_expand_parameter(halfword tok, halfword *tail)
7013{
7014 halfword value = 0;
7015 switch (tok) {
7016
7017 case I_token_l: case I_token_o: value = lmt_main_control_state.loop_iterator; break;
7018 case P_token_l: case P_token_o: value = tex_previous_loop_iterator_delta(1); break;
7019 case G_token_l: case G_token_o: value = tex_previous_loop_iterator_delta(2); break;
7020
7021 case H_token_l: case H_token_o: return tex_aux_expand_escaped(hash_token_o, tail);
7022 case L_token_l: case L_token_o: return tex_aux_expand_escaped(newline_token_o, tail);
7023
7024 case Q_token_l: case Q_token_o: return tex_aux_expand_escaped(double_quote_token_o, tail);
7025 case R_token_l: case R_token_o: return tex_aux_expand_escaped(return_token_o, tail);
7026 case S_token_l: case S_token_o: return tex_aux_expand_escaped(space_token_o, tail);
7027 case T_token_l: case T_token_o: return tex_aux_expand_escaped(tab_token_o, tail);
7028 case X_token_l: case X_token_o: return tex_aux_expand_escaped(backslash_token_o, tail);
7029
7030
7031 default: return null;
7032 }
7033
7034 {
7035 int saved_selector = lmt_print_state.selector;
7036 lmt_print_state.selector = new_string_selector_code;
7037 tex_print_int(value);
7038 lmt_print_state.selector = saved_selector;
7039 return tex_cur_str_toks(tail);
7040 }
7041}
7042
7043halfword tex_expand_iterator(halfword tok)
7044{
7045 switch (tok) {
7046 case I_token_l: case I_token_o: return lmt_main_control_state.loop_iterator;
7047 case P_token_l: case P_token_o: return tex_previous_loop_iterator_delta(1);
7048 case G_token_l: case G_token_o: return tex_previous_loop_iterator_delta(2);
7049 default: return 0;
7050 }
7051}
7052static void tex_aux_run_parameter(void)
7053{
7054 tex_get_token();
7055 {
7056 int okay = tex_expand_parameter(cur_tok, NULL);
7057 if (okay) {
7058 tex_begin_inserted_list(okay);
7059 } else {
7060 tex_back_input(cur_tok);
7061 tex_aux_run_illegal_case();
7062 }
7063 }
7064}
7065
7066
7082
7083inline static void tex_aux_big_switch(int mode, int cmd)
7084{
7085
7086 switch (cmd) {
7087
7088 case arithmic_cmd:
7089 case internal_integer_cmd:
7090 case register_integer_cmd:
7091 case internal_attribute_cmd:
7092 case register_attribute_cmd:
7093 case internal_posit_cmd:
7094 case register_posit_cmd:
7095 case internal_dimension_cmd:
7096 case register_dimension_cmd:
7097 case font_property_cmd :
7098 case internal_glue_cmd:
7099 case register_glue_cmd:
7100 case internal_muglue_cmd:
7101 case register_muglue_cmd:
7102 case internal_toks_cmd:
7103 case register_toks_cmd:
7104 case define_char_code_cmd:
7105 case def_cmd:
7106 case define_family_cmd:
7107 case define_font_cmd:
7108 case hyphenation_cmd:
7109 case let_cmd:
7110 case prefix_cmd:
7111 case register_cmd:
7112 case auxiliary_cmd:
7113 case set_box_cmd:
7114 case box_property_cmd:
7115 case set_font_cmd:
7116 case interaction_cmd:
7117 case math_parameter_cmd:
7118 case page_property_cmd:
7119 case specification_cmd:
7120 case shorthand_def_cmd:
7121 case association_cmd:
7122 case lua_value_cmd:
7123 case integer_cmd:
7124 case index_cmd:
7125 case dimension_cmd:
7126 case posit_cmd:
7127 case gluespec_cmd:
7128 case mugluespec_cmd:
7129 case combine_toks_cmd:
7130 case some_item_cmd: tex_run_prefixed_command(); break;
7131 case fontspec_cmd: tex_run_font_spec(); break;
7132 case parameter_cmd: tex_aux_run_parameter(); break;
7133 case iterator_value_cmd: tex_aux_run_illegal_case(); break;
7134 case after_something_cmd: tex_aux_run_after_something(); break;
7135 case begin_group_cmd: tex_aux_run_begin_group(); break;
7136 case penalty_cmd: tex_aux_run_penalty(); break;
7137 case case_shift_cmd: tex_aux_run_case_shift(); break;
7138 case catcode_table_cmd: tex_aux_run_catcode_table(); break;
7139 case end_cs_name_cmd: tex_aux_run_cs_error(); break;
7140 case end_group_cmd: tex_aux_run_end_group(); break;
7141 case end_local_cmd: tex_aux_run_end_local(); break;
7142 case ignore_something_cmd: tex_aux_run_ignore_something(); break;
7143 case insert_cmd: tex_run_insert(); break;
7144 case kern_cmd: tex_aux_run_kern(); break;
7145 case leader_cmd: tex_aux_run_leader(); break;
7146 case legacy_cmd: tex_aux_run_legacy(); break;
7147 case local_box_cmd: tex_aux_run_local_box(); break;
7148 case lua_protected_call_cmd:
7149 case lua_semi_protected_call_cmd: tex_aux_run_lua_protected_call(); break;
7150 case lua_function_call_cmd: tex_aux_run_lua_function_call(); break;
7151 case make_box_cmd: tex_aux_run_make_box(); break;
7152 case mark_cmd: tex_run_mark(); break;
7153 case message_cmd: tex_aux_run_message(); break;
7154 case node_cmd: tex_aux_run_node(); break;
7155 case relax_cmd:
7156 case ignore_cmd: tex_aux_run_relax(); break;
7157 case active_char_cmd: tex_aux_run_active(); break;
7158 case remove_item_cmd: tex_aux_run_remove_item(); break;
7159 case right_brace_cmd: tex_aux_run_right_brace(); break;
7160 case vcenter_cmd: tex_run_vcenter(); break;
7161 case xray_cmd: tex_aux_run_show_whatever(); break;
7162 case alignment_cmd:
7163 case alignment_tab_cmd: tex_run_alignment_error(); break;
7164 case end_template_cmd: tex_run_alignment_end_template(); break;
7165
7166
7167
7168 case math_fraction_cmd: mode == mmode ? tex_run_math_fraction() : tex_aux_run_insert_dollar_sign(); break;
7169 case delimiter_number_cmd: mode == mmode ? tex_run_math_delimiter_number() : tex_aux_run_insert_dollar_sign(); break;
7170 case math_fence_cmd: mode == mmode ? tex_run_math_fence() : tex_aux_run_insert_dollar_sign(); break;
7171 case math_modifier_cmd: mode == mmode ? tex_run_math_modifier() : tex_aux_run_insert_dollar_sign(); break;
7172 case math_accent_cmd: mode == mmode ? tex_run_math_accent() : tex_aux_run_insert_dollar_sign(); break;
7173 case math_choice_cmd: mode == mmode ? tex_run_math_choice() : tex_aux_run_insert_dollar_sign(); break;
7174 case math_component_cmd: mode == mmode ? tex_run_math_math_component() : tex_aux_run_insert_dollar_sign(); break;
7175 case math_style_cmd: mode == mmode ? tex_run_math_style() : tex_aux_run_insert_dollar_sign(); break;
7176 case mkern_cmd: mode == mmode ? tex_aux_run_mkern() : tex_aux_run_insert_dollar_sign(); break;
7177 case mskip_cmd: mode == mmode ? tex_aux_run_mglue() : tex_aux_run_insert_dollar_sign(); break;
7178 case math_radical_cmd: mode == mmode ? tex_run_math_radical() : tex_aux_run_insert_dollar_sign(); break;
7179 case subscript_cmd:
7180 case superscript_cmd:
7181 case math_script_cmd: mode == mmode ? tex_run_math_script() : tex_aux_run_insert_dollar_sign(); break;
7182 case equation_number_cmd: mode == mmode ? tex_run_math_equation_number() : tex_aux_run_illegal_case(); break;
7183 case left_brace_cmd: mode == mmode ? tex_run_math_left_brace() : tex_aux_run_left_brace(); break;
7184
7185
7186
7187 case vadjust_cmd: mode == vmode ? tex_aux_run_illegal_case() : tex_run_vadjust(); break;
7188 case discretionary_cmd: mode == vmode ? tex_aux_run_new_paragraph() : tex_aux_run_discretionary(); break;
7189 case explicit_space_cmd: mode == vmode ? tex_aux_run_new_paragraph() : tex_aux_run_space(); break;
7190 case hmove_cmd: mode == vmode ? tex_aux_run_move() : tex_aux_run_illegal_case(); break;
7191 case vmove_cmd: mode == vmode ? tex_aux_run_illegal_case() : tex_aux_run_move(); break;
7192 case hskip_cmd: mode == vmode ? tex_aux_run_new_paragraph() : tex_aux_run_glue(); break;
7193 case un_hbox_cmd: mode == vmode ? tex_aux_run_new_paragraph() : tex_run_unpackage(); break;
7194
7195
7196
7197 case math_char_number_cmd:
7198 switch (mode) {
7199 case vmode: tex_aux_run_math_non_math(); break;
7200 case hmode: tex_run_text_math_char_number(); break;
7201 case mmode: tex_run_math_math_char_number(); break;
7202 }
7203 break;
7204 case italic_correction_cmd:
7205 switch (mode) {
7206 case vmode: tex_aux_run_illegal_case(); break;
7207 case hmode: tex_aux_run_text_italic_correction(); break;
7208 case mmode: tex_run_math_italic_correction(); break;
7209 }
7210 break;
7211 case mathspec_cmd:
7212 switch (mode) {
7213 case vmode: tex_aux_run_math_non_math(); break;
7214 case hmode: tex_run_text_math_spec(); break;
7215 case mmode: tex_run_math_math_spec(); break;
7216 }
7217 break;
7218 case char_given_cmd:
7219 case letter_cmd:
7220 case other_char_cmd:
7221 switch (mode) {
7222 case vmode: tex_aux_run_new_paragraph(); break;
7223 case hmode: tex_aux_run_text_letter(); break;
7224 case mmode: tex_run_math_letter(); break;
7225 }
7226 break;
7227
7228 case accent_cmd:
7229 switch (mode) {
7230 case vmode: tex_aux_run_new_paragraph(); break;
7231 case hmode: tex_aux_run_text_accent(); break;
7232 case mmode: tex_run_math_accent(); break;
7233 }
7234 break;
7235 case boundary_cmd:
7236 switch (mode) {
7237 case vmode: tex_aux_run_par_boundary(); break;
7238 case hmode: tex_aux_run_text_boundary(); break;
7239 case mmode: tex_aux_run_math_boundary(); break;
7240 }
7241 break;
7242 case char_number_cmd:
7243 switch (mode) {
7244 case vmode: tex_aux_run_new_paragraph(); break;
7245 case hmode: tex_aux_run_text_char_number(); break;
7246 case mmode: tex_run_math_char_number(); break;
7247 }
7248 break;
7249 case math_shift_cmd:
7250 case math_shift_cs_cmd:
7251 switch (mode) {
7252 case vmode: tex_aux_run_new_paragraph(); break;
7253 case hmode: tex_run_math_initialize(); break;
7254 case mmode: tex_run_math_shift(); break;
7255 }
7256 break;
7257 case end_paragraph_cmd:
7258 switch (mode) {
7259 case vmode: tex_aux_run_paragraph_end_vmode(); break;
7260 case hmode: tex_aux_run_paragraph_end_hmode(); break;
7261 case mmode: tex_aux_run_relax(); break;
7262 }
7263 break;
7264 case spacer_cmd:
7265 switch (mode) {
7266 case vmode: tex_aux_run_relax(); break;
7267 case hmode: tex_aux_run_space(); break;
7268 case mmode: tex_aux_run_math_space(); break;
7269 }
7270 break;
7271 case begin_paragraph_cmd:
7272 switch (mode) {
7273 case vmode: tex_aux_run_begin_paragraph_vmode(); break;
7274 case hmode: tex_aux_run_begin_paragraph_hmode(); break;
7275 case mmode: tex_aux_run_begin_paragraph_mmode(); break;
7276 }
7277 break;
7278 case end_job_cmd:
7279 switch (mode) {
7280 case vmode: tex_aux_run_end_job(); break;
7281 case hmode: tex_aux_run_head_for_vmode(); break;
7282 case mmode: tex_aux_run_insert_dollar_sign(); break;
7283 }
7284 break;
7285
7286 case vskip_cmd:
7287 switch (mode) {
7288 case vmode: tex_aux_run_glue(); break;
7289 case hmode: tex_aux_run_head_for_vmode(); break;
7290 case mmode: tex_aux_run_insert_dollar_sign(); break;
7291 }
7292 break;
7293 case un_vbox_cmd:
7294 switch (mode) {
7295 case vmode: tex_run_unpackage(); break;
7296 case hmode: tex_aux_run_head_for_vmode(); break;
7297 case mmode: tex_aux_run_insert_dollar_sign(); break;
7298 }
7299 break;
7300
7301 case halign_cmd:
7302 switch (mode) {
7303 case vmode: tex_run_alignment_initialize(); break;
7304 case hmode: tex_aux_run_head_for_vmode(); break;
7305 case mmode: tex_aux_run_halign_mmode(); break;
7306 }
7307 break;
7308 case valign_cmd:
7309 switch (mode) {
7310 case vmode: tex_aux_run_new_paragraph(); break;
7311 case hmode: tex_run_alignment_initialize(); break;
7312 case mmode: tex_aux_run_insert_dollar_sign(); break;
7313 }
7314 break;
7315
7316 case hrule_cmd:
7317 switch (mode) {
7318 case vmode: tex_aux_run_hrule(); break;
7319 case hmode: tex_aux_run_head_for_vmode(); break;
7320 case mmode: tex_aux_run_insert_dollar_sign(); break;
7321 }
7322 break;
7323 case vrule_cmd:
7324 switch (mode) {
7325 case vmode: tex_aux_run_new_paragraph(); break;
7326 case hmode: tex_aux_run_vrule(); break;
7327 case mmode: tex_aux_run_mrule(); break;
7328 }
7329 break;
7330
7331
7332
7333 default:
7334
7335 tex_confusion("unknown cmd code");
7336 break;
7337 }
7338
7339}
7340
7341
7345
7346void tex_initialize_variables(void)
7347{
7348 if (lmt_main_state.run_state == initializing_state) {
7349
7350 tolerance_par = default_tolerance;
7351 hang_after_par = default_hangafter;
7352 max_dead_cycles_par = default_deadcycles;
7353 math_pre_display_gap_factor_par = default_pre_display_gap;
7354
7355
7356 math_font_control_par = assumed_math_control;
7357 math_eqno_gap_step_par = default_eqno_gap_step;
7358 px_dimension_par = one_bp;
7359 eu_factor_par = eu_def_factor;
7360 show_node_details_par = 2;
7361 ex_hyphen_char_par = '-';
7362 escape_char_par = '\\';
7363 end_line_char_par = '\r';
7364 output_box_par = default_output_box;
7365 adjust_spacing_step_par = -1;
7366 adjust_spacing_stretch_par = -1;
7367 adjust_spacing_shrink_par = -1;
7368 math_double_script_mode_par = -1,
7369 math_glue_mode_par = default_math_glue_mode;
7370 hyphenation_mode_par = default_hyphenation_mode;
7371 glyph_scale_par = scaling_factor;
7372 glyph_x_scale_par = scaling_factor;
7373 glyph_y_scale_par = scaling_factor;
7374 glyph_x_offset_par = 0;
7375 glyph_y_offset_par = 0;
7376 math_begin_class_par = math_begin_class;
7377 math_end_class_par = math_end_class;
7378 math_left_class_par = unset_noad_class;
7379 math_right_class_par = unset_noad_class;
7380 math_display_penalty_factor_par = scaling_factor;
7381 math_inline_penalty_factor_par = scaling_factor;
7382 pre_inline_penalty_par = max_integer;
7383 post_inline_penalty_par = max_integer;
7384 pre_short_inline_penalty_par = max_integer;
7385 post_short_inline_penalty_par = max_integer;
7386 variable_family_par = -1,
7387 ignore_depth_criterion_par = ignore_depth;
7388 aux_get_date_and_time(&time_par, &day_par, &month_par, &year_par, &lmt_engine_state.utc_time);
7389 }
7390}
7391 |