1
4
5# include "luametatex.h"
6
7static void tex_aux_scan_expr (halfword level, int braced);
8static void tex_aux_scan_expression (int level, int braced);
9static void tex_aux_scan_integer_expression (int braced);
10static void tex_aux_scan_dimension_expression (int braced);
11
12
15
16static inline void tex_push_back(halfword tok, halfword cmd, halfword chr)
17{
18 if (cmd != spacer_cmd && tok != deep_frozen_relax_token && ! (cmd == relax_cmd && chr == no_relax_code)) {
19 tex_back_input(tok);
20 }
21}
22
23
34
35
36
37void tex_scan_left_brace(void)
38{
39
40 while(1) {
41 tex_get_x_token();
42 switch (cur_cmd) {
43 case left_brace_cmd:
44
45 return;
46 case spacer_cmd:
47 case relax_cmd:
48
49
50 break;
51 default:
52
53 tex_handle_error(
54 back_error_type,
55 "Missing { inserted",
56 "A left brace was mandatory here, so I've put one in."
57 );
58 cur_tok = left_brace_token + '{';
59 cur_cmd = left_brace_cmd;
60 cur_chr = '{';
61 ++lmt_input_state.align_state;
62 return;
63 }
64 }
65}
66
67
73
74void tex_scan_optional_equals(void)
75{
76
77 do {
78 tex_get_x_token();
79 } while (cur_cmd == spacer_cmd);
80 if (cur_tok != equal_token) {
81 tex_back_input(cur_tok);
82 }
83}
84
85
90
91static void tex_aux_mu_error(int n)
92{
93 tex_handle_error(
94 normal_error_type,
95 "Incompatible glue units (case %i)",
96 n,
97 "I'm going to assume that 1mu=1pt when they're mixed."
98 );
99}
100
101
134
135
140
141typedef enum arithmic_errors {
142 arithmic_error_reset,
143 arithmic_error_overflow,
144 arithmic_error_division_by_zero,
145} arithmic_errors;
146
147scanner_state_info lmt_scanner_state = {
148 .current_cmd = 0,
149 .current_chr = 0,
150 .current_cs = 0,
151
152 .current_tok = 0,
153 .current_val = 0,
154 .current_val_level = 0,
155 .current_box = 0,
156 .last_cs_name = 0,
157 .arithmic_error = 0,
158 .expression_depth = 0,
159};
160
161
172
173static inline void tex_aux_downgrade_cur_val(int level, int succeeded, int negative)
174{
175 switch (cur_val_level) {
176 case posit_val_level:
177 if (negative) {
178 cur_val = tex_posit_neg(cur_val);
179 }
180 switch (level) {
181 case dimension_val_level:
182 cur_val = tex_posit_to_dimension(cur_val);
183 cur_val_level = level;
184 break;
185 case integer_val_level:
186 case attribute_val_level:
187 cur_val = (halfword) tex_posit_to_integer(cur_val);
188 cur_val_level = level;
189 break;
190 }
191
192
193
194 break;
195 case integer_val_level:
196 if (cur_val_level > level) {
197 cur_val_level = level;
198 }
199 if (negative) {
200 cur_val = -cur_val;
201 }
202 if (level == posit_val_level) {
203 cur_val = tex_integer_to_posit(cur_val).v;
204 }
205 break;
206 case attribute_val_level:
207 if (cur_val_level > level) {
208 cur_val_level = level;
209 }
210 if (negative) {
211 cur_val = -cur_val;
212 }
213 if (level == posit_val_level) {
214 cur_val = tex_integer_to_posit(cur_val).v;
215 }
216 break;
217 case dimension_val_level:
218 if (cur_val_level > level) {
219 cur_val_level = level;
220 }
221 if (negative) {
222 cur_val = -cur_val;
223 }
224 if (level == posit_val_level) {
225 cur_val = tex_dimension_to_posit(cur_val).v;
226 }
227 break;
228 case muglue_val_level:
229 if (level == glue_val_level) {
230 goto COPYGLUE;
231 }
232 case glue_val_level:
233 if (level == posit_val_level) {
234 cur_val_level = level;
235 cur_val = tex_dimension_to_posit(negative ? - glue_amount(cur_val) : glue_amount(cur_val)).v;
236 } else if (cur_val_level > level) {
237
238 cur_val_level = level;
239 cur_val = negative ? - glue_amount(cur_val) : glue_amount(cur_val);
240 } else {
241 COPYGLUE:
242 if (succeeded == 1) {
243 cur_val = tex_new_glue_spec_node(cur_val);
244 }
245 if (negative) {
246 glue_amount(cur_val) = -glue_amount(cur_val);
247 glue_stretch(cur_val) = -glue_stretch(cur_val);
248 glue_shrink(cur_val) = -glue_shrink(cur_val);
249 }
250 }
251 break;
252 case token_val_level:
253 case font_val_level:
254 case mathspec_val_level:
255 case fontspec_val_level:
256
261 break;
262
263
264
265
266 default:
267 tex_confusion("downgrade");
268 }
269}
270
271
280
281static void tex_aux_set_cur_val_by_lua_value_cmd(halfword index, halfword property)
282{
283 int category = lua_value_none_code;
284 halfword value = 0;
285 strnumber u = tex_save_cur_string();
286 lmt_token_state.luacstrings = 0;
287 category = lmt_function_call_by_category(index, property, &value);
288 switch (category) {
289 case lua_value_none_code:
290 cur_val_level = no_val_level;
291 break;
292 case lua_value_integer_code:
293 case lua_value_cardinal_code:
294 cur_val_level = integer_val_level;
295 break;
296 case lua_value_dimension_code:
297 cur_val_level = dimension_val_level;
298 break;
299 case lua_value_skip_code:
300 cur_val_level = glue_val_level;
301 break;
302 case lua_value_boolean_code:
303
304 value = value ? 1 : 0;
305 cur_val_level = integer_val_level;
306 break;
307 case lua_value_float_code:
308 cur_val_level = posit_val_level;
309 break;
310 case lua_value_string_code:
311 cur_val_level = no_val_level;
312 break;
313 case lua_value_node_code:
314 case lua_value_direct_code:
315 if (value) {
316 switch (node_type(value)) {
317 case hlist_node:
318 case vlist_node:
319 case whatsit_node:
320 case rule_node:
321 cur_val_level = list_val_level;
322 break;
323 default:
324
325 value = null;
326 cur_val_level = no_val_level;
327 break;
328 }
329 } else {
330 value = null;
331 cur_val_level = no_val_level;
332 }
333 break;
334 case lua_value_conditional_code:
335
336 default:
337 cur_val_level = no_val_level;
338 break;
339 }
340 cur_val = value;
341 tex_restore_cur_string(u);
342 if (lmt_token_state.luacstrings > 0) {
343 tex_lua_string_start();
344 }
345}
346
347halfword tex_scan_lua_value(int index)
348{
349 tex_aux_set_cur_val_by_lua_value_cmd(index, 0);
350 return cur_val_level;
351}
352
353static halfword tex_aux_scan_register_index(void)
354{
355 do {
356 tex_get_x_token();
357 } while (cur_cmd == spacer_cmd);
358 switch (cur_cmd) {
359 case register_toks_cmd : return cur_chr - register_toks_base;
360 case register_integer_cmd : return cur_chr - register_integer_base;
361 case register_attribute_cmd : return cur_chr - register_attribute_base;
362 case register_posit_cmd : return cur_chr - register_posit_base;
363 case register_dimension_cmd : return cur_chr - register_dimension_base;
364 case register_glue_cmd : return cur_chr - register_glue_base;
365 case register_muglue_cmd : return cur_chr - register_muglue_base;
366 case char_given_cmd : return cur_chr;
367 case mathspec_cmd : return tex_get_math_spec(cur_chr).character_value;
368 case integer_cmd : return cur_chr;
369
370 case posit_cmd : return cur_chr;
371 case dimension_cmd : return cur_chr;
372 default : return -1;
373 }
374}
375
376static halfword tex_aux_scan_character_index(void)
377{
378 halfword result = -1;
379 tex_get_token();
380 if (cur_tok < cs_token_flag) {
381 result = cur_chr;
382 } else if (cur_cmd == char_given_cmd) {
383 result = cur_chr;
384 } else if (cur_cmd == mathspec_cmd) {
385 result = tex_get_math_spec(cur_chr).character_value;
386 } else {
387 strnumber txt = cs_text(cur_tok - cs_token_flag);
388 if (tex_single_letter(txt)) {
389 result = aux_str2uni(str_string(txt));
390 } else if (tex_is_active_cs(txt)) {
391 result = active_cs_value(txt);
392 } else {
393 result = max_character_code + 1;
394 }
395 }
396 return result > max_character_code ? -1 : result;
397}
398
399
405
406static int tex_aux_set_cur_val_by_some_cmd(int code)
407{
408 switch (code) {
409 case lastpenalty_code:
410 cur_val_level = integer_val_level;
411 goto COMMON;
412 case lastkern_code:
413 cur_val_level = dimension_val_level;
414 goto COMMON;
415 case lastskip_code:
416 cur_val_level = glue_val_level;
417 goto COMMON;
418 case lastboundary_code:
419 cur_val_level = integer_val_level;
420 COMMON:
421 {
422 cur_val = 0;
423 if (cur_list.tail != contribute_head && ! (cur_list.tail && node_type(cur_list.tail) == glyph_node) && cur_list.mode != nomode) {
424 switch (code) {
425 case lastpenalty_code:
426 if (node_type(cur_list.tail) == penalty_node) {
427 cur_val = penalty_amount(cur_list.tail);
428 }
429 break;
430 case lastkern_code:
431 if (node_type(cur_list.tail) == kern_node) {
432 cur_val = kern_amount(cur_list.tail);
433 }
434 break;
435 case lastskip_code:
436 if (node_type(cur_list.tail) == glue_node) {
437 cur_val = cur_list.tail;
438 if (node_subtype(cur_list.tail) == mu_glue) {
439 cur_val_level = muglue_val_level;
440 }
441 }
442 break;
443 case lastboundary_code:
444 if (node_type(cur_list.tail) == boundary_node && node_subtype(cur_list.tail) == user_boundary) {
445 cur_val = boundary_data(cur_list.tail);
446 }
447 break;
448 }
449 } else if (cur_list.mode == vmode && cur_list.tail == cur_list.head) {
450 switch (code) {
451 case lastpenalty_code:
452 cur_val = lmt_page_builder_state.last_penalty;
453 break;
454 case lastkern_code:
455 cur_val = lmt_page_builder_state.last_kern;
456 break;
457 case lastskip_code:
458 if (lmt_page_builder_state.last_glue != max_halfword) {
459 cur_val = lmt_page_builder_state.last_glue;
460 }
461 break;
462 case lastboundary_code:
463 cur_val = lmt_page_builder_state.last_boundary;
464 break;
465 }
466 }
467 break;
468 }
469 case last_node_type_code:
470
474 {
475 cur_val_level = integer_val_level;
476 if (cur_list.tail != contribute_head && cur_list.mode != nomode) {
477 cur_val = node_type(cur_list.tail);
478 } else if (cur_list.mode == vmode && cur_list.tail == cur_list.head) {
479 cur_val = lmt_page_builder_state.last_node_type;
480 } else if (cur_list.tail == cur_list.head || cur_list.mode == nomode) {
481 cur_val = -1;
482 } else {
483 cur_val = node_type(cur_list.tail);
484 }
485 break;
486 }
487 case last_node_subtype_code:
488 {
489 cur_val_level = integer_val_level;
490 if (cur_list.tail != contribute_head && cur_list.mode != nomode) {
491 cur_val = node_subtype(cur_list.tail);
492 } else if (cur_list.mode == vmode && cur_list.tail == cur_list.head) {
493 cur_val = lmt_page_builder_state.last_node_subtype;
494 } else if (cur_list.tail == cur_list.head || cur_list.mode == nomode) {
495 cur_val = -1;
496 } else {
497 cur_val = node_subtype(cur_list.tail);
498 }
499 break;
500 }
501 case input_line_no_code:
502 cur_val = lmt_input_state.input_line;
503 cur_val_level = integer_val_level;
504 break;
505 case badness_code:
506 cur_val = lmt_packaging_state.last_badness;
507 cur_val_level = integer_val_level;
508 break;
509 case overshoot_code:
510 cur_val = lmt_packaging_state.last_overshoot;
511 cur_val_level = dimension_val_level;
512 break;
513 case luametatex_major_version_code:
514 cur_val = lmt_version_state.majorversion;
515 cur_val_level = integer_val_level;
516 break;
517 case luametatex_minor_version_code:
518 cur_val = lmt_version_state.minorversion;
519 cur_val_level = integer_val_level;
520 break;
521 case luametatex_release_code:
522 cur_val = lmt_version_state.release;
523 cur_val_level = integer_val_level;
524 break;
525 case luatex_version_code:
526 cur_val = lmt_version_state.version;
527 cur_val_level = integer_val_level;
528 break;
529 case luatex_revision_code:
530 cur_val = lmt_version_state.revision;
531 cur_val_level = integer_val_level;
532 break;
533 case current_group_level_code:
534 cur_val = cur_level - level_one;
535 cur_val_level = integer_val_level;
536 break;
537 case current_group_type_code:
538 cur_val = cur_group;
539 cur_val_level = integer_val_level;
540 break;
541 case current_stack_size_code:
542 cur_val = lmt_save_state.save_stack_data.ptr;
543 cur_val_level = integer_val_level;
544 break;
545 case current_if_level_code:
546 {
547 halfword q = lmt_condition_state.cond_ptr;
548 cur_val = 0;
549 while (q) {
550 ++cur_val;
551 q = node_next(q);
552 }
553 cur_val_level = integer_val_level;
554 break;
555 }
556 case current_if_type_code:
557 {
558
565 cur_val = lmt_condition_state.cond_ptr ? (lmt_condition_state.cur_if - first_real_if_test_code) : -1;
566 cur_val_level = integer_val_level;
567 break;
568 }
569 case current_if_branch_code:
570 {
571 switch (lmt_condition_state.if_limit) {
572 case if_code:
573 cur_val = 0;
574 break;
575 case fi_code:
576 cur_val = -1;
577 break;
578 case else_code:
579 case or_code:
580 case or_else_code:
581 case or_unless_code:
582 cur_val = 1;
583 break;
584 default:
585 cur_val = 0;
586 break;
587 }
588 cur_val_level = integer_val_level;
589 break;
590 }
591 case glue_stretch_order_code:
592 case glue_shrink_order_code:
593 {
594
599 halfword q = tex_scan_glue(glue_val_level, 0, 0);
600 cur_val = (code == glue_stretch_order_code) ? glue_stretch_order(q) : glue_shrink_order(q);
601 tex_flush_node(q);
602 cur_val_level = integer_val_level;
603 break;
604 }
605 case font_id_code:
606 {
607 cur_val = tex_scan_font_identifier(NULL);
608 cur_val_level = integer_val_level;
609 break;
610 }
611 case glyph_x_scaled_code:
612 {
613 cur_val = tex_font_x_scaled(tex_scan_dimension(0, 0, 0, 1, NULL, NULL));
614 cur_val_level = dimension_val_level;
615 break;
616 }
617 case glyph_y_scaled_code:
618 {
619 cur_val = tex_font_y_scaled(tex_scan_dimension(0, 0, 0, 1, NULL, NULL));
620 cur_val_level = dimension_val_level;
621 break;
622 }
623 case font_spec_id_code:
624 case font_spec_scale_code:
625 case font_spec_xscale_code:
626 case font_spec_yscale_code:
627 case font_spec_slant_code:
628 case font_spec_weight_code:
629 {
630 halfword fs = tex_scan_fontspec_identifier();
631 if (fs) {
632 switch (code) {
633 case font_spec_id_code:
634 cur_val = font_spec_identifier(fs);
635 break;
636 case font_spec_scale_code:
637 cur_val = font_spec_scale(fs);
638 break;
639 case font_spec_xscale_code:
640 cur_val = font_spec_x_scale(fs);
641 break;
642 case font_spec_yscale_code:
643 cur_val = font_spec_y_scale(fs);
644 break;
645 case font_spec_slant_code:
646 cur_val = font_spec_slant(fs);
647 break;
648 case font_spec_weight_code:
649 cur_val = font_spec_weight(fs);
650 break;
651 }
652 } else {
653 cur_val = 0;
654 }
655 cur_val_level = integer_val_level;
656 break;
657 }
658 case font_char_wd_code:
659 case font_char_ht_code:
660 case font_char_dp_code:
661 case font_char_ic_code:
662 case font_char_ta_code:
663 case font_char_ba_code:
664 case scaled_font_char_wd_code:
665 case scaled_font_char_ht_code:
666 case scaled_font_char_dp_code:
667 case scaled_font_char_ic_code:
668 case scaled_font_char_ta_code:
669 case scaled_font_char_ba_code:
670 {
671 halfword fnt = tex_scan_font_identifier(NULL);
672 halfword chr = tex_scan_char_number(0);
673 if (tex_char_exists(fnt, chr)) {
674 switch (code) {
675 case font_char_wd_code:
676 case scaled_font_char_wd_code:
677 cur_val = tex_char_width_from_font(fnt, chr);
678 break;
679 case font_char_ht_code:
680 case scaled_font_char_ht_code:
681 cur_val = tex_char_height_from_font(fnt, chr);
682 break;
683 case font_char_dp_code:
684 case scaled_font_char_dp_code:
685 cur_val = tex_char_depth_from_font(fnt, chr);
686 break;
687 case font_char_ic_code:
688 case scaled_font_char_ic_code:
689 cur_val = tex_char_italic_from_font(fnt, chr);
690 break;
691 case font_char_ta_code:
692 case scaled_font_char_ta_code:
693 cur_val = tex_char_top_anchor_from_font(fnt, chr);
694 break;
695 case font_char_ba_code:
696 case scaled_font_char_ba_code:
697 cur_val = tex_char_bottom_anchor_from_font(fnt, chr);
698 break;
699 }
700 switch (code) {
701 case scaled_font_char_wd_code:
702 case scaled_font_char_ic_code:
703 case scaled_font_char_ta_code:
704 case scaled_font_char_ba_code:
705 cur_val = tex_font_x_scaled(cur_val);
706 break;
707 case scaled_font_char_ht_code:
708 case scaled_font_char_dp_code:
709 cur_val = tex_font_y_scaled(cur_val);
710 break;
711 }
712 } else {
713 cur_val = 0;
714 }
715 cur_val_level = dimension_val_level;
716 break;
717 }
718 case font_size_code:
719 {
720 halfword fnt = tex_scan_font_identifier(NULL);
721 cur_val = font_size(fnt);
722 cur_val_level = dimension_val_level;
723 break;
724 }
725 case font_math_control_code:
726 {
727 halfword fnt = tex_scan_font_identifier(NULL);
728 cur_val = font_mathcontrol(fnt);
729 cur_val_level = integer_val_level;
730 break;
731 }
732 case font_text_control_code:
733 {
734 halfword fnt = tex_scan_font_identifier(NULL);
735 cur_val = font_textcontrol(fnt);
736 cur_val_level = integer_val_level;
737 break;
738 }
739 case math_scale_code:
740 {
741 halfword fnt = tex_scan_font_identifier(NULL);
742 if (tex_is_valid_font(fnt)) {
743 cur_val = tex_get_math_font_scale(fnt, tex_math_style_to_size(tex_current_math_style()));
744 } else {
745 cur_val = 1000;
746 }
747 cur_val_level = integer_val_level;
748 break;
749 }
750 case math_style_code:
751 {
752 cur_val = tex_current_math_style();
753 if (cur_val < 0) {
754 cur_val = text_style;
755 }
756 cur_val_level = integer_val_level;
757 break;
758 }
759 case math_main_style_code:
760 {
761 cur_val = tex_current_math_main_style();
762 if (cur_val < 0) {
763 cur_val = text_style;
764 }
765 cur_val_level = integer_val_level;
766 break;
767 }
768 case math_parent_style_code:
769 {
770 cur_val = tex_current_math_parent_style();
771 if (cur_val < 0) {
772 cur_val = text_style;
773 }
774 cur_val_level = integer_val_level;
775 break;
776 }
777 case math_style_font_id_code:
778 {
779 halfword style = tex_scan_math_style_identifier(0, 0);
780 halfword family = tex_scan_math_family_number();
781 cur_val = tex_fam_fnt(family, tex_size_of_style(style));
782 cur_val_level = integer_val_level;
783 break;
784 }
785 case math_stack_style_code:
786 {
787 cur_val = tex_math_style_variant(cur_list.math_style, math_parameter_stack_variant);
788 if (cur_val < 0) {
789 cur_val = text_style;
790 }
791 cur_val_level = integer_val_level;
792 break;
793 }
794 case math_char_class_code:
795 case math_char_fam_code:
796 case math_char_slot_code:
797
798 {
799 mathcodeval mval = tex_no_math_code();
800 mathdictval dval = tex_no_dict_code();
801 if (tex_scan_math_cmd_val(&mval, &dval)) {
802 switch (code) {
803 case math_char_class_code:
804 cur_val = mval.class_value;
805 break;
806 case math_char_fam_code:
807 cur_val = mval.family_value;
808 break;
809 case math_char_slot_code:
810 cur_val = mval.character_value;
811 break;
812 default:
813 cur_val = 0;
814 break;
815 }
816 } else {
817 cur_val = 0;
818 }
819 cur_val_level = integer_val_level;
820 break;
821 }
822 case scaled_slant_per_point_code:
823 case scaled_interword_space_code:
824 case scaled_interword_stretch_code:
825 case scaled_interword_shrink_code:
826 case scaled_ex_height_code:
827 case scaled_em_width_code:
828 case scaled_extra_space_code:
829 {
830 cur_val = tex_get_scaled_parameter(cur_font_par, (code - scaled_slant_per_point_code + 1));
831 cur_val_level = dimension_val_level;
832 break;
833 }
834 case scaled_math_axis_code:
835 case scaled_math_ex_height_code:
836 case scaled_math_em_width_code:
837 {
838 halfword style = tex_scan_math_style_identifier(0, 0);
839 switch (code) {
840 case scaled_math_axis_code:
841 cur_val = tex_math_parameter_x_scaled(style, math_parameter_axis);
842 break;
843 case scaled_math_ex_height_code:
844 cur_val = tex_math_parameter_y_scaled(style, math_parameter_exheight);
845 break;
846 case scaled_math_em_width_code:
847 cur_val = tex_math_parameter_x_scaled(style, math_parameter_quad);
848 break;
849 }
850 cur_val_level = dimension_val_level;
851 break;
852 }
853 case last_arguments_code:
854 {
855 cur_val = lmt_expand_state.arguments;
856 cur_val_level = integer_val_level;
857 break;
858 }
859 case parameter_count_code:
860 {
861 cur_val = tex_get_parameter_count();
862 cur_val_level = integer_val_level;
863 break;
864 }
865 case parameter_index_code:
866 {
867 cur_val = tex_get_parameter_index(tex_scan_parameter_index());
868 cur_val_level = integer_val_level;
869 break;
870 }
871
883 case insert_progress_code:
884 {
885 cur_val = tex_get_insert_progress(tex_scan_integer(0, NULL, NULL));
886 cur_val_level = dimension_val_level;
887 break;
888 }
889 case left_margin_kern_code:
890 case right_margin_kern_code:
891 {
892 halfword v = tex_scan_integer(0, NULL, NULL);
893 halfword b = box_register(v);
894 if (b && (node_type(b) == hlist_node)) {
895 if (code == left_margin_kern_code) {
896 cur_val = tex_left_marginkern(box_list(b));
897 } else {
898 cur_val = tex_right_marginkern(box_list(b));
899 }
900 } else {
901 tex_normal_error("marginkern", "a hbox expected");
902 cur_val = 0;
903 }
904 cur_val_level = dimension_val_level;
905 break;
906 }
907 case par_shape_length_code:
908 {
909 cur_val = par_shape_par ? specification_count(par_shape_par) : 0;
910 cur_val_level = integer_val_level;
911 break;
912 }
913 case par_shape_indent_code:
914 case par_shape_width_code:
915 {
916 halfword shape = par_shape_par;
917 if (shape) {
918 halfword index = tex_scan_integer(0, NULL, NULL);
919 if (index >= 1 && index <= specification_count(shape)) {
920 cur_val = code == par_shape_indent_code ? tex_get_specification_indent(shape, index) : tex_get_specification_width(shape, index);
921 } else {
922 cur_val = 0;
923 }
924 } else {
925 cur_val = 0;
926 }
927 cur_val_level = dimension_val_level;
928 break;
929 }
930 case balance_shape_vsize_code:
931 case balance_shape_top_space_code:
932 case balance_shape_bottom_space_code:
933 {
934 halfword shape = balance_shape_par;
935 if (shape) {
936 halfword index = tex_scan_integer(0, NULL, NULL);
937 if (index >= 1) {
938 switch (code) {
939 case balance_shape_vsize_code:
940 cur_val = tex_get_balance_vsize(shape, index);
941 break;
942 case balance_shape_top_space_code:
943 cur_val = glue_amount(tex_get_balance_topskip(shape, index));
944 break;
945 case balance_shape_bottom_space_code:
946 cur_val = glue_amount(tex_get_balance_bottomskip(shape, index));
947 break;
948 }
949 } else {
950 cur_val = 0;
951 }
952 } else {
953 cur_val = 0;
954 }
955 cur_val_level = dimension_val_level;
956 break;
957 }
958 case glue_stretch_code:
959 case glue_shrink_code:
960 {
961 halfword q = tex_scan_glue(glue_val_level, 0, 0);
962 cur_val = code == glue_stretch_code ? glue_stretch(q) : glue_shrink(q);
963 tex_flush_node(q);
964 cur_val_level = dimension_val_level;
965 break;
966 }
967 case mu_to_glue_code:
968 cur_val = tex_scan_glue(muglue_val_level, 0, 0);
969 cur_val_level = glue_val_level;
970 return 1;
971 case glue_to_mu_code:
972 cur_val = tex_scan_glue(glue_val_level, 0, 0);
973 cur_val_level = muglue_val_level;
974 return 1;
975 case numexpr_code:
976
977 tex_aux_scan_expr(integer_val_level, 0);
978 return 1;
979 case posexpr_code:
980 tex_aux_scan_expr(posit_val_level, 0);
981 return 1;
982 case dimexpr_code:
983 tex_aux_scan_expr(dimension_val_level, 0);
984 return 1;
985 case glueexpr_code:
986 tex_aux_scan_expr(glue_val_level, 0);
987 return 1;
988 case muexpr_code:
989 tex_aux_scan_expr(muglue_val_level, 0);
990 return 1;
991 case numexpression_code:
992 tex_aux_scan_integer_expression(0);
993 return 1;
994 case dimexpression_code:
995 tex_aux_scan_dimension_expression(0);
996 return 1;
997 case numexperimental_code:
998 tex_aux_scan_expression(integer_val_level, 0);
999 return 1;
1000 case dimexperimental_code:
1001 tex_aux_scan_expression(dimension_val_level, 0);
1002 return 1;
1003
1004
1005
1006
1007 case numeric_scale_code:
1008 cur_val_level = integer_val_level;
1009 cur_val = tex_scan_scale(0);
1010 return 1;
1011 case numeric_scaled_code:
1012 {
1013 scaled n = tex_scan_scale(0);
1014 scaled i = tex_scan_integer(0, NULL, NULL);
1015 cur_val_level = integer_val_level;
1016 cur_val = tex_xn_over_d(i, n, scaling_factor);
1017 }
1018 return 1;
1019 case index_of_register_code:
1020 cur_val = tex_aux_scan_register_index();
1021 cur_val_level = integer_val_level;
1022 return 1;
1023 case index_of_character_code:
1024 cur_val = tex_aux_scan_character_index();
1025 cur_val_level = integer_val_level;
1026 return 1;
1027 case last_chk_integer_code:
1028 cur_val_level = integer_val_level;
1029 cur_val = lmt_condition_state.chk_integer;
1030 return 1;
1031 case last_chk_dimension_code:
1032 cur_val_level = dimension_val_level;
1033 cur_val = lmt_condition_state.chk_dimension;
1034 return 1;
1035 case last_left_class_code:
1036 cur_val_level = integer_val_level;
1037 cur_val = lmt_math_state.last_left;
1038 if (! valid_math_class_code(cur_val)) {
1039 cur_val = unset_noad_class;
1040 }
1041 return 1;
1042 case last_right_class_code:
1043 cur_val_level = integer_val_level;
1044 cur_val = lmt_math_state.last_right;
1045 if (! valid_math_class_code(cur_val)) {
1046 cur_val = unset_noad_class;
1047 }
1048 return 1;
1049 case last_atom_class_code:
1050 cur_val_level = integer_val_level;
1051 cur_val = lmt_math_state.last_atom;
1052 if (! valid_math_class_code(cur_val)) {
1053 cur_val = unset_noad_class;
1054 }
1055 return 1;
1056 case nested_loop_iterator_code:
1057 cur_val = tex_nested_loop_iterator();
1058 cur_val_level = integer_val_level;
1059 return 1;
1060 case previous_loop_iterator_code:
1061 cur_val = tex_previous_loop_iterator();
1062 cur_val_level = integer_val_level;
1063 return 1;
1064 case current_loop_iterator_code:
1065 case last_loop_iterator_code:
1066 cur_val_level = integer_val_level;
1067 cur_val = lmt_main_control_state.loop_iterator;
1068 return 1;
1069 case current_loop_nesting_code:
1070 cur_val_level = integer_val_level;
1071 cur_val = lmt_main_control_state.loop_nesting;
1072 return 1;
1073 case last_par_trigger_code:
1074 cur_val_level = integer_val_level;
1075 cur_val = lmt_main_control_state.last_par_trigger;
1076 return 1;
1077 case last_par_context_code:
1078 cur_val_level = integer_val_level;
1079 cur_val = lmt_main_control_state.last_par_context;
1080 return 1;
1081 case last_page_extra_code:
1082 cur_val_level = integer_val_level;
1083 cur_val = lmt_page_builder_state.last_extra_used;
1084 return 1;
1085 case math_atom_glue_code:
1086 {
1087 halfword style = tex_scan_math_style_identifier(0, 0);
1088 halfword leftclass = tex_scan_math_class_number(0);
1089 halfword rightclass = tex_scan_math_class_number(0);
1090 cur_val = tex_math_spacing_glue(leftclass, rightclass, style);
1091 cur_val_level = muglue_val_level;
1092 break;
1093 }
1094 }
1095 return 0;
1096}
1097
1098static void tex_aux_set_cur_val_by_auxiliary_cmd(int code)
1099{
1100 switch (code) {
1101 case space_factor_code:
1102 if (is_h_mode(cur_list.mode)) {
1103 cur_val = cur_list.space_factor;
1104 } else {
1105 tex_handle_error(normal_error_type, "Improper %C", auxiliary_cmd, code,
1106 "You can refer to \\spacefactor only in horizontal mode and not in \n"
1107 "inside \\write. So I'm forgetting what you said and using zero instead."
1108 );
1109 cur_val = 0;
1110 }
1111 cur_val_level = integer_val_level;
1112 break;
1113 case prev_depth_code:
1114 if (is_v_mode(cur_list.mode)) {
1115 cur_val = cur_list.prev_depth;
1116 } else {
1117 tex_handle_error(normal_error_type, "Improper %C", auxiliary_cmd, code,
1118 "You can refer to \\prevdepth only in horizontal mode and not in \n"
1119 "inside \\write. So I'm forgetting what you said and using zero instead."
1120 );
1121 cur_val = 0;
1122 }
1123 cur_val_level = dimension_val_level;
1124 break;
1125 case prev_graf_code:
1126 if (cur_list.mode == nomode) {
1127
1128 cur_val = 0;
1129 } else {
1130 cur_val = lmt_nest_state.nest[tex_vmode_nest_index()].prev_graf;
1131 }
1132 cur_val_level = integer_val_level;
1133 break;
1134 case interaction_mode_code:
1135 cur_val = lmt_error_state.interaction;
1136 cur_val_level = integer_val_level;
1137 break;
1138 case insert_mode_code:
1139 cur_val = lmt_insert_state.mode;
1140 cur_val_level = integer_val_level;
1141 break;
1142 }
1143}
1144
1145
1149
1150static void tex_aux_set_cur_val_by_specification_cmd(int code)
1151{
1152 halfword spec = eq_value(code);
1153 cur_val = spec ? tex_aux_get_specification_value(spec, code) : 0;
1154 cur_val_level = integer_val_level;
1155}
1156
1157# define page_state_okay (lmt_page_builder_state.contents == contribute_nothing && ! lmt_page_builder_state.output_active)
1158
1159static void tex_aux_set_cur_val_by_page_property_cmd(int code)
1160{
1161 switch (code) {
1162 case page_goal_code:
1163 cur_val = page_state_okay ? max_dimension : lmt_page_builder_state.goal;
1164 cur_val_level = dimension_val_level;
1165 break;
1166 case page_vsize_code:
1167 cur_val = page_state_okay ? 0 : lmt_page_builder_state.vsize;
1168 cur_val_level = dimension_val_level;
1169 break;
1170 case page_total_code:
1171 cur_val = page_state_okay ? 0 : lmt_page_builder_state.total;
1172 cur_val_level = dimension_val_level;
1173 break;
1174 case page_excess_code:
1175 cur_val = page_state_okay ? 0 : lmt_page_builder_state.excess;
1176 cur_val_level = dimension_val_level;
1177 break;
1178 case page_depth_code:
1179 cur_val = page_state_okay ? 0 : lmt_page_builder_state.depth;
1180 cur_val_level = dimension_val_level;
1181 break;
1182 case page_stretch_code:
1183 cur_val = page_state_okay ? 0 : lmt_page_builder_state.stretch;
1184 cur_val_level = dimension_val_level;
1185 break;
1186 case page_fistretch_code:
1187 cur_val = page_state_okay ? 0 : lmt_page_builder_state.fistretch;
1188 cur_val_level = dimension_val_level;
1189 break;
1190 case page_filstretch_code:
1191 cur_val = page_state_okay ? 0 : lmt_page_builder_state.filstretch;
1192 cur_val_level = dimension_val_level;
1193 break;
1194 case page_fillstretch_code:
1195 cur_val = page_state_okay ? 0 : lmt_page_builder_state.fillstretch;
1196 cur_val_level = dimension_val_level;
1197 break;
1198 case page_filllstretch_code:
1199 cur_val = page_state_okay ? 0 : lmt_page_builder_state.filllstretch;
1200 cur_val_level = dimension_val_level;
1201 break;
1202 case page_shrink_code:
1203 cur_val = page_state_okay ? 0 : lmt_page_builder_state.shrink;
1204 cur_val_level = dimension_val_level;
1205 break;
1206 case page_last_height_code:
1207 cur_val = page_state_okay ? 0 : lmt_page_builder_state.last_height;
1208 cur_val_level = dimension_val_level;
1209 break;
1210 case page_last_depth_code:
1211 cur_val = page_state_okay ? 0 : lmt_page_builder_state.last_depth;
1212 cur_val_level = dimension_val_level;
1213 break;
1214 case page_last_stretch_code:
1215 cur_val = page_state_okay ? 0 : lmt_page_builder_state.last_stretch;
1216 cur_val_level = dimension_val_level;
1217 break;
1218 case page_last_fistretch_code:
1219 cur_val = page_state_okay ? 0 : lmt_page_builder_state.last_fistretch;
1220 cur_val_level = dimension_val_level;
1221 break;
1222 case page_last_filstretch_code:
1223 cur_val = page_state_okay ? 0 : lmt_page_builder_state.last_filstretch;
1224 cur_val_level = dimension_val_level;
1225 break;
1226 case page_last_fillstretch_code:
1227 cur_val = page_state_okay ? 0 : lmt_page_builder_state.last_fillstretch;
1228 cur_val_level = dimension_val_level;
1229 break;
1230 case page_last_filllstretch_code:
1231 cur_val = page_state_okay ? 0 : lmt_page_builder_state.last_filllstretch;
1232 cur_val_level = dimension_val_level;
1233 break;
1234 case page_last_shrink_code:
1235 cur_val = page_state_okay ? 0 : lmt_page_builder_state.last_shrink;
1236 cur_val_level = dimension_val_level;
1237 break;
1238 case dead_cycles_code:
1239 cur_val = lmt_page_builder_state.dead_cycles;
1240 cur_val_level = integer_val_level;
1241 break;
1242 case insert_penalties_code:
1243 cur_val = lmt_page_builder_state.insert_penalties;
1244 cur_val_level = integer_val_level;
1245 break;
1246 case insert_heights_code:
1247 cur_val = lmt_page_builder_state.insert_heights;
1248 cur_val_level = dimension_val_level;
1249 break;
1250 case insert_storing_code:
1251 cur_val = lmt_insert_state.storing;
1252 cur_val_level = integer_val_level;
1253 break;
1254 case insert_distance_code:
1255 cur_val = tex_get_insert_distance(tex_scan_integer(0, NULL, NULL));
1256 cur_val_level = glue_val_level;
1257 break;
1258 case insert_multiplier_code:
1259 cur_val = tex_get_insert_multiplier(tex_scan_integer(0, NULL, NULL));
1260 cur_val_level = integer_val_level;
1261 break;
1262 case insert_limit_code:
1263 cur_val = tex_get_insert_limit(tex_scan_integer(0, NULL, NULL));
1264 cur_val_level = dimension_val_level;
1265 break;
1266 case insert_storage_code:
1267 cur_val = tex_get_insert_storage(tex_scan_integer(0, NULL, NULL));
1268 cur_val_level = integer_val_level;
1269 break;
1270 case insert_penalty_code:
1271 cur_val = tex_get_insert_penalty(tex_scan_integer(0, NULL, NULL));
1272 cur_val_level = integer_val_level;
1273 break;
1274 case insert_maxdepth_code:
1275 cur_val = tex_get_insert_maxdepth(tex_scan_integer(0, NULL, NULL));
1276 cur_val_level = dimension_val_level;
1277 break;
1278 case insert_height_code:
1279 cur_val = tex_get_insert_height(tex_scan_integer(0, NULL, NULL));
1280 cur_val_level = dimension_val_level;
1281 break;
1282 case insert_depth_code:
1283 cur_val = tex_get_insert_depth(tex_scan_integer(0, NULL, NULL));
1284 cur_val_level = dimension_val_level;
1285 break;
1286 case insert_width_code:
1287 cur_val = tex_get_insert_width(tex_scan_integer(0, NULL, NULL));
1288 cur_val_level = dimension_val_level;
1289 break;
1290 case insert_line_height_code:
1291 cur_val = tex_get_insert_line_height(tex_scan_integer(0, NULL, NULL));
1292 cur_val_level = dimension_val_level;
1293 break;
1294 case insert_line_depth_code:
1295 cur_val = tex_get_insert_line_depth(tex_scan_integer(0, NULL, NULL));
1296 cur_val_level = dimension_val_level;
1297 break;
1298 case insert_stretch_code:
1299 cur_val = tex_get_insert_stretch(tex_scan_integer(0, NULL, NULL));
1300 cur_val_level = dimension_val_level;
1301 break;
1302 case insert_shrink_code:
1303 cur_val = tex_get_insert_shrink(tex_scan_integer(0, NULL, NULL));
1304 cur_val_level = dimension_val_level;
1305 break;
1306 case split_last_depth_code:
1307 cur_val = lmt_packaging_state.split_last_depth;
1308 cur_val_level = dimension_val_level;
1309 break;
1310 case split_last_height_code:
1311 cur_val = lmt_packaging_state.split_last_height;
1312 cur_val_level = dimension_val_level;
1313 break;
1314 case split_last_shrink_code:
1315 cur_val = lmt_packaging_state.split_last_shrink;
1316 cur_val_level = dimension_val_level;
1317 break;
1318 case split_last_stretch_code:
1319 cur_val = lmt_packaging_state.split_last_stretch;
1320 cur_val_level = dimension_val_level;
1321 break;
1322 case mvl_currently_active_code:
1323 cur_val = tex_current_mvl(NULL, NULL);
1324 cur_val_level = integer_val_level;
1325 break;
1326 default:
1327 tex_confusion("page property");
1328 break;
1329 }
1330}
1331
1332static void tex_aux_set_cur_val_by_define_char_cmd(int code)
1333{
1334 halfword index = tex_scan_char_number(0);
1335 switch (code) {
1336 case catcode_charcode:
1337 code = tex_get_cat_code(cat_code_table_par, index);
1338 break;
1339 case lccode_charcode:
1340 code = tex_get_lc_code(index);
1341 break;
1342 case uccode_charcode:
1343 code = tex_get_uc_code(index);
1344 break;
1345 case sfcode_charcode:
1346 code = tex_get_sf_code(index);
1347 break;
1348 case hccode_charcode:
1349 code = tex_get_hc_code(index);
1350 break;
1351 case hmcode_charcode:
1352 code = tex_get_hm_code(index);
1353 break;
1354 case amcode_charcode:
1355 code = tex_get_am_code(index);
1356 break;
1357 case cccode_charcode:
1358 code = tex_get_cc_code(index);
1359 break;
1360 case mathcode_charcode:
1361 case extmathcode_charcode:
1362 code = tex_get_math_code_number(index);
1363 break;
1364 case delcode_charcode:
1365 case extdelcode_charcode:
1366 code = tex_get_del_code_number(index);
1367 break;
1368 default:
1369 tex_confusion("scan char");
1370 break;
1371 }
1372 cur_val = code;
1373 cur_val_level = integer_val_level;
1374}
1375
1376
1382
1383static halfword tex_aux_scan_math_style_number(halfword code)
1384{
1385 switch (code) {
1386 case yet_unset_math_style:
1387 return tex_scan_math_style_identifier(0, 0);
1388 case scaled_math_style:
1389 return cur_list.math_scale;
1390 case former_choice_math_style:
1391 return 0;
1392 default:
1393 return code;
1394 }
1395}
1396
1397static void tex_aux_set_cur_val_by_math_style_cmd(halfword code)
1398{
1399 cur_val = tex_aux_scan_math_style_number(code);
1400 cur_val_level = integer_val_level;
1401}
1402
1403
1411
1412
1413
1414static void tex_aux_missing_number_error(int where)
1415{
1416 tex_handle_error(
1417 back_error_type,
1418 "Missing number, case %i, treated as zero", where,
1419 "A number should have been here; I inserted '0'. (If you can't figure out why I\n"
1420 "needed to see a number, look up 'weird error' in the index to The TeXbook.)"
1421 );
1422}
1423
1424static void tex_aux_scan_dimension_out_of_range_error(int where) {
1425 tex_handle_error(
1426 normal_error_type,
1427 "Dimension too large, case %i", where,
1428 "I can't work with sizes bigger than about 19 feet (45 Theodores as of 2023),\n"
1429 "575 centimeters, 2300 Toves, 230 Ediths or 16383 points. Continue and I'll use\n"
1430 "the largest value I can."
1431 );
1432}
1433
1434static void tex_aux_scan_integer_out_of_range_error(int where) {
1435 tex_handle_error(
1436 normal_error_type,
1437 "Number too large, case %i", where,
1438 "I can only go up to 2147483647 = '17777777777 = \"7FFFFFFF, so I'm using that\n"
1439 "number instead of yours."
1440 );
1441}
1442
1443static void tex_aux_improper_constant_error(void)
1444{
1445 tex_handle_error(
1446 back_error_type,
1447 "Improper alphabetic constant",
1448 "A one-character control sequence belongs after a ` mark. So I'm essentially\n"
1449 "inserting \\0 here."
1450 );
1451}
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471static int tex_aux_scan_hyph_data_number(halfword code, halfword *target)
1472{
1473 switch (code) {
1474 case prehyphenchar_code:
1475 *target = tex_get_pre_hyphen_char(language_par);
1476 break;
1477 case posthyphenchar_code:
1478 *target = tex_get_post_hyphen_char(language_par);
1479 break;
1480 case preexhyphenchar_code:
1481 *target = tex_get_pre_exhyphen_char(language_par);
1482 break;
1483 case postexhyphenchar_code:
1484 *target = tex_get_post_exhyphen_char(language_par);
1485 break;
1486 case hyphenationmin_code:
1487 *target = tex_get_hyphenation_min(language_par);
1488 break;
1489 case hjcode_code:
1490 *target = tex_get_hj_code(language_par, tex_scan_integer(0, NULL, NULL));
1491 break;
1492 default:
1493 return 0;
1494 }
1495 return 1;
1496}
1497
1498static void tex_aux_set_cur_val_by_math_parameter_cmd(halfword chr)
1499{
1500 switch (chr) {
1501 case math_parameter_reset_spacing:
1502
1503 case math_parameter_set_spacing:
1504 case math_parameter_let_spacing:
1505 case math_parameter_copy_spacing:
1506 {
1507 halfword left = tex_scan_math_class_number(0);
1508 halfword right = tex_scan_math_class_number(0);
1509 halfword style = tex_scan_math_style_identifier(0, 0);
1510 halfword node = tex_math_spacing_glue(left, right, style);
1511 cur_val = node ? node : zero_glue;
1512 cur_val_level = muglue_val_level;
1513 break;
1514 }
1515 case math_parameter_set_atom_rule:
1516 case math_parameter_let_atom_rule:
1517 case math_parameter_copy_atom_rule:
1518
1519 case math_parameter_copy_parent:
1520 case math_parameter_set_defaults:
1521 {
1522
1523
1524 break;
1525 }
1526 case math_parameter_let_parent:
1527 {
1528 halfword mathclass = tex_scan_math_class_number(0);
1529 if (valid_math_class_code(mathclass)) {
1530 cur_val = tex_math_has_class_parent(mathclass);
1531 cur_val_level = integer_val_level;
1532 }
1533 break;
1534 }
1535 case math_parameter_set_pre_penalty:
1536 case math_parameter_set_post_penalty:
1537 case math_parameter_set_display_pre_penalty:
1538 case math_parameter_set_display_post_penalty:
1539 {
1540 halfword mathclass = tex_scan_math_class_number(0);
1541 if (valid_math_class_code(mathclass)) {
1542 switch (chr) {
1543 case math_parameter_set_pre_penalty:
1544 cur_val = count_parameter(first_math_pre_penalty_code + mathclass);
1545 break;
1546 case math_parameter_set_post_penalty:
1547 cur_val = count_parameter(first_math_post_penalty_code + mathclass);
1548 break;
1549 case math_parameter_set_display_pre_penalty:
1550 cur_val = count_parameter(first_math_display_pre_penalty_code + mathclass);
1551 break;
1552 case math_parameter_set_display_post_penalty:
1553 cur_val = count_parameter(first_math_display_post_penalty_code + mathclass);
1554 break;
1555 }
1556 } else {
1557 cur_val = 0;
1558 }
1559 cur_val_level = integer_val_level;
1560 break;
1561 }
1562 case math_parameter_ignore:
1563 {
1564 halfword code = tex_scan_math_parameter();
1565 cur_val = code >= 0 ? count_parameter(first_math_ignore_code + code) : 0;
1566 cur_val_level = integer_val_level;
1567 break;
1568 }
1569 case math_parameter_options:
1570 {
1571 halfword mathclass = tex_scan_math_class_number(0);
1572 if (valid_math_class_code(mathclass)) {
1573 cur_val = count_parameter(first_math_options_code + mathclass);
1574 } else {
1575 cur_val = 0;
1576 }
1577 break;
1578 }
1579 default:
1580 {
1581 cur_val = tex_scan_math_style_identifier(0, 0);
1582 switch (math_parameter_value_type(chr)) {
1583 case math_integer_parameter:
1584 cur_val_level = integer_val_level;
1585 break;
1586 case math_dimension_parameter:
1587 cur_val_level = dimension_val_level;
1588 break;
1589 case math_muglue_parameter:
1590 cur_val_level = muglue_val_level;
1591 break;
1592 case math_style_parameter:
1593 cur_val_level = integer_val_level;
1594 break;
1595 }
1596 chr = tex_get_math_parameter(cur_val, chr, NULL);
1597 if (cur_val_level == muglue_val_level) {
1598 switch (chr) {
1599 case petty_muskip_code:
1600 chr = petty_muskip_par;
1601 break;
1602 case tiny_muskip_code:
1603 chr = tiny_muskip_par;
1604 break;
1605 case thin_muskip_code:
1606 chr = thin_muskip_par;
1607 break;
1608 case med_muskip_code:
1609 chr = med_muskip_par;
1610 break;
1611 case thick_muskip_code:
1612 chr = thick_muskip_par;
1613 break;
1614 }
1615 }
1616 cur_val = chr;
1617 break;
1618 }
1619 }
1620}
1621
1622static void tex_aux_set_cur_val_by_box_property_cmd(halfword chr)
1623{
1624
1625 halfword n = tex_scan_box_register_number();
1626 halfword b = box_register(n);
1627 switch (chr) {
1628 case box_width_code:
1629 cur_val = b ? box_width(b) : 0;
1630 cur_val_level = dimension_val_level;
1631 break;
1632 case box_height_code:
1633 cur_val = b ? box_height(b) : 0;
1634 cur_val_level = dimension_val_level;
1635 break;
1636 case box_depth_code:
1637 cur_val = b ? box_depth(b) : 0;
1638 cur_val_level = dimension_val_level;
1639 break;
1640 case box_direction_code:
1641 cur_val = b ? box_dir(b) : 0;
1642 cur_val_level = integer_val_level;
1643 break;
1644 case box_geometry_code:
1645 cur_val = b ? box_geometry(b) : 0;
1646 cur_val_level = integer_val_level;
1647 break;
1648 case box_orientation_code:
1649 cur_val = b ? box_orientation(b) : 0;
1650 cur_val_level = integer_val_level;
1651 break;
1652 case box_anchor_code:
1653 case box_anchors_code:
1654 cur_val = b ? box_anchor(b) : 0;
1655 cur_val_level = integer_val_level;
1656 break;
1657 case box_source_code:
1658 cur_val = b ? box_source_anchor(b) : 0;
1659 cur_val_level = integer_val_level;
1660 break;
1661 case box_target_code:
1662 cur_val = b ? box_target_anchor(b) : 0;
1663 cur_val_level = integer_val_level;
1664 break;
1665 case box_xoffset_code:
1666 cur_val = b ? box_x_offset(b) : 0;
1667 cur_val_level = dimension_val_level;
1668 break;
1669 case box_yoffset_code:
1670 cur_val = b ? box_y_offset(b) : 0;
1671 cur_val_level = dimension_val_level;
1672 break;
1673 case box_xmove_code:
1674 cur_val = b ? (box_width(b) - box_x_offset(b)) : 0;
1675 cur_val_level = dimension_val_level;
1676 break;
1677 case box_ymove_code:
1678 cur_val = b ? (box_total(b) - box_y_offset(b)) : 0;
1679 cur_val_level = dimension_val_level;
1680 break;
1681 case box_total_code:
1682 cur_val = b ? box_total(b) : 0;
1683 cur_val_level = dimension_val_level;
1684 break;
1685 case box_shift_code:
1686 cur_val = b ? box_shift_amount(b) : 0;
1687 cur_val_level = dimension_val_level;
1688 break;
1689 case box_adapt_code:
1690 cur_val = 0;
1691 cur_val_level = integer_val_level;
1692 break;
1693 case box_repack_code:
1694 if (node_type(b) == hlist_node) {
1695 cur_val = box_list(b) ? tex_natural_hsize(box_list(b), NULL) : 0;
1696 } else {
1697 cur_val = box_list(b) ? tex_natural_vsize(box_list(b)) : 0;
1698 }
1699 cur_val_level = dimension_val_level;
1700 break;
1701 case box_stretch_code:
1702 cur_val = box_list(b) ? tex_stretch(b) : 0;
1703 cur_val_level = dimension_val_level;
1704 break;
1705 case box_shrink_code:
1706 cur_val = box_list(b) ? tex_shrink(b) : 0;
1707 cur_val_level = dimension_val_level;
1708 break;
1709 case box_subtype_code:
1710 cur_val = node_subtype(b);
1711 cur_val_level = integer_val_level;
1712 break;
1713 case box_freeze_code:
1714 cur_val = node_type(b) == hlist_node ? box_width(b) : box_total(b);
1715 cur_val_level = dimension_val_level;
1716 break;
1717 case box_migrate_code:
1718 cur_val = 0;
1719 if (node_type(b) == hlist_node) {
1720 if (box_pre_migrated(b)) { cur_val |= auto_migrate_pre; }
1721 if (box_post_migrated(b)) { cur_val |= auto_migrate_post; }
1722 }
1723 cur_val_level = integer_val_level;
1724 break;
1725 case box_limitate_code:
1726
1727 cur_val = node_type(b) == hlist_node ? box_width(b) : box_total(b);
1728 cur_val_level = dimension_val_level;
1729 break;
1730 case box_finalize_code:
1731
1732 cur_val = node_type(b) == hlist_node ? box_width(b) : box_total(b);
1733 cur_val_level = dimension_val_level;
1734 break;
1735 case box_limit_code:
1736
1737 cur_val = node_type(b) == hlist_node ? box_width(b) : box_total(b);
1738 cur_val_level = dimension_val_level;
1739 break;
1740 case box_attribute_code:
1741 {
1742 halfword att = tex_scan_attribute_register_number();
1743 cur_val = b ? tex_has_attribute(b, att, unused_attribute_value) : unused_attribute_value;
1744 cur_val_level = integer_val_level;
1745 break;
1746 }
1747 case box_vadjust_code:
1748 cur_val = 0;
1749 if (b) {
1750 if (box_pre_adjusted(b)) {
1751 cur_val |= has_pre_adjust;
1752 }
1753 if (box_post_adjusted(b)) {
1754 cur_val |= has_post_adjust;
1755 }
1756 if (box_pre_migrated(b)) {
1757 cur_val |= has_pre_migrated;
1758 }
1759 if (box_post_migrated(b)) {
1760 cur_val |= has_post_migrated;
1761 }
1762 }
1763 cur_val_level = integer_val_level;
1764 break;
1765 case box_inserts_code:
1766 cur_val = tex_identify_inserts(b, 0);
1767 cur_val_level = integer_val_level;
1768 break;
1769 }
1770}
1771
1772static void tex_aux_set_cur_val_by_font_property_cmd(halfword chr)
1773{
1774 switch (chr) {
1775 case font_hyphen_code:
1776 {
1777 halfword fnt = tex_scan_font_identifier(NULL);
1778 cur_val = font_hyphen_char(fnt);
1779 cur_val_level = integer_val_level;
1780 break;
1781 }
1782 case font_skew_code:
1783 {
1784 halfword fnt = tex_scan_font_identifier(NULL);
1785 cur_val = font_skew_char(fnt);
1786 cur_val_level = integer_val_level;
1787 break;
1788 }
1789 case font_lp_code:
1790 {
1791 halfword fnt = tex_scan_font_identifier(NULL);
1792 halfword chr = tex_scan_char_number(0);
1793 cur_val = tex_char_lp_from_font(fnt, chr);
1794 cur_val_level = dimension_val_level;
1795 break;
1796 }
1797 case font_rp_code:
1798 {
1799 halfword fnt = tex_scan_font_identifier(NULL);
1800 halfword chr = tex_scan_char_number(0);
1801 cur_val = tex_char_rp_from_font(fnt, chr);
1802 cur_val_level = dimension_val_level;
1803 break;
1804 }
1805 case font_ef_code:
1806 {
1807 halfword fnt = tex_scan_font_identifier(NULL);
1808 halfword chr = tex_scan_char_number(0);
1809 cur_val = tex_char_ef_from_font(fnt, chr);
1810 cur_val_level = integer_val_level;
1811 break;
1812 }
1813 case font_cf_code:
1814 {
1815 halfword fnt = tex_scan_font_identifier(NULL);
1816 halfword chr = tex_scan_char_number(0);
1817 cur_val = tex_char_cf_from_font(fnt, chr);
1818 cur_val_level = integer_val_level;
1819 break;
1820 }
1821 case font_dimension_code:
1822 {
1823 cur_val = tex_get_font_dimension();
1824 cur_val_level = dimension_val_level;
1825 break;
1826 }
1827 case scaled_font_dimension_code:
1828 {
1829 cur_val = tex_get_scaled_font_dimension();
1830 cur_val_level = dimension_val_level;
1831 break;
1832 }
1833 }
1834}
1835
1836static void tex_aux_set_cur_val_by_register_cmd(halfword chr)
1837{
1838 switch (chr) {
1839 case integer_val_level:
1840 {
1841 halfword n = tex_scan_integer_register_number();
1842 cur_val = count_register(n);
1843 break;
1844 }
1845 case attribute_val_level:
1846 {
1847 halfword n = tex_scan_attribute_register_number();
1848 cur_val = attribute_register(n);
1849 break;
1850 }
1851 case posit_val_level:
1852 {
1853 halfword n = tex_scan_posit_register_number();
1854 cur_val = posit_register(n);
1855 break;
1856 }
1857 case dimension_val_level:
1858 {
1859 scaled n = tex_scan_dimension_register_number();
1860 cur_val = dimension_register(n);
1861 break;
1862 }
1863 case glue_val_level:
1864 {
1865 halfword n = tex_scan_glue_register_number();
1866 cur_val = skip_register(n);
1867 break;
1868 }
1869 case muglue_val_level:
1870 {
1871 halfword n = tex_scan_muglue_register_number();
1872 cur_val = muskip_register(n);
1873 break;
1874 }
1875 case token_val_level:
1876 {
1877 halfword n = tex_scan_toks_register_number();
1878 cur_val = toks_register(n);
1879 break;
1880 }
1881 }
1882 cur_val_level = chr;
1883}
1884
1885static void tex_aux_set_cur_val_by_math_spec_cmd(halfword chr)
1886{
1887 cur_val = chr;
1888 if (chr) {
1889 switch (node_subtype(chr)) {
1890 case tex_mathcode:
1891 cur_val = math_spec_value(chr);
1892 cur_val_level = integer_val_level;
1893 break;
1894 case umath_mathcode:
1895
1896 case mathspec_mathcode:
1897 cur_val_level = mathspec_val_level;
1898 break;
1899 default:
1900 cur_val = 0;
1901 cur_val_level = integer_val_level;
1902 break;
1903 }
1904 } else {
1905 cur_val_level = integer_val_level;
1906 }
1907}
1908
1909static halfword tex_aux_scan_something_internal(halfword cmd, halfword chr, int level, int negative, halfword property)
1910{
1911 int succeeded = 1;
1912 switch (cmd) {
1913
1914 case char_given_cmd:
1915 cur_val = chr;
1916 cur_val_level = integer_val_level;
1917 break;
1918 case some_item_cmd:
1919 {
1920
1924 int save_cur_chr = cur_chr;
1925 cur_chr = chr;
1926 if (tex_aux_set_cur_val_by_some_cmd(chr)) {
1927 succeeded = 2;
1928 } else {
1929 cur_chr = save_cur_chr;
1930 }
1931 break;
1932 }
1933 case internal_toks_cmd:
1934 case register_toks_cmd:
1935 cur_val = eq_value(chr);
1936 cur_val_level = token_val_level;
1937 break;
1938 case internal_integer_cmd:
1939 case register_integer_cmd:
1940 case internal_attribute_cmd:
1941 case register_attribute_cmd:
1942 cur_val = eq_value(chr);
1943 cur_val_level = integer_val_level;
1944 if (level == posit_val_level) {
1945 cur_val = (halfword) tex_posit_to_integer(cur_val);
1946 }
1947 break;
1948 case internal_posit_cmd:
1949 case register_posit_cmd:
1950 cur_val = eq_value(chr);
1951 cur_val_level = posit_val_level;
1952 break;
1953 case internal_dimension_cmd:
1954 case register_dimension_cmd:
1955 cur_val = eq_value(chr);
1956 cur_val_level = dimension_val_level;
1957 if (level == posit_val_level) {
1958 cur_val = tex_posit_to_dimension(cur_val);
1959 }
1960 break;
1961 case internal_glue_cmd:
1962 case register_glue_cmd:
1963 cur_val = eq_value(chr);
1964 cur_val_level = glue_val_level;
1965 break;
1966 case internal_muglue_cmd:
1967 case register_muglue_cmd:
1968 cur_val = eq_value(chr);
1969 cur_val_level = muglue_val_level;
1970 break;
1971 case lua_value_cmd:
1972 tex_aux_set_cur_val_by_lua_value_cmd(chr, property);
1973 if (cur_val_level == no_val_level) {
1974 return 0;
1975 }
1976 break;
1977 case iterator_value_cmd:
1978 cur_val = chr > 0x100000 ? - (chr - 0x100000) : chr;
1979 cur_val_level = integer_val_level;
1980 break;
1981 case math_style_cmd:
1982 tex_aux_set_cur_val_by_math_style_cmd(chr);
1983 break;
1984 case auxiliary_cmd:
1985 tex_aux_set_cur_val_by_auxiliary_cmd(chr);
1986 break;
1987 case page_property_cmd:
1988 tex_aux_set_cur_val_by_page_property_cmd(chr);
1989 break;
1990 case specification_cmd:
1991 tex_aux_set_cur_val_by_specification_cmd(chr);
1992 break;
1993 case define_char_code_cmd:
1994 tex_aux_set_cur_val_by_define_char_cmd(chr);
1995 break;
1996
1997 case define_font_cmd:
1998
1999 if (level == token_val_level) {
2000 cur_val = cur_font_par;
2001 cur_val_level = font_val_level;
2002 return cur_val;
2003 } else {
2004 break;
2005 }
2006 case set_font_cmd:
2007
2008 if (level == token_val_level) {
2009 cur_val = cur_chr;
2010 cur_val_level = font_val_level;
2011 return cur_val;
2012 } else {
2013 break;
2014 }
2015 case define_family_cmd:
2016 {
2017 halfword fam = tex_scan_math_family_number();
2018 cur_val = tex_fam_fnt(fam, chr);
2019 cur_val_level = font_val_level;
2020 return cur_val;
2021 }
2022 case math_parameter_cmd:
2023 tex_aux_set_cur_val_by_math_parameter_cmd(chr);
2024 break;
2025 case box_property_cmd:
2026 tex_aux_set_cur_val_by_box_property_cmd(chr);
2027 break;
2028 case font_property_cmd:
2029 tex_aux_set_cur_val_by_font_property_cmd(chr);
2030 break;
2031 case register_cmd:
2032 tex_aux_set_cur_val_by_register_cmd(chr);
2033 break;
2034 case ignore_something_cmd:
2035 break;
2036 case hyphenation_cmd:
2037 if (tex_aux_scan_hyph_data_number(chr, &cur_val)) {
2038 cur_val_level = integer_val_level;
2039 break;
2040 } else {
2041 goto DEFAULT;
2042 }
2043 case integer_cmd:
2044 case index_cmd:
2045 cur_val = chr;
2046 cur_val_level = integer_val_level;
2047 break;
2048 case dimension_cmd:
2049 cur_val = chr;
2050 cur_val_level = dimension_val_level;
2051 break;
2052 case posit_cmd:
2053 cur_val = chr;
2054 cur_val_level = posit_val_level;
2055 break;
2056 case gluespec_cmd:
2057 cur_val = chr;
2058 cur_val_level = glue_val_level;
2059 break;
2060 case mugluespec_cmd:
2061 cur_val = chr;
2062 cur_val_level = muglue_val_level;
2063 break;
2064 case mathspec_cmd:
2065 tex_aux_set_cur_val_by_math_spec_cmd(chr);
2066 break;
2067 case fontspec_cmd:
2068 cur_val = tex_get_font_identifier(chr) ? chr : null;
2069 cur_val_level = fontspec_val_level;
2070 break;
2071 case association_cmd:
2072 switch (chr) {
2073 case unit_association_code:
2074 cur_val = tex_get_unit_class(tex_scan_unit_register_number(0));
2075 cur_val_level = integer_val_level;
2076 break;
2077 }
2078 break;
2079 case begin_paragraph_cmd:
2080 switch (chr) {
2081 case snapshot_par_code:
2082 {
2083 halfword par = tex_find_par_par(cur_list.head);
2084 cur_val = par ? par_state(par) : 0;
2085 cur_val_level = integer_val_level;
2086 break;
2087 }
2088
2089 case wrapup_par_code:
2090 {
2091 halfword par = tex_find_par_par(cur_list.head);
2092 cur_val = par ? par_end_par_tokens(par) : null;
2093 cur_val_level = token_val_level;
2094 break;
2095 }
2096 default:
2097 goto DEFAULT;
2098 }
2099 break;
2100
2116
2119 case parameter_cmd:
2120 tex_get_x_token();
2121 if (valid_iterator_reference(cur_tok)) {
2122 cur_val = tex_expand_iterator(cur_tok);
2123 cur_val_level = integer_val_level;
2124 break;
2125 } else {
2126 goto DEFAULT;
2127 }
2128 case interaction_cmd:
2129 cur_val = cur_chr;
2130 cur_val_level = integer_val_level;
2131 break;
2132 case specificationspec_cmd:
2133 {
2134 quarterword code = node_subtype(chr);
2135 halfword count = tex_get_specification_count(chr);
2136 if (count) {
2137 switch (code) {
2138 case integer_list_code:
2139 case dimension_list_code:
2140 case posit_list_code:
2141 {
2142
2143 halfword index = tex_scan_integer(0, NULL, NULL);
2144 halfword value = 0;
2145 if (index) {
2146 if (index < 0) {
2147 index = count + index + 1;
2148 }
2149 if (index > count && specification_rotate(chr)) {
2150 index = (index % specification_count(chr));
2151 if (index == 0) {
2152 index = specification_count(chr);
2153 }
2154 }
2155 if (index >= 1 && index <= count) {
2156 if (specification_double(chr)) {
2157 switch (tex_scan_integer(0, NULL, NULL)) {
2158 case 1:
2159 value = tex_get_specification_nepalty(chr, index);
2160 if (specification_integer(chr)) {
2161 code = integer_list_code;
2162 }
2163 break;
2164 case 2:
2165 value = tex_get_specification_penalty(chr, index);
2166 break;
2167 }
2168 } else {
2169 value = tex_get_specification_penalty(chr, index);
2170 }
2171 } else {
2172 tex_specification_range_error(chr);
2173 }
2174 switch (code) {
2175 case integer_list_code:
2176 cur_val = value;
2177 cur_val_level = integer_val_level;
2178 break ;
2179 case dimension_list_code:
2180 cur_val = value;
2181 cur_val_level = dimension_val_level;
2182 break;
2183 case posit_list_code:
2184 cur_val = value;
2185 cur_val_level = posit_val_level;
2186 break;
2187 }
2188 } else {
2189 cur_val = count;
2190 cur_val_level = integer_val_level;
2191 }
2192 }
2193 break;
2194 default:
2195 cur_val = count;
2196 cur_val_level = integer_val_level;
2197 break;
2198 }
2199 } else {
2200 cur_val = count;
2201 cur_val_level = integer_val_level;
2202 }
2203 break;
2204 }
2205# if (match_experiment)
2206case integer_reference_cmd:
2207 {
2208 halfword n = cur_chr;
2209 if (node_token_flagged(n)) {
2210 tex_get_token();
2211 n = node_token_sum(n,cur_chr);
2212 }
2213 cur_val = n;
2214 cur_val_level = integer_val_level;
2215 break;
2216 }
2217case dimension_reference_cmd:
2218 {
2219 halfword n = cur_chr;
2220 if (node_token_flagged(n)) {
2221 tex_get_token();
2222 n = node_token_sum(n,cur_chr);
2223 }
2224 cur_val = n;
2225 cur_val_level = dimension_val_level;
2226 break;
2227 }
2228# endif
2229 default:
2230 DEFAULT:
2231
2232 tex_handle_error(
2233 normal_error_type,
2234 "You can't use '%C' after \\the",
2235 cmd, chr,
2236 "I'm forgetting what you said and using zero instead."
2237 );
2238 cur_val = 0;
2239 cur_val_level = (level == token_val_level) ? integer_val_level : dimension_val_level;
2240 break;
2241 }
2242 tex_aux_downgrade_cur_val(level, succeeded, negative);
2243 return cur_val;
2244}
2245
2246void tex_scan_something_simple(halfword cmd, halfword chr)
2247{
2248 if (cmd >= min_internal_cmd && cmd <= max_internal_cmd) {
2249 tex_aux_scan_something_internal(cmd, chr, no_val_level, 0, 0);
2250 } else {
2251
2252
2253
2254
2255
2256
2257 cur_val = 0;
2258 cur_val_level = integer_val_level;
2259 }
2260}
2261
2262
2272
2273static inline halfword tex_aux_scan_limited_int(int optional_equal, int min, int max, const char *invalid)
2274{
2275 halfword v = tex_scan_integer(optional_equal, NULL, NULL);
2276 if (v < min || v > max) {
2277 tex_handle_error(
2278 normal_error_type,
2279 "%s (%i) should be in the range %i..%i",
2280 invalid, v, min, max,
2281 "I'm going to use 0 instead of that illegal code value."
2282 );
2283 return 0;
2284 } else {
2285 return v;
2286 }
2287}
2288
2289halfword tex_scan_integer_register_number (void) { return tex_aux_scan_limited_int(0, 0, max_integer_register_index, "Integer register index"); }
2290halfword tex_scan_dimension_register_number (void) { return tex_aux_scan_limited_int(0, 0, max_dimension_register_index, "Dimension register index"); }
2291halfword tex_scan_attribute_register_number (void) { return tex_aux_scan_limited_int(0, 0, max_attribute_register_index, "Attribute register index"); }
2292halfword tex_scan_posit_register_number (void) { return tex_aux_scan_limited_int(0, 0, max_posit_register_index, "Posit register index"); }
2293halfword tex_scan_glue_register_number (void) { return tex_aux_scan_limited_int(0, 0, max_glue_register_index, "Glue register index"); }
2294halfword tex_scan_muglue_register_number (void) { return tex_aux_scan_limited_int(0, 0, max_muglue_register_index, "Muglue register index"); }
2295halfword tex_scan_toks_register_number (void) { return tex_aux_scan_limited_int(0, 0, max_toks_register_index, "Toks register index"); }
2296halfword tex_scan_box_register_number (void) { return tex_aux_scan_limited_int(0, 0, max_box_register_index, "Box register index"); }
2297halfword tex_scan_unit_register_number (int optional_equal) { return tex_aux_scan_limited_int(optional_equal, 0, max_unit_register_index, "Unit register index"); }
2298halfword tex_scan_mark_number (void) { return tex_aux_scan_limited_int(0, 0, max_mark_index, "Marks index"); }
2299halfword tex_scan_char_number (int optional_equal) { return tex_aux_scan_limited_int(optional_equal, 0, max_character_code, "Character code"); }
2300halfword tex_scan_math_char_number (void) { return tex_aux_scan_limited_int(0, 0, max_math_character_code, "Character code"); }
2301halfword tex_scan_math_family_number (void) { return tex_aux_scan_limited_int(0, 0, max_math_family_index, "Math family"); }
2302halfword tex_scan_math_properties_number (void) { return tex_aux_scan_limited_int(0, 0, max_math_property, "Math properties"); }
2303halfword tex_scan_math_group_number (void) { return tex_aux_scan_limited_int(0, 0, max_math_group, "Math group"); }
2304halfword tex_scan_math_index_number (void) { return tex_aux_scan_limited_int(0, 0, max_math_index, "Math index"); }
2305halfword tex_scan_math_discretionary_number (int optional_equal) { return tex_aux_scan_limited_int(optional_equal, 0, max_math_discretionary, "Math discretionary"); }
2306singleword tex_scan_box_index (void) { return (singleword) tex_aux_scan_limited_int(0, 0, max_box_index, "Box index"); }
2307singleword tex_scan_box_axis (void) { return (singleword) tex_aux_scan_limited_int(0, 0, max_box_axis, "Box axis"); }
2308halfword tex_scan_category_code (int optional_equal) { return tex_aux_scan_limited_int(optional_equal, 0, max_category_code,"Category code"); }
2309halfword tex_scan_space_factor (int optional_equal) { return tex_aux_scan_limited_int(optional_equal, min_space_factor, max_space_factor, "Space factor"); }
2310halfword tex_scan_scale_factor (int optional_equal) { return tex_aux_scan_limited_int(optional_equal, min_scale_factor, max_scale_factor, "Scale factor"); }
2311halfword tex_scan_function_reference (int optional_equal) { return tex_aux_scan_limited_int(optional_equal, 0, max_function_reference, "Function reference"); }
2312halfword tex_scan_bytecode_reference (int optional_equal) { return tex_aux_scan_limited_int(optional_equal, 0, max_bytecode_index, "Bytecode reference"); }
2313halfword tex_scan_limited_scale (int optional_equal) { return tex_aux_scan_limited_int(optional_equal, -max_limited_scale, max_limited_scale, "Limited scale"); }
2314halfword tex_scan_positive_scale (int optional_equal) { return tex_aux_scan_limited_int(optional_equal, min_limited_scale, max_limited_scale, "Limited scale"); }
2315halfword tex_scan_positive_number (int optional_equal) { return tex_aux_scan_limited_int(optional_equal, 0, max_integer, "Positive number"); }
2316halfword tex_scan_parameter_index (void) { return tex_aux_scan_limited_int(0, 0, 15, "Parameter index"); }
2317halfword tex_scan_classification_code (int optional_equal) { return tex_aux_scan_limited_int(optional_equal, 0, max_classification_code,"Classification code"); }
2318
2319halfword tex_scan_math_class_number(int optional_equal)
2320{
2321 halfword v = tex_aux_scan_limited_int(optional_equal, -1, max_math_class_code + 1, "Math class");
2322 if (v >= 0 && v <= max_math_class_code) {
2323 return v;
2324 } else {
2325 return unset_noad_class;
2326 }
2327}
2328
2329
2345
2346
2359
2360static void tex_aux_scan_integer_no_number(int where)
2361{
2362
2363 if (lmt_error_state.intercept) {
2364 lmt_error_state.last_intercept = 1 ;
2365 if (cur_cmd != spacer_cmd) {
2366 tex_back_input(cur_tok);
2367 }
2368 } else {
2369 tex_aux_missing_number_error(where);
2370 }
2371}
2372
2373halfword tex_scan_integer(int optional_equal, int *radix, int *grouped)
2374{
2375 bool negative = false;
2376 long long result = 0;
2377 while (1) {
2378 tex_get_x_token();
2379 if (cur_cmd == spacer_cmd) {
2380 continue;
2381 } else if (cur_cmd == left_brace_cmd) {
2382 tex_aux_scan_integer_expression(1);
2383
2384 result = cur_val;
2385 if (grouped) {
2386 *grouped = 1;
2387 }
2388 goto THATSIT;
2389 } else if (cur_tok == equal_token) {
2390 if (optional_equal) {
2391 optional_equal = 0;
2392 continue;
2393 } else {
2394 break;
2395 }
2396 } else if (cur_tok == minus_token) {
2397 negative = ! negative;
2398 } else if (cur_tok != plus_token) {
2399 break;
2400 }
2401 };
2402 if (cur_tok == alpha_token) {
2403
2408 tex_get_token();
2409 if (cur_tok < cs_token_flag) {
2410 result = cur_chr;
2411 if (cur_cmd == right_brace_cmd) {
2412 ++lmt_input_state.align_state;
2413
2414 } else if (cur_cmd == left_brace_cmd || cur_cmd == relax_cmd) {
2415
2416 --lmt_input_state.align_state;
2417 }
2418 } else {
2419
2423 strnumber txt = cs_text(cur_tok - cs_token_flag);
2424 if (tex_single_letter(txt)) {
2425 result = aux_str2uni(str_string(txt));
2426 } else if (tex_is_active_cs(txt)) {
2427 result = active_cs_value(txt);
2428 } else {
2429 result = max_character_code + 1;
2430 }
2431 }
2432 if (result > max_character_code) {
2433 if (lmt_error_state.intercept) {
2434 lmt_error_state.last_intercept = 1;
2435 tex_back_input(cur_tok);
2436 } else {
2437 tex_aux_improper_constant_error();
2438 return 0;
2439 }
2440 } else {
2441
2442 tex_get_x_token();
2443 if (cur_cmd != spacer_cmd) {
2444 tex_back_input(cur_tok);
2445 }
2446 }
2447 } else if ((cur_cmd >= min_internal_cmd && cur_cmd <= max_internal_cmd) || cur_cmd == parameter_cmd) {
2448 result = tex_aux_scan_something_internal(cur_cmd, cur_chr, integer_val_level, 0, 0);
2449 if (cur_val_level != integer_val_level) {
2450 tex_aux_scan_integer_no_number(6);
2451 return 0;
2452 }
2453 } else {
2454
2455 bool vacuous = true;
2456 bool ok_so_far = true;
2457
2460 switch (cur_tok) {
2461 case octal_token:
2462 {
2463 if (radix) {
2464 *radix = 8;
2465 }
2466 while (1) {
2467 unsigned d = 0;
2468 tex_get_x_token();
2469 if ((cur_tok >= zero_token) && (cur_tok <= seven_token)) {
2470 d = cur_tok - zero_token;
2471 } else {
2472 goto DONE;
2473 }
2474 vacuous = false;
2475 if (ok_so_far) {
2476 result = result * 8 + d;
2477 if (result > max_integer) {
2478 result = max_integer;
2479 if (lmt_error_state.intercept) {
2480 vacuous = true;
2481 goto DONE;
2482 } else {
2483 tex_aux_scan_integer_out_of_range_error(1);
2484 }
2485 ok_so_far = 0;
2486 }
2487 }
2488 }
2489
2490 }
2491 case hex_token:
2492 {
2493 if (radix) {
2494 *radix = 16;
2495 }
2496 while (1) {
2497 unsigned d = 0;
2498 tex_get_x_token();
2499 if ((cur_tok >= zero_token) && (cur_tok <= nine_token)) {
2500 d = cur_tok - zero_token;
2501 } else if ((cur_tok >= A_token_l) && (cur_tok <= F_token_l)) {
2502 d = cur_tok - A_token_l + 10;
2503 } else if ((cur_tok >= A_token_o) && (cur_tok <= F_token_o)) {
2504 d = cur_tok - A_token_o + 10;
2505 } else {
2506 goto DONE;
2507 }
2508 vacuous = false;
2509 if (ok_so_far) {
2510 result = result * 16 + d;
2511 if (result > max_integer) {
2512 result = max_integer;
2513 if (lmt_error_state.intercept) {
2514 vacuous = true;
2515 goto DONE;
2516 } else {
2517 tex_aux_scan_integer_out_of_range_error(2);
2518 }
2519 ok_so_far = false;
2520 }
2521 }
2522 }
2523
2524 }
2525 default:
2526 if (radix) {
2527 *radix = 10;
2528 }
2529 while (1) {
2530 unsigned d = 0;
2531 if ((cur_tok >= zero_token) && (cur_tok <= nine_token)) {
2532 d = cur_tok - zero_token;
2533 } else {
2534 goto DONE;
2535 }
2536 vacuous = false;
2537 if (ok_so_far) {
2538 result = result * 10 + d;
2539 if (result > max_integer) {
2540 result = max_integer;
2541 if (lmt_error_state.intercept) {
2542 vacuous = true;
2543 goto DONE;
2544 } else {
2545 tex_aux_scan_integer_out_of_range_error(3);
2546 }
2547 ok_so_far = false;
2548 }
2549 }
2550 tex_get_x_token();
2551 }
2552
2553 }
2554 DONE:
2555 if (vacuous) {
2556 tex_aux_scan_integer_no_number(7);
2557 } else {
2558 tex_push_back(cur_tok, cur_cmd, cur_chr);
2559 }
2560 }
2561
2562 THATSIT:
2563 cur_val = (halfword) (negative ? - result : result);
2564 return cur_val;
2565}
2566
2567void tex_scan_integer_validate(void)
2568{
2569 while (1) {
2570 tex_get_x_token();
2571 if (cur_cmd == spacer_cmd || cur_tok == minus_token) {
2572 continue;
2573 } else if (cur_tok != plus_token) {
2574 break;
2575 }
2576 };
2577 if (cur_tok == alpha_token) {
2578 long long result = 0;
2579 tex_get_token();
2580 if (cur_tok < cs_token_flag) {
2581 result = cur_chr;
2582
2583 if (cur_cmd == right_brace_cmd) {
2584 ++lmt_input_state.align_state;
2585 } else if (cur_cmd == left_brace_cmd || cur_cmd == relax_cmd) {
2586 --lmt_input_state.align_state;
2587 }
2588 } else {
2589 strnumber txt = cs_text(cur_tok - cs_token_flag);
2590 if (tex_single_letter(txt)) {
2591 result = aux_str2uni(str_string(txt));
2592 } else if (tex_is_active_cs(txt)) {
2593 result = active_cs_value(txt);
2594 } else {
2595 result = max_character_code + 1;
2596 }
2597 }
2598 if (result > max_character_code) {
2599 if (lmt_error_state.intercept) {
2600 lmt_error_state.last_intercept = 1;
2601 tex_back_input(cur_tok);
2602 } else {
2603 tex_aux_improper_constant_error();
2604 }
2605 } else {
2606 tex_get_x_token();
2607 if (cur_cmd != spacer_cmd) {
2608 tex_back_input(cur_tok);
2609 }
2610 }
2611 } else if ((cur_cmd >= min_internal_cmd && cur_cmd <= max_internal_cmd) || cur_cmd == parameter_cmd) {
2612 tex_aux_scan_something_internal(cur_cmd, cur_chr, integer_val_level, 0, 0);
2613 if (cur_val_level != integer_val_level) {
2614 tex_aux_scan_integer_no_number(8);
2615 }
2616 } else {
2617 bool vacuous = true;
2618 switch (cur_tok) {
2619 case octal_token:
2620 while (1) {
2621 tex_get_x_token();
2622 if (! (cur_tok >= zero_token && cur_tok <= seven_token)) {
2623 goto DONE;
2624 }
2625 vacuous = false;
2626 }
2627 case hex_token:
2628 while (1) {
2629 tex_get_x_token();
2630 if (! ((cur_tok >= zero_token && cur_tok <= nine_token) ||
2631 (cur_tok >= A_token_l && cur_tok <= F_token_l ) ||
2632 (cur_tok >= A_token_o && cur_tok <= F_token_o ) )) {
2633 goto DONE;
2634 }
2635 vacuous = false;
2636 }
2637 default:
2638 while (1) {
2639 if (! (cur_tok >= zero_token && cur_tok <= nine_token)) {
2640 goto DONE;
2641 }
2642 vacuous = false;
2643 tex_get_x_token();
2644 }
2645 }
2646 DONE:
2647 if (vacuous) {
2648 tex_aux_scan_integer_no_number(9);
2649 } else {
2650 tex_push_back(cur_tok, cur_cmd, cur_chr);
2651 }
2652 }
2653}
2654
2655int tex_scan_cardinal(int optional_equal, unsigned *value, int dontbark)
2656{
2657 long long result = 0;
2658 while (1) {
2659 tex_get_x_token();
2660 if (cur_cmd != spacer_cmd) {
2661 if (optional_equal && (cur_tok == equal_token)) {
2662 optional_equal = 0;
2663 } else if (cur_cmd == left_brace_cmd) {
2664 tex_aux_scan_integer_expression(1);
2665
2666
2667 if (result < 0) {
2668
2669
2670
2671
2672
2673
2674 result = 0;
2675 cur_val = 0;
2676 return 0;
2677 } else {
2678 result = cur_val;
2679 }
2680 goto THATSIT;
2681 } else {
2682 break;
2683 }
2684 }
2685 }
2686 if (cur_cmd >= min_internal_cmd && cur_cmd <= max_internal_cmd) {
2687 result = tex_aux_scan_something_internal(cur_cmd, cur_chr, integer_val_level, 0, 0);
2688 } else {
2689 bool vacuous = true;
2690 switch (cur_tok) {
2691 case octal_token:
2692 {
2693 while (1) {
2694 unsigned d = 0;
2695 tex_get_x_token();
2696 if ((cur_tok >= zero_token) && (cur_tok <= seven_token)) {
2697 d = cur_tok - zero_token;
2698 } else {
2699 goto DONE;
2700 }
2701 vacuous = false;
2702 result = result * 8 + d;
2703 if (result > max_cardinal) {
2704 result = max_cardinal;
2705 }
2706 }
2707
2708 }
2709 case hex_token:
2710 {
2711 while (1) {
2712 unsigned d = 0;
2713 tex_get_x_token();
2714 if ((cur_tok >= zero_token) && (cur_tok <= nine_token)) {
2715 d = cur_tok - zero_token;
2716 } else if ((cur_tok >= A_token_l) && (cur_tok <= F_token_l)) {
2717 d = cur_tok - A_token_l + 10;
2718 } else if ((cur_tok >= A_token_o) && (cur_tok <= F_token_o)) {
2719 d = cur_tok - A_token_o + 10;
2720 } else {
2721 goto DONE;
2722 }
2723 vacuous = false;
2724 result = result * 16 + d;
2725 if (result > max_cardinal) {
2726 result = max_cardinal;
2727 }
2728 }
2729
2730 }
2731 default:
2732 {
2733 while (1) {
2734 unsigned d = 0;
2735 if ((cur_tok >= zero_token) && (cur_tok <= nine_token)) {
2736 d = cur_tok - zero_token;
2737 } else {
2738 goto DONE;
2739 }
2740 vacuous = false;
2741 result = result * 10 + d;
2742 if (result > max_cardinal) {
2743 result = max_cardinal;
2744 }
2745 tex_get_x_token();
2746 }
2747
2748 }
2749 }
2750 DONE:
2751 if (vacuous) {
2752 if (dontbark) {
2753 return 0;
2754 } else {
2755 tex_aux_missing_number_error(1);
2756 }
2757 } else {
2758 tex_push_back(cur_tok, cur_cmd, cur_chr);
2759 }
2760 }
2761 THATSIT:
2762 *value = (unsigned) result;
2763 cur_val = (halfword) result;
2764 return 1;
2765}
2766
2767
2773
2774static halfword tex_aux_coerced_glue(halfword value, halfword level)
2775{
2776 if (level == glue_val_level || level == muglue_val_level) {
2777 int v = glue_amount(value);
2778 tex_flush_node(value);
2779 return v;
2780 } else {
2781 return value;
2782 }
2783}
2784
2785
2820
2821static void tex_aux_scan_dimension_mu_error(void) {
2822 tex_handle_error(
2823 normal_error_type,
2824 "Illegal unit of measure (mu inserted)",
2825 "The unit of measurement in math glue must be mu." );
2826
2827}
2828
2829static void tex_aux_scan_dimension_fi_error(void) {
2830 tex_handle_error(
2831 normal_error_type,
2832 "Illegal unit of measure",
2833 "The unit of measurement can't be fi, fil, fill or filll here." );
2834
2835}
2836
2837
2843
2844static void tex_aux_scan_dimension_unknown_unit_error(void) {
2845 tex_handle_error(
2846 normal_error_type,
2847 "Illegal unit of measure (pt inserted)",
2848 "Dimensions can be in units of em, ex, sp, cm, mm, es, ts, pt, bp, dk, pc, dd\n"
2849 "cc or in; but yours is a new one! I'll assume that you meant to say pt, for\n"
2850 "printer's points: two letters. User units also have at most two characters."
2851 );
2852}
2853
2854static void tex_aux_scan_expression_unexpected_negation_error(void) {
2855 tex_handle_error(
2856 normal_error_type,
2857 "Unexpected minus, not or unequal symbol found at the start of an expression",
2858 "You can use {-{...}} but not -{...} in expressions because it would give\n"
2859 "unexpected results. I'll ignore this negation.\n"
2860 );
2861}
2862
2863# define set_conversion(A,B) do { num=(A); denom=(B); } while(0)
2864
2865
2874
2875typedef enum scanned_unit {
2876 no_unit_scanned,
2877 normal_unit_scanned,
2878 scaled_point_scanned,
2879 relative_unit_scanned,
2880 math_unit_scanned,
2881 flexible_unit_scanned,
2882 quantitity_unit_scanned,
2883} scanned_unit;
2884
2885
2914
2915
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3106
3107
3113
3114# define unit_hashes(a,b,c,d) \
3115 unit_parameter_hash(a,c): \
3116 case unit_parameter_hash(b,d): \
3117 case unit_parameter_hash(a,d): \
3118 case unit_parameter_hash(b,c)
3119
3120int tex_valid_userunit(halfword cmd, halfword chr, halfword cs)
3121{
3122 (void) cs;
3123 switch (cmd) {
3124 case call_cmd:
3125 case protected_call_cmd:
3126 case semi_protected_call_cmd:
3127 case constant_call_cmd:
3128 return chr && ! get_token_preamble(chr);
3129 case internal_dimension_cmd:
3130 case register_dimension_cmd:
3131 case dimension_cmd:
3132 case lua_value_cmd:
3133 return 1;
3134 default:
3135 return 0;
3136 }
3137}
3138
3139int tex_get_unit_class(halfword index)
3140{
3141 halfword class = unit_parameter(index);
3142 return class < 0 ? - class : class ? user_unit_class : unset_unit_class;
3143}
3144
3145int tex_get_userunit(halfword index, scaled *value)
3146{
3147 halfword cs = unit_parameter(index);
3148 if (cs > 0) {
3149 halfword cmd = eq_type(cs);
3150 halfword chr = eq_value(cs);
3151 switch (cmd) {
3152 case internal_dimension_cmd:
3153 case register_dimension_cmd:
3154 *value = eq_value(chr);
3155 return relative_unit_scanned;
3156 case dimension_cmd:
3157 *value = chr;
3158 return relative_unit_scanned;
3159 case call_cmd:
3160 case protected_call_cmd:
3161 case semi_protected_call_cmd:
3162 case constant_call_cmd:
3163 if (chr && ! get_token_preamble(chr)) {
3164 halfword list = token_link(chr);
3165
3166 tex_begin_associated_list(list);
3167 tex_aux_scan_expr(dimension_val_level, 0);
3168 if (cur_val_level == dimension_val_level) {
3169 *value = cur_val;
3170 return 1;
3171 }
3172
3173 }
3174
3175 *value = 0;
3176 return 1;
3177 case lua_value_cmd:
3178
3179 tex_aux_set_cur_val_by_lua_value_cmd(chr, index);
3180 if (cur_val_level == dimension_val_level) {
3181 *value = cur_val;
3182 return 1;
3183 }
3184 }
3185 }
3186
3187 *value = 0;
3188 return 0;
3189}
3190
3191void tex_initialize_units(void)
3192{
3193 unit_parameter(unit_parameter_hash('p','t')) = - tex_unit_class;
3194 unit_parameter(unit_parameter_hash('c','m')) = - tex_unit_class;
3195 unit_parameter(unit_parameter_hash('m','m')) = - tex_unit_class;
3196 unit_parameter(unit_parameter_hash('e','m')) = - tex_unit_class;
3197 unit_parameter(unit_parameter_hash('e','x')) = - tex_unit_class;
3198 unit_parameter(unit_parameter_hash('s','p')) = - tex_unit_class;
3199 unit_parameter(unit_parameter_hash('b','p')) = - tex_unit_class;
3200 unit_parameter(unit_parameter_hash('f','i')) = - tex_unit_class;
3201 unit_parameter(unit_parameter_hash('t','s')) = - luametatex_unit_class;
3202 unit_parameter(unit_parameter_hash('e','s')) = - luametatex_unit_class;
3203 unit_parameter(unit_parameter_hash('e','u')) = - luametatex_unit_class;
3204 unit_parameter(unit_parameter_hash('d','k')) = - luametatex_unit_class;
3205 unit_parameter(unit_parameter_hash('m','u')) = - tex_unit_class;
3206 unit_parameter(unit_parameter_hash('d','d')) = - tex_unit_class;
3207 unit_parameter(unit_parameter_hash('c','c')) = - tex_unit_class;
3208 unit_parameter(unit_parameter_hash('p','c')) = - tex_unit_class;
3209 unit_parameter(unit_parameter_hash('p','x')) = - pdftex_unit_class;
3210 unit_parameter(unit_parameter_hash('i','n')) = - tex_unit_class;
3211}
3212
3213static int tex_aux_scan_unit(halfword *num, halfword *denom, halfword *value, halfword *order)
3214{
3215
3216 do {
3217 tex_get_x_token();
3218 } while (cur_cmd == spacer_cmd);
3219 if (cur_cmd >= min_internal_cmd && cur_cmd <= max_internal_cmd) {
3220 return quantitity_unit_scanned;
3221 } else {
3222 int chrone, chrtwo, index;
3223 halfword tokone, toktwo;
3224 halfword save_cur_cs = cur_cs;
3225 tokone = cur_tok;
3226 if (cur_cmd == letter_cmd || cur_cmd == other_char_cmd) {
3227 chrone = cur_chr;
3228 } else {
3229 goto BACK_ONE;
3230 }
3231 tex_get_x_token();
3232 toktwo = cur_tok;
3233 if (cur_cmd == letter_cmd || cur_cmd == other_char_cmd) {
3234 chrtwo = cur_chr;
3235 } else {
3236 goto BACK_TWO;
3237 }
3238 cur_cs = save_cur_cs;
3239 index = unit_parameter_index(chrone, chrtwo);
3240 if (index >= 0) {
3241 switch (index) {
3242 case unit_hashes('p','P','t','T'):
3243 return normal_unit_scanned;
3244 case unit_hashes('c','C','m','M'):
3245 *num = 7227;
3246 *denom = 254;
3247 return normal_unit_scanned;
3248 case unit_hashes('m','M','m','M'):
3249 *num = 7227;
3250 *denom = 2540;
3251 return normal_unit_scanned;
3252 case unit_hashes('e','E','m','M'):
3253 *value = tex_get_scaled_em_width(cur_font_par);
3254 return relative_unit_scanned;
3255 case unit_hashes('e','E','x','X'):
3256 *value = tex_get_scaled_ex_height(cur_font_par);
3257 return relative_unit_scanned;
3258 case unit_hashes('s','S','p','P'):
3259 return scaled_point_scanned;
3260 case unit_hashes('b','B','p','P'):
3261 *num = 7227;
3262 *denom = 7200;
3263 return normal_unit_scanned;
3264 case unit_hashes('f','F','i','I'):
3265 if (order) {
3266 *order = fi_glue_order;
3267 if (tex_scan_character("lL", 0, 0, 0)) {
3268 *order = fil_glue_order;
3269 if (tex_scan_character("lL", 0, 0, 0)) {
3270 *order = fill_glue_order;
3271 if (tex_scan_character("lL", 0, 0, 0)) {
3272 *order = filll_glue_order;
3273 }
3274 }
3275 }
3276 return flexible_unit_scanned;
3277 }
3278 break;
3279 case unit_hashes('t','T','s','S'):
3280 *num = 4588;
3281 *denom = 645;
3282 return normal_unit_scanned;
3283 case unit_hashes('e','E','s','S'):
3284 *num = 9176;
3285 *denom = 129;
3286 return normal_unit_scanned;
3287 case unit_hashes('e','E','u','U'):
3288 *num = 9176 * eu_factor_par;
3289 *denom = 129 * 10;
3290 return normal_unit_scanned;
3291 case unit_hashes('d','D','k','K'):
3292 *num = 49838;
3293 *denom = 7739;
3294 return normal_unit_scanned;
3295 case unit_hashes('m','M','u','U'):
3296 if (order) {
3297 return math_unit_scanned;
3298 } else {
3299 break;
3300 }
3301 case unit_hashes('d','D','d','D'):
3302 *num = 1238;
3303 *denom = 1157;
3304 return normal_unit_scanned;
3305 case unit_hashes('c','C','c','C'):
3306 *num = 14856;
3307 *denom = 1157;
3308 return normal_unit_scanned;
3309 case unit_hashes('p','P','c','C'):
3310 *num = 12;
3311 *denom = 1;
3312 return normal_unit_scanned;
3313 case unit_hashes('p','P','x','X'):
3314 *value = px_dimension_par;
3315 return relative_unit_scanned;
3316 case unit_hashes('i','I','n','N'):
3317 *num = 7227;
3318 *denom = 100;
3319 return normal_unit_scanned;
3320 case unit_hashes('n','N','o','O'):
3321
3322 return scaled_point_scanned;
3323
3324
3325
3326
3327
3328
3329
3330
3331 default:
3332 if (tex_get_userunit(index, value)) {
3333 return relative_unit_scanned;
3334 }
3335 }
3336 }
3337 BACK_TWO:
3338 tex_back_input(toktwo);
3339 BACK_ONE:
3340 tex_back_input(tokone);
3341 cur_cs = save_cur_cs;
3342 return no_unit_scanned;
3343 }
3344}
3345
3346static int tex_aux_scan_unit_only(halfword *value)
3347{
3348 int chrone, chrtwo, index;
3349 halfword tokone, toktwo;
3350 halfword save_cur_cs = cur_cs;
3351 tokone = cur_tok;
3352 if (cur_cmd == letter_cmd || cur_cmd == other_char_cmd) {
3353 chrone = cur_chr;
3354 } else {
3355 goto BACK_ONE;
3356 }
3357 tex_get_x_token();
3358 toktwo = cur_tok;
3359 if (cur_cmd == letter_cmd || cur_cmd == other_char_cmd) {
3360 chrtwo = cur_chr;
3361 } else {
3362 goto BACK_TWO;
3363 }
3364 cur_cs = save_cur_cs;
3365 index = unit_parameter_index(chrone, chrtwo);
3366 if (index >= 0) {
3367 switch (index) {
3368 case unit_hashes('p','P','t','T'):
3369 return normal_unit_scanned;
3370 case unit_hashes('c','C','m','M'):
3371 *value = 1864679;
3372 return normal_unit_scanned;
3373 case unit_hashes('m','M','m','M'):
3374 *value = 186467;
3375 return normal_unit_scanned;
3376 case unit_hashes('e','E','m','M'):
3377 *value = tex_get_scaled_em_width(cur_font_par);
3378 return relative_unit_scanned;
3379 case unit_hashes('e','E','x','X'):
3380 *value = tex_get_scaled_ex_height(cur_font_par);
3381 return relative_unit_scanned;
3382 case unit_hashes('s','S','p','P'):
3383 *value = 1;
3384 return scaled_point_scanned;
3385 case unit_hashes('b','B','p','P'):
3386 *value = 65781;
3387 return normal_unit_scanned;
3388 case unit_hashes('t','T','s','S'):
3389 *value = 466169;
3390 return normal_unit_scanned;
3391 case unit_hashes('e','E','s','S'):
3392 *value = 4661692;
3393 return normal_unit_scanned;
3394 case unit_hashes('e','E','u','U'):
3395 *value = tex_round_xn_over_d(4661692, eu_factor_par, scaling_factor);
3396 return normal_unit_scanned;
3397 case unit_hashes('d','D','k','K'):
3398 *value = 422042;
3399 return normal_unit_scanned;
3400 case unit_hashes('d','D','d','D'):
3401 *value = 70124;
3402 return normal_unit_scanned;
3403 case unit_hashes('c','C','c','C'):
3404 *value = 841489;
3405 return normal_unit_scanned;
3406 case unit_hashes('p','P','c','C'):
3407 *value = 786432;
3408 return normal_unit_scanned;
3409 case unit_hashes('p','P','x','X'):
3410 *value = px_dimension_par;
3411 return relative_unit_scanned;
3412 case unit_hashes('i','I','n','N'):
3413 *value = 4736286;
3414 return normal_unit_scanned;
3415 case unit_hashes('n','N','o','O'):
3416
3417 *value = 1;
3418 return normal_unit_scanned;
3419 default:
3420 if (tex_get_userunit(index, value)) {
3421 return relative_unit_scanned;
3422 }
3423 }
3424 }
3425 BACK_TWO:
3426 tex_back_input(toktwo);
3427 BACK_ONE:
3428 tex_back_input(tokone);
3429 cur_cs = save_cur_cs;
3430 return no_unit_scanned;
3431}
3432
3433
3441
3442halfword tex_scan_dimension(int mu, int inf, int shortcut, int optional_equal, halfword *order, int *grouped)
3443{
3444 bool negative = false;
3445 int fraction = 0;
3446 int num = 0;
3447 int denom = 0;
3448 scaled v = 0;
3449 int save_cur_val;
3450 halfword cur_order = normal_glue_order;
3451 lmt_scanner_state.arithmic_error = 0;
3452 if (! shortcut) {
3453 while (1) {
3454 tex_get_x_token();
3455 if (cur_cmd == spacer_cmd) {
3456 continue;
3457 } else if (cur_cmd == left_brace_cmd) {
3458 tex_aux_scan_dimension_expression(1);
3459 if (grouped) {
3460 *grouped = 1;
3461 }
3462 goto THATSIT;
3463
3464 } else if (cur_tok == equal_token) {
3465 if (optional_equal) {
3466 optional_equal = 0;
3467 continue;
3468 } else {
3469 break;
3470 }
3471 } else if (cur_tok == minus_token) {
3472 negative = ! negative;
3473 } else if (cur_tok != plus_token) {
3474 break;
3475 }
3476 }
3477 if (cur_cmd >= min_internal_cmd && cur_cmd <= max_internal_cmd) {
3478 cur_val = tex_aux_scan_something_internal(cur_cmd, cur_chr, mu ? muglue_val_level : dimension_val_level, 0, 0);
3479 if (mu) {
3480 cur_val = tex_aux_coerced_glue(cur_val, cur_val_level);
3481 if (cur_val_level == muglue_val_level) {
3482 goto ATTACH_SIGN;
3483 } else if (cur_val_level != integer_val_level) {
3484 tex_aux_mu_error(2);
3485 }
3486 } else if (cur_val_level == dimension_val_level) {
3487 goto ATTACH_SIGN;
3488 } else if (cur_val_level == posit_val_level) {
3489 cur_val = tex_posit_to_dimension(cur_val);
3490 goto ATTACH_SIGN;
3491 }
3492 } else {
3493 int has_fraction = tex_token_is_separator(cur_tok);
3494 if (has_fraction) {
3495 cur_val = 0;
3496 } else {
3497 int cur_radix;
3498 tex_back_input(cur_tok);
3499 cur_val = tex_scan_integer(0, &cur_radix, NULL);
3500 if (cur_radix == 10 && tex_token_is_separator(cur_tok)) {
3501 has_fraction = 1;
3502 tex_get_token();
3503 }
3504 }
3505 if (has_fraction) {
3506 unsigned k = 0;
3507 unsigned char digits[18];
3508 while (1) {
3509 tex_get_x_token();
3510 if ((cur_tok > nine_token) || (cur_tok < zero_token)) {
3511 break;
3512 } else if (k < 17) {
3513 digits[k] = (unsigned char) (cur_tok - zero_token);
3514 ++k;
3515 }
3516 }
3517 fraction = tex_round_decimals_digits(digits, k);
3518 if (cur_cmd != spacer_cmd) {
3519 tex_back_input(cur_tok);
3520 }
3521 }
3522 }
3523 } else {
3524
3525 }
3526
3527 if (cur_val < 0) {
3528 negative = ! negative;
3529 cur_val = -cur_val;
3530 }
3531 save_cur_val = cur_val;
3532
3536 if (! lmt_error_state.last_intercept) {
3537 switch (tex_aux_scan_unit(&num, &denom, &v, &cur_order)) {
3538 case no_unit_scanned:
3539
3540 if (lmt_error_state.intercept) {
3541 lmt_error_state.last_intercept = 1;
3542 } else {
3543 tex_aux_scan_dimension_unknown_unit_error();
3544 }
3545 goto ATTACH_FRACTION;
3546 case normal_unit_scanned:
3547
3548 if (mu) {
3549 tex_aux_scan_dimension_unknown_unit_error();
3550 } else if (num) {
3551 int remainder = 0;
3552 cur_val = tex_xn_over_d_r(cur_val, num, denom, &remainder);
3553 fraction = (num * fraction + unity * remainder) / denom;
3554 cur_val += fraction / unity;
3555 fraction = fraction % unity;
3556 }
3557 goto ATTACH_FRACTION;
3558 case scaled_point_scanned:
3559
3560 if (mu) {
3561 tex_aux_scan_dimension_unknown_unit_error();
3562 }
3563 goto DONE;
3564 case relative_unit_scanned:
3565
3566 if (mu) {
3567 tex_aux_scan_dimension_unknown_unit_error();
3568 }
3569 cur_val = tex_nx_plus_y(save_cur_val, v, tex_xn_over_d(v, fraction, unity));
3570 goto DONE;
3571 case math_unit_scanned:
3572
3573 if (! mu) {
3574 tex_aux_scan_dimension_mu_error();
3575 }
3576 goto ATTACH_FRACTION;
3577 case flexible_unit_scanned:
3578
3579 if (mu) {
3580 tex_aux_scan_dimension_unknown_unit_error();
3581 } else if (! inf) {
3582 if (! order && lmt_error_state.intercept) {
3583 lmt_error_state.last_intercept = 1;
3584 } else {
3585 tex_aux_scan_dimension_fi_error();
3586 }
3587 }
3588 goto ATTACH_FRACTION;
3589 case quantitity_unit_scanned:
3590
3591 cur_val = tex_aux_scan_something_internal(cur_cmd, cur_chr, mu ? muglue_val_level : dimension_val_level, 0, 0);
3592 if (mu) {
3593 cur_val = tex_aux_coerced_glue(cur_val, cur_val_level);
3594 if (cur_val_level != muglue_val_level) {
3595 tex_aux_mu_error(3);
3596 }
3597 }
3598 v = cur_val;
3599 cur_val = tex_nx_plus_y(save_cur_val, v, tex_xn_over_d(v, fraction, unity));
3600 goto ATTACH_SIGN;
3601 }
3602 }
3603 ATTACH_FRACTION:
3604 if (cur_val >= 040000) {
3605 lmt_scanner_state.arithmic_error = 1;
3606 } else {
3607 cur_val = cur_val * unity + fraction;
3608 }
3609 DONE:
3610 tex_get_x_token();
3611 tex_push_back(cur_tok, cur_cmd, cur_chr);
3612 ATTACH_SIGN:
3613 if (lmt_scanner_state.arithmic_error || (abs(cur_val) >= 010000000000)) {
3614 if (lmt_error_state.intercept) {
3615 lmt_error_state.last_intercept = 1;
3616 } else {
3617 tex_aux_scan_dimension_out_of_range_error(1);
3618 }
3619 cur_val = max_dimension;
3620 lmt_scanner_state.arithmic_error = 0;
3621 }
3622 THATSIT:
3623 if (order) {
3624 *order = cur_order;
3625 }
3626 if (negative) {
3627 cur_val = -cur_val;
3628 }
3629 return cur_val;
3630}
3631
3632void tex_scan_dimension_validate(void)
3633{
3634 lmt_scanner_state.arithmic_error = 0;
3635 while (1) {
3636 tex_get_x_token();
3637 if (cur_cmd == spacer_cmd || cur_tok == minus_token) {
3638 continue;
3639 } else if (cur_tok != plus_token) {
3640 break;
3641 }
3642 }
3643 if (cur_cmd >= min_internal_cmd && cur_cmd <= max_internal_cmd) {
3644 tex_aux_scan_something_internal(cur_cmd, cur_chr, dimension_val_level, 0, 0);
3645 if (cur_val_level == dimension_val_level || cur_val_level == posit_val_level) {
3646 return;
3647 }
3648 } else {
3649 int has_fraction = tex_token_is_separator(cur_tok);
3650 if (! has_fraction) {
3651 int cur_radix;
3652 tex_back_input(cur_tok);
3653 tex_scan_integer(0, &cur_radix, NULL);
3654 if (cur_radix == 10 && tex_token_is_separator(cur_tok)) {
3655 has_fraction = 1;
3656 tex_get_token();
3657 }
3658 }
3659 if (has_fraction) {
3660 while (1) {
3661 tex_get_x_token();
3662 if (cur_tok > nine_token || cur_tok < zero_token) {
3663 break;
3664 }
3665 }
3666 if (cur_cmd != spacer_cmd) {
3667 tex_back_input(cur_tok);
3668 }
3669 }
3670 }
3671 {
3672 int num = 0;
3673 int denom = 0;
3674 scaled value;
3675 switch (tex_aux_scan_unit(&num, &denom, &value, NULL)) {
3676 case no_unit_scanned:
3677 case flexible_unit_scanned:
3678 lmt_error_state.last_intercept = 1;
3679 break;
3680 case normal_unit_scanned:
3681 case scaled_point_scanned:
3682 case relative_unit_scanned:
3683 case math_unit_scanned:
3684 break;
3685 case quantitity_unit_scanned:
3686 tex_aux_scan_something_internal(cur_cmd, cur_chr, dimension_val_level, 0, 0);
3687 return;
3688 }
3689 }
3690 tex_get_x_token();
3691 tex_push_back(cur_tok, cur_cmd, cur_chr);
3692}
3693
3694
3705
3706
3707
3708halfword tex_scan_glue(int level, int optional_equal, int options_too)
3709{
3710
3711 bool negative = false;
3712
3713 halfword q = null;
3714
3715 int mu = level == muglue_val_level;
3716
3717 do {
3718
3719 while (1) {
3720 tex_get_x_token();
3721 if (cur_cmd != spacer_cmd) {
3722 if (optional_equal && (cur_tok == equal_token)) {
3723 optional_equal = 0;
3724 } else if (cur_cmd == left_brace_cmd) {
3725
3726 tex_aux_scan_expr(level, 1);
3727 cur_val_level = level;
3728 return cur_val;
3729 } else {
3730 break;
3731 }
3732 }
3733 }
3734 if (cur_tok == minus_token) {
3735 negative = ! negative;
3736 cur_tok = plus_token;
3737 }
3738 } while (cur_tok == plus_token);
3739 if (cur_cmd >= min_internal_cmd && cur_cmd <= max_internal_cmd) {
3740 cur_val = tex_aux_scan_something_internal(cur_cmd, cur_chr, level, negative, 0);
3741 if (cur_val_level >= glue_val_level) {
3742 if (cur_val_level != level) {
3743 tex_aux_mu_error(4);
3744 }
3745 return cur_val;
3746 }
3747 if (cur_val_level == integer_val_level) {
3748 cur_val = tex_scan_dimension(mu, 0, 1, 0, NULL, NULL);
3749
3754
3755
3756 } else if (level == muglue_val_level) {
3757 tex_aux_mu_error(5);
3758 }
3759 } else {
3760 tex_back_input(cur_tok);
3761 cur_val = tex_scan_dimension(mu, 0, 0, 0, NULL, NULL);
3762 if (negative) {
3763 cur_val = -cur_val;
3764 }
3765 }
3766
3770 q = tex_new_glue_spec_node(zero_glue);
3771 glue_amount(q) = cur_val;
3772 while (1) {
3773 switch (tex_scan_character("pmlPML", 0, 1, 0)) {
3774 case 0:
3775 return q;
3776 case 'p': case 'P':
3777 if (tex_scan_mandate_keyword("plus", 1)) {
3778 halfword order = normal_glue_order;
3779 glue_stretch(q) = tex_scan_dimension(mu, 1, 0, 0, &order, NULL);
3780 glue_stretch_order(q) = order;
3781 }
3782 break;
3783 case 'm': case 'M':
3784 if (tex_scan_mandate_keyword("minus", 1)) {
3785 halfword order = normal_glue_order;
3786 glue_shrink(q) = tex_scan_dimension(mu, 1, 0, 0, &order, NULL);
3787 glue_shrink_order(q) = order;
3788 }
3789 break;
3790 case 'l': case 'L':
3791 if (options_too && tex_scan_mandate_keyword("limit", 1)) {
3792 glue_options(q) |= glue_option_limit;
3793 break;
3794 } else {
3795
3796 }
3797 default:
3798 tex_aux_show_keyword_error(options_too ? "plus|minus|limit" : "plus|minus");
3799 return q;
3800 }
3801 }
3802}
3803
3804
3817
3818halfword tex_scan_font(int optional_equal)
3819{
3820 halfword fv = null;
3821 halfword id, fs;
3822 if (optional_equal) {
3823 tex_scan_optional_equals();
3824 }
3825 id = tex_scan_font_identifier(&fv);
3826 if (fv) {
3827 fs = tex_copy_node(fv);
3828 } else {
3829
3830 fs = tex_new_node(font_spec_node, normal_code);
3831 font_spec_identifier(fs) = id;
3832 font_spec_scale(fs) = unused_scale_value;
3833 font_spec_x_scale(fs) = unused_scale_value;
3834 font_spec_y_scale(fs) = unused_scale_value;
3835 font_spec_slant(fs) = 0;
3836 font_spec_weight(fs) = 0;
3837 }
3838 while (1) {
3839 switch (tex_scan_character("asxywoASXYWO", 0, 1, 0)) {
3840 case 0:
3841 return fs;
3842 case 'a': case 'A':
3843 if (tex_scan_mandate_keyword("all", 1)) {
3844 font_spec_scale(fs) = tex_scan_scale_factor(0);
3845 font_spec_x_scale(fs) = tex_scan_scale_factor(0);
3846 font_spec_y_scale(fs) = tex_scan_scale_factor(0);
3847 font_spec_slant(fs) = tex_scan_scale_factor(0);
3848 font_spec_weight(fs) = tex_scan_scale_factor(0);
3849 font_spec_state(fs) |= font_spec_all_set;
3850 }
3851 break;
3852 case 's': case 'S':
3853 switch (tex_scan_character("clCL", 0, 1, 0)) {
3854 case 'c': case 'C':
3855 if (tex_scan_mandate_keyword("scale", 2)) {
3856 font_spec_scale(fs) = tex_scan_scale_factor(0);
3857 font_spec_state(fs) |= font_spec_scale_set;
3858 }
3859 break;
3860 case 'l': case 'L':
3861 if (tex_scan_mandate_keyword("slant", 2)) {
3862 font_spec_slant(fs) = tex_scan_scale_factor(0);
3863 font_spec_state(fs) |= font_spec_slant_set;
3864 }
3865 break;
3866 default:
3867 tex_aux_show_keyword_error("scale|slant");
3868 return fs;
3869 }
3870 break;
3871 case 'x': case 'X':
3872 if (tex_scan_mandate_keyword("xscale", 1)) {
3873 font_spec_x_scale(fs) = tex_scan_scale_factor(0);
3874 font_spec_state(fs) |= font_spec_x_scale_set;
3875 }
3876 break;
3877 case 'y': case 'Y':
3878 if (tex_scan_mandate_keyword("yscale", 1)) {
3879 font_spec_y_scale(fs) = tex_scan_scale_factor(0);
3880 font_spec_state(fs) |= font_spec_y_scale_set;
3881 }
3882 break;
3883 case 'w': case 'W':
3884 if (tex_scan_mandate_keyword("weight", 1)) {
3885 font_spec_weight(fs) = tex_scan_scale_factor(0);
3886 font_spec_state(fs) |= font_spec_weight_set;
3887 }
3888 break;
3889 case 'o': case 'O':
3890 if (tex_scan_mandate_keyword("oblique", 1)) {
3891 font_spec_slant(fs) = tex_scan_scale_factor(0);
3892 font_spec_state(fs) |= font_spec_slant_set;
3893 }
3894 break;
3895 default:
3896 return fs;
3897 }
3898 }
3899}
3900
3901
3910
3911# define push_selector { \
3912 saved_selector = lmt_print_state.selector; \
3913 lmt_print_state.selector = new_string_selector_code; \
3914}
3915
3916# define pop_selector { \
3917 lmt_print_state.selector = saved_selector; \
3918}
3919
3920halfword tex_the_value_toks(int code, halfword *tail, halfword property)
3921{
3922 tex_get_x_token();
3923 cur_val = tex_aux_scan_something_internal(cur_cmd, cur_chr, token_val_level, 0, property);
3924 switch (cur_val_level) {
3925 case integer_val_level:
3926 case attribute_val_level:
3927 {
3928 int saved_selector;
3929 push_selector;
3930 tex_print_int(cur_val);
3931 pop_selector;
3932 return tex_cur_str_toks(tail);
3933 }
3934 case posit_val_level:
3935 {
3936 int saved_selector;
3937 push_selector;
3938 tex_print_posit(cur_val);
3939 pop_selector;
3940 return tex_cur_str_toks(tail);
3941 }
3942 case dimension_val_level:
3943 {
3944 int saved_selector;
3945 push_selector;
3946 tex_print_dimension(cur_val, code == the_without_unit_code ? no_unit : pt_unit);
3947 pop_selector;
3948 return tex_cur_str_toks(tail);
3949 }
3950 case glue_val_level:
3951 case muglue_val_level:
3952 {
3953 int saved_selector;
3954 push_selector;
3955 tex_print_spec(cur_val, (code != the_without_unit_code) ? (cur_val_level == glue_val_level ? pt_unit : mu_unit) : no_unit);
3956 tex_flush_node(cur_val);
3957 pop_selector;
3958 return tex_cur_str_toks(tail);
3959 }
3960 case token_val_level:
3961 {
3962
3963 halfword h = null;
3964 halfword p = null;
3965 if (cur_val) {
3966
3967 halfword r = token_link(cur_val);
3968 while (r) {
3969 p = tex_store_new_token(p, token_info(r));
3970 if (! h) {
3971 h = p;
3972 }
3973 r = token_link(r);
3974 }
3975 }
3976 if (tail) {
3977 *tail = p;
3978 }
3979 return h;
3980 }
3981 case font_val_level:
3982 {
3983 int saved_selector;
3984 push_selector;
3985 tex_print_font_identifier(cur_val);
3986 pop_selector;
3987 return tex_cur_str_toks(tail);
3988 }
3989 case mathspec_val_level:
3990 {
3991
3992 if (cur_val) {
3993 int saved_selector;
3994 push_selector;
3995 tex_print_mathspec(cur_val);
3996 pop_selector;
3997 return tex_cur_str_toks(tail);
3998 } else {
3999 return null;
4000 }
4001 }
4002 case fontspec_val_level:
4003 {
4004
4005 if (cur_val) {
4006 int saved_selector;
4007 push_selector;
4008 tex_print_font_specifier(cur_val);
4009 pop_selector;
4010 return tex_cur_str_toks(tail);
4011 } else {
4012 return null;
4013 }
4014 }
4015 case list_val_level:
4016 {
4017 if (cur_val) {
4018
4019 halfword copy = tex_copy_node(cur_val);
4020 tex_tail_append(copy);
4021 cur_val = null;
4022 }
4023 break;
4024 }
4025 }
4026 return null;
4027}
4028
4029void tex_detokenize_list(halfword head)
4030{
4031 int saved_selector;
4032 push_selector;
4033 tex_show_token_list(head, 0, 0);
4034 pop_selector;
4035}
4036
4037halfword tex_the_detokenized_toks(halfword *tail, int expand, int protect)
4038{
4039 halfword head = expand ? tex_scan_toks_expand(0, tail, 1, protect) : tex_scan_general_text(tail);
4040 if (head) {
4041 halfword first = expand ? token_link(head) : head;
4042 if (first) {
4043 int saved_selector;
4044 push_selector;
4045 tex_show_token_list(first, 0, protect);
4046 pop_selector;
4047 tex_flush_token_list(head);
4048 return tex_cur_str_toks(tail);
4049 }
4050 }
4051 return null;
4052}
4053
4054
4061
4062halfword tex_the_toks(int code, halfword *tail)
4063{
4064 switch (code) {
4065 case the_code:
4066 case the_without_unit_code:
4067 return tex_the_value_toks(code, tail, 0);
4068
4069
4070 case unexpanded_code:
4071 return tex_scan_general_text(tail);
4072 case detokenize_code:
4073 case expanded_detokenize_code:
4074 case protected_detokenize_code:
4075 case protected_expanded_detokenize_code:
4076 return tex_the_detokenized_toks(tail,
4077 code == expanded_detokenize_code || code == protected_expanded_detokenize_code,
4078 code == protected_detokenize_code || code == protected_expanded_detokenize_code
4079 );
4080 default:
4081 return null;
4082 }
4083}
4084
4085strnumber tex_the_scanned_result(void)
4086{
4087
4088 strnumber r;
4089
4090 int saved_selector;
4091 push_selector;
4092 switch (cur_val_level) {
4093 case integer_val_level:
4094 case attribute_val_level:
4095 tex_print_int(cur_val);
4096 break;
4097 case posit_val_level:
4098 tex_print_posit(cur_val);
4099 break;
4100 case dimension_val_level:
4101 tex_print_dimension(cur_val, pt_unit);
4102 break;
4103 case glue_val_level:
4104 tex_print_spec(cur_val, pt_unit);
4105 tex_flush_node(cur_val);
4106 break;
4107 case muglue_val_level:
4108 tex_print_spec(cur_val, mu_unit);
4109 tex_flush_node(cur_val);
4110 break;
4111 case token_val_level:
4112 if (cur_val) {
4113 tex_token_show(cur_val);
4114 break;
4115 } else {
4116 r = get_nullstr();
4117 goto DONE;
4118 }
4119
4130 default:
4131 r = get_nullstr();
4132 goto DONE;
4133 }
4134 r = tex_make_string();
4135 DONE:
4136 pop_selector;
4137 return r;
4138}
4139
4140
4147
4148static halfword tex_aux_scan_font_id_and_parameter(halfword *fnt, halfword *n)
4149{
4150 *n = tex_scan_integer(0, NULL, NULL);
4151 *fnt = tex_scan_font_identifier(NULL);
4152 if (*n <= 0 || *n > max_integer) {
4153 tex_handle_error(
4154 normal_error_type,
4155 "Font '%s' has at most %i fontdimen parameters",
4156 font_original(*fnt), font_parameter_count(*fnt),
4157 "The font parameter index is out of range."
4158 );
4159 return 0;
4160 } else {
4161 return 1;
4162 }
4163}
4164
4165void tex_set_font_dimension(void)
4166{
4167 halfword fnt, n;
4168 if (tex_aux_scan_font_id_and_parameter(&fnt, &n)) {
4169 tex_set_font_parameter(fnt, n, tex_scan_dimension(0, 0, 0, 1, NULL, NULL));
4170 }
4171}
4172
4173halfword tex_get_font_dimension(void)
4174{
4175 halfword fnt, n;
4176 return tex_aux_scan_font_id_and_parameter(&fnt, &n) ? tex_get_font_parameter(fnt, n) : null;
4177}
4178
4179void tex_set_scaled_font_dimension(void)
4180{
4181 halfword fnt, n;
4182 if (tex_aux_scan_font_id_and_parameter(&fnt, &n)) {
4183 tex_set_scaled_parameter(fnt, n, tex_scan_dimension(0, 0, 0, 1, NULL, NULL));
4184 }
4185}
4186
4187halfword tex_get_scaled_font_dimension(void)
4188{
4189 halfword fnt, n;
4190 return tex_aux_scan_font_id_and_parameter(&fnt, &n) ? tex_get_scaled_parameter(fnt, n) : null;
4191}
4192
4193
4194
4195halfword tex_scan_math_style_identifier(int tolerant, int styles)
4196{
4197 halfword style = tex_scan_integer(0, NULL, NULL);
4198 if (is_valid_math_style(style)) {
4199 return style;
4200 } else if (styles && are_valid_math_styles(style)) {
4201 return style;
4202 } else if (tolerant) {
4203 return -1;
4204 } else {
4205 tex_handle_error(
4206 back_error_type,
4207 "Missing math style, treated as \\displaystyle",
4208 "A style should have been here; I inserted '\\displaystyle'."
4209 );
4210 return display_style;
4211 }
4212}
4213
4214halfword tex_scan_math_parameter(void)
4215{
4216 do {
4217 tex_get_x_token();
4218 } while (cur_cmd == spacer_cmd);
4219 if (cur_cmd == math_parameter_cmd && cur_chr < math_parameter_last) {
4220 return cur_chr;
4221 } else {
4222 tex_handle_error(
4223 normal_error_type,
4224 "Invalid math parameter",
4225 "I'm going to ignore this one."
4226 );
4227 return -1;
4228 }
4229}
4230
4231halfword tex_scan_fontspec_identifier(void)
4232{
4233
4234 do {
4235 tex_get_x_token();
4236 } while (cur_cmd == spacer_cmd);
4237 if (cur_cmd == fontspec_cmd) {
4238 return cur_chr;
4239 } else {
4240 return 0;
4241 }
4242}
4243
4244halfword tex_scan_font_identifier(halfword *spec)
4245{
4246
4247 do {
4248 tex_get_x_token();
4249 } while (cur_cmd == spacer_cmd);
4250 switch (cur_cmd) {
4251 case define_font_cmd:
4252 return cur_font_par;
4253 case set_font_cmd:
4254 return cur_chr;
4255 case fontspec_cmd:
4256 {
4257 halfword fnt = tex_get_font_identifier(cur_chr);
4258 if (fnt && spec) {
4259 *spec = fnt ? cur_chr : null;
4260 }
4261 return fnt;
4262 }
4263 case define_family_cmd:
4264 {
4265 halfword siz = cur_chr;
4266 halfword fam = tex_scan_math_family_number();
4267 halfword fnt = tex_fam_fnt(fam, siz);
4268 return fnt;
4269 }
4270 case register_integer_cmd:
4271 {
4272
4273 halfword fnt = register_integer_number(cur_chr);
4274 if (tex_is_valid_font(fnt)) {
4275 return fnt;
4276 } else {
4277 break;
4278 }
4279 }
4280 case integer_cmd:
4281 {
4282
4283 halfword fnt = cur_chr;
4284 if (tex_is_valid_font(fnt)) {
4285 return fnt;
4286 } else {
4287 break;
4288 }
4289 }
4290 case internal_integer_cmd:
4291 {
4292
4293 if (internal_integer_number(cur_chr) == font_code) {
4294 halfword fnt = tex_scan_integer(0, NULL, NULL);
4295 if (tex_is_valid_font(fnt)) {
4296 return fnt;
4297 }
4298 }
4299 break;
4300 }
4301 default:
4302 {
4303
4304 unsigned fnt = null_font;
4305 tex_back_input(cur_tok);
4306 if (tex_scan_cardinal(0, &fnt, 1)) {
4307 if (tex_is_valid_font((halfword) fnt)) {
4308 return (halfword) fnt;
4309 }
4310 }
4311 break;
4312 }
4313 }
4314 tex_handle_error(
4315 back_error_type,
4316 "Missing or invalid font identifier (or equivalent) or integer (register or otherwise)",
4317 "I was looking for a control sequence whose current meaning has been defined by\n"
4318 "\\font or a valid font id number."
4319 );
4320 return null_font;
4321}
4322
4323
4332
4333halfword tex_scan_general_text(halfword *tail)
4334{
4335
4336 halfword p = get_reference_token();
4337 halfword head;
4338
4339 halfword unbalance = 0;
4340 halfword saved_scanner_status = lmt_input_state.scanner_status;
4341 halfword saved_warning_index = lmt_input_state.warning_index;
4342 halfword saved_def_ref = lmt_input_state.def_ref;
4343 lmt_input_state.scanner_status = scanner_is_absorbing;
4344 lmt_input_state.warning_index = cur_cs;
4345 lmt_input_state.def_ref = p;
4346
4347 tex_scan_left_brace();
4348 while (1) {
4349 tex_get_token();
4350 if (! cur_cs) {
4351 switch (cur_cmd) {
4352 case left_brace_cmd:
4353 if (! cur_cs) {
4354 ++unbalance;
4355 }
4356 break;
4357 case right_brace_cmd:
4358 if (unbalance) {
4359 --unbalance;
4360 break;
4361 } else {
4362 goto DONE;
4363 }
4364 }
4365 }
4366 p = tex_store_new_token(p, cur_tok);
4367 }
4368 DONE:
4369 head = token_link(lmt_input_state.def_ref);
4370 if (tail) {
4371 *tail = head ? p : null;
4372 }
4373
4374 tex_put_available_token(lmt_input_state.def_ref);
4375 lmt_input_state.scanner_status = saved_scanner_status;
4376 lmt_input_state.warning_index = saved_warning_index;
4377 lmt_input_state.def_ref = saved_def_ref;
4378 return head;
4379}
4380
4381
4418
4419static inline bool tex_parameter_escape_mode(void)
4420{
4421 return (parameter_mode_par & parameter_escape_mode) == parameter_escape_mode;
4422}
4423
4424halfword tex_scan_toks_normal(int left_brace_found, halfword *tail)
4425{
4426 halfword unbalance = 0;
4427 halfword result = get_reference_token();
4428 halfword p = result;
4429 lmt_input_state.scanner_status = scanner_is_absorbing;
4430 lmt_input_state.warning_index = cur_cs;
4431 lmt_input_state.def_ref = result;
4432 if (! left_brace_found) {
4433 tex_scan_left_brace();
4434 }
4435 while (1) {
4436 tex_get_token();
4437 switch (cur_cmd) {
4438 case left_brace_cmd:
4439 if (! cur_cs) {
4440 ++unbalance;
4441 }
4442 break;
4443 case right_brace_cmd:
4444 if (! cur_cs) {
4445 if (unbalance) {
4446 --unbalance;
4447 } else {
4448 goto DONE;
4449 }
4450 }
4451 break;
4452 case prefix_cmd:
4453 if (cur_chr == enforced_code && (! overload_mode_par || lmt_main_state.run_state != production_state)) {
4454 cur_tok = token_val(prefix_cmd, always_code);
4455 }
4456 break;
4457 }
4458 p = tex_store_new_token(p, cur_tok);
4459 }
4460 DONE:
4461 lmt_input_state.scanner_status = scanner_is_normal;
4462 if (tail) {
4463 *tail = p;
4464 }
4465 return result;
4466}
4467
4468halfword tex_scan_toks_expand(int left_brace_found, halfword *tail, int expandconstant, int keepparameters)
4469{
4470 halfword unbalance = 0;
4471 halfword result = get_reference_token();
4472 halfword p = result;
4473 lmt_input_state.scanner_status = scanner_is_absorbing;
4474 lmt_input_state.warning_index = cur_cs;
4475 lmt_input_state.def_ref = result;
4476 if (! left_brace_found) {
4477 tex_scan_left_brace();
4478 }
4479 while (1) {
4480 PICKUP:
4481 tex_get_next();
4482 switch (cur_cmd) {
4483 case call_cmd:
4484 case tolerant_call_cmd:
4485 tex_expand_current_token();
4486 goto PICKUP;
4487 case constant_call_cmd:
4488 {
4489 halfword h = token_link(cur_chr);
4490 while (h) {
4491 p = tex_store_new_token(p, token_info(h));
4492 h = token_link(h);
4493 }
4494 goto PICKUP;
4495 }
4496 case protected_call_cmd:
4497 case tolerant_protected_call_cmd:
4498 cur_tok = cs_token_flag + cur_cs;
4499 goto APPENDTOKEN;
4500 case semi_protected_call_cmd:
4501 case tolerant_semi_protected_call_cmd:
4502 if (expandconstant) {
4503 tex_expand_current_token();
4504 goto PICKUP;
4505 } else {
4506 cur_tok = cs_token_flag + cur_cs;
4507 goto APPENDTOKEN;
4508 }
4509 case the_cmd:
4510 {
4511 halfword t = null;
4512 halfword h = tex_the_toks(cur_chr, &t);
4513 if (h) {
4514 set_token_link(p, h);
4515 p = t;
4516 }
4517 goto PICKUP;
4518 }
4519 case parameter_cmd:
4520 {
4521
4522 halfword tok1, tok2;
4523 tex_x_token();
4524 tok1 = cur_tok;
4525 tex_get_next();
4526 tex_x_token();
4527 tok2 = cur_tok;
4528 if (keepparameters || ! tex_parameter_escape_mode()) {
4529
4530 } else {
4531 halfword t;
4532 halfword h = tex_expand_parameter(tok2, &t);
4533 if (h) {
4534 set_token_link(p, h);
4535 p = t;
4536 goto PICKUP;
4537 } else {
4538 tex_flush_token_list(h);
4539 }
4540 }
4541 p = tex_store_new_token(p, tok1);
4542 p = tex_store_new_token(p, tok2);
4543 goto PICKUP;
4544 }
4545 case prefix_cmd:
4546 if (cur_chr == enforced_code && (! overload_mode_par || lmt_main_state.run_state != production_state)) {
4547 cur_tok = token_val(prefix_cmd, always_code);
4548 goto APPENDTOKEN;
4549 }
4550 default:
4551 if (cur_cmd > max_command_cmd) {
4552 tex_expand_current_token();
4553 goto PICKUP;
4554 } else {
4555 goto DONEEXPANDING;
4556 }
4557 }
4558 DONEEXPANDING:
4559 tex_x_token();
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569 if (! cur_cs) {
4570 switch (cur_cmd) {
4571 case left_brace_cmd:
4572 ++unbalance;
4573 break;
4574 case right_brace_cmd:
4575 if (unbalance) {
4576 --unbalance;
4577 } else {
4578 goto FINALYDONE;
4579 }
4580 break;
4581 }
4582 }
4583 APPENDTOKEN:
4584 p = tex_store_new_token(p, cur_tok);
4585 }
4586 FINALYDONE:
4587 lmt_input_state.scanner_status = scanner_is_normal;
4588 if (tail) {
4589 *tail = p;
4590 }
4591 return result;
4592}
4593
4594static void tex_aux_too_many_parameters_error(void)
4595{
4596 tex_handle_error(
4597 normal_error_type,
4598 "You already have 15 parameters",
4599 "I'm going to ignore the # sign you just used, as well the token that followed it.\n"
4600
4601 );
4602}
4603
4604static void tex_aux_parameters_order_error(void)
4605{
4606 tex_handle_error(
4607 back_error_type,
4608 "Parameters must be numbered consecutively",
4609 "I've inserted the digit you should have used after the #."
4610 );
4611}
4612
4613static void tex_aux_missing_brace_error(void)
4614{
4615 tex_handle_error(
4616 normal_error_type,
4617 "Missing { inserted",
4618 "Where was the left brace? You said something like '\\def\\a}', which I'm going to\n"
4619 "interpret as '\\def\\a{}'."
4620 );
4621}
4622
4623static void tex_aux_illegal_parameter_in_body_error(void)
4624{
4625 tex_handle_error(
4626 back_error_type,
4627 "Illegal parameter number in definition of %S",
4628 lmt_input_state.warning_index,
4629 "You meant to type ## instead of #, right? Or maybe a } was forgotten somewhere\n"
4630 "earlier, and things are all screwed up? I'm going to assume that you meant ##."
4631 );
4632}
4633
4634
4654
4655
4656
4657static int tex_aux_valid_macro_preamble(halfword *p, int *counter, halfword *hash_brace)
4658{
4659 halfword h = *p;
4660 while (1) {
4661 tex_get_token();
4662 switch (cur_cmd) {
4663 case left_brace_cmd:
4664 case right_brace_cmd:
4665 if (cur_cs) {
4666 break;
4667 } else {
4668 goto DONE;
4669 }
4670 case parameter_cmd:
4671 tex_get_token();
4672
4682 if (cur_tok < left_brace_limit) {
4683
4684
4685 *hash_brace = cur_tok;
4686 *p = tex_store_new_token(*p, cur_tok);
4687 *p = tex_store_new_token(*p, end_match_token);
4688 set_token_preamble(h, macro_with_preamble);
4689 set_token_parameters(h, *counter);
4690 return 1;
4691 } else if (*counter == 0xF) {
4692 tex_aux_too_many_parameters_error();
4693 } else {
4694 switch (cur_tok) {
4695 case zero_token:
4696 ++*counter;
4697 cur_tok = match_token;
4698 break;
4699 case asterisk_token:
4700 cur_tok = spacer_match_token;
4701 break;
4702 case plus_token:
4703 ++*counter;
4704 cur_tok = keep_match_token;
4705 break;
4706 case minus_token:
4707 cur_tok = thrash_match_token;
4708 break;
4709 case period_token:
4710 cur_tok = par_spacer_match_token;
4711 break;
4712 case comma_token:
4713 cur_tok = keep_spacer_match_token;
4714 break;
4715 case slash_token:
4716 ++*counter;
4717 cur_tok = prune_match_token;
4718 break;
4719 case colon_token:
4720 cur_tok = continue_match_token;
4721 break;
4722 case semi_colon_token:
4723 cur_tok = quit_match_token;
4724 break;
4725 case equal_token:
4726 ++*counter;
4727 cur_tok = mandate_match_token;
4728 break;
4729 case circumflex_token_l:
4730 case circumflex_token_o:
4731 ++*counter;
4732 cur_tok = leading_match_token;
4733 break;
4734 case underscore_token_l:
4735 case underscore_token_o:
4736 ++*counter;
4737 cur_tok = mandate_keep_match_token;
4738 break;
4739 case at_token_l:
4740 case at_token_o:
4741 cur_tok = par_command_match_token;
4742 break;
4743# if (match_experiment)
4744case d_token_l:
4745case d_token_o:
4746 ++*counter;
4747 cur_tok = dimension_match_token;
4748 break;
4749case i_token_l:
4750case i_token_o:
4751 ++*counter;
4752 cur_tok = integer_match_token;
4753 break;
4754# endif
4755 case L_token_l:
4756 case L_token_o:
4757 cur_tok = left_match_token;
4758 break;
4759 case R_token_l:
4760 case R_token_o:
4761 cur_tok = right_match_token;
4762 break;
4763 case G_token_l:
4764 case G_token_o:
4765 cur_tok = gobble_match_token;
4766 break;
4767 case M_token_l:
4768 case M_token_o:
4769 cur_tok = gobble_more_match_token;
4770 break;
4771 case S_token_l:
4772 case S_token_o:
4773 cur_tok = brackets_match_token;
4774 break;
4775 case P_token_l:
4776 case P_token_o:
4777 cur_tok = parentheses_match_token;
4778 break;
4779 case X_token_l:
4780 case X_token_o:
4781 cur_tok = angles_match_token;
4782 break;
4783 default:
4784 if (cur_tok >= one_token && cur_tok <= nine_token) {
4785 ++*counter;
4786 if ((cur_tok - other_token - '0') == *counter) {
4787 cur_tok += match_token - other_token ;
4788 break;
4789 }
4790 } else if (cur_tok >= A_token_l && cur_tok <= F_token_l) {
4791 ++*counter;
4792 if ((cur_tok - A_token_l + 10) == *counter) {
4793 cur_tok += match_token - letter_token;
4794 break;
4795 }
4796 }
4797 tex_aux_parameters_order_error();
4798 cur_tok = match_token;
4799 break;
4800 }
4801 }
4802 break;
4803 case end_paragraph_cmd:
4804 if (! auto_paragraph_mode(auto_paragraph_macro)) {
4805 cur_tok = par_command_match_token;
4806 }
4807 break;
4808 }
4809 *p = tex_store_new_token(*p, cur_tok);
4810 }
4811 DONE:
4812 if (h != *p) {
4813 *p = tex_store_new_token(*p, end_match_token);
4814 set_token_preamble(h, macro_with_preamble);
4815 set_token_parameters(h, *counter);
4816 }
4817 if (cur_cmd == right_brace_cmd) {
4818 ++lmt_input_state.align_state;
4819 tex_aux_missing_brace_error();
4820 return 0;
4821 } else {
4822 return 1;
4823 }
4824}
4825
4826halfword tex_scan_macro_normal(void)
4827{
4828 halfword hash_brace = 0;
4829 halfword counter = 0;
4830 halfword result = get_reference_token();
4831 halfword p = result;
4832 lmt_input_state.scanner_status = scanner_is_defining;
4833 lmt_input_state.warning_index = cur_cs;
4834 lmt_input_state.def_ref = result;
4835 if (tex_aux_valid_macro_preamble(&p, &counter, &hash_brace)) {
4836 halfword unbalance = 0;
4837 while (1) {
4838 tex_get_token();
4839 switch (cur_cmd) {
4840 case left_brace_cmd:
4841 if (! cur_cs) {
4842 ++unbalance;
4843 }
4844 break;
4845 case right_brace_cmd:
4846 if (! cur_cs) {
4847 if (unbalance) {
4848 --unbalance;
4849 } else {
4850 goto FINALYDONE;
4851 }
4852 }
4853 break;
4854 case parameter_cmd:
4855 {
4856 halfword s = cur_tok;
4857 tex_get_token();
4858 if (cur_cmd == parameter_cmd) {
4859
4860 } else {
4861 halfword n;
4862 if (cur_tok >= one_token && cur_tok <= nine_token) {
4863 n = cur_chr - '0';
4864 } else if (cur_tok >= A_token_l && cur_tok <= F_token_l) {
4865 n = cur_chr - '0' - gap_match_count;
4866 } else {
4867 n = counter + 1;
4868 }
4869 if (n <= counter) {
4870 cur_tok = token_val(parameter_reference_cmd, n);
4871 } else {
4872 halfword v = tex_parameter_escape_mode() ? valid_parameter_reference(cur_tok) : 0;
4873 if (v) {
4874 p = tex_store_new_token(p, token_val(parameter_cmd, match_visualizer));
4875 } else {
4876 tex_aux_illegal_parameter_in_body_error();
4877 cur_tok = s;
4878 }
4879 }
4880 }
4881 }
4882 break;
4883 case prefix_cmd:
4884 if (cur_chr == enforced_code && (! overload_mode_par || lmt_main_state.run_state != production_state)) {
4885 cur_tok = token_val(prefix_cmd, always_code);
4886 }
4887 break;
4888 default:
4889 break;
4890 }
4891 p = tex_store_new_token(p, cur_tok);
4892 }
4893 }
4894 FINALYDONE:
4895 lmt_input_state.scanner_status = scanner_is_normal;
4896 if (hash_brace) {
4897 p = tex_store_new_token(p, hash_brace);
4898 }
4899 return result;
4900}
4901
4902halfword tex_scan_macro_expand(void)
4903{
4904 halfword hash_brace = 0;
4905 halfword counter = 0;
4906 halfword result = get_reference_token();
4907 halfword p = result;
4908 lmt_input_state.scanner_status = scanner_is_defining;
4909 lmt_input_state.warning_index = cur_cs;
4910 lmt_input_state.def_ref = result;
4911 if (tex_aux_valid_macro_preamble(&p, &counter, &hash_brace)) {
4912 halfword unbalance = 0;
4913 while (1) {
4914 PICKUP:
4915 tex_get_next();
4916 switch (cur_cmd) {
4917 case call_cmd:
4918 case tolerant_call_cmd:
4919 tex_expand_current_token();
4920 goto PICKUP;
4921 case index_cmd:
4922 tex_inject_parameter(cur_chr);
4923 goto PICKUP;
4924 case constant_call_cmd:
4925 {
4926 halfword h = token_link(cur_chr);
4927 while (h) {
4928 p = tex_store_new_token(p, token_info(h));
4929 h = token_link(h);
4930 }
4931 goto PICKUP;
4932 }
4933 case protected_call_cmd:
4934 case semi_protected_call_cmd:
4935 case tolerant_protected_call_cmd:
4936 case tolerant_semi_protected_call_cmd:
4937 cur_tok = cs_token_flag + cur_cs;
4938 goto APPENDTOKEN;
4939 case the_cmd:
4940 {
4941 halfword t = null;
4942 halfword h = tex_the_toks(cur_chr, &t);
4943 if (h) {
4944 set_token_link(p, h);
4945 p = t;
4946 }
4947 goto PICKUP;
4948 }
4949 case relax_cmd:
4950 if (cur_chr == no_relax_code) {
4951
4952 goto PICKUP;
4953 } else {
4954 goto DONEEXPANDING;
4955 }
4956 case prefix_cmd:
4957 if (cur_chr == enforced_code && (! overload_mode_par || lmt_main_state.run_state != production_state)) {
4958 cur_tok = token_val(prefix_cmd, always_code);
4959 goto APPENDTOKEN;
4960 } else {
4961 goto DONEEXPANDING;
4962 }
4963 case parameter_cmd:
4964 {
4965
4966 halfword s = cur_tok;
4967 tex_get_x_token();
4968 if (cur_cmd == parameter_cmd) {
4969
4970 } else {
4971 halfword n;
4972 if (cur_tok >= one_token && cur_tok <= nine_token) {
4973 n = cur_chr - '0';
4974 } else if (cur_tok >= A_token_l && cur_tok <= F_token_l) {
4975 n = cur_chr - '0' - gap_match_count;
4976 } else {
4977 n = counter + 1;
4978 }
4979 if (n <= counter) {
4980 cur_tok = token_val(parameter_reference_cmd, n);
4981 } else {
4982 halfword v = tex_parameter_escape_mode() ? valid_parameter_reference(cur_tok) : 0;
4983 if (v) {
4984 halfword t = null;
4985 halfword h = tex_expand_parameter(cur_tok, &t);
4986 if (h) {
4987 set_token_link(p, h);
4988 p = t;
4989 }
4990 goto PICKUP;
4991 } else {
4992 tex_aux_illegal_parameter_in_body_error();
4993 cur_tok = s;
4994 }
4995 }
4996 }
4997 goto APPENDTOKEN;
4998 }
4999 case left_brace_cmd:
5000 if (cur_cs) {
5001 cur_tok = cs_token_flag + cur_cs;
5002 } else {
5003 cur_tok = token_val(cur_cmd, cur_chr);
5004 ++unbalance;
5005 }
5006 goto APPENDTOKEN;
5007 case right_brace_cmd:
5008 if (cur_cs) {
5009 cur_tok = cs_token_flag + cur_cs;
5010 goto APPENDTOKEN;
5011 } else {
5012 cur_tok = token_val(cur_cmd, cur_chr);
5013 if (unbalance) {
5014 --unbalance;
5015 goto APPENDTOKEN;
5016 } else {
5017 goto FINALYDONE;
5018 }
5019 }
5020 default:
5021 if (cur_cmd > max_command_cmd) {
5022 tex_expand_current_token();
5023 goto PICKUP;
5024 } else {
5025 goto DONEEXPANDING;
5026 }
5027 }
5028 DONEEXPANDING:
5029 if (cur_cs) {
5030 cur_tok = cs_token_flag + cur_cs;
5031 } else {
5032 cur_tok = token_val(cur_cmd, cur_chr);
5033 }
5034 APPENDTOKEN:
5035 p = tex_store_new_token(p, cur_tok);
5036 }
5037 }
5038 FINALYDONE:
5039 lmt_input_state.scanner_status = scanner_is_normal;
5040 if (hash_brace) {
5041 p = tex_store_new_token(p, hash_brace);
5042 }
5043 return result;
5044}
5045
5046
5059
5060typedef enum expression_states {
5061 expression_none,
5062 expression_not,
5063 expression_add,
5064 expression_subtract,
5065 expression_multiply,
5066 expression_divide,
5067 expression_scale,
5068 expression_idivide,
5069 expression_imodulo,
5070 expression_positive,
5071 expression_negative,
5072
5073 expression_bor,
5074 expression_band,
5075 expression_bxor,
5076 expression_bnot,
5077
5078 expression_bset,
5079 expression_bunset,
5080
5081 expression_bleft,
5082 expression_bright,
5083
5084 expression_less,
5085 expression_lessequal,
5086 expression_equal,
5087 expression_moreequal,
5088 expression_more,
5089 expression_unequal,
5090
5091
5092
5093
5094 expression_or,
5095 expression_and,
5096
5097 expression_cor,
5098 expression_cand,
5099} expression_states;
5100
5101
5111
5112static inline void tex_aux_normalize_glue(halfword g)
5113{
5114 if (! glue_stretch(g)) {
5115 glue_stretch_order(g) = normal_glue_order;
5116 }
5117 if (! glue_shrink(g)) {
5118 glue_shrink_order(g) = normal_glue_order;
5119 }
5120}
5121
5122
5135
5136static inline int tex_aux_add_or_sub(int x, int y, int max_answer, int operation)
5137{
5138 switch (operation) {
5139 case expression_subtract:
5140 y = -y;
5141
5142 case expression_add:
5143 if (x >= 0) {
5144 if (y <= max_answer - x) {
5145 return x + y;
5146 } else {
5147 lmt_scanner_state.arithmic_error = 1;
5148 }
5149 } else if (y >= -max_answer - x) {
5150 return x + y;
5151 } else {
5152 lmt_scanner_state.arithmic_error = 1;
5153 }
5154 break;
5155 }
5156 return 0;
5157}
5158
5159
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202static inline int tex_aux_quotient(int n, int d, int rounded)
5203{
5204 if (d == 0) {
5205 lmt_scanner_state.arithmic_error = 1;
5206 return 0;
5207 } else if (rounded) {
5208 return lround((double) n / (double) d);
5209 } else {
5210 return n / d;
5211 }
5212}
5213
5214static inline int tex_aux_modulo(int n, int d)
5215{
5216 if (d == 0) {
5217 lmt_scanner_state.arithmic_error = 1;
5218 return 0;
5219 } else {
5220 return n % d;
5221 }
5222}
5223
5224int tex_quotient(int n, int d, int round)
5225{
5226 return tex_aux_quotient(n, d, round);
5227}
5228
5229
5240
5241int tex_fract(int x, int n, int d, int max_answer)
5242{
5243
5244 bool negative = false;
5245
5246 int a = 0;
5247
5248 int f;
5249
5250 int h;
5251
5252 int r;
5253
5254 int t;
5255 if (d == 0) {
5256 goto TOO_BIG;
5257 }
5258 if (x == 0) {
5259 return 0;
5260 }
5261 if (n == d) {
5262 return x;
5263 }
5264 if (d < 0) {
5265 d = -d;
5266 negative = true;
5267 }
5268 if (x < 0) {
5269 x = -x;
5270 negative = ! negative;
5271 }
5272 if (n < 0) {
5273 n = -n;
5274 negative = ! negative;
5275 }
5276 t = n / d;
5277 if (t > max_answer / x) {
5278 goto TOO_BIG;
5279 }
5280 a = t * x;
5281 n = n - t * d;
5282 if (n == 0) {
5283 goto FOUND;
5284 }
5285 t = x / d;
5286 if (t > (max_answer - a) / n) {
5287 goto TOO_BIG;
5288 }
5289 a = a + t * n;
5290 x = x - t * d;
5291 if (x == 0) {
5292 goto FOUND;
5293 }
5294 if (x < n) {
5295 t = x;
5296 x = n;
5297 n = t;
5298 }
5299
5310 f = 0;
5311 r = (d / 2) - d;
5312 h = -r;
5313 while (1) {
5314 if (odd(n)) {
5315 r = r + x;
5316 if (r >= 0) {
5317 r = r - d;
5318 ++f;
5319 }
5320 }
5321 n = n / 2;
5322 if (n == 0) {
5323 break;
5324 } else if (x < h) {
5325 x = x + x;
5326 } else {
5327 t = x - d;
5328 x = t + x;
5329 f = f + n;
5330 if (x < n) {
5331 if (x == 0) {
5332 break;
5333 } else {
5334 t = x;
5335 x = n;
5336 n = t;
5337 }
5338 }
5339 }
5340 }
5341 if (f > (max_answer - a)) {
5342 goto TOO_BIG;
5343 }
5344 a = a + f;
5345 FOUND:
5346 if (negative) {
5347 a = -a;
5348 }
5349 goto DONE;
5350 TOO_BIG:
5351 lmt_scanner_state.arithmic_error = 1;
5352 a = 0;
5353 DONE:
5354 return a;
5355}
5356
5357
5363
5364# define max_expression_depth 1000
5365# define max_sub_expression_depth 1000
5366
5367static void tex_aux_scan_missing_error(void)
5368{
5369 tex_handle_error(
5370 back_error_type,
5371 "Missing ) inserted for expression",
5372 "I was expecting to see an operator or ')' but didn't."
5373 );
5374}
5375
5376static void tex_aux_scan_unexpected_relax_error(void)
5377{
5378 tex_handle_error(
5379 back_error_type,
5380 "Unexpected \\relax in expression",
5381 "I was expecting to see an operator or '}' but didn't."
5382 );
5383}
5384
5385static void tex_aux_scan_unexpected_whatever_error(void)
5386{
5387 tex_handle_error(
5388 back_error_type,
5389 "Unexpected token in expression",
5390 "I was expecting to see an operator or '}' but didn't."
5391 );
5392}
5393
5394static void tex_aux_scan_brace_error(void)
5395{
5396 tex_handle_error(
5397 back_error_type,
5398 "I ran into a curly brace mismatch",
5399 "You seem to have a mixup of () and {} or are missing at least one of them."
5400 );
5401}
5402
5403static void tex_aux_scan_parent_error(void)
5404{
5405 tex_handle_error(
5406 back_error_type,
5407 "I ran into a parenthesis mismatch",
5408 "You seem to have a mixup of () and {} or are missing at least one of them."
5409 );
5410}
5411
5412static void tex_aux_scan_zero_divide_error(void)
5413{
5414 tex_handle_error(
5415 back_error_type,
5416 "I can't divide by zero",
5417 "I was expecting to see a nonzero number. Didn't."
5418 );
5419}
5420
5421static void tex_aux_scan_expr(halfword level, int braced)
5422{
5423
5424 int result;
5425
5426 int state;
5427
5428 int operation;
5429
5430 int expression;
5431
5432 int term;
5433
5434 int factor = 0;
5435
5436 int numerator;
5437
5438 int error_a = lmt_scanner_state.arithmic_error;
5439 int error_b = 0;
5440
5441 halfword top = null;
5442 int nonelevel = level == posit_val_level ? posit_val_level : integer_val_level;
5443
5444 cur_val_level = level;
5445 lmt_scanner_state.expression_depth++;
5446 if (lmt_scanner_state.expression_depth > max_expression_depth) {
5447 tex_fatal_error("\\*expr can only be nested " LMT_TOSTRING(max_expression_depth) " deep");
5448 }
5449 RESTART:
5450 result = expression_none;
5451 state = expression_none;
5452 expression = 0;
5453 term = 0;
5454 numerator = 0;
5455 CONTINUE:
5456 operation = state == expression_none ? level : nonelevel;
5457
5462 while (1) {
5463 tex_get_x_token();
5464 if (cur_cmd == spacer_cmd) {
5465 continue;
5466 } else if (cur_tok == left_parent_token) {
5467
5468 halfword t = tex_get_node(expression_node_size);
5469 node_type(t) = expression_node;
5470 node_subtype(t) = 0;
5471
5472 node_next(t) = top;
5473 expression_type(t) = (singleword) level;
5474 expression_state(t) = (singleword) state;
5475 expression_result(t) = (singleword) result;
5476 expression_expression(t) = expression;
5477 expression_term(t) = term;
5478 expression_numerator(t) = numerator;
5479 top = t;
5480 level = operation;
5481 goto RESTART;
5482 } else {
5483 tex_back_input(cur_tok);
5484 break;
5485 }
5486 }
5487
5493 switch (operation) {
5494 case integer_val_level:
5495 case attribute_val_level:
5496 factor = tex_scan_integer(0, NULL, NULL);
5497 break;
5498 case posit_val_level:
5499 factor = tex_scan_posit(0);
5500 break;
5501 case dimension_val_level:
5502 factor = tex_scan_dimension(0, 0, 0, 0, NULL, NULL);
5503 break;
5504 case glue_val_level:
5505 factor = tex_scan_glue(glue_val_level, 0, 0);
5506 break;
5507 case muglue_val_level:
5508 factor = tex_scan_glue(muglue_val_level, 0, 0);
5509 break;
5510 }
5511 FOUND:
5512
5516 do {
5517 tex_get_x_token();
5518 } while (cur_cmd == spacer_cmd);
5519 switch (cur_tok) {
5520 case plus_token:
5521 operation = expression_add;
5522 break;
5523 case minus_token:
5524 operation = expression_subtract;
5525 break;
5526 case asterisk_token:
5527 operation = expression_multiply;
5528 break;
5529 case slash_token:
5530 operation = expression_divide;
5531 break;
5532 case colon_token:
5533 if (etex_expr_mode_par) {
5534 goto MAKESOMEFOLKHAPPY;
5535 } else {
5536 operation = expression_idivide;
5537 }
5538 break;
5539 case semi_colon_token:
5540 if (etex_expr_mode_par) {
5541 goto MAKESOMEFOLKHAPPY;
5542 } else {
5543 operation = expression_imodulo;
5544 }
5545 break;
5546
5550 default:
5551 MAKESOMEFOLKHAPPY:
5552 operation = expression_none;
5553 if (! top) {
5554 if (cur_cmd == relax_cmd) {
5555
5556 } else if (braced == 1 && cur_cmd == right_brace_cmd) {
5557
5558 } else {
5559 tex_back_input(cur_tok);
5560 }
5561 } else if (braced == 1 && cur_cmd == right_brace_cmd) {
5562
5563 } else if (cur_tok == right_parent_token) {
5564
5565 } else {
5566 tex_aux_scan_missing_error();
5567 }
5568 break;
5569 }
5570 lmt_scanner_state.arithmic_error = error_b;
5571
5572 switch (level) {
5573 case integer_val_level:
5574 case attribute_val_level:
5575 if ((factor > max_integer) || (factor < min_integer)) {
5576 lmt_scanner_state.arithmic_error = 1;
5577 factor = 0;
5578 }
5579 break;
5580 case posit_val_level:
5581 if ((factor > max_integer) || (factor < min_integer)) {
5582 lmt_scanner_state.arithmic_error = 1;
5583 factor = 0;
5584 }
5585 break;
5586 case dimension_val_level:
5587 if (abs(factor) > max_dimension) {
5588 lmt_scanner_state.arithmic_error = 1;
5589 factor = 0;
5590 }
5591 break;
5592 case glue_val_level:
5593 case muglue_val_level:
5594 if ((abs(glue_amount(factor)) > max_dimension) || (abs(glue_stretch(factor)) > max_dimension) || (abs(glue_shrink(factor)) > max_dimension)) {
5595 lmt_scanner_state.arithmic_error = 1;
5596 tex_reset_glue_to_zero(factor);
5597 }
5598 break;
5599 default:
5600 if ((state > expression_subtract) && ((factor > max_integer) || (factor < min_integer))) {
5601 lmt_scanner_state.arithmic_error = 1;
5602 factor = 0;
5603 }
5604 }
5605
5606 switch (state) {
5607 case expression_none:
5608
5614 term = factor;
5615 if ((level >= glue_val_level) && (operation != expression_none)) {
5616
5617 tex_aux_normalize_glue(term);
5618
5619
5620 }
5621 break;
5622 case expression_multiply:
5623
5627 if (operation == expression_divide) {
5628 numerator = factor;
5629 operation = expression_scale;
5630 } else {
5631 switch (level) {
5632 case integer_val_level:
5633 case attribute_val_level:
5634 term = tex_multiply_integers(term, factor);
5635 break;
5636 case posit_val_level:
5637 term = tex_posit_mul(term, factor);
5638 break;
5639 case dimension_val_level:
5640 term = tex_nx_plus_y(term, factor, 0);
5641 break;
5642 default:
5643 glue_amount(term) = tex_nx_plus_y(glue_amount(term), factor, 0);
5644 glue_stretch(term) = tex_nx_plus_y(glue_stretch(term), factor, 0);
5645 glue_shrink(term) = tex_nx_plus_y(glue_shrink(term), factor, 0);
5646 break;
5647 }
5648 }
5649 break;
5650 case expression_divide:
5651
5652 switch (level) {
5653 case integer_val_level:
5654 case attribute_val_level:
5655 case dimension_val_level:
5656 term = tex_aux_quotient(term, factor, 1);
5657 break;
5658 case posit_val_level:
5659 if (factor == 0) {
5660 lmt_scanner_state.arithmic_error = 1;
5661 term = 0;
5662 } else {
5663 term = tex_posit_div(term, factor);
5664 }
5665 break;
5666 default:
5667 glue_amount(term) = tex_aux_quotient(glue_amount(term), factor, 1);
5668 glue_stretch(term) = tex_aux_quotient(glue_stretch(term), factor, 1);
5669 glue_shrink(term) = tex_aux_quotient(glue_shrink(term), factor, 1);
5670 break;
5671 }
5672 break;
5673 case expression_scale:
5674
5675 switch (level) {
5676 case integer_val_level:
5677 case attribute_val_level:
5678 term = tex_fract(term, numerator, factor, max_integer);
5679 break;
5680 case posit_val_level:
5681 if (numerator == 0) {
5682 lmt_scanner_state.arithmic_error = 1;
5683 term = 0;
5684 } else {
5685 term = tex_posit_div(tex_posit_mul(term, factor), numerator);
5686 }
5687 break;
5688 case dimension_val_level:
5689 term = tex_fract(term, numerator, factor, max_dimension);
5690 break;
5691 default:
5692 glue_amount(term) = tex_fract(glue_amount(term), numerator, factor, max_dimension);
5693 glue_stretch(term) = tex_fract(glue_stretch(term), numerator, factor, max_dimension);
5694 glue_shrink(term) = tex_fract(glue_shrink(term), numerator, factor, max_dimension);
5695 break;
5696 }
5697 break;
5698 case expression_idivide:
5699
5700 if (level < glue_val_level) {
5701 term = tex_aux_quotient(term, factor, 0);
5702 } else {
5703 glue_amount(term) = tex_aux_quotient(glue_amount(term), factor, 0);
5704 glue_stretch(term) = tex_aux_quotient(glue_stretch(term), factor, 0);
5705 glue_shrink(term) = tex_aux_quotient(glue_shrink(term), factor, 0);
5706 }
5707 break;
5708 case expression_imodulo:
5709
5710 if (level < glue_val_level) {
5711 term = tex_aux_modulo(term, factor);
5712 } else {
5713 glue_amount(term) = tex_aux_modulo(glue_amount(term), factor);
5714 glue_stretch(term) = tex_aux_modulo(glue_stretch(term), factor);
5715 glue_shrink(term) = tex_aux_modulo(glue_shrink(term), factor);
5716 }
5717 break;
5718 }
5719 if (operation > expression_subtract) {
5720 state = operation;
5721 } else {
5722
5726 state = expression_none;
5727 if (result == expression_none) {
5728 expression = term;
5729 } else {
5730 switch (level) {
5731 case integer_val_level:
5732 case attribute_val_level:
5733 expression = tex_aux_add_or_sub(expression, term, max_integer, result);
5734 break;
5735 case posit_val_level:
5736 switch (result) {
5737 case expression_subtract:
5738 expression = tex_posit_sub(expression, term);
5739 break;
5740 case expression_add:
5741 expression = tex_posit_add(expression, term);
5742 break;
5743 }
5744 break;
5745 case dimension_val_level:
5746 expression = tex_aux_add_or_sub(expression, term, max_dimension, result);
5747 break;
5748 default :
5749
5754 glue_amount(expression) = tex_aux_add_or_sub(glue_amount(expression), glue_amount(term), max_dimension, result);
5755 if (glue_stretch_order(expression) == glue_stretch_order(term)) {
5756 glue_stretch(expression) = tex_aux_add_or_sub(glue_stretch(expression), glue_stretch(term), max_dimension, result);
5757 } else if ((glue_stretch_order(expression) < glue_stretch_order(term)) && (glue_stretch(term) != 0)) {
5758 glue_stretch(expression) = glue_stretch(term);
5759 glue_stretch_order(expression) = glue_stretch_order(term);
5760 }
5761 if (glue_shrink_order(expression) == glue_shrink_order(term)) {
5762 glue_shrink(expression) = tex_aux_add_or_sub(glue_shrink(expression), glue_shrink(term), max_dimension, result);
5763 } else if ((glue_shrink_order(expression) < glue_shrink_order(term)) && (glue_shrink(term) != 0)) {
5764 glue_shrink(expression) = glue_shrink(term);
5765 glue_shrink_order(expression) = glue_shrink_order(term);
5766 }
5767 tex_flush_node(term);
5768 tex_aux_normalize_glue(expression);
5769 break;
5770 }
5771 }
5772 result = operation;
5773 }
5774 error_b = lmt_scanner_state.arithmic_error;
5775 if (operation != expression_none) {
5776 goto CONTINUE;
5777 } else if (top) {
5778
5779 halfword newtop = node_next(top);
5780 factor = expression;
5781 expression = expression_expression(top);
5782 term = expression_term(top);
5783 numerator = expression_numerator(top);
5784 state = (singleword) expression_state(top);
5785 result = (singleword) expression_result(top);
5786 level = (singleword) expression_type(top);
5787 tex_free_node(top, expression_node_size);
5788 top = newtop;
5789 goto FOUND;
5790 } else if (error_b) {
5791 switch (level) {
5792 case posit_val_level:
5793 case integer_val_level:
5794 case attribute_val_level:
5795 tex_aux_scan_integer_out_of_range_error(4);
5796 expression = 0;
5797 break;
5798 case glue_val_level:
5799 case muglue_val_level:
5800 tex_reset_glue_to_zero(expression);
5801 case dimension_val_level:
5802 tex_aux_scan_dimension_out_of_range_error(2);
5803 break;
5804 }
5805 }
5806 lmt_scanner_state.arithmic_error = error_a;
5807 lmt_scanner_state.expression_depth--;
5808 cur_val_level = level;
5809 cur_val = expression;
5810}
5811
5812halfword tex_scan_expr(halfword level)
5813{
5814 tex_aux_scan_expr(level, 0);
5815 return cur_val;
5816}
5817
5818static halfword tex_aux_scan_unit_applied(halfword value, halfword fraction, int *has_unit, int has_fraction)
5819{
5820 halfword num = 0;
5821 halfword denom = 0;
5822 scaled unit = 0;
5823 *has_unit = 1;
5824 switch (tex_aux_scan_unit(&num, &denom, &unit, NULL)) {
5825 case normal_unit_scanned:
5826 if (num) {
5827 int remainder = 0;
5828 value = tex_xn_over_d_r(value, num, denom, &remainder);
5829 fraction = (num * fraction + unity * remainder) / denom;
5830 value += fraction / unity;
5831 fraction = fraction % unity;
5832 }
5833 *has_unit = 1;
5834 if (value >= 040000) {
5835 lmt_scanner_state.arithmic_error = 1;
5836 value = 040000;
5837 }
5838 return value * unity + fraction;
5839 case scaled_point_scanned:
5840 *has_unit = 0;
5841 return value;
5842 case relative_unit_scanned:
5843 return tex_nx_plus_y(value, unit, tex_xn_over_d(unit, fraction, unity));
5844 case quantitity_unit_scanned:
5845 cur_val = tex_aux_scan_something_internal(cur_cmd, cur_chr, dimension_val_level, 0, 0);
5846 value = tex_nx_plus_y(value, cur_val, tex_xn_over_d(cur_val, fraction, unity));
5847 return value;
5848 case no_unit_scanned:
5849 if (has_fraction) {
5850 *has_unit = 0;
5851 return value * unity + fraction;
5852 } else {
5853
5854 }
5855 default:
5856 break;
5857
5858
5859 }
5860 *has_unit = 0;
5861 return value;
5862}
5863
5864static halfword tex_scan_bit_integer(int *radix)
5865{
5866 bool negative = false;
5867 long long result = 0;
5868 while (1) {
5869 if (cur_tok == minus_token) {
5870 negative = ! negative;
5871 } else if (cur_tok == plus_token) {
5872
5873 } else if (cur_cmd == spacer_cmd) {
5874
5875 } else {
5876 break;
5877 }
5878 tex_get_token();
5879 }
5880 if (cur_tok == alpha_token) {
5881 tex_get_token();
5882 if (cur_tok < cs_token_flag) {
5883 result = cur_chr;
5884 } else {
5885 strnumber txt = cs_text(cur_tok - cs_token_flag);
5886 if (tex_single_letter(txt)) {
5887 result = aux_str2uni(str_string(txt));
5888 } else if (tex_is_active_cs(txt)) {
5889 result = active_cs_value(txt);
5890 } else {
5891 result = max_character_code + 1;
5892 }
5893 }
5894 if (result > max_character_code) {
5895 tex_aux_improper_constant_error();
5896 return 0;
5897 }
5898 } else if ((cur_cmd >= min_internal_cmd && cur_cmd <= max_internal_cmd) || cur_cmd == parameter_cmd) {
5899 result = tex_aux_scan_something_internal(cur_cmd, cur_chr, integer_val_level, 0, 0);
5900 if (cur_val_level != integer_val_level) {
5901 tex_aux_missing_number_error(2);
5902 return 0;
5903 }
5904 } else {
5905 bool vacuous = true;
5906 bool ok_so_far = true;
5907 switch (cur_tok) {
5908 case octal_token:
5909 {
5910 if (radix) {
5911 *radix = 8;
5912 }
5913 while (1) {
5914 unsigned d = 0;
5915 tex_get_x_token();
5916 if ((cur_tok >= zero_token) && (cur_tok <= seven_token)) {
5917 d = cur_tok - zero_token;
5918 } else {
5919 goto DONE;
5920 }
5921 vacuous = false;
5922 if (ok_so_far) {
5923 result = result * 8 + d;
5924 if (result > max_integer) {
5925 result = max_integer;
5926 tex_aux_scan_integer_out_of_range_error(5);
5927 ok_so_far = false;
5928 }
5929 }
5930 }
5931
5932 }
5933 case hex_token:
5934 {
5935 if (radix) {
5936 *radix = 16;
5937 }
5938 while (1) {
5939 unsigned d = 0;
5940 tex_get_x_token();
5941 if ((cur_tok >= zero_token) && (cur_tok <= nine_token)) {
5942 d = cur_tok - zero_token;
5943 } else if ((cur_tok >= A_token_l) && (cur_tok <= F_token_l)) {
5944 d = cur_tok - A_token_l + 10;
5945 } else if ((cur_tok >= A_token_o) && (cur_tok <= F_token_o)) {
5946 d = cur_tok - A_token_o + 10;
5947 } else {
5948 goto DONE;
5949 }
5950 vacuous = false;
5951 if (ok_so_far) {
5952 result = result * 16 + d;
5953 if (result > max_integer) {
5954 result = max_integer;
5955 tex_aux_scan_integer_out_of_range_error(6);
5956 ok_so_far = false;
5957 }
5958 }
5959 }
5960
5961 }
5962 default:
5963 {
5964 if (radix) {
5965 *radix = 10;
5966 }
5967 while (1) {
5968 unsigned d = 0;
5969 if ((cur_tok >= zero_token) && (cur_tok <= nine_token)) {
5970 d = cur_tok - zero_token;
5971 } else {
5972 goto DONE;
5973 }
5974 vacuous = false;
5975 if (ok_so_far) {
5976 result = result * 10 + d;
5977 if (result > max_integer) {
5978 result = max_integer;
5979 tex_aux_scan_integer_out_of_range_error(7);
5980 ok_so_far = false;
5981 }
5982 }
5983 tex_get_x_token();
5984 }
5985
5986 }
5987 }
5988 DONE:
5989 if (vacuous) {
5990 tex_aux_missing_number_error(3);
5991 } else {
5992 tex_push_back(cur_tok, cur_cmd, cur_chr);
5993 }
5994 }
5995 cur_val = (halfword) (negative ? - result : result);
5996 return cur_val;
5997}
5998
5999static halfword tex_scan_bit_dimension(int *has_fraction, int *has_unit)
6000{
6001 bool negative = false;
6002 int fraction = 0;
6003 *has_fraction = 0;
6004 *has_unit = 0;
6005 lmt_scanner_state.arithmic_error = 0;
6006 while (1) {
6007 if (cur_tok == minus_token) {
6008 negative = ! negative;
6009 } else if (cur_tok == plus_token) {
6010
6011 } else if (cur_cmd == spacer_cmd) {
6012
6013 } else {
6014 break;
6015 }
6016 tex_get_token();
6017 }
6018 if (cur_cmd >= min_internal_cmd && cur_cmd <= max_internal_cmd) {
6019 cur_val = tex_aux_scan_something_internal(cur_cmd, cur_chr, dimension_val_level, 0, 0);
6020 if (cur_val_level == dimension_val_level) {
6021 *has_unit = 1;
6022 goto ATTACH_SIGN;
6023 }
6024 } else if (tex_token_is_unit(cur_tok) && tex_aux_scan_unit_only(&cur_val) != no_unit_scanned) {
6025 *has_unit = 1;
6026 goto NEARLY_DONE;
6027 } else {
6028 *has_fraction = tex_token_is_separator(cur_tok);
6029 if (*has_fraction) {
6030
6031 cur_val = 0;
6032 } else {
6033 int cur_radix = 10;
6034 cur_val = tex_scan_bit_integer(&cur_radix);
6035 if (cur_radix == 10 && tex_token_is_separator(cur_tok)) {
6036 *has_fraction = 1;
6037 tex_get_token();
6038 }
6039 }
6040 if (*has_fraction) {
6041 unsigned k = 0;
6042 unsigned char digits[18];
6043 while (1) {
6044 tex_get_x_token();
6045 if (cur_tok > nine_token || cur_tok < zero_token) {
6046 break;
6047 } else if (k < 17) {
6048 digits[k] = (unsigned char) (cur_tok - zero_token);
6049 ++k;
6050 }
6051 }
6052 fraction = tex_round_decimals_digits(digits, k);
6053 if (cur_cmd != spacer_cmd) {
6054
6055 tex_back_input(cur_tok);
6056 }
6057 }
6058 }
6059 cur_val = tex_aux_scan_unit_applied(cur_val, fraction, has_unit, *has_fraction);
6060 ATTACH_SIGN:
6061 if (lmt_scanner_state.arithmic_error || (abs(cur_val) >= 010000000000)) {
6062 tex_aux_scan_dimension_out_of_range_error(3);
6063 cur_val = max_dimension;
6064 lmt_scanner_state.arithmic_error = 0;
6065 }
6066 NEARLY_DONE:
6067 if (negative) {
6068 cur_val = -cur_val;
6069 }
6070 return cur_val;
6071}
6072
6073
6101
6102int tex_scanned_expression(int level)
6103{
6104 tex_aux_scan_expression(level, 0);
6105 return cur_val;
6106}
6107
6108
6112
6113halfword tex_scan_scale(int optional_equal)
6114{
6115 bool negative = false;
6116 lmt_scanner_state.arithmic_error = 0;
6117 do {
6118 while (1) {
6119 tex_get_x_token();
6120 if (cur_cmd != spacer_cmd) {
6121 if (optional_equal && (cur_tok == equal_token)) {
6122 optional_equal = 0;
6123 } else {
6124 break;
6125 }
6126 }
6127 }
6128 if (cur_tok == minus_token) {
6129 negative = ! negative;
6130 cur_tok = plus_token;
6131 }
6132 } while (cur_tok == plus_token);
6133 if (cur_cmd >= min_internal_cmd && cur_cmd <= max_internal_cmd) {
6134 cur_val = tex_aux_scan_something_internal(cur_cmd, cur_chr, integer_val_level, 0, 0);
6135 } else {
6136 int has_fraction = tex_token_is_separator(cur_tok);
6137 if (has_fraction) {
6138 cur_val = 0;
6139 } else {
6140 int cur_radix;
6141 tex_back_input(cur_tok);
6142 cur_val = tex_scan_integer(0, &cur_radix, NULL);
6143 tex_get_token();
6144 if (cur_radix == 10 && tex_token_is_separator(cur_tok)) {
6145 has_fraction = 1;
6146 }
6147 }
6148 cur_val = cur_val * 1000;
6149 if (has_fraction) {
6150 unsigned k = 4;
6151 while (1) {
6152 tex_get_x_token();
6153 if (cur_tok < zero_token || cur_tok > nine_token) {
6154 break;
6155 } else if (k == 1) {
6156
6157 if (cur_tok >= five_token && cur_tok <= nine_token) {
6158 cur_val += 1;
6159 }
6160 --k;
6161 } else if (k) {
6162 cur_val = cur_val + (k == 4 ? 100 : (k == 3 ? 10 : 1)) * (cur_tok - zero_token);
6163 --k;
6164 }
6165 }
6166 }
6167 tex_push_back(cur_tok, cur_cmd, cur_chr);
6168 }
6169 if (negative) {
6170 cur_val = -cur_val;
6171 }
6172 if (lmt_scanner_state.arithmic_error || (abs(cur_val) >= 0x40000000)) {
6173
6174 cur_val = max_dimension;
6175 lmt_scanner_state.arithmic_error = 0;
6176 }
6177 return cur_val;
6178}
6179
6180
6181
6182# define max_posit_size 60
6183
6184halfword tex_scan_posit(int optional_equal)
6185{
6186 int hexadecimal = 1;
6187 int exponent = 1;
6188 bool negative = false;
6189 int b = 0;
6190 char buffer[max_posit_size+4] = { 0 };
6191 do {
6192 while (1) {
6193 tex_get_x_token();
6194 if (cur_cmd != spacer_cmd) {
6195 if (optional_equal && (cur_tok == equal_token)) {
6196 optional_equal = 0;
6197 } else {
6198 break;
6199 }
6200 }
6201 }
6202 if (cur_tok == minus_token) {
6203 negative = ! negative;
6204 cur_tok = plus_token;
6205 }
6206 } while (cur_tok == plus_token);
6207 if (cur_cmd >= min_internal_cmd && cur_cmd <= max_internal_cmd) {
6208 cur_val = tex_aux_scan_something_internal(cur_cmd, cur_chr, posit_val_level, 0, 0);
6209 } else {
6210 if (negative) {
6211 buffer[b++] = '-';
6212 }
6213
6214 if (hexadecimal && (cur_tok == zero_token)) {
6215 buffer[b++] = '0';
6216 tex_get_x_token();
6217 if (tex_token_is_hexadecimal(cur_tok)) {
6218 buffer[b++] = 'x';
6219 goto SCANHEXADECIMAL;
6220 } else {
6221 goto PICKUPDECIMAL;
6222 }
6223 } else {
6224 goto SCANDECIMAL;
6225 }
6226 SCANDECIMAL:
6227 if (tex_token_is_separator(cur_tok)) {
6228 buffer[b++] = '.';
6229 while (1) {
6230 tex_get_x_token();
6231 if (tex_token_is_digit(cur_tok)) {
6232 buffer[b++] = (unsigned char) cur_chr;
6233 } else if (exponent) {
6234 goto DECIMALEXPONENT;
6235 } else {
6236 tex_back_input(cur_tok);
6237 goto DONE;
6238 }
6239 if (b >= 60) {
6240 goto TOOBIG;
6241 }
6242 }
6243 } else {
6244 goto PICKUPDECIMAL;
6245 }
6246 while (1) {
6247 tex_get_x_token();
6248 PICKUPDECIMAL:
6249 if (tex_token_is_digit(cur_tok)) {
6250 buffer[b++] = (unsigned char) cur_chr;
6251 } else if (tex_token_is_separator(cur_tok)) {
6252 buffer[b++] = '.';
6253 while (1) {
6254 tex_get_x_token();
6255 if (tex_token_is_digit(cur_tok)) {
6256 buffer[b++] = (unsigned char) cur_chr;
6257 } else {
6258 tex_back_input(cur_tok);
6259 break;
6260 }
6261 }
6262 } else if (exponent) {
6263 goto DECIMALEXPONENT;
6264 } else {
6265 tex_back_input(cur_tok);
6266 goto DONE;
6267 }
6268 if (b >= max_posit_size) {
6269 goto TOOBIG;
6270 }
6271 }
6272 DECIMALEXPONENT:
6273 if (tex_token_is_exponent(cur_tok)) {
6274 buffer[b++] = (unsigned char) cur_chr;
6275 tex_get_x_token();
6276 if (tex_token_is_sign(cur_tok)) {
6277 buffer[b++] = (unsigned char) cur_chr;
6278 } else if (tex_token_is_digit(cur_tok)) {
6279 buffer[b++] = (unsigned char) cur_chr;
6280 }
6281 while (1) {
6282 tex_get_x_token();
6283 if (tex_token_is_digit(cur_tok)) {
6284 buffer[b++] = (unsigned char) cur_chr;
6285 } else {
6286 break;
6287 }
6288 if (b >= max_posit_size) {
6289 goto TOOBIG;
6290 }
6291 }
6292 }
6293 tex_back_input(cur_tok);
6294 goto DONE;
6295 SCANHEXADECIMAL:
6296 tex_get_x_token();
6297 if (tex_token_is_separator(cur_tok)) {
6298 buffer[b++] = '.';
6299 while (1) {
6300 tex_get_x_token();
6301 if (tex_token_is_xdigit(cur_tok)) {
6302 buffer[b++] = (unsigned char) cur_chr;
6303 } else if (exponent) {
6304 goto HEXADECIMALEXPONENT;
6305 } else {
6306 tex_back_input(cur_tok);
6307 goto DONE;
6308 }
6309 if (b >= max_posit_size) {
6310 goto TOOBIG;
6311 }
6312 }
6313 } else {
6314
6315 tex_back_input(cur_tok);
6316 while (1) {
6317 tex_get_x_token();
6318 if (tex_token_is_xdigit(cur_tok)) {
6319 buffer[b++] = (unsigned char) cur_chr;
6320 } else if (tex_token_is_separator(cur_tok)) {
6321 buffer[b++] = '.';
6322 while (1) {
6323 tex_get_x_token();
6324 if (tex_token_is_xdigit(cur_tok)) {
6325 buffer[b++] = (unsigned char) cur_chr;
6326 } else {
6327 tex_back_input(cur_tok);
6328 break;
6329 }
6330 }
6331 } else if (exponent) {
6332 goto HEXADECIMALEXPONENT;
6333 } else {
6334 tex_back_input(cur_tok);
6335 goto DONE;
6336 }
6337 if (b >= max_posit_size) {
6338 goto TOOBIG;
6339 }
6340 }
6341 }
6342 HEXADECIMALEXPONENT:
6343 if (tex_token_is_xexponent(cur_tok)) {
6344 buffer[b++] = (unsigned char) cur_chr;
6345 tex_get_x_token();
6346 if (tex_token_is_sign(cur_tok)) {
6347 buffer[b++] = (unsigned char) cur_chr;
6348 } else if (tex_token_is_xdigit(cur_tok)) {
6349 buffer[b++] = (unsigned char) cur_chr;
6350 }
6351 while (1) {
6352 tex_get_x_token();
6353 if (tex_token_is_xdigit(cur_tok)) {
6354 buffer[b++] = (unsigned char) cur_chr;
6355 } else {
6356 break;
6357 }
6358 if (b >= max_posit_size) {
6359 goto TOOBIG;
6360 }
6361 }
6362 }
6363 tex_back_input(cur_tok);
6364 DONE:
6365 if (b) {
6366 double d = strtod(buffer, NULL);
6367 cur_val = tex_double_to_posit(d).v;
6368 return cur_val;
6369 } else {
6370 tex_aux_missing_number_error(4);
6371 }
6372 TOOBIG:
6373 cur_val = tex_integer_to_posit(0).v;
6374 }
6375 return cur_val;
6376}
6377
6378int tex_scan_tex_value(halfword level, halfword *value)
6379{
6380 tex_aux_scan_expr(level, 0);
6381 *value = cur_val;
6382 return 1;
6383}
6384
6385quarterword tex_scan_direction(int optional_equal)
6386{
6387 int i = tex_scan_integer(optional_equal, NULL, NULL);
6388 return (quarterword) checked_direction_value(i);
6389}
6390
6391halfword tex_scan_geometry(int optional_equal)
6392{
6393 int i = tex_scan_integer(optional_equal, NULL, NULL);
6394 return checked_geometry_value(i);
6395}
6396
6397halfword tex_scan_orientation(int optional_equal)
6398{
6399 halfword i = tex_scan_integer(optional_equal, NULL, NULL);
6400 return checked_orientation_value(i);
6401}
6402
6403halfword tex_scan_anchor(int optional_equal)
6404{
6405 halfword a = tex_scan_integer(optional_equal, NULL, NULL);
6406 halfword l = (a >> 16) & 0xFFFF;
6407 halfword r = a & 0xFFFF;
6408 return (checked_anchor_value(l) << 16) + checked_anchor_value(r);
6409}
6410
6411halfword tex_scan_anchors(int optional_equal)
6412{
6413 halfword l = tex_scan_integer(optional_equal, NULL, NULL) & 0xFFFF;
6414 halfword r = tex_scan_integer(0, NULL, NULL) & 0xFFFF;
6415 return (checked_anchor_value(l) << 16) + checked_anchor_value(r);
6416}
6417
6418halfword tex_scan_attribute(halfword attrlist)
6419{
6420 halfword i = tex_scan_attribute_register_number();
6421 halfword v = tex_scan_integer(1, NULL, NULL);
6422 if (eq_value(register_attribute_location(i)) != v) {
6423 if (attrlist) {
6424 attrlist = tex_patch_attribute_list(attrlist, i, v);
6425 } else {
6426 attrlist = tex_copy_attribute_list_set(tex_current_attribute_list(), i, v);
6427 }
6428 }
6429 return attrlist;
6430}
6431
6432halfword tex_scan_extra_attribute(halfword attrlist)
6433{
6434 halfword i = tex_scan_attribute_register_number();
6435 halfword v = tex_scan_integer(1, NULL, NULL);
6436 if (attrlist) {
6437 attrlist = tex_patch_attribute_list(attrlist, i, v);
6438 } else {
6439 attrlist = tex_copy_attribute_list_set(null, i, v);
6440 }
6441 return attrlist;
6442}
6443
6444# undef factor
6445
6446static inline halfword tex_scan_aux_o(void)
6447{
6448 tex_get_x_token();
6449 switch (cur_tok) {
6450 case r_token_l: case r_token_o:
6451 return expression_or;
6452 default:
6453 tex_aux_show_keyword_error("or");
6454 return expression_none;
6455 }
6456}
6457
6458static inline halfword tex_scan_aux_a(void)
6459{
6460 tex_get_x_token();
6461 switch (cur_tok) {
6462 case n_token_l: case n_token_o:
6463 tex_get_x_token();
6464 switch (cur_tok) {
6465 case d_token_l: case d_token_o:
6466 return expression_and;
6467 default:
6468 goto A_ERROR;
6469 }
6470 default:
6471 A_ERROR:
6472 tex_aux_show_keyword_error("and");
6473 return expression_none;
6474 }
6475}
6476
6477static inline halfword tex_scan_aux_n(void)
6478{
6479 tex_get_x_token();
6480 switch (cur_tok) {
6481 case o_token_l: case o_token_o:
6482 tex_get_x_token();
6483 switch (cur_tok) {
6484 case t_token_l: case t_token_o:
6485 return expression_not;
6486 default:
6487 goto N_ERROR;
6488 }
6489 case p_token_l: case p_token_o:
6490 tex_get_x_token();
6491 switch (cur_tok) {
6492 case m_token_l: case m_token_o:
6493 return expression_positive;
6494 default:
6495 goto N_ERROR;
6496 }
6497 case m_token_l: case m_token_o:
6498 tex_get_x_token();
6499 switch (cur_tok) {
6500 case p_token_l: case p_token_o:
6501 return expression_negative;
6502 default:
6503 goto N_ERROR;
6504 }
6505 default:
6506 N_ERROR:
6507 tex_aux_show_keyword_error("not|nmp|npm");
6508 return expression_none;
6509 }
6510}
6511
6512static inline halfword tex_scan_aux_m(void)
6513{
6514 tex_get_x_token();
6515 switch (cur_tok) {
6516 case o_token_l: case o_token_o:
6517 tex_get_x_token();
6518 switch (cur_tok) {
6519 case d_token_l: case d_token_o:
6520 return expression_imodulo;
6521 default:
6522 goto M_ERROR;
6523 }
6524 default:
6525 M_ERROR:
6526 tex_aux_show_keyword_error("mod");
6527 return expression_none;
6528 }
6529}
6530
6531static inline halfword tex_scan_aux_d(void)
6532{
6533 tex_get_x_token();
6534 switch (cur_tok) {
6535 case i_token_l: case i_token_o:
6536 tex_get_x_token();
6537 switch (cur_tok) {
6538 case v_token_l: case v_token_o:
6539 return expression_idivide;
6540 default:
6541 goto M_ERROR;
6542 }
6543 default:
6544 M_ERROR:
6545 tex_aux_show_keyword_error("div");
6546 return expression_none;
6547 }
6548}
6549
6550static inline halfword tex_scan_aux_b(void)
6551{
6552 tex_get_x_token();
6553 switch (cur_tok) {
6554 case a_token_l: case a_token_o:
6555 tex_get_x_token();
6556 switch (cur_tok) {
6557 case n_token_l: case n_token_o:
6558 tex_get_x_token();
6559 switch (cur_tok) {
6560 case d_token_l: case d_token_o:
6561 return expression_band;
6562 default:
6563 goto B_ERROR;
6564 }
6565 default:
6566 goto B_ERROR;
6567 }
6568 break;
6569 case o_token_l: case o_token_o:
6570 tex_get_x_token();
6571 switch (cur_tok) {
6572 case r_token_l: case r_token_o:
6573 return expression_bor;
6574 default:
6575 goto B_ERROR;
6576 }
6577 break;
6578 case x_token_l: case x_token_o:
6579 tex_get_x_token();
6580 switch (cur_tok) {
6581 case o_token_l: case o_token_o:
6582 tex_get_x_token();
6583 switch (cur_tok) {
6584 case r_token_l: case r_token_o:
6585 return expression_bxor;
6586 default:
6587 goto B_ERROR;
6588 }
6589 default:
6590 goto B_ERROR;
6591 }
6592 break;
6593 case s_token_l: case s_token_o:
6594 tex_get_x_token();
6595 switch (cur_tok) {
6596 case e_token_l: case e_token_o:
6597 tex_get_x_token();
6598 switch (cur_tok) {
6599 case t_token_l: case t_token_o:
6600 return expression_bset;
6601 default:
6602 goto B_ERROR;
6603 }
6604 default:
6605 goto B_ERROR;
6606 }
6607 break;
6608 case u_token_l: case u_token_o:
6609 tex_get_x_token();
6610 switch (cur_tok) {
6611 case n_token_l: case n_token_o:
6612 tex_get_x_token();
6613 switch (cur_tok) {
6614 case s_token_l: case s_token_o:
6615 tex_get_x_token();
6616 switch (cur_tok) {
6617 case e_token_l: case e_token_o:
6618 tex_get_x_token();
6619 switch (cur_tok) {
6620 case t_token_l: case t_token_o:
6621 return expression_bset;
6622 default:
6623 goto B_ERROR;
6624 }
6625 default:
6626 goto B_ERROR;
6627 }
6628 default:
6629 goto B_ERROR;
6630 }
6631 default:
6632 goto B_ERROR;
6633 }
6634 break;
6635 default:
6636 B_ERROR:
6637 tex_aux_show_keyword_error("band|bor|bxor|bset|bunset");
6638 return expression_none;
6639 }
6640}
6641
6642static inline halfword tex_scan_aux_c(void)
6643{
6644 tex_get_x_token();
6645 switch (cur_tok) {
6646 case a_token_l: case a_token_o:
6647 tex_get_x_token();
6648 switch (cur_tok) {
6649 case n_token_l: case n_token_o:
6650 tex_get_x_token();
6651 switch (cur_tok) {
6652 case d_token_l: case d_token_o:
6653 return expression_cand;
6654 default:
6655 goto C_ERROR;
6656 }
6657 default:
6658 goto C_ERROR;
6659 }
6660 break;
6661 case o_token_l: case o_token_o:
6662 tex_get_x_token();
6663 switch (cur_tok) {
6664 case r_token_l: case r_token_o:
6665 return expression_cor;
6666 default:
6667 goto C_ERROR;
6668 }
6669 default:
6670 C_ERROR:
6671 tex_aux_show_keyword_error("cand|cor");
6672 return expression_none;
6673 }
6674}
6675
6676static inline halfword tex_scan_aux_equal(int *alreadygotten)
6677{
6678 tex_get_x_token();
6679 switch (cur_tok) {
6680 case equal_token:
6681 return expression_equal;
6682 default:
6683 *alreadygotten = 1;
6684 return expression_equal;
6685 }
6686}
6687
6688static inline halfword tex_scan_aux_less(int *alreadygotten)
6689{
6690 tex_get_x_token();
6691 switch (cur_tok) {
6692 case less_token:
6693 return expression_bleft;
6694 case equal_token:
6695 return expression_lessequal;
6696 case more_token:
6697 return expression_unequal;
6698 default:
6699 *alreadygotten = 1;
6700 return expression_less;
6701 }
6702}
6703
6704static inline halfword tex_scan_aux_more(int *alreadygotten)
6705{
6706 tex_get_x_token();
6707 switch (cur_tok) {
6708 case more_token:
6709 return expression_bright;
6710 case equal_token:
6711 return expression_moreequal;
6712 default:
6713 *alreadygotten = 1;
6714 return expression_more;
6715 }
6716}
6717
6718static inline halfword tex_scan_aux_tilde(int *alreadygotten)
6719{
6720 tex_get_x_token();
6721 switch (cur_tok) {
6722 case equal_token:
6723 return expression_unequal;
6724 default:
6725 *alreadygotten = 1;
6726 return expression_bnot;
6727 }
6728}
6729
6730static inline halfword tex_scan_aux_exclamation(int *alreadygotten)
6731{
6732 tex_get_x_token();
6733 switch (cur_tok) {
6734 case equal_token:
6735 return expression_unequal;
6736 default:
6737 *alreadygotten = 1;
6738 return expression_not;
6739 }
6740}
6741
6742static inline halfword tex_scan_aux_ampersand(int *alreadygotten)
6743{
6744 tex_get_x_token();
6745 switch (cur_tok) {
6746 case ampersand_token_l: case ampersand_token_o: case ampersand_token_t:
6747 return expression_and;
6748 default:
6749 *alreadygotten = 1;
6750 return expression_band;
6751 }
6752}
6753
6754static inline halfword tex_scan_aux_bar(int *alreadygotten)
6755{
6756 tex_get_x_token();
6757 switch (cur_tok) {
6758 case bar_token_l: case bar_token_o:
6759 return expression_or;
6760 default:
6761 *alreadygotten = 1;
6762 return expression_bor;
6763 }
6764}
6765
6766static inline long long tex_aux_double_rounded_long_long(double d)
6767{
6768 if (d < min_doubleinteger) {
6769 tex_aux_scan_integer_out_of_range_error(10);
6770 return min_longinteger;
6771 } else if (d > max_doubleinteger) {
6772 tex_aux_scan_integer_out_of_range_error(10);
6773 return max_longinteger;
6774 } else {
6775 return llround(d);
6776 }
6777}
6778
6779
6794
6795static inline long long tex_aux_long_long(long long l)
6796{
6797 if (l < min_longinteger) {
6798 tex_aux_scan_integer_out_of_range_error(10);
6799 return min_longinteger;
6800 } else if (l > max_longinteger) {
6801 tex_aux_scan_integer_out_of_range_error(10);
6802 return max_longinteger;
6803 } else {
6804 return l;
6805 }
6806}
6807
6808
6809
6810static void tex_aux_scan_integer_expression(int braced)
6811{
6812 int result;
6813 int state;
6814 int operation;
6815 int negate;
6816 int nothing;
6817 int positive;
6818 int negative;
6819 int bnothing;
6820 long long expression;
6821 long long term;
6822 long long factor = 0;
6823 long long numerator;
6824 int error_a = lmt_scanner_state.arithmic_error;
6825 int error_b = 0;
6826 halfword top = null;
6827 int alreadygotten = 0;
6828 int depth = 0;
6829 cur_val_level = integer_val_level;
6830 lmt_scanner_state.expression_depth++;
6831 if (lmt_scanner_state.expression_depth > max_expression_depth) {
6832 tex_fatal_error("\\numexpression can only be nested " LMT_TOSTRING(max_expression_depth) " deep");
6833 }
6834 RESTART:
6835 result = expression_none;
6836 state = expression_none;
6837 expression = 0;
6838 term = 0;
6839 numerator = 0;
6840 negate = 0;
6841 nothing = 0;
6842 positive = 0;
6843 negative = 0;
6844 bnothing = 0;
6845 CONTINUE:
6846
6847 AGAIN:
6848 if (alreadygotten) {
6849 alreadygotten = 0;
6850 goto ALREADYGOTTEN;
6851 }
6852 while (1) {
6853 tex_get_x_token();
6854 ALREADYGOTTEN:
6855 switch (cur_cmd) {
6856 case spacer_cmd:
6857 continue;
6858 case left_brace_cmd:
6859 if ((negate || nothing || positive || negative) && braced == 0) {
6860 tex_aux_scan_expression_unexpected_negation_error();
6861 break;
6862 } else {
6863 ++braced;
6864 if (braced > 1) {
6865 goto PUSH;
6866 } else {
6867 goto AGAIN;
6868 }
6869 }
6870 case right_brace_cmd:
6871 if (braced > 1) {
6872 --braced;
6873 goto POP;
6874 } else {
6875 break;
6876 }
6877 case end_paragraph_cmd:
6878 if (braced) {
6879 continue;
6880 } else {
6881 break;
6882 }
6883 default:
6884 switch (cur_tok) {
6885 case minus_token:
6886 negate = ! negate;
6887 continue;
6888 case plus_token:
6889 continue;
6890 case n_token_l:
6891 case n_token_o:
6892 switch (tex_scan_aux_n()) {
6893 case expression_not: nothing = ! nothing;
6894 continue;
6895 case expression_positive:
6896 positive = 1;
6897 continue;
6898 case expression_negative:
6899 negative = 1;
6900 continue;
6901 default:
6902 break;
6903 }
6904 case tilde_token_l:
6905 case tilde_token_o:
6906 if (tex_scan_aux_tilde(&alreadygotten) == expression_bnot) {
6907 bnothing = ! bnothing;
6908 continue;
6909 } else {
6910 alreadygotten = 0;
6911 goto ALREADYGOTTEN;
6912 }
6913 case exclamation_token_l:
6914 case exclamation_token_o:
6915 if (tex_scan_aux_exclamation(&alreadygotten) == expression_not) {
6916 nothing = ! nothing;
6917 continue;
6918 } else {
6919 alreadygotten = 0;
6920 goto ALREADYGOTTEN;
6921 }
6922 case plus_minus_token:
6923 positive = 1;
6924 continue;
6925 case minus_plus_token:
6926 negative = 1;
6927 continue;
6928 case left_parent_token:
6929 PUSH:
6930 ++depth;
6931 if (depth > max_sub_expression_depth) {
6932 tex_fatal_error("sub expressions can only be nested " LMT_TOSTRING(max_sub_expression_depth) " deep");
6933 }
6934 {
6935 halfword newtop = tex_get_node(lmtx_expression_node_size);
6936 node_type(newtop) = lmtx_expression_node;
6937 node_subtype(newtop) = cur_tok == left_parent_token ? 0x1 : 0x2;
6938 node_next(newtop) = top;
6939 lmtx_expression_type(newtop) = (singleword) integer_val_level;
6940 lmtx_expression_state(newtop) = (singleword) state;
6941 lmtx_expression_result(newtop) = (singleword) result;
6942 lmtx_expression_negate(newtop) = (singleword) (negate | (nothing << 1) | (bnothing << 2) | (positive << 3) | (negative << 4));
6943 lmtx_expression_expression(newtop) = expression;
6944 lmtx_expression_term(newtop) = term;
6945 lmtx_expression_numerator(newtop) = numerator;
6946 top = newtop;
6947 goto RESTART;
6948 }
6949 default:
6950 goto ACTION;
6951 }
6952 }
6953 }
6954 ACTION:
6955 factor = tex_scan_bit_integer(NULL);
6956 if (negate) {
6957 factor = - factor;
6958 negate = 0;
6959 }
6960 if (nothing) {
6961 factor = factor ? 0 : 1;
6962 nothing = 0;
6963 }
6964 if (bnothing) {
6965 factor = ~ factor;
6966 bnothing = 0;
6967 }
6968 if (positive) {
6969 if (factor < 0) {
6970 factor = - factor;
6971 }
6972 positive = 0;
6973 }
6974 if (negative) {
6975 if (factor > 0) {
6976 factor = - factor;
6977 }
6978 negative = 0;
6979 }
6980 FOUND:
6981 do {
6982 tex_get_x_token();
6983 } while (cur_cmd == spacer_cmd || (braced && cur_cmd == end_paragraph_cmd));
6984 switch (cur_tok) {
6985 case plus_token : operation = expression_add; break;
6986 case minus_token : operation = expression_subtract; break;
6987 case asterisk_token : operation = expression_multiply; break;
6988 case slash_token : operation = expression_divide; break;
6989 case colon_token : operation = expression_idivide; break;
6990 case semi_colon_token:
6991 case percentage_token: operation = expression_imodulo; break;
6992
6993 case equal_token: operation = tex_scan_aux_equal(&alreadygotten); break;
6994 case less_token : operation = tex_scan_aux_less(&alreadygotten); break;
6995 case more_token : operation = tex_scan_aux_more(&alreadygotten); break;
6996
6997 case not_equal_token : operation = expression_unequal; break;
6998 case less_or_equal_token: operation = expression_lessequal; break;
6999 case more_or_equal_token: operation = expression_moreequal; break;
7000
7001 case conditional_and_token: operation = expression_cand; break;
7002 case conditional_or_token : operation = expression_cor; break;
7003
7004 case a_token_l: case a_token_o: operation = tex_scan_aux_a(); break;
7005 case b_token_l: case b_token_o: operation = tex_scan_aux_b(); break;
7006 case c_token_l: case c_token_o: operation = tex_scan_aux_c(); break;
7007 case d_token_l: case d_token_o: operation = tex_scan_aux_d(); break;
7008 case m_token_l: case m_token_o: operation = tex_scan_aux_m(); break;
7009 case o_token_l: case o_token_o: operation = tex_scan_aux_o(); break;
7010 case v_token_l: case v_token_o: operation = expression_bor; break;
7011
7012 case ampersand_token_l :
7013 case ampersand_token_o :
7014 case ampersand_token_t : operation = tex_scan_aux_ampersand(&alreadygotten); break;
7015 case circumflex_token_l:
7016 case circumflex_token_o:
7017 case circumflex_token_s: operation = expression_bxor; break;
7018 case bar_token_l :
7019 case bar_token_o : operation = tex_scan_aux_bar(&alreadygotten); break;
7020
7021 default:
7022 operation = expression_none;
7023 if (! top) {
7024 if (cur_cmd == relax_cmd) {
7025 if (braced > 0) {
7026 tex_aux_scan_unexpected_relax_error();
7027 } else {
7028
7029 }
7030 } else if (braced == 1 && cur_cmd == right_brace_cmd) {
7031
7032 } else {
7033 if (braced > 0) {
7034 tex_aux_scan_unexpected_whatever_error();
7035 }
7036 tex_back_input(cur_tok);
7037 }
7038 } else if (cur_cmd == right_brace_cmd) {
7039 if (braced) {
7040 --braced;
7041 } else {
7042 tex_back_input(cur_tok);
7043 }
7044 } else if (cur_tok != right_parent_token) {
7045 tex_aux_scan_missing_error();
7046 }
7047 break;
7048 }
7049 lmt_scanner_state.arithmic_error = error_b;
7050 if (state > expression_subtract) {
7051 if (factor > max_integer || factor < min_integer) {
7052 lmt_scanner_state.arithmic_error = 1;
7053 factor = 0;
7054 }
7055 }
7056 switch (state) {
7057 case expression_none:
7058 term = factor;
7059 break;
7060 case expression_multiply:
7061 if (operation == expression_divide) {
7062 numerator = factor;
7063 operation = expression_scale;
7064 } else {
7065 term = tex_aux_long_long((double) term * (double) factor);
7066 }
7067 break;
7068 case expression_divide:
7069
7070 term = tex_aux_double_rounded_long_long((double) term / (double) factor);
7071 break;
7072 case expression_scale:
7073 term = tex_aux_double_rounded_long_long((double) term * (double) numerator / (double) factor);
7074 break;
7075 case expression_idivide:
7076 term = term / factor;
7077 break;
7078 case expression_imodulo:
7079 term = tex_aux_double_rounded_long_long(fmod((double) term, (double) factor));
7080 break;
7081
7082 case expression_equal : term = term == factor; break;
7083 case expression_less : term = term < factor; break;
7084 case expression_more : term = term > factor; break;
7085 case expression_lessequal: term = term <= factor; break;
7086 case expression_moreequal: term = term >- factor; break;
7087 case expression_unequal : term = term != factor; break;
7088 case expression_bleft : term = term << factor; break;
7089 case expression_bright : term = term >> factor; break;
7090
7091 case expression_or : term = (term || factor) ? 1 : 0; break;
7092 case expression_and : term = (term && factor) ? 1 : 0; break;
7093
7094 case expression_cor : term = term ? term : (factor ? factor : 0); break;
7095 case expression_cand : term = (term && factor) ? factor : 0; break;
7096
7097 case expression_bor : term |= factor; break;
7098 case expression_band : term &= factor; break;
7099 case expression_bxor : term ^= factor; break;
7100
7101 case expression_bset : term = term | ((long long) 1 << (factor - 1)); break;
7102 case expression_bunset : term = term & ~ ((long long) 1 << (factor - 1)); break;
7103
7104 case expression_not:
7105
7106 term = term ? 0 : 1;
7107 break;
7108 }
7109 if (operation > expression_subtract) {
7110 state = operation;
7111 } else {
7112 state = expression_none;
7113 switch (result) {
7114 case expression_add : expression = tex_aux_long_long(expression + term); break;
7115 case expression_subtract: expression = tex_aux_long_long(expression - term); break;
7116
7117 case expression_not : expression = term ? 0 : 1; break;
7118 case expression_bnot : expression = ~ term; break;
7119
7120 default:
7121 expression = term;
7122 break;
7123 }
7124 result = operation;
7125 }
7126 error_b = lmt_scanner_state.arithmic_error;
7127 if (operation != expression_none) {
7128 goto CONTINUE;
7129 } else if (top) {
7130 POP:
7131 --depth;
7132 {
7133 halfword newtop = node_next(top);
7134 factor = expression;
7135 expression = lmtx_expression_expression(top);
7136 term = lmtx_expression_term(top);
7137 numerator = lmtx_expression_numerator(top);
7138 state = lmtx_expression_state(top);
7139 result = lmtx_expression_result(top);
7140 switch (node_subtype(top)) {
7141 case 0x1:
7142 if (cur_tok != right_parent_token) {
7143 expression = 0;
7144 tex_aux_scan_parent_error();
7145 tex_flush_node_list(top);
7146 top = null;
7147 goto DONE;
7148 }
7149 break;
7150 case 0x2:
7151 if (cur_cmd != right_brace_cmd) {
7152 expression = 0;
7153 tex_aux_scan_brace_error();
7154 tex_flush_node_list(top);
7155 top = null;
7156 goto DONE;
7157 }
7158 break;
7159 }
7160 if (lmtx_expression_negate(top) & 0x01) {
7161 factor = - factor;
7162 }
7163 if (lmtx_expression_negate(top) & 0x02) {
7164 factor = factor ? 0 : 1;
7165 }
7166 if (lmtx_expression_negate(top) & 0x04) {
7167 factor = ~ factor;
7168 }
7169 if ((lmtx_expression_negate(top) & 0x08) && factor < 0) {
7170 factor = - factor;
7171 }
7172 if ((lmtx_expression_negate(top) & 0x10) && factor > 0) {
7173 factor = - factor;
7174 }
7175 tex_free_node(top, lmtx_expression_node_size);
7176 top = newtop;
7177 goto FOUND;
7178 }
7179 } else if (error_b) {
7180 tex_aux_scan_integer_out_of_range_error(8);
7181 expression = 0;
7182 }
7183 DONE:
7184 lmt_scanner_state.arithmic_error = error_a;
7185 lmt_scanner_state.expression_depth--;
7186
7187 cur_val_level = integer_val_level;
7188 if (expression < min_integer) {
7189 tex_aux_scan_integer_out_of_range_error(9);
7190 cur_val = min_integer;
7191 } else if (expression > max_integer) {
7192 tex_aux_scan_integer_out_of_range_error(9);
7193 cur_val = max_integer;
7194 } else {
7195 cur_val = (halfword) expression;
7196 }
7197}
7198
7199typedef enum expression_type {
7200 expression_type_integer,
7201 expression_type_dimension,
7202 expression_type_float,
7203} expression_type;
7204
7205static long long tex_aux_expression_d_round(double d, halfword *termtype, halfword factortype)
7206{
7207 switch (*termtype) {
7208 case expression_type_integer:
7209 *termtype = factortype;
7210 break;
7211 case expression_type_dimension:
7212 switch (factortype) {
7213 case expression_type_integer:
7214 *termtype = expression_type_dimension;
7215 break;
7216 case expression_type_dimension:
7217 d /= 65536;
7218 *termtype = expression_type_dimension;
7219 break;
7220 case expression_type_float:
7221 d /= 65536;
7222 *termtype = expression_type_dimension;
7223 break;
7224 }
7225 break;
7226 case expression_type_float:
7227 switch (factortype) {
7228 case expression_type_integer:
7229 *termtype = expression_type_float;
7230 break;
7231 case expression_type_dimension:
7232 d /= 65536;
7233 *termtype = expression_type_dimension;
7234 break;
7235 case expression_type_float:
7236 d /= 65536;
7237 *termtype = expression_type_float;
7238 break;
7239 }
7240 break;
7241 }
7242 if (d < min_doubleinteger) {
7243 return min_longinteger;
7244 } else if (d > max_doubleinteger) {
7245 return max_longinteger;
7246 } else {
7247 return longlonground(d);
7248 }
7249}
7250
7251static long long tex_aux_expression_d_divide(double d, halfword *termtype, halfword factortype)
7252{
7253 switch (*termtype) {
7254 case expression_type_integer:
7255 *termtype = factortype;
7256 break;
7257 case expression_type_dimension:
7258 switch (factortype) {
7259 case expression_type_integer:
7260 *termtype = expression_type_dimension;
7261 break;
7262 case expression_type_dimension:
7263 d *= 65536;
7264 *termtype = expression_type_dimension;
7265 break;
7266 case expression_type_float:
7267 d *= 65536;
7268 *termtype = expression_type_dimension;
7269 break;
7270 }
7271 break;
7272 case expression_type_float:
7273 switch (factortype) {
7274 case expression_type_integer:
7275 *termtype = expression_type_float;
7276 break;
7277 case expression_type_dimension:
7278 d *= 65536;
7279 *termtype = expression_type_dimension;
7280 break;
7281 case expression_type_float:
7282 d *= 65536;
7283 *termtype = expression_type_float;
7284 break;
7285 }
7286 break;
7287 }
7288 if (d < min_doubleinteger) {
7289 return min_longinteger;
7290 } else if (d > max_doubleinteger) {
7291 return max_longinteger;
7292 } else {
7293 return longlonground(d);
7294 }
7295}
7296
7297static long long tex_aux_expression_d_round_divide(double d, halfword *termtype, halfword factortype, halfword divtype)
7298{
7299 switch (*termtype) {
7300 case expression_type_integer:
7301 *termtype = factortype;
7302 break;
7303 case expression_type_dimension:
7304 switch (factortype) {
7305 case expression_type_integer:
7306 *termtype = expression_type_dimension;
7307 break;
7308 case expression_type_dimension:
7309 d /= 65536;
7310 *termtype = expression_type_dimension;
7311 break;
7312 case expression_type_float:
7313 d /= 65536;
7314 *termtype = expression_type_dimension;
7315 break;
7316 }
7317 break;
7318 case expression_type_float:
7319 switch (factortype) {
7320 case expression_type_integer:
7321 *termtype = expression_type_float;
7322 break;
7323 case expression_type_dimension:
7324 d /= 65536;
7325 *termtype = expression_type_dimension;
7326 break;
7327 case expression_type_float:
7328 d /= 65536;
7329 *termtype = expression_type_float;
7330 break;
7331 }
7332 break;
7333 }
7334
7335 switch (*termtype) {
7336 case expression_type_integer:
7337 *termtype = divtype;
7338 break;
7339 case expression_type_dimension:
7340 switch (divtype) {
7341 case expression_type_integer:
7342 *termtype = expression_type_dimension;
7343 break;
7344 case expression_type_dimension:
7345 d *= 65536;
7346 *termtype = expression_type_dimension;
7347 break;
7348 case expression_type_float:
7349 d *= 65536;
7350 *termtype = expression_type_dimension;
7351 break;
7352 }
7353 break;
7354 case expression_type_float:
7355 switch (divtype) {
7356 case expression_type_integer:
7357 *termtype = expression_type_float;
7358 break;
7359 case expression_type_dimension:
7360 d *= 65536;
7361 *termtype = expression_type_dimension;
7362 break;
7363 case expression_type_float:
7364 d *= 65536;
7365 *termtype = expression_type_float;
7366 break;
7367 }
7368 break;
7369 }
7370 if (d < min_doubleinteger) {
7371 return min_longinteger;
7372 } else if (d > max_doubleinteger) {
7373 return max_longinteger;
7374 } else {
7375 return longlonground(d);
7376 }
7377}
7378
7379static long long tex_aux_expression_d_floor(double d, halfword *termtype, halfword factortype)
7380{
7381 switch (*termtype) {
7382 case expression_type_integer:
7383 *termtype = factortype;
7384 break;
7385 case expression_type_dimension:
7386 switch (factortype) {
7387 case expression_type_integer:
7388 *termtype = expression_type_dimension;
7389 break;
7390 case expression_type_dimension:
7391 d /= 65536;
7392 *termtype = expression_type_dimension;
7393 break;
7394 case expression_type_float:
7395 d /= 65536;
7396 *termtype = expression_type_dimension;
7397 break;
7398 }
7399 break;
7400 case expression_type_float:
7401 switch (factortype) {
7402 case expression_type_integer:
7403 *termtype = expression_type_float;
7404 break;
7405 case expression_type_dimension:
7406 d /= 65536;
7407 *termtype = expression_type_dimension;
7408 break;
7409 case expression_type_float:
7410 d /= 65536;
7411 *termtype = expression_type_float;
7412 break;
7413 }
7414 break;
7415 }
7416 if (d < min_doubleinteger) {
7417 return min_longinteger;
7418 } else if (d > max_doubleinteger) {
7419 return max_longinteger;
7420 } else {
7421 return (long long) d;
7422 }
7423}
7424
7425
7426
7427static void tex_aux_scan_dimension_expression(int braced)
7428{
7429 int result;
7430 int state;
7431 int operation;
7432 int negate;
7433 int nothing;
7434 int positive;
7435 int negative;
7436 int expressiontype;
7437 int termtype;
7438 int factortype = expression_type_integer;
7439 int numeratortype;
7440 long long expression;
7441 long long term;
7442 long long factor = 0;
7443 long long numerator;
7444 int error_a = lmt_scanner_state.arithmic_error;
7445 int error_b = 0;
7446 halfword top = null;
7447 int alreadygotten = 0;
7448 int depth = 0;
7449 cur_val_level = dimension_val_level;
7450 lmt_scanner_state.expression_depth++;
7451 if (lmt_scanner_state.expression_depth > max_expression_depth) {
7452 tex_fatal_error("\\dimexpression can only be nested " LMT_TOSTRING(max_expression_depth) " deep");
7453 }
7454 RESTART:
7455 result = expression_none;
7456 state = expression_none;
7457 expressiontype = expression_type_dimension;
7458 termtype = expression_type_dimension;
7459 numeratortype = expression_type_integer;
7460 expression = 0;
7461 term = 0;
7462 numerator = 0;
7463 negate = 0;
7464 nothing = 0;
7465 positive = 0;
7466 negative = 0;
7467 CONTINUE:
7468 operation = dimension_val_level;
7469 AGAIN:
7470 if (alreadygotten) {
7471 alreadygotten = 0;
7472 goto ALREADYGOTTEN;
7473 }
7474 while (1) {
7475 tex_get_x_token();
7476 ALREADYGOTTEN:
7477 switch (cur_cmd ){
7478 case spacer_cmd:
7479 continue;
7480 case left_brace_cmd:
7481 if ((negate || nothing || positive || negative) && braced == 0) {
7482 tex_aux_scan_expression_unexpected_negation_error();
7483 break;
7484 } else {
7485 ++braced;
7486 if (braced > 1) {
7487 goto PUSH;
7488 } else {
7489 goto AGAIN;
7490 }
7491 }
7492 case right_brace_cmd:
7493 if (braced > 1) {
7494 --braced;
7495 goto POP;
7496 } else {
7497 break;
7498 }
7499 case end_paragraph_cmd:
7500 if (braced) {
7501 continue;
7502 } else {
7503 break;
7504 }
7505 default:
7506 switch (cur_tok) {
7507 case minus_token:
7508 negate = ! negate;
7509 continue;
7510 case plus_token:
7511 continue;
7512 case n_token_l:
7513 case n_token_o:
7514 switch (tex_scan_aux_n()) {
7515 case expression_not:
7516 nothing = ! nothing;
7517 continue;
7518 case expression_positive:
7519 positive = 1;
7520 continue;
7521 case expression_negative:
7522 negative = 1;
7523 continue;
7524 default:
7525 break;
7526 }
7527 case exclamation_token_l:
7528 case exclamation_token_o:
7529 if (tex_scan_aux_exclamation(&alreadygotten) == expression_not) {
7530 nothing = ! nothing;
7531 continue;
7532 } else {
7533 alreadygotten = 0;
7534 goto ALREADYGOTTEN;
7535 }
7536 case plus_minus_token:
7537 positive = 1;
7538 continue;
7539 case minus_plus_token:
7540 negative = 1;
7541 continue;
7542 case left_parent_token:
7543 PUSH:
7544 ++depth;
7545 if (depth > max_sub_expression_depth) {
7546 tex_fatal_error("sub expressions can only be nested " LMT_TOSTRING(max_sub_expression_depth) " deep");
7547 }
7548 {
7549 halfword newtop = tex_get_node(lmtx_expression_node_size);
7550 node_type(newtop) = lmtx_expression_node;
7551 node_subtype(newtop) = cur_tok == left_parent_token ? 0x1 : 0x2;
7552 node_next(newtop) = top;
7553 lmtx_expression_type(newtop) = (singleword) dimension_val_level;
7554 lmtx_expression_state(newtop) = (singleword) state;
7555 lmtx_expression_result(newtop) = (singleword) result;
7556 lmtx_expression_negate(newtop) = (singleword) (negate | (nothing << 1) | (positive << 3) | (negative << 4));
7557 lmtx_expression_expression(newtop) = expression;
7558 lmtx_expression_term(newtop) = term;
7559 lmtx_expression_numerator(newtop) = numerator;
7560 lmtx_expression_type_expression(newtop) = expressiontype;
7561 lmtx_expression_type_term(newtop) = termtype;
7562 lmtx_expression_type_numerator(newtop) = numeratortype;
7563 top = newtop;
7564 goto RESTART;
7565 }
7566 default:
7567 goto ACTION;
7568 }
7569 }
7570 }
7571 ACTION:
7572 {
7573 int has_fraction = 0;
7574 int has_unit = 1;
7575 factor = tex_scan_bit_dimension(&has_fraction, &has_unit);
7576 if (has_unit) {
7577 factortype = expression_type_dimension;
7578 } else if (has_fraction) {
7579 factortype = expression_type_float;
7580 } else {
7581 factortype = expression_type_integer;
7582 }
7583 }
7584 if (negate) {
7585 factor = - factor;
7586 negate = 0;
7587 }
7588 if (nothing) {
7589 factor = factor ? 0 : 1;
7590 nothing = 0;
7591 factortype = expression_type_integer;
7592 }
7593 if (positive) {
7594 if (factor < 0) {
7595 factor = - factor;
7596 }
7597 positive = 0;
7598 }
7599 if (negative) {
7600 if (factor > 0) {
7601 factor = - factor;
7602 }
7603 negative = 0;
7604 }
7605 FOUND:
7606 do {
7607 tex_get_x_token();
7608 } while (cur_cmd == spacer_cmd || (braced && cur_cmd == end_paragraph_cmd));
7609 switch (cur_tok) {
7610 case plus_token : operation = expression_add; break;
7611 case minus_token : operation = expression_subtract; break;
7612 case asterisk_token : operation = expression_multiply; break;
7613 case slash_token : operation = expression_divide; break;
7614 case colon_token : operation = expression_idivide; break;
7615 case semi_colon_token:
7616 case percentage_token: operation = expression_imodulo; break;
7617
7618 case equal_token: operation = tex_scan_aux_equal(&alreadygotten); break;
7619 case less_token : operation = tex_scan_aux_less(&alreadygotten); break;
7620 case more_token : operation = tex_scan_aux_more(&alreadygotten); break;
7621
7622 case not_equal_token : operation = expression_unequal; break;
7623 case less_or_equal_token: operation = expression_lessequal; break;
7624 case more_or_equal_token: operation = expression_moreequal; break;
7625
7626 case conditional_and_token: operation = expression_cand; break;
7627 case conditional_or_token : operation = expression_cor; break;
7628
7629 case a_token_l: case a_token_o: operation = tex_scan_aux_a(); break;
7630 case c_token_l: case c_token_o: operation = tex_scan_aux_c(); break;
7631 case d_token_l: case d_token_o: operation = tex_scan_aux_d(); break;
7632 case m_token_l: case m_token_o: operation = tex_scan_aux_m(); break;
7633 case o_token_l: case o_token_o: operation = tex_scan_aux_o(); break;
7634
7635 default:
7636 operation = expression_none;
7637 if (! top) {
7638 if (cur_cmd == relax_cmd) {
7639 if (braced > 0) {
7640 tex_aux_scan_unexpected_relax_error();
7641 } else {
7642
7643 }
7644 } else if (braced == 1 && cur_cmd == right_brace_cmd) {
7645
7646 } else {
7647 if (braced > 0) {
7648 tex_aux_scan_unexpected_whatever_error();
7649 }
7650 tex_back_input(cur_tok);
7651 }
7652 } else if (cur_cmd == right_brace_cmd) {
7653 if (braced) {
7654 --braced;
7655 } else {
7656 tex_back_input(cur_tok);
7657 }
7658 } else if (cur_tok != right_parent_token) {
7659 tex_aux_scan_missing_error();
7660 }
7661 break;
7662 }
7663 lmt_scanner_state.arithmic_error = error_b;
7664 if (llabs(factor) > max_dimension) {
7665 lmt_scanner_state.arithmic_error = 1;
7666 factor = 0;
7667 }
7668 switch (state) {
7669 case expression_none:
7670 term = factor;
7671 termtype = factortype;
7672 break;
7673 case expression_multiply:
7674 if (operation == expression_divide) {
7675 numerator = factor;
7676 numeratortype = factortype;
7677 operation = expression_scale;
7678 } else {
7679 term = tex_aux_expression_d_round((double) term * (double) factor, &termtype, factortype);
7680 }
7681 break;
7682 case expression_divide:
7683 if (factor == 0) {
7684 lmt_scanner_state.arithmic_error = 1;
7685 term = 0;
7686 termtype = expression_type_integer;
7687 } else {
7688 term = tex_aux_expression_d_divide((double) term / (double) factor, &termtype, factortype);
7689 }
7690 break;
7691 case expression_scale:
7692 if (factor == 0) {
7693 lmt_scanner_state.arithmic_error = 1;
7694 term = 0;
7695 termtype = expression_type_integer;
7696 } else {
7697
7698
7699 term = tex_aux_expression_d_round_divide((double) term * (double) numerator / (double) factor, &termtype, numeratortype, factortype);
7700 }
7701 break;
7702 case expression_idivide:
7703 if (factor == 0) {
7704 lmt_scanner_state.arithmic_error = 1;
7705 term = 0;
7706 termtype = expression_type_integer;
7707 } else {
7708 term = tex_aux_expression_d_floor((double) term / (double) factor, &termtype, factortype);
7709 }
7710 break;
7711 case expression_imodulo:
7712 if (factor == 0) {
7713 lmt_scanner_state.arithmic_error = 1;
7714 term = 0;
7715 termtype = expression_type_integer;
7716 } else {
7717 term = tex_aux_expression_d_divide(fmod((double) term, (double) factor), &termtype, factortype);
7718 }
7719 break;
7720
7721 case expression_equal:
7722
7723 term = term == factor;
7724 termtype = expression_type_integer;
7725 break;
7726 case expression_less:
7727
7728 term = term < factor;
7729 termtype = expression_type_integer;
7730 break;
7731 case expression_more:
7732
7733 term = term > factor;
7734 termtype = expression_type_integer;
7735 break;
7736 case expression_lessequal:
7737
7738 term = term <= factor;
7739 termtype = expression_type_integer;
7740 break;
7741 case expression_moreequal:
7742
7743 term = term >- factor;
7744 termtype = expression_type_integer;
7745 break;
7746 case expression_unequal:
7747
7748 term = term != factor;
7749 termtype = expression_type_integer;
7750 break;
7751 case expression_or:
7752
7753 term = (term || factor) ? 1 : 0;
7754 termtype = expression_type_integer;
7755 break;
7756 case expression_and:
7757
7758 term = (term && factor) ? 1 : 0;
7759 termtype = expression_type_integer;
7760 break;
7761 case expression_cor:
7762 if (term) {
7763
7764 } else if (factor) {
7765 term = factor;
7766 termtype = factortype;
7767 } else {
7768 term = 0;
7769 termtype = expression_type_integer;
7770 }
7771 break;
7772 case expression_cand:
7773 if (term && factor) {
7774 term = factor;
7775 termtype = factortype;
7776 } else {
7777 term = 0;
7778 termtype = expression_type_integer;
7779 }
7780 break;
7781 case expression_not:
7782
7783
7784 term = ! term;
7785 termtype = expression_type_integer;
7786 break;
7787
7788 }
7789 if (operation > expression_subtract) {
7790 state = operation;
7791 } else {
7792 state = expression_none;
7793 switch (result) {
7794 case expression_add:
7795
7796 expression = expression + term;
7797 expressiontype = expression_type_dimension;
7798 break;
7799 case expression_subtract:
7800
7801 expression = expression - term;
7802 expressiontype = expression_type_dimension;
7803 break;
7804 case expression_not:
7805 expression = term ? 0 : 1;
7806 expressiontype = expression_type_dimension;
7807 break;
7808
7809 default:
7810 expression = term;
7811 expressiontype = termtype;
7812 break;
7813 }
7814 result = operation;
7815 }
7816 error_b = lmt_scanner_state.arithmic_error;
7817 if (operation != expression_none) {
7818 goto CONTINUE;
7819 } else if (top) {
7820 POP:
7821 --depth;
7822 {
7823 halfword newtop = node_next(top);
7824 factor = expression;
7825 expression = lmtx_expression_expression(top);
7826 term = lmtx_expression_term(top);
7827 numerator = lmtx_expression_numerator(top);
7828 state = lmtx_expression_state(top);
7829 result = lmtx_expression_result(top);
7830 expressiontype = lmtx_expression_type_expression(top);
7831 termtype = lmtx_expression_type_term(top);
7832 numeratortype = lmtx_expression_type_numerator(top);
7833 switch (node_subtype(top)) {
7834 case 0x1:
7835 if (cur_tok != right_parent_token) {
7836 expression = 0;
7837 tex_aux_scan_parent_error();
7838 tex_flush_node_list(top);
7839 top = null;
7840 goto DONE;
7841 }
7842 break;
7843 case 0x2:
7844 if (cur_cmd != right_brace_cmd) {
7845 expression = 0;
7846 tex_aux_scan_brace_error();
7847 tex_flush_node_list(top);
7848 top = null;
7849 goto DONE;
7850 }
7851 break;
7852 }
7853 if (lmtx_expression_negate(top) & 0x01) {
7854 factor = - factor;
7855 }
7856 if (lmtx_expression_negate(top) & 0x02) {
7857 factor = factor ? 0 : 1;
7858 factortype = expression_type_integer;
7859 }
7860 if ((lmtx_expression_negate(top) & 0x08) && factor < 0) {
7861 factor = - factor;
7862 }
7863 if ((lmtx_expression_negate(top) & 0x10) && factor > 0) {
7864 factor = - factor;
7865 }
7866 tex_free_node(top, lmtx_expression_node_size);
7867 top = newtop;
7868 goto FOUND;
7869 }
7870 } else if (error_b) {
7871 tex_aux_scan_dimension_out_of_range_error(4);
7872 expression = 0;
7873 }
7874 DONE:
7875 lmt_scanner_state.arithmic_error = error_a;
7876 lmt_scanner_state.expression_depth--;
7877 cur_val_level = dimension_val_level;
7878 if (expression < min_dimension) {
7879 tex_aux_scan_dimension_out_of_range_error(5);
7880 cur_val = min_dimension;
7881 } else if (expression > max_dimension) {
7882 tex_aux_scan_dimension_out_of_range_error(5);
7883 cur_val = max_dimension;
7884 } else {
7885 cur_val = (halfword) expression;
7886 }
7887}
7888
7889
7918
7919
7922
7923typedef enum bit_expression_states {
7924 bit_expression_none,
7925
7926 bit_expression_bor,
7927 bit_expression_band,
7928 bit_expression_bxor,
7929 bit_expression_bnot,
7930
7931 bit_expression_bset,
7932 bit_expression_bunset,
7933
7934 bit_expression_bleft,
7935 bit_expression_bright,
7936
7937 bit_expression_less,
7938 bit_expression_lessequal,
7939 bit_expression_equal,
7940 bit_expression_moreequal,
7941 bit_expression_more,
7942 bit_expression_unequal,
7943
7944 bit_expression_add,
7945 bit_expression_subtract,
7946
7947 bit_expression_multiply,
7948 bit_expression_divide,
7949
7950 bit_expression_div,
7951 bit_expression_mod,
7952
7953
7954
7955 bit_expression_not,
7956
7957 bit_expression_pm,
7958 bit_expression_mp,
7959
7960 bit_expression_or,
7961 bit_expression_and,
7962
7963 bit_expression_cor,
7964 bit_expression_cand,
7965
7966 bit_expression_open_parent,
7967 bit_expression_close_parent,
7968 bit_expression_open_brace,
7969 bit_expression_close_brace,
7970
7971 bit_expression_number,
7972 bit_expression_float,
7973 bit_expression_dimension,
7974
7975 bit_expression_plus,
7976 bit_expression_minus,
7977 bit_expression_flip,
7978 bit_expression_positive,
7979 bit_expression_negative,
7980
7981
7982
7983 bit_expression_sin,
7984 bit_expression_cos,
7985 bit_expression_tan,
7986 bit_expression_asin,
7987 bit_expression_acos,
7988 bit_expression_atan,
7989
7990 bit_expression_sinh,
7991 bit_expression_cosh,
7992 bit_expression_tanh,
7993 bit_expression_asinh,
7994 bit_expression_acosh,
7995 bit_expression_atanh,
7996
7997 bit_expression_ceil,
7998 bit_expression_floor,
7999 bit_expression_round,
8000 bit_expression_abs,
8001
8002 bit_expression_sqrt,
8003 bit_expression_log,
8004 bit_expression_ln,
8005 bit_expression_exp,
8006
8007
8008
8009 bit_expression_last,
8010} bit_expression_states;
8011
8012static int bit_operator_precedence[bit_expression_last+1] = {
8013 0,
8014
8015 4,
8016 6,
8017 5,
8018 10,
8019
8020 7,
8021 7,
8022
8023 7,
8024 7,
8025
8026 3,
8027 3,
8028 3,
8029 3,
8030 3,
8031 3,
8032
8033 8,
8034 8,
8035
8036 9,
8037 9,
8038
8039 9,
8040 9,
8041
8042
8043
8044 10,
8045
8046 10,
8047 10,
8048
8049 1,
8050 2,
8051
8052 1,
8053 2,
8054
8055 0,
8056 0,
8057 0,
8058 0,
8059
8060 0,
8061 0,
8062 0,
8063
8064 0, 0, 0, 0, 0,
8065
8066 0, 0, 0, 0, 0, 0,
8067 0, 0, 0, 0, 0, 0,
8068 0, 0, 0, 0,
8069 0, 0, 0, 0,
8070
8071 0
8072};
8073
8074static const char *bit_expression_names[bit_expression_last+1] = {
8075 "none",
8076 "bor", "band", "bxor", "bnot",
8077 "bset", "bunset",
8078 "<<", ">>",
8079 "<", "<=", "==", ">=", ">", "<>",
8080 "+", "-",
8081 "*", "/",
8082 "div", "mod",
8083 "not",
8084 "±", "∓"
8085 "or", "and",
8086 "cor", "cand",
8087 "open (", "close )", "open {", "close }",
8088 "number", "float", "dimension",
8089 "plus","minus","flip","positive", "negative",
8090
8091 "sin", "cos", "tan", "asin", "acos", "atan",
8092 "sinh", "cosh", "tanh", "asinh", "acosh", "atanh",
8093 "ceil", "floor", "round", "abs",
8094 "sqrt", "log", "ln", "exp",
8095
8096 "null"
8097};
8098
8099
8103
8104# define factor 1
8105
8106typedef struct stack_info {
8107 halfword head;
8108 halfword tail;
8109} stack_info;
8110
8111static stack_info tex_aux_new_stack(void)
8112{
8113 return (stack_info) {
8114 .head = null,
8115 .tail = null,
8116 };
8117}
8118
8119static void tex_aux_dispose_stack(stack_info *stack)
8120{
8121
8122 halfword current = stack->head;
8123 while (current) {
8124 halfword next = node_next(current);
8125 tex_free_node(current, rpn_expression_node_size);
8126 current = next;
8127 }
8128}
8129
8130static void tex_push_stack_entry(stack_info *stack, long long value)
8131{
8132 halfword n = tex_get_node(rpn_expression_node_size);
8133 node_type(n) = rpn_expression_node;
8134 node_subtype(n) = 0;
8135 rpn_expression_entry(n) = value;
8136 if (! stack->head) {
8137 stack->head = n;
8138 } else if (stack->head == stack->tail) {
8139 node_next(stack->head) = n;
8140 node_prev(n) = stack->head;
8141 } else {
8142 node_prev(n) = stack->tail;
8143 node_next(stack->tail) = n;
8144 }
8145 stack->tail = n;
8146}
8147
8148static long long tex_pop_stack_entry(stack_info *stack)
8149{
8150 halfword t = stack->tail;
8151 if (t) {
8152 long long v = rpn_expression_entry(t);
8153 if (t == stack->head) {
8154 stack->head = null;
8155 stack->tail = null;
8156 } else {
8157 stack->tail = node_prev(t);
8158 node_next(stack->tail) = null;
8159 }
8160 tex_free_node(t, rpn_expression_node_size);
8161 return v;
8162 } else {
8163 return 0;
8164 }
8165}
8166
8167static void tex_move_stack_entry(stack_info *target, stack_info *source)
8168{
8169 halfword n = source->tail;
8170 if (n == source->head) {
8171 source->head = null;
8172 source->tail = null;
8173 } else {
8174 source->tail = node_prev(n);
8175 }
8176 if (! target->head) {
8177 target->head = n;
8178 node_prev(n) = null;
8179 } else if (target->head == target->tail) {
8180 node_next(target->head) = n;
8181 node_prev(n) = target->head;
8182 } else {
8183 node_prev(n) = target->tail;
8184 node_next(target->tail) = n;
8185 }
8186 node_next(n) = null;
8187 target->tail = n;
8188}
8189
8190static void tex_take_stack_entry(stack_info *target, stack_info *source, halfword current)
8191{
8192 while (source->head != current) {
8193 halfword next = node_next(source->head);
8194 tex_free_node(source->head, rpn_expression_node_size);
8195 source->head = next;
8196 }
8197 if (current == source->tail) {
8198 source->head = null;
8199 source->tail = null;
8200 } else {
8201 source->head = node_next(current);
8202 }
8203 if (! target->head) {
8204 target->head = current;
8205 node_prev(current) = null;
8206 } else if (target->head == target->tail) {
8207 node_next(target->head) = current;
8208 node_prev(current) = target->head;
8209 } else {
8210 node_prev(current) = target->tail;
8211 node_next(target->tail) = current;
8212 }
8213 node_next(current) = null;
8214 target->tail = current;
8215}
8216
8217# define e_v(value) ((value > max_integer) ? max_integer : ((value < min_integer) ? min_integer : (halfword) value))
8218
8219static void tex_aux_print_expression_entry(halfword type, long long value)
8220{
8221 switch (type) {
8222 case bit_expression_number:
8223 tex_print_int(e_v(value));
8224 break;
8225 case bit_expression_float:
8226 tex_print_dimension(e_v(value), no_unit);
8227 break;
8228 case bit_expression_dimension:
8229 tex_print_dimension(e_v(value), pt_unit);
8230 break;
8231 default:
8232 if (value >= 0 && value <= 38) {
8233 tex_print_str(bit_expression_names[value]);
8234 }
8235 break;
8236 }
8237}
8238
8239
8240
8241
8242
8243
8244
8245
8246
8247
8248static void tex_aux_trace_expression(stack_info stack, halfword level, halfword n, int what)
8249{
8250 tex_begin_diagnostic();
8251 if (n > 0) {
8252 tex_print_format(level == dimension_val_level ? "[dimexpression rpn %i %s:" : "[numexpression rpn %i %s:", n, what ? "r" :"s");
8253 if (! stack.head) {
8254 tex_print_char(' ');
8255 }
8256 } else {
8257 tex_print_str(level == dimension_val_level ? "[dimexpression rpn:" : "[numexpression rpn:");
8258 }
8259 for (halfword current = stack.head; current; current = node_next(current)) {
8260 tex_print_char(' ');
8261 tex_aux_print_expression_entry(node_subtype(current), rpn_expression_entry(current));
8262 }
8263 tex_print_char(']');
8264 tex_end_diagnostic();
8265}
8266
8267static inline halfword tex_scan_aux_function(int *alreadygotten)
8268{
8269 tex_get_x_token();
8270 switch (cur_tok) {
8271 case a_token_l: case a_token_o:
8272 tex_get_x_token();
8273 switch (cur_tok) {
8274 case b_token_l: case b_token_o:
8275 tex_get_x_token();
8276 switch (cur_tok) {
8277 case s_token_l: case s_token_o:
8278 return bit_expression_abs;
8279 }
8280 break;
8281 case c_token_l: case c_token_o:
8282 tex_get_x_token();
8283 switch (cur_tok) {
8284 case o_token_l: case o_token_o:
8285 tex_get_x_token();
8286 switch (cur_tok) {
8287 case s_token_l: case s_token_o:
8288 tex_get_x_token();
8289 switch (cur_tok) {
8290 case h_token_l: case h_token_o:
8291 return bit_expression_acosh;
8292 default:
8293 *alreadygotten = 1;
8294 return bit_expression_acos;
8295 }
8296 }
8297 break;
8298 }
8299 case s_token_l: case s_token_o:
8300 tex_get_x_token();
8301 switch (cur_tok) {
8302 case i_token_l: case i_token_o:
8303 tex_get_x_token();
8304 switch (cur_tok) {
8305 case n_token_l: case n_token_o:
8306 tex_get_x_token();
8307 switch (cur_tok) {
8308 case h_token_l: case h_token_o:
8309 return bit_expression_asinh;
8310 default:
8311 *alreadygotten = 1;
8312 return bit_expression_asin;
8313 }
8314 }
8315 break;
8316 }
8317 case t_token_l: case t_token_o:
8318 tex_get_x_token();
8319 switch (cur_tok) {
8320 case a_token_l: case a_token_o:
8321 tex_get_x_token();
8322 switch (cur_tok) {
8323 case n_token_l: case n_token_o:
8324 tex_get_x_token();
8325 switch (cur_tok) {
8326 case h_token_l: case h_token_o:
8327 return bit_expression_atanh;
8328 default:
8329 *alreadygotten = 1;
8330 return bit_expression_atan;
8331 }
8332 }
8333 break;
8334 }
8335 }
8336 break;
8337 case c_token_l: case c_token_o:
8338 tex_get_x_token();
8339 switch (cur_tok) {
8340 case e_token_l: case e_token_o:
8341 tex_get_x_token();
8342 switch (cur_tok) {
8343 case e_token_l: case e_token_o:
8344 tex_get_x_token();
8345 switch (cur_tok) {
8346 case i_token_l: case i_token_o:
8347 tex_get_x_token();
8348 switch (cur_tok) {
8349 case l_token_l: case l_token_o:
8350 return bit_expression_ceil;
8351 }
8352 break;
8353 }
8354 break;
8355 }
8356 break;
8357 case o_token_l: case o_token_o:
8358 tex_get_x_token();
8359 switch (cur_tok) {
8360 case s_token_l: case s_token_o:
8361 tex_get_x_token();
8362 switch (cur_tok) {
8363 case h_token_l: case h_token_o:
8364 return bit_expression_cosh;
8365 default:
8366 *alreadygotten = 1;
8367 return bit_expression_cos;
8368 }
8369 }
8370 break;
8371 }
8372 break;
8373 case e_token_l: case e_token_o:
8374 tex_get_x_token();
8375 switch (cur_tok) {
8376 case x_token_l: case x_token_o:
8377 tex_get_x_token();
8378 switch (cur_tok) {
8379 case p_token_l: case p_token_o:
8380 return bit_expression_exp;
8381 }
8382 break;
8383 }
8384 break;
8385 case f_token_l: case f_token_o:
8386 tex_get_x_token();
8387 switch (cur_tok) {
8388 case l_token_l: case l_token_o:
8389 tex_get_x_token();
8390 switch (cur_tok) {
8391 case o_token_l: case o_token_o:
8392 tex_get_x_token();
8393 switch (cur_tok) {
8394 case o_token_l: case o_token_o:
8395 tex_get_x_token();
8396 switch (cur_tok) {
8397 case r_token_l: case r_token_o:
8398 return bit_expression_floor;
8399 }
8400 break;
8401 }
8402 break;
8403 }
8404 break;
8405 }
8406 break;
8407 case l_token_l: case l_token_o:
8408 tex_get_x_token();
8409 switch (cur_tok) {
8410 case n_token_l: case n_token_o:
8411 return bit_expression_ln;
8412 case o_token_l: case o_token_o:
8413 tex_get_x_token();
8414 switch (cur_tok) {
8415 case g_token_l: case g_token_o:
8416 return bit_expression_log;
8417 }
8418 break;
8419 }
8420 break;
8421 case r_token_l: case r_token_o:
8422 tex_get_x_token();
8423 switch (cur_tok) {
8424 case o_token_l: case o_token_o:
8425 tex_get_x_token();
8426 switch (cur_tok) {
8427 case u_token_l: case u_token_o:
8428 tex_get_x_token();
8429 switch (cur_tok) {
8430 case n_token_l: case n_token_o:
8431 tex_get_x_token();
8432 switch (cur_tok) {
8433 case d_token_l: case d_token_o:
8434 return bit_expression_round;
8435 }
8436 break;
8437 }
8438 break;
8439 }
8440 break;
8441 }
8442 break;
8443 case s_token_l: case s_token_o:
8444 tex_get_x_token();
8445 switch (cur_tok) {
8446 case i_token_l: case i_token_o:
8447 tex_get_x_token();
8448 switch (cur_tok) {
8449 case n_token_l: case n_token_o:
8450 tex_get_x_token();
8451 switch (cur_tok) {
8452 case h_token_l: case h_token_o:
8453 return bit_expression_sinh;
8454 default:
8455 *alreadygotten = 1;
8456 return bit_expression_sin;
8457 }
8458 }
8459 break;
8460 case q_token_l: case q_token_o:
8461 tex_get_x_token();
8462 switch (cur_tok) {
8463 case q_token_l: case q_token_o:
8464 tex_get_x_token();
8465 switch (cur_tok) {
8466 case r_token_l: case r_token_o:
8467 tex_get_x_token();
8468 switch (cur_tok) {
8469 case t_token_l: case t_token_o:
8470 return bit_expression_sqrt;
8471 }
8472 break;
8473 }
8474 break;
8475 }
8476 break;
8477 }
8478 break;
8479 case t_token_l: case t_token_o:
8480 tex_get_x_token();
8481 switch (cur_tok) {
8482 case a_token_l: case a_token_o:
8483 tex_get_x_token();
8484 switch (cur_tok) {
8485 case n_token_l: case n_token_o:
8486 tex_get_x_token();
8487 switch (cur_tok) {
8488 case h_token_l: case h_token_o:
8489 return bit_expression_tanh;
8490 default:
8491 *alreadygotten = 1;
8492 return bit_expression_tan;
8493 }
8494 }
8495 break;
8496 }
8497 break;
8498 }
8499 tex_aux_show_keyword_error("function");
8500 return expression_none;
8501
8502}
8503
8504static double tex_aux_function_argument(stack_info *s)
8505{
8506 switch (node_subtype(s->tail)) {
8507 case bit_expression_float:
8508 case bit_expression_dimension:
8509 return (double) rpn_expression_entry(s->tail) / 65536.0;
8510 default:
8511 return (double) rpn_expression_entry(s->tail);
8512 }
8513}
8514
8515static long long tex_aux_function_result(stack_info *s, double v)
8516{
8517 switch (node_subtype(s->tail)) {
8518 case bit_expression_float:
8519 case bit_expression_dimension:
8520 break;
8521 default:
8522 node_subtype(s->tail) = bit_expression_float;
8523 break;
8524 }
8525 return longlonground(v * 65536);
8526}
8527
8528static void tex_aux_scan_expression(int level, int braced)
8529{
8530 stack_info operators = tex_aux_new_stack();
8531 stack_info reverse = tex_aux_new_stack();
8532 stack_info stack = tex_aux_new_stack();
8533 halfword operation = bit_expression_none;
8534 int alreadygotten = 0;
8535 int trace = tracing_expressions_par;
8536 halfword lastoperation = bit_expression_none;
8537 int negate = 0;
8538 int nothing = 0;
8539 int positive = 0;
8540 int negative = 0;
8541 int initial = 1;
8542 int depth = 0;
8543 lmt_scanner_state.expression_depth++;
8544 if (lmt_scanner_state.expression_depth > max_expression_depth) {
8545 tex_fatal_error("\\*expression can only be nested " LMT_TOSTRING(max_expression_depth) " deep");
8546 }
8547 while (1) {
8548 HERE:
8549 if (alreadygotten) {
8550 alreadygotten = 0;
8551 } else {
8552 tex_get_x_token();
8553 }
8554 operation = bit_expression_none;
8555 switch (cur_cmd) {
8556 case relax_cmd:
8557 goto COLLECTED;
8558 case left_brace_cmd:
8559 if (! braced) {
8560 braced = 1;
8561 continue;
8562 } else {
8563 ++braced;
8564 tex_push_stack_entry(&operators, bit_expression_open_brace);
8565 goto PUSH;
8566 }
8567 case right_brace_cmd:
8568 --braced;
8569 if (! braced) {
8570 goto COLLECTED;
8571 } else {
8572 while (operators.tail && rpn_expression_entry(operators.tail) != bit_expression_open_brace) {
8573 tex_move_stack_entry(&reverse, &operators);
8574 }
8575 if (! operators.tail) {
8576 goto BRACEERROR;
8577 }
8578 goto POP;
8579 }
8580 case spacer_cmd:
8581 case end_paragraph_cmd:
8582 continue;
8583 default:
8584 switch (cur_tok) {
8585 case left_parent_token:
8586 tex_push_stack_entry(&operators, bit_expression_open_parent);
8587 PUSH:
8588 ++depth;
8589 if (depth > max_sub_expression_depth) {
8590 tex_fatal_error("sub expressions can only be nested " LMT_TOSTRING(max_sub_expression_depth) " deep");
8591 }
8592 rpn_expression_negate(operators.tail) = (singleword) (negate | (nothing << 1) | (positive << 2) | (negative << 3));
8593 negate = 0;
8594 nothing = 0;
8595 positive = 0;
8596 negative = 0;
8597 lastoperation = bit_expression_none;
8598 continue;
8599 case right_parent_token:
8600 while (operators.tail && rpn_expression_entry(operators.tail) != bit_expression_open_parent) {
8601 tex_move_stack_entry(&reverse, &operators);
8602 }
8603 if (! operators.tail) {
8604 goto PARENTERROR;
8605 }
8606 POP:
8607 --depth;
8608 if (rpn_expression_negate(operators.tail) & 0x01) {
8609 tex_push_stack_entry(&reverse, bit_expression_minus);
8610 }
8611 if (rpn_expression_negate(operators.tail) & 0x02) {
8612 tex_push_stack_entry(&reverse, bit_expression_flip);
8613 }
8614 if (rpn_expression_negate(operators.tail) & 0x04) {
8615 tex_push_stack_entry(&reverse, bit_expression_positive);
8616 }
8617 if (rpn_expression_negate(operators.tail) & 0x08) {
8618 tex_push_stack_entry(&reverse, bit_expression_negative);
8619 }
8620 tex_pop_stack_entry(&operators);
8621 continue;
8622 case plus_token:
8623 if (lastoperation != bit_expression_none || initial) {
8624 operation = bit_expression_none;
8625 goto HERE;
8626 } else {
8627 operation = bit_expression_add;
8628 break;
8629 }
8630 case minus_token:
8631 if (lastoperation != bit_expression_none || initial) {
8632 operation = bit_expression_none;
8633 negate = ! negate;
8634 goto HERE;
8635 } else {
8636 operation = bit_expression_subtract;
8637 break;
8638 }
8639
8640 case asterisk_token : operation = bit_expression_multiply; break;
8641 case slash_token : operation = bit_expression_divide ; break;
8642 case colon_token : operation = bit_expression_div ; break;
8643 case percentage_token:
8644 case semi_colon_token: operation = bit_expression_mod ; break;
8645
8646
8647 case at_sign_token_l: case at_sign_token_o:
8648 if (level == dimension_val_level) {
8649 operation = tex_scan_aux_function(&alreadygotten);
8650 } else {
8651 goto UNEXPECTED;
8652 }
8653 break;
8654
8655 case ampersand_token_l: case ampersand_token_o: case ampersand_token_t:
8656 tex_get_x_token();
8657 switch (cur_tok) {
8658 case ampersand_token_l: case ampersand_token_o: case ampersand_token_t:
8659 operation = bit_expression_and;
8660 goto OKAY;
8661 }
8662 operation = bit_expression_band;
8663 alreadygotten = 1;
8664 break;
8665
8666 case not_equal_token : operation = bit_expression_unequal ; break;
8667 case less_or_equal_token : operation = bit_expression_lessequal; break;
8668 case more_or_equal_token : operation = bit_expression_moreequal; break;
8669 case conditional_and_token: operation = bit_expression_cand ; break;
8670 case conditional_or_token : operation = bit_expression_cor ; break;
8671
8672 case circumflex_token_l: case circumflex_token_o: case circumflex_token_s:
8673 operation = bit_expression_bxor;
8674 break;
8675 case bar_token_l: case bar_token_o:
8676 tex_get_x_token();
8677 switch (cur_tok) {
8678 case bar_token_l: case bar_token_o:
8679 operation = bit_expression_or;
8680 goto OKAY;
8681 }
8682 operation = bit_expression_bor;
8683 alreadygotten = 1;
8684 break;
8685 case less_token:
8686 tex_get_x_token();
8687 switch (cur_tok) {
8688 case less_token : operation = bit_expression_bleft ; goto OKAY;
8689 case equal_token: operation = bit_expression_lessequal; goto OKAY;
8690 case more_token : operation = bit_expression_unequal ; goto OKAY;
8691 }
8692 operation = bit_expression_less;
8693 alreadygotten = 1;
8694 break;
8695 case more_token:
8696 tex_get_x_token();
8697 switch (cur_tok) {
8698 case more_token : operation = bit_expression_bright ; goto OKAY;
8699 case equal_token: operation = bit_expression_moreequal; goto OKAY;
8700 }
8701 operation = bit_expression_more;
8702 alreadygotten = 1;
8703 break;
8704 case equal_token:
8705 tex_get_x_token();
8706 switch (cur_tok) {
8707 case equal_token:
8708 break;
8709 default:
8710 alreadygotten = 1;
8711 break;
8712 }
8713 operation = bit_expression_equal;
8714 break;
8715
8716 case plus_minus_token: positive = 1; operation = bit_expression_none; goto HERE;
8717 case minus_plus_token: negative = 1; operation = bit_expression_none; goto HERE;
8718
8719 case tilde_token_l: case tilde_token_o:
8720 tex_get_x_token();
8721 switch (cur_tok) {
8722 case equal_token:
8723 operation = bit_expression_unequal;
8724 goto OKAY;
8725 }
8726 operation = bit_expression_bnot;
8727 alreadygotten = 1;
8728 break;
8729 case exclamation_token_l: case exclamation_token_o:
8730 tex_get_x_token();
8731 switch (cur_tok) {
8732 case equal_token:
8733 operation = bit_expression_unequal;
8734 goto OKAY;
8735 }
8736 operation = bit_expression_not;
8737 alreadygotten = 1;
8738 break;
8739 case m_token_l: case m_token_o:
8740 tex_get_x_token();
8741 switch (cur_tok) {
8742 case o_token_l: case o_token_o:
8743 tex_get_x_token();
8744 switch (cur_tok) {
8745 case d_token_l: case d_token_o:
8746 operation = bit_expression_mod;
8747 goto OKAY;
8748 }
8749 }
8750 goto UNEXPECTED;
8751 case d_token_l: case d_token_o:
8752 tex_get_x_token();
8753 switch (cur_tok) {
8754 case i_token_l: case i_token_o:
8755 tex_get_x_token();
8756 switch (cur_tok) {
8757 case v_token_l: case v_token_o:
8758 operation = bit_expression_div;
8759 goto OKAY;
8760 }
8761 }
8762 goto UNEXPECTED;
8763 case n_token_l: case n_token_o:
8764 tex_get_x_token();
8765 switch (cur_tok) {
8766 case o_token_l: case o_token_o:
8767 tex_get_x_token();
8768 switch (cur_tok) {
8769 case t_token_l: case t_token_o:
8770 if (lastoperation != bit_expression_none || initial) {
8771 operation = bit_expression_none;
8772 nothing = ! nothing;
8773 goto HERE;
8774 } else {
8775 operation = bit_expression_not;
8776 goto OKAY;
8777 }
8778 }
8779 case p_token_l: case p_token_o:
8780 tex_get_x_token();
8781 switch (cur_tok) {
8782 case m_token_l: case m_token_o:
8783 if (lastoperation != bit_expression_none || initial) {
8784 operation = bit_expression_none;
8785 positive = 1;
8786 goto HERE;
8787 } else {
8788 operation = bit_expression_pm;
8789 goto OKAY;
8790 }
8791 }
8792 case m_token_l: case m_token_o:
8793 tex_get_x_token();
8794 switch (cur_tok) {
8795 case p_token_l: case p_token_o:
8796 if (lastoperation != bit_expression_none || initial) {
8797 operation = bit_expression_none;
8798 negative = 1;
8799 goto HERE;
8800 } else {
8801 operation = bit_expression_mp;
8802 goto OKAY;
8803 }
8804 }
8805 }
8806 goto UNEXPECTED;
8807 case a_token_l: case a_token_o:
8808 tex_get_x_token();
8809 switch (cur_tok) {
8810 case n_token_l: case n_token_o:
8811 tex_get_x_token();
8812 switch (cur_tok) {
8813 case d_token_l: case d_token_o:
8814 operation = bit_expression_and;
8815 goto OKAY;
8816 }
8817 break;
8818 }
8819 goto UNEXPECTED;
8820 case b_token_l: case b_token_o:
8821 tex_get_x_token();
8822 switch (cur_tok) {
8823 case a_token_l: case a_token_o:
8824 tex_get_x_token();
8825 switch (cur_tok) {
8826 case n_token_l: case n_token_o:
8827 tex_get_x_token();
8828 switch (cur_tok) {
8829 case d_token_l: case d_token_o:
8830 operation = bit_expression_band;
8831 goto OKAY;
8832 }
8833 }
8834 break;
8835 case o_token_l: case o_token_o:
8836 tex_get_x_token();
8837 switch (cur_tok) {
8838 case r_token_l: case r_token_o:
8839 operation = bit_expression_bor;
8840 goto OKAY;
8841 }
8842 break;
8843 case x_token_l: case x_token_o:
8844 tex_get_x_token();
8845 switch (cur_tok) {
8846 case o_token_l: case o_token_o:
8847 tex_get_x_token();
8848 switch (cur_tok) {
8849 case r_token_l: case r_token_o:
8850 operation = bit_expression_bxor;
8851 goto OKAY;
8852 }
8853 }
8854 break;
8855 case s_token_l: case s_token_o:
8856 tex_get_x_token();
8857 switch (cur_tok) {
8858 case e_token_l: case e_token_o:
8859 tex_get_x_token();
8860 switch (cur_tok) {
8861 case t_token_l: case t_token_o:
8862 operation = bit_expression_bset;
8863 goto OKAY;
8864 }
8865 }
8866 break;
8867 case u_token_l: case u_token_o:
8868 tex_get_x_token();
8869 switch (cur_tok) {
8870 case n_token_l: case n_token_o:
8871 tex_get_x_token();
8872 switch (cur_tok) {
8873 case s_token_l: case s_token_o:
8874 tex_get_x_token();
8875 switch (cur_tok) {
8876 case e_token_l: case e_token_o:
8877 tex_get_x_token();
8878 switch (cur_tok) {
8879 case t_token_l: case t_token_o:
8880 operation = bit_expression_bset;
8881 goto OKAY;
8882 }
8883 }
8884 }
8885 }
8886 break;
8887 }
8888 goto UNEXPECTED;
8889 case c_token_l: case c_token_o:
8890 tex_get_x_token();
8891 switch (cur_tok) {
8892 case a_token_l: case a_token_o:
8893 tex_get_x_token();
8894 switch (cur_tok) {
8895 case n_token_l: case n_token_o:
8896 tex_get_x_token();
8897 switch (cur_tok) {
8898 case d_token_l: case d_token_o:
8899 operation = bit_expression_cand;
8900 goto OKAY;
8901 }
8902 }
8903 break;
8904 case o_token_l: case o_token_o:
8905 tex_get_x_token();
8906 switch (cur_tok) {
8907 case r_token_l: case r_token_o:
8908 operation = bit_expression_cor;
8909 goto OKAY;
8910 }
8911 break;
8912 }
8913 goto UNEXPECTED;
8914 case o_token_l: case o_token_o:
8915 tex_get_x_token();
8916 switch (cur_tok) {
8917 case r_token_l: case r_token_o:
8918 operation = bit_expression_or;
8919 goto OKAY;
8920 }
8921 goto UNEXPECTED;
8922 case v_token_l: case v_token_o:
8923 operation = bit_expression_bor;
8924 break;
8925 default:
8926 goto NUMBER;
8927 }
8928 OKAY:
8929 while (operators.tail && bit_operator_precedence[rpn_expression_entry(operators.tail)] >= bit_operator_precedence[operation]) {
8930
8931 tex_move_stack_entry(&reverse, &operators);
8932 }
8933 tex_push_stack_entry(&operators, operation);
8934 lastoperation = operation;
8935 break;
8936 NUMBER:
8937 lastoperation = bit_expression_none;
8938 initial = 0;
8939
8940 {
8941 int has_fraction = 0;
8942 int has_unit = 0;
8943 operation = level == dimension_val_level ? tex_scan_bit_dimension(&has_fraction, &has_unit) : tex_scan_bit_integer(NULL);
8944 if (negate) {
8945 operation = - operation;
8946 negate = 0;
8947 }
8948 if (nothing) {
8949 operation = operation ? 0 : 1;
8950 nothing = 0;
8951 }
8952 if (positive) {
8953 if (operation < 0) {
8954 operation = - operation;
8955 }
8956 positive = 0;
8957 }
8958 if (negative) {
8959 if (operation > 0) {
8960 operation = - operation;
8961 }
8962 negative = 0;
8963 }
8964 tex_push_stack_entry(&reverse, operation * factor);
8965 if (level == dimension_val_level && has_unit) {
8966 node_subtype(reverse.tail) = bit_expression_dimension;
8967 } else if (has_fraction) {
8968 node_subtype(reverse.tail) = bit_expression_float;
8969 } else {
8970 node_subtype(reverse.tail) = bit_expression_number;
8971 }
8972 continue;
8973 }
8974 }
8975 }
8976 COLLECTED:
8977 while (operators.tail) {
8978 tex_move_stack_entry(&reverse, &operators);
8979 }
8980
8981
9006 if (trace == 1) {
9007 tex_aux_trace_expression(reverse, level, 0, 0);
9008 }
9009 {
9010 halfword current = reverse.head;
9011 int step = 0;
9012 while (current) {
9013 halfword next = node_next(current);
9014 halfword subtype = node_subtype(current);
9015 if (trace > 1) {
9016 step = step + 1;
9017 tex_aux_trace_expression(reverse, level, step, 0);
9018 tex_aux_trace_expression(stack, level, step, 1);
9019 }
9020 switch (subtype) {
9021 case bit_expression_number:
9022 case bit_expression_float:
9023 case bit_expression_dimension:
9024 tex_take_stack_entry(&stack, &reverse, current);
9025 break;
9026 default:
9027 {
9028 halfword token = (halfword) rpn_expression_entry(current);
9029 long long v = 0;
9030 switch (token) {
9031
9032 case bit_expression_bnot : v = stack.tail ? ~ rpn_expression_entry(stack.tail) : 0; break;
9033 case bit_expression_plus : v = stack.tail ? rpn_expression_entry(stack.tail) : 0; break;
9034 case bit_expression_minus: v = stack.tail ? - rpn_expression_entry(stack.tail) : 0; break;
9035
9036 case bit_expression_not : v = stack.tail ? (rpn_expression_entry(stack.tail) ? 0 : 1) : 0; break;
9037 case bit_expression_flip: v = stack.tail ? (rpn_expression_entry(stack.tail) ? 0 : 1) : 1; break;
9038
9039 case bit_expression_positive: v = stack.tail ? rpn_expression_entry(stack.tail) : 0; if (v < 0) { v = - v; } break;
9040 case bit_expression_negative: v = stack.tail ? rpn_expression_entry(stack.tail) : 0; if (v > 0) { v = - v; } break;
9041
9042 case bit_expression_sin : { v = stack.tail ? tex_aux_function_result(&stack, sin (tex_aux_function_argument(&stack))) : 0; } break;
9043 case bit_expression_cos : { v = stack.tail ? tex_aux_function_result(&stack, cos (tex_aux_function_argument(&stack))) : 0; } break;
9044 case bit_expression_tan : { v = stack.tail ? tex_aux_function_result(&stack, tan (tex_aux_function_argument(&stack))) : 0; } break;
9045 case bit_expression_asin : { v = stack.tail ? tex_aux_function_result(&stack, asin (tex_aux_function_argument(&stack))) : 0; } break;
9046 case bit_expression_acos : { v = stack.tail ? tex_aux_function_result(&stack, acos (tex_aux_function_argument(&stack))) : 0; } break;
9047 case bit_expression_atan : { v = stack.tail ? tex_aux_function_result(&stack, atan (tex_aux_function_argument(&stack))) : 0; } break;
9048 case bit_expression_sinh : { v = stack.tail ? tex_aux_function_result(&stack, sinh (tex_aux_function_argument(&stack))) : 0; } break;
9049 case bit_expression_cosh : { v = stack.tail ? tex_aux_function_result(&stack, cosh (tex_aux_function_argument(&stack))) : 0; } break;
9050 case bit_expression_tanh : { v = stack.tail ? tex_aux_function_result(&stack, tanh (tex_aux_function_argument(&stack))) : 0; } break;
9051 case bit_expression_asinh: { v = stack.tail ? tex_aux_function_result(&stack, asinh(tex_aux_function_argument(&stack))) : 0; } break;
9052 case bit_expression_acosh: { v = stack.tail ? tex_aux_function_result(&stack, acosh(tex_aux_function_argument(&stack))) : 0; } break;
9053 case bit_expression_atanh: { v = stack.tail ? tex_aux_function_result(&stack, atanh(tex_aux_function_argument(&stack))) : 0; } break;
9054 case bit_expression_ceil : { v = stack.tail ? tex_aux_function_result(&stack, ceil (tex_aux_function_argument(&stack))) : 0; } break;
9055 case bit_expression_floor: { v = stack.tail ? tex_aux_function_result(&stack, floor(tex_aux_function_argument(&stack))) : 0; } break;
9056 case bit_expression_round: { v = stack.tail ? tex_aux_function_result(&stack, round(tex_aux_function_argument(&stack))) : 0; } break;
9057 case bit_expression_abs : { v = stack.tail ? tex_aux_function_result(&stack, abs (tex_aux_function_argument(&stack))) : 0; } break;
9058 case bit_expression_sqrt : { v = stack.tail ? tex_aux_function_result(&stack, sqrt (tex_aux_function_argument(&stack))) : 0; } break;
9059 case bit_expression_log : { v = stack.tail ? tex_aux_function_result(&stack, log10(tex_aux_function_argument(&stack))) : 0; } break;
9060 case bit_expression_ln : { v = stack.tail ? tex_aux_function_result(&stack, log (tex_aux_function_argument(&stack))) : 0; } break;
9061 case bit_expression_exp : { v = stack.tail ? tex_aux_function_result(&stack, exp (tex_aux_function_argument(&stack))) : 0; } break;
9062
9063 default:
9064 {
9065 quarterword sa, sb;
9066 long long va, vb;
9067 sb = node_subtype(stack.tail);
9068 vb = tex_pop_stack_entry(&stack);
9069 if (stack.tail) {
9070 sa = node_subtype(stack.tail);
9071 va = rpn_expression_entry(stack.tail);
9072
9073 if (sa == sb) {
9074
9075 } else if (sa == bit_expression_number) {
9076 va = va * 65536;
9077 sa = bit_expression_float;
9078 node_subtype(stack.tail) = sb;
9079 } else if (sb == bit_expression_number) {
9080 vb = vb * 65536;
9081 sb = bit_expression_float;
9082 }
9083
9084 } else {
9085 sa = bit_expression_number;
9086 va = 0;
9087 }
9088 switch (token) {
9089 case bit_expression_bor : v = va | vb; break;
9090 case bit_expression_band : v = va & vb; break;
9091 case bit_expression_bxor : v = va ^ vb; break;
9092
9093 case bit_expression_bset : v = va | ((long long) 1 << (vb - 1)); break;
9094 case bit_expression_bunset : v = va & ~ ((long long) 1 << (vb - 1)); break;
9095
9096 case bit_expression_bleft : v = va << vb; break;
9097 case bit_expression_bright : v = va >> vb; break;
9098 case bit_expression_less : v = va < vb; break;
9099 case bit_expression_lessequal: v = va <= vb; break;
9100 case bit_expression_equal : v = va == vb; break;
9101 case bit_expression_moreequal: v = va >= vb; break;
9102 case bit_expression_more : v = va > vb; break;
9103 case bit_expression_unequal : v = va != vb; break;
9104
9105 case bit_expression_add : v = va + vb; break;
9106 case bit_expression_subtract : v = va - vb; break;
9107
9108 case bit_expression_multiply:
9109
9110 {
9111 double d = (double) va * (double) vb;
9112 if (sa == bit_expression_float) {
9113 d = d / (65536 * factor);
9114 } else if (sb == bit_expression_float) {
9115 d = d / (65536 * factor);
9116 } else {
9117 d = d / factor;
9118 }
9119 if (sa == bit_expression_dimension || sb == bit_expression_dimension) {
9120 node_subtype(stack.tail) = bit_expression_dimension;
9121 }
9122 v = longlonground(d);
9123 }
9124 break;
9125 case bit_expression_divide:
9126
9127 if (vb) {
9128 double d = (double) va / (double) vb;
9129 if (sa == bit_expression_float) {
9130
9131 d = d * (65536 * factor);
9132 } else if (sb == bit_expression_float) {
9133
9134 d = d * (65536 * factor);
9135 } else {
9136 d = d * factor;
9137 }
9138 if (sa == bit_expression_dimension || sb == bit_expression_dimension) {
9139 node_subtype(stack.tail) = bit_expression_dimension;
9140 }
9141 v = longlonground(d);
9142 } else {
9143 goto ZERO;
9144 }
9145 break;
9146
9147 case bit_expression_mod : v = va % vb; break;
9148 case bit_expression_div : v = va / vb; break;
9149
9150 case bit_expression_or : v = (va || vb) ? 1 : 0 ; break;
9151 case bit_expression_and : v = (va && vb) ? 1 : 0 ; break;
9152
9153 case bit_expression_cor : v = va ? va : (vb ? vb : 0); break;
9154 case bit_expression_cand: v = (va && vb) ? vb : 0 ; break;
9155
9156 default:
9157 v = 0;
9158 break;
9159 }
9160 }
9161 }
9162
9163 if (node_subtype(stack.tail) == bit_expression_number) {
9164 if (v < min_integer) {
9165 v = min_integer;
9166 } else if (v > max_integer) {
9167 v = max_integer;
9168 }
9169 } else {
9170 if (v < min_longinteger) {
9171 v = min_longinteger;
9172 } else if (v > max_longinteger) {
9173 v = max_longinteger;
9174 }
9175 }
9176
9177 rpn_expression_entry(stack.tail) = v;
9178 break;
9179 }
9180 }
9181 current = next;
9182 }
9183 }
9184 goto DONE;
9185 BRACEERROR:
9186 tex_aux_scan_brace_error();
9187 goto DONE;
9188 PARENTERROR:
9189 tex_aux_scan_parent_error();
9190 goto DONE;
9191 ZERO:
9192 tex_aux_scan_zero_divide_error();
9193 goto DONE;
9194 UNEXPECTED:
9195 tex_handle_error(
9196 back_error_type,
9197 "Premature end of expression",
9198 "I was expecting to see an integer or bitwise operator. Didn't."
9199 );
9200 DONE:
9201 lmt_scanner_state.expression_depth--;
9202 cur_val = scaledround(((double) rpn_expression_entry(stack.tail)) / factor);
9203 cur_val_level = level;
9204 tex_aux_dispose_stack(&stack);
9205 tex_aux_dispose_stack(&reverse);
9206 tex_aux_dispose_stack(&operators);
9207}
9208 |