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