1
4
5
28
29# include "luametatex.h"
30
31
32
33typedef struct lua_token_package {
34 struct {
35 quarterword level;
36 quarterword how;
37 };
38 singleword cmd;
39 singleword flag;
40 halfword chr;
41 halfword cs;
42} lua_token_package;
43
44
69
70# define ignore_entry -1
71# define direct_entry -2
72
73void lmt_tokenlib_initialize(void)
74{
75
76 lmt_interface.command_names = lmt_memory_malloc((register_dimension_reference_cmd + 2) * sizeof(command_item));
77
78 lmt_interface.command_names[escape_cmd] = (command_item) { .id = escape_cmd, .lua = lua_key_index(escape), .name = lua_key(escape), .kind = character_command_item, .min = 0, .max = max_character_code, .base = 0, .fixedvalue = too_big_char };
79 lmt_interface.command_names[left_brace_cmd] = (command_item) { .id = left_brace_cmd, .lua = lua_key_index(left_brace), .name = lua_key(left_brace), .kind = character_command_item, .min = 0, .max = max_character_code, .base = 0, .fixedvalue = 0 };
80 lmt_interface.command_names[right_brace_cmd] = (command_item) { .id = right_brace_cmd, .lua = lua_key_index(right_brace), .name = lua_key(right_brace), .kind = character_command_item, .min = 0, .max = max_character_code, .base = 0, .fixedvalue = 0 };
81 lmt_interface.command_names[math_shift_cmd] = (command_item) { .id = math_shift_cmd, .lua = lua_key_index(math_shift), .name = lua_key(math_shift), .kind = character_command_item, .min = 0, .max = max_character_code, .base = 0, .fixedvalue = 0 };
82 lmt_interface.command_names[alignment_tab_cmd] = (command_item) { .id = alignment_tab_cmd, .lua = lua_key_index(alignment_tab), .name = lua_key(alignment_tab), .kind = character_command_item, .min = 0, .max = max_character_code, .base = 0, .fixedvalue = 0 };
83 lmt_interface.command_names[end_line_cmd] = (command_item) { .id = end_line_cmd, .lua = lua_key_index(end_line), .name = lua_key(end_line), .kind = character_command_item, .min = 0, .max = max_character_code, .base = 0, .fixedvalue = 0 };
84 lmt_interface.command_names[parameter_cmd] = (command_item) { .id = parameter_cmd, .lua = lua_key_index(parameter), .name = lua_key(parameter), .kind = character_command_item, .min = 0, .max = max_character_code, .base = 0, .fixedvalue = 0 };
85 lmt_interface.command_names[superscript_cmd] = (command_item) { .id = superscript_cmd, .lua = lua_key_index(superscript), .name = lua_key(superscript), .kind = character_command_item, .min = 0, .max = max_character_code, .base = 0, .fixedvalue = 0 };
86 lmt_interface.command_names[subscript_cmd] = (command_item) { .id = subscript_cmd, .lua = lua_key_index(subscript), .name = lua_key(subscript), .kind = character_command_item, .min = 0, .max = max_character_code, .base = 0, .fixedvalue = 0 };
87 lmt_interface.command_names[ignore_cmd] = (command_item) { .id = ignore_cmd, .lua = lua_key_index(ignore), .name = lua_key(ignore), .kind = character_command_item, .min = 0, .max = max_character_code, .base = 0, .fixedvalue = 0 };
88 lmt_interface.command_names[spacer_cmd] = (command_item) { .id = spacer_cmd, .lua = lua_key_index(spacer), .name = lua_key(spacer), .kind = character_command_item, .min = 0, .max = max_character_code, .base = 0, .fixedvalue = 0 };
89 lmt_interface.command_names[letter_cmd] = (command_item) { .id = letter_cmd, .lua = lua_key_index(letter), .name = lua_key(letter), .kind = character_command_item, .min = 0, .max = max_character_code, .base = 0, .fixedvalue = 0 };
90 lmt_interface.command_names[other_char_cmd] = (command_item) { .id = other_char_cmd, .lua = lua_key_index(other_char), .name = lua_key(other_char), .kind = character_command_item, .min = 0, .max = max_character_code, .base = 0, .fixedvalue = 0 };
91 lmt_interface.command_names[active_char_cmd] = (command_item) { .id = active_char_cmd, .lua = lua_key_index(active_char), .name = lua_key(active_char), .kind = character_command_item, .min = 0, .max = max_character_code, .base = 0, .fixedvalue = too_big_char };
92 lmt_interface.command_names[comment_cmd] = (command_item) { .id = comment_cmd, .lua = lua_key_index(comment), .name = lua_key(comment), .kind = character_command_item, .min = 0, .max = max_character_code, .base = 0, .fixedvalue = 0 };
93 lmt_interface.command_names[invalid_char_cmd] = (command_item) { .id = invalid_char_cmd, .lua = lua_key_index(invalid_char), .name = lua_key(invalid_char), .kind = character_command_item, .min = 0, .max = max_character_code, .base = 0, .fixedvalue = 0 };
94 lmt_interface.command_names[relax_cmd] = (command_item) { .id = relax_cmd, .lua = lua_key_index(relax), .name = lua_key(relax), .kind = regular_command_item, .min = 0, .max = last_relax_code, .base = 0, .fixedvalue = 0 };
95 lmt_interface.command_names[end_template_cmd] = (command_item) { .id = end_template_cmd, .lua = lua_key_index(alignment), .name = lua_key(alignment), .kind = regular_command_item, .min = 0, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
96 lmt_interface.command_names[alignment_cmd] = (command_item) { .id = alignment_cmd, .lua = lua_key_index(end_template), .name = lua_key(end_template), .kind = regular_command_item, .min = 0, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
97 lmt_interface.command_names[match_cmd] = (command_item) { .id = match_cmd, .lua = lua_key_index(match), .name = lua_key(match), .kind = regular_command_item, .min = 0, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
98 lmt_interface.command_names[end_match_cmd] = (command_item) { .id = end_match_cmd, .lua = lua_key_index(end_match), .name = lua_key(end_match), .kind = regular_command_item, .min = 0, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
99 lmt_interface.command_names[parameter_reference_cmd] = (command_item) { .id = parameter_reference_cmd, .lua = lua_key_index(parameter_reference), .name = lua_key(parameter_reference), .kind = regular_command_item, .min = 0, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
100 lmt_interface.command_names[end_paragraph_cmd] = (command_item) { .id = end_paragraph_cmd, .lua = lua_key_index(end_paragraph), .name = lua_key(end_paragraph), .kind = regular_command_item, .min = 0, .max = last_end_paragraph_code, .base = 0, .fixedvalue = 0 };
101 lmt_interface.command_names[end_job_cmd] = (command_item) { .id = end_job_cmd, .lua = lua_key_index(end_job), .name = lua_key(end_job), .kind = regular_command_item, .min = 0, .max = last_end_job_code, .base = 0, .fixedvalue = 0 };
102 lmt_interface.command_names[delimiter_number_cmd] = (command_item) { .id = delimiter_number_cmd, .lua = lua_key_index(delimiter_number), .name = lua_key(delimiter_number), .kind = regular_command_item, .min = 0, .max = last_math_delimiter_code, .base = 0, .fixedvalue = 0 };
103 lmt_interface.command_names[char_number_cmd] = (command_item) { .id = char_number_cmd, .lua = lua_key_index(char_number), .name = lua_key(char_number), .kind = regular_command_item, .min = 0, .max = last_char_number_code, .base = 0, .fixedvalue = 0 };
104 lmt_interface.command_names[math_char_number_cmd] = (command_item) { .id = math_char_number_cmd, .lua = lua_key_index(math_char_number), .name = lua_key(math_char_number), .kind = regular_command_item, .min = 0, .max = last_math_char_number_code, .base = 0, .fixedvalue = 0 };
105 lmt_interface.command_names[mark_cmd] = (command_item) { .id = mark_cmd, .lua = lua_key_index(mark), .name = lua_key(mark), .kind = regular_command_item, .min = 0, .max = last_set_mark_code, .base = 0, .fixedvalue = 0 };
106 lmt_interface.command_names[node_cmd] = (command_item) { .id = node_cmd, .lua = lua_key_index(node), .name = lua_key(node), .kind = node_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
107 lmt_interface.command_names[xray_cmd] = (command_item) { .id = xray_cmd, .lua = lua_key_index(xray), .name = lua_key(xray), .kind = regular_command_item, .min = 0, .max = last_xray_code, .base = 0, .fixedvalue = 0 };
108 lmt_interface.command_names[make_box_cmd] = (command_item) { .id = make_box_cmd, .lua = lua_key_index(make_box), .name = lua_key(make_box), .kind = regular_command_item, .min = 0, .max = last_nu_box_code, .base = 0, .fixedvalue = 0 };
109 lmt_interface.command_names[hmove_cmd] = (command_item) { .id = hmove_cmd, .lua = lua_key_index(hmove), .name = lua_key(hmove), .kind = regular_command_item, .min = 0, .max = last_move_code, .base = 0, .fixedvalue = 0 };
110 lmt_interface.command_names[vmove_cmd] = (command_item) { .id = vmove_cmd, .lua = lua_key_index(vmove), .name = lua_key(vmove), .kind = regular_command_item, .min = 0, .max = last_move_code, .base = 0, .fixedvalue = 0 };
111 lmt_interface.command_names[un_hbox_cmd] = (command_item) { .id = un_hbox_cmd, .lua = lua_key_index(un_hbox), .name = lua_key(un_hbox), .kind = regular_command_item, .min = 0, .max = last_un_box_code, .base = 0, .fixedvalue = 0 };
112 lmt_interface.command_names[un_vbox_cmd] = (command_item) { .id = un_vbox_cmd, .lua = lua_key_index(un_vbox), .name = lua_key(un_vbox), .kind = regular_command_item, .min = 0, .max = last_un_box_code, .base = 0, .fixedvalue = 0 };
113 lmt_interface.command_names[remove_item_cmd] = (command_item) { .id = remove_item_cmd, .lua = lua_key_index(remove_item), .name = lua_key(remove_item), .kind = regular_command_item, .min = 0, .max = last_remove_item_code, .base = 0, .fixedvalue = 0 };
114 lmt_interface.command_names[hskip_cmd] = (command_item) { .id = hskip_cmd, .lua = lua_key_index(hskip), .name = lua_key(hskip), .kind = regular_command_item, .min = first_skip_code, .max = last_skip_code, .base = 0, .fixedvalue = 0 };
115 lmt_interface.command_names[vskip_cmd] = (command_item) { .id = vskip_cmd, .lua = lua_key_index(vskip), .name = lua_key(vskip), .kind = regular_command_item, .min = first_skip_code, .max = last_skip_code, .base = 0, .fixedvalue = 0 };
116 lmt_interface.command_names[mskip_cmd] = (command_item) { .id = mskip_cmd, .lua = lua_key_index(mskip), .name = lua_key(mskip), .kind = regular_command_item, .min = 0, .max = last_mskip_code, .base = 0, .fixedvalue = 0 };
117 lmt_interface.command_names[kern_cmd] = (command_item) { .id = kern_cmd, .lua = lua_key_index(kern), .name = lua_key(kern), .kind = regular_command_item, .min = 0, .max = last_kern_code, .base = 0, .fixedvalue = 0 };
118 lmt_interface.command_names[mkern_cmd] = (command_item) { .id = mkern_cmd, .lua = lua_key_index(mkern), .name = lua_key(mkern), .kind = regular_command_item, .min = 0, .max = 0, .base = 0, .fixedvalue = 0 };
119 lmt_interface.command_names[leader_cmd] = (command_item) { .id = leader_cmd, .lua = lua_key_index(leader), .name = lua_key(leader), .kind = regular_command_item, .min = first_leader_code, .max = last_leader_code, .base = 0, .fixedvalue = 0 };
120 lmt_interface.command_names[legacy_cmd] = (command_item) { .id = legacy_cmd, .lua = lua_key_index(legacy), .name = lua_key(legacy), .kind = regular_command_item, .min = first_legacy_code, .max = last_legacy_code , .base = 0, .fixedvalue = 0 };
121 lmt_interface.command_names[local_box_cmd] = (command_item) { .id = local_box_cmd, .lua = lua_key_index(local_box), .name = lua_key(local_box), .kind = regular_command_item, .min = first_local_box_code, .max = last_local_box_code, .base = 0, .fixedvalue = 0 };
122 lmt_interface.command_names[halign_cmd] = (command_item) { .id = halign_cmd, .lua = lua_key_index(halign), .name = lua_key(halign), .kind = regular_command_item, .min = 0, .max = 0, .base = 0, .fixedvalue = 0 };
123 lmt_interface.command_names[valign_cmd] = (command_item) { .id = valign_cmd, .lua = lua_key_index(valign), .name = lua_key(valign), .kind = regular_command_item, .min = 0, .max = 0, .base = 0, .fixedvalue = 0 };
124 lmt_interface.command_names[vrule_cmd] = (command_item) { .id = vrule_cmd, .lua = lua_key_index(vrule), .name = lua_key(vrule), .kind = regular_command_item, .min = first_rule_code, .max = last_rule_code, .base = 0, .fixedvalue = 0 };
125 lmt_interface.command_names[hrule_cmd] = (command_item) { .id = hrule_cmd, .lua = lua_key_index(hrule), .name = lua_key(hrule), .kind = regular_command_item, .min = first_rule_code, .max = last_rule_code, .base = 0, .fixedvalue = 0 };
126 lmt_interface.command_names[insert_cmd] = (command_item) { .id = insert_cmd, .lua = lua_key_index(insert), .name = lua_key(insert), .kind = regular_command_item, .min = 0, .max = 0, .base = 0, .fixedvalue = 0 };
127 lmt_interface.command_names[vadjust_cmd] = (command_item) { .id = vadjust_cmd, .lua = lua_key_index(vadjust), .name = lua_key(vadjust), .kind = regular_command_item, .min = 0, .max = 0, .base = 0, .fixedvalue = 0 };
128 lmt_interface.command_names[ignore_something_cmd] = (command_item) { .id = ignore_something_cmd, .lua = lua_key_index(ignore_something), .name = lua_key(ignore_something), .kind = regular_command_item, .min = 0, .max = last_ignore_something_code, .base = 0, .fixedvalue = 0 };
129 lmt_interface.command_names[after_something_cmd] = (command_item) { .id = after_something_cmd, .lua = lua_key_index(after_something), .name = lua_key(after_something), .kind = regular_command_item, .min = 0, .max = last_after_something_code, .base = 0, .fixedvalue = 0 };
130 lmt_interface.command_names[penalty_cmd] = (command_item) { .id = penalty_cmd, .lua = lua_key_index(penalty), .name = lua_key(penalty), .kind = regular_command_item, .min = 0, .max = 0, .base = 0, .fixedvalue = 0 };
131 lmt_interface.command_names[begin_paragraph_cmd] = (command_item) { .id = begin_paragraph_cmd, .lua = lua_key_index(begin_paragraph), .name = lua_key(begin_paragraph), .kind = regular_command_item, .min = 0, .max = last_begin_paragraph_code, .base = 0, .fixedvalue = 0 };
132 lmt_interface.command_names[italic_correction_cmd] = (command_item) { .id = italic_correction_cmd, .lua = lua_key_index(italic_correction), .name = lua_key(italic_correction), .kind = regular_command_item, .min = 0, .max = 0, .base = 0, .fixedvalue = 0 };
133 lmt_interface.command_names[accent_cmd] = (command_item) { .id = accent_cmd, .lua = lua_key_index(accent), .name = lua_key(accent), .kind = regular_command_item, .min = 0, .max = 0, .base = 0, .fixedvalue = 0 };
134 lmt_interface.command_names[math_accent_cmd] = (command_item) { .id = math_accent_cmd, .lua = lua_key_index(math_accent), .name = lua_key(math_accent), .kind = regular_command_item, .min = 0, .max = last_math_accent_code, .base = 0, .fixedvalue = 0 };
135 lmt_interface.command_names[discretionary_cmd] = (command_item) { .id = discretionary_cmd, .lua = lua_key_index(discretionary), .name = lua_key(discretionary), .kind = regular_command_item, .min = 0, .max = last_discretionary_code, .base = 0, .fixedvalue = 0 };
136 lmt_interface.command_names[equation_number_cmd] = (command_item) { .id = equation_number_cmd, .lua = lua_key_index(equation_number), .name = lua_key(equation_number), .kind = regular_command_item, .min = first_location_code, .max = last_location_code, .base = 0, .fixedvalue = 0 };
137 lmt_interface.command_names[math_fence_cmd] = (command_item) { .id = math_fence_cmd, .lua = lua_key_index(math_fence), .name = lua_key(math_fence), .kind = regular_command_item, .min = first_fence_code, .max = last_fence_code, .base = 0, .fixedvalue = 0 };
138 lmt_interface.command_names[math_component_cmd] = (command_item) { .id = math_component_cmd, .lua = lua_key_index(math_component), .name = lua_key(math_component), .kind = regular_command_item, .min = first_math_component_type, .max = last_math_component_type, .base = 0, .fixedvalue = 0 };
139 lmt_interface.command_names[math_modifier_cmd] = (command_item) { .id = math_modifier_cmd, .lua = lua_key_index(math_modifier), .name = lua_key(math_modifier), .kind = regular_command_item, .min = first_math_modifier_code, .max = last_math_modifier_code, .base = 0, .fixedvalue = 0 };
140 lmt_interface.command_names[math_fraction_cmd] = (command_item) { .id = math_fraction_cmd, .lua = lua_key_index(math_fraction), .name = lua_key(math_fraction), .kind = regular_command_item, .min = 0, .max = last_math_fraction_code, .base = 0, .fixedvalue = 0 };
141 lmt_interface.command_names[math_style_cmd] = (command_item) { .id = math_style_cmd, .lua = lua_key_index(math_style), .name = lua_key(math_style), .kind = regular_command_item, .min = 0, .max = last_math_style, .base = 0, .fixedvalue = 0 };
142 lmt_interface.command_names[math_choice_cmd] = (command_item) { .id = math_choice_cmd, .lua = lua_key_index(math_choice), .name = lua_key(math_choice), .kind = regular_command_item, .min = 0, .max = last_math_choice_code, .base = 0, .fixedvalue = 0 };
143 lmt_interface.command_names[vcenter_cmd] = (command_item) { .id = vcenter_cmd, .lua = lua_key_index(vcenter), .name = lua_key(vcenter), .kind = regular_command_item, .min = 0, .max = 0, .base = 0, .fixedvalue = 0 };
144 lmt_interface.command_names[case_shift_cmd] = (command_item) { .id = case_shift_cmd, .lua = lua_key_index(case_shift), .name = lua_key(case_shift), .kind = regular_command_item, .min = 0, .max = last_case_shift_code, .base = 0, .fixedvalue = 0 };
145 lmt_interface.command_names[message_cmd] = (command_item) { .id = message_cmd, .lua = lua_key_index(message), .name = lua_key(message), .kind = regular_command_item, .min = 0, .max = last_message_code, .base = 0, .fixedvalue = 0 };
146 lmt_interface.command_names[catcode_table_cmd] = (command_item) { .id = catcode_table_cmd, .lua = lua_key_index(catcode_table), .name = lua_key(catcode_table), .kind = regular_command_item, .min = 0, .max = last_catcode_table_code, .base = 0, .fixedvalue = 0 };
147 lmt_interface.command_names[end_local_cmd] = (command_item) { .id = end_local_cmd, .lua = lua_key_index(end_local), .name = lua_key(end_local), .kind = regular_command_item, .min = 0, .max = 0, .base = 0, .fixedvalue = 0 };
148 lmt_interface.command_names[lua_function_call_cmd] = (command_item) { .id = lua_function_call_cmd, .lua = lua_key_index(lua_function_call), .name = lua_key(lua_function_call), .kind = reference_command_item, .min = 0, .max = max_function_reference, .base = 0, .fixedvalue = 0 };
149 lmt_interface.command_names[lua_protected_call_cmd] = (command_item) { .id = lua_protected_call_cmd, .lua = lua_key_index(lua_protected_call), .name = lua_key(lua_protected_call), .kind = reference_command_item, .min = 0, .max = max_function_reference, .base = 0, .fixedvalue = 0 };
150 lmt_interface.command_names[lua_semi_protected_call_cmd] = (command_item) { .id = lua_semi_protected_call_cmd, .lua = lua_key_index(lua_semiprotected_call), .name = lua_key(lua_semiprotected_call), .kind = reference_command_item, .min = 0, .max = max_function_reference, .base = 0, .fixedvalue = 0 };
151 lmt_interface.command_names[begin_group_cmd] = (command_item) { .id = begin_group_cmd, .lua = lua_key_index(begin_group), .name = lua_key(begin_group), .kind = regular_command_item, .min = 0, .max = last_begin_group_code, .base = 0, .fixedvalue = 0 };
152 lmt_interface.command_names[end_group_cmd] = (command_item) { .id = end_group_cmd, .lua = lua_key_index(end_group), .name = lua_key(end_group), .kind = regular_command_item, .min = 0, .max = 0, .base = 0, .fixedvalue = 0 };
153 lmt_interface.command_names[explicit_space_cmd] = (command_item) { .id = explicit_space_cmd, .lua = lua_key_index(explicit_space), .name = lua_key(explicit_space), .kind = regular_command_item, .min = 0, .max = 0, .base = 0, .fixedvalue = 0 };
154 lmt_interface.command_names[boundary_cmd] = (command_item) { .id = boundary_cmd, .lua = lua_key_index(boundary), .name = lua_key(boundary), .kind = regular_command_item, .min = 0, .max = last_boundary_code, .base = 0, .fixedvalue = 0 };
155 lmt_interface.command_names[math_radical_cmd] = (command_item) { .id = math_radical_cmd, .lua = lua_key_index(math_radical), .name = lua_key(math_radical), .kind = regular_command_item, .min = 0, .max = last_radical_code, .base = 0, .fixedvalue = 0 };
156 lmt_interface.command_names[math_script_cmd] = (command_item) { .id = math_script_cmd, .lua = lua_key_index(math_script), .name = lua_key(math_script), .kind = regular_command_item, .min = 0, .max = last_math_script_code, .base = 0, .fixedvalue = 0 };
157 lmt_interface.command_names[math_shift_cs_cmd] = (command_item) { .id = math_shift_cs_cmd, .lua = lua_key_index(math_shift_cs), .name = lua_key(math_shift_cs), .kind = regular_command_item, .min = 0, .max = last_math_shift_cs_code, .base = 0, .fixedvalue = 0 };
158 lmt_interface.command_names[end_cs_name_cmd] = (command_item) { .id = end_cs_name_cmd, .lua = lua_key_index(end_cs_name), .name = lua_key(end_cs_name), .kind = regular_command_item, .min = 0, .max = 0, .base = 0, .fixedvalue = 0 };
159 lmt_interface.command_names[char_given_cmd] = (command_item) { .id = char_given_cmd, .lua = lua_key_index(char_given), .name = lua_key(char_given), .kind = character_command_item, .min = 0, .max = max_character_code, .base = 0, .fixedvalue = 0 };
160 lmt_interface.command_names[some_item_cmd] = (command_item) { .id = some_item_cmd, .lua = lua_key_index(some_item), .name = lua_key(some_item), .kind = regular_command_item, .min = 0, .max = last_some_item_code, .base = 0, .fixedvalue = 0 };
161 lmt_interface.command_names[internal_toks_cmd] = (command_item) { .id = internal_toks_cmd, .lua = lua_key_index(internal_toks), .name = lua_key(internal_toks), .kind = internal_command_item, .min = first_toks_code, .max = last_toks_code, .base = internal_toks_base, .fixedvalue = 0 };
162 lmt_interface.command_names[register_toks_cmd] = (command_item) { .id = register_toks_cmd, .lua = lua_key_index(register_toks), .name = lua_key(register_toks), .kind = register_command_item, .min = 0, .max = biggest_reg, .base = register_toks_base, .fixedvalue = 0 };
163 lmt_interface.command_names[internal_integer_cmd] = (command_item) { .id = internal_integer_cmd, .lua = lua_key_index(internal_integer), .name = lua_key(internal_integer), .kind = internal_command_item, .min = first_integer_code, .max = last_integer_code, .base = internal_integer_base, .fixedvalue = 0 };
164 lmt_interface.command_names[register_integer_cmd] = (command_item) { .id = register_integer_cmd, .lua = lua_key_index(register_integer), .name = lua_key(register_integer), .kind = register_command_item, .min = 0, .max = max_integer_register_index, .base = register_integer_base, .fixedvalue = 0 };
165 lmt_interface.command_names[internal_attribute_cmd] = (command_item) { .id = internal_attribute_cmd, .lua = lua_key_index(internal_attribute), .name = lua_key(internal_attribute), .kind = unused_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
166 lmt_interface.command_names[register_attribute_cmd] = (command_item) { .id = register_attribute_cmd, .lua = lua_key_index(register_attribute), .name = lua_key(register_attribute), .kind = register_command_item, .min = 0, .max = max_attribute_register_index, .base = register_attribute_base, .fixedvalue = 0 };
167 lmt_interface.command_names[internal_posit_cmd] = (command_item) { .id = internal_posit_cmd, .lua = lua_key_index(internal_posit), .name = lua_key(internal_posit), .kind = unused_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
168 lmt_interface.command_names[register_posit_cmd] = (command_item) { .id = register_posit_cmd, .lua = lua_key_index(register_posit), .name = lua_key(register_posit), .kind = register_command_item, .min = 0, .max = max_posit_register_index, .base = register_posit_base, .fixedvalue = 0 };
169 lmt_interface.command_names[internal_dimension_cmd] = (command_item) { .id = internal_dimension_cmd, .lua = lua_key_index(internal_dimension), .name = lua_key(internal_dimension), .kind = internal_command_item, .min = first_dimension_code, .max = last_dimension_code, .base = internal_dimension_base, .fixedvalue = 0 };
170 lmt_interface.command_names[register_dimension_cmd] = (command_item) { .id = register_dimension_cmd, .lua = lua_key_index(register_dimension), .name = lua_key(register_dimension), .kind = register_command_item, .min = 0, .max = max_dimension_register_index, .base = register_dimension_base, .fixedvalue = 0 };
171 lmt_interface.command_names[internal_glue_cmd] = (command_item) { .id = internal_glue_cmd, .lua = lua_key_index(internal_glue), .name = lua_key(internal_glue), .kind = internal_command_item, .min = first_glue_code, .max = last_glue_code, .base = internal_glue_base, .fixedvalue = 0 };
172 lmt_interface.command_names[register_glue_cmd] = (command_item) { .id = register_glue_cmd, .lua = lua_key_index(register_glue), .name = lua_key(register_glue), .kind = register_command_item, .min = 0, .max = max_glue_register_index, .base = register_glue_base, .fixedvalue = 0 };
173 lmt_interface.command_names[internal_muglue_cmd] = (command_item) { .id = internal_muglue_cmd, .lua = lua_key_index(internal_muglue), .name = lua_key(internal_muglue), .kind = internal_command_item, .min = first_muglue_code, .max = last_muglue_code, .base = internal_muglue_base, .fixedvalue = 0 };
174 lmt_interface.command_names[register_muglue_cmd] = (command_item) { .id = register_muglue_cmd, .lua = lua_key_index(register_muglue), .name = lua_key(register_muglue), .kind = register_command_item, .min = 0, .max = max_muglue_register_index, .base = register_muglue_base, .fixedvalue = 0 };
175 lmt_interface.command_names[lua_value_cmd] = (command_item) { .id = lua_value_cmd, .lua = lua_key_index(lua_value), .name = lua_key(lua_value), .kind = reference_command_item, .min = 0, .max = max_function_reference, .base = 0, .fixedvalue = 0 };
176 lmt_interface.command_names[iterator_value_cmd] = (command_item) { .id = iterator_value_cmd, .lua = lua_key_index(iterator_value), .name = lua_key(iterator_value), .kind = data_command_item, .min = min_iterator_value, .max = max_iterator_value, .base = 0, .fixedvalue = 0 };
177 lmt_interface.command_names[font_property_cmd] = (command_item) { .id = font_property_cmd, .lua = lua_key_index(font_property), .name = lua_key(font_property), .kind = regular_command_item, .min = 0, .max = last_font_property_code, .base = 0, .fixedvalue = 0 };
178 lmt_interface.command_names[auxiliary_cmd] = (command_item) { .id = auxiliary_cmd, .lua = lua_key_index(auxiliary), .name = lua_key(auxiliary), .kind = regular_command_item, .min = 0, .max = last_auxiliary_code, .base = 0, .fixedvalue = 0 };
179 lmt_interface.command_names[page_property_cmd] = (command_item) { .id = page_property_cmd, .lua = lua_key_index(page_property), .name = lua_key(page_property), .kind = regular_command_item, .min = 0, .max = last_page_property_code, .base = 0, .fixedvalue = 0 };
180 lmt_interface.command_names[box_property_cmd] = (command_item) { .id = box_property_cmd, .lua = lua_key_index(box_property), .name = lua_key(box_property), .kind = regular_command_item, .min = 0, .max = last_box_property_code, .base = 0, .fixedvalue = 0 };
181 lmt_interface.command_names[specification_cmd] = (command_item) { .id = specification_cmd, .lua = lua_key_index(specification), .name = lua_key(specification), .kind = token_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
182 lmt_interface.command_names[define_char_code_cmd] = (command_item) { .id = define_char_code_cmd, .lua = lua_key_index(define_char_code), .name = lua_key(define_char_code), .kind = regular_command_item, .min = 0, .max = last_charcode_code, .base = 0, .fixedvalue = 0 };
183 lmt_interface.command_names[define_family_cmd] = (command_item) { .id = define_family_cmd, .lua = lua_key_index(define_family), .name = lua_key(define_family), .kind = regular_command_item, .min = 0, .max = last_math_size, .base = 0, .fixedvalue = 0 };
184 lmt_interface.command_names[math_parameter_cmd] = (command_item) { .id = math_parameter_cmd, .lua = lua_key_index(math_parameter), .name = lua_key(math_parameter), .kind = regular_command_item, .min = 0, .max = last_math_parameter, .base = 0, .fixedvalue = 0 };
185
186 lmt_interface.command_names[set_font_cmd] = (command_item) { .id = set_font_cmd, .lua = lua_key_index(set_font), .name = lua_key(set_font), .kind = data_command_item, .min = 0, .max = max_font_size, .base = 0, .fixedvalue = 0 };
187 lmt_interface.command_names[define_font_cmd] = (command_item) { .id = define_font_cmd, .lua = lua_key_index(define_font), .name = lua_key(define_font), .kind = token_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
188 lmt_interface.command_names[integer_cmd] = (command_item) { .id = integer_cmd, .lua = lua_key_index(integer), .name = lua_key(integer), .kind = data_command_item, .min = min_integer, .max = max_integer, .base = direct_entry, .fixedvalue = 0 };
189 lmt_interface.command_names[index_cmd] = (command_item) { .id = index_cmd, .lua = lua_key_index(index), .name = lua_key(index), .kind = data_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
190 lmt_interface.command_names[posit_cmd] = (command_item) { .id = posit_cmd, .lua = lua_key_index(posit), .name = lua_key(posit), .kind = data_command_item, .min = min_posit, .max = max_posit, .base = direct_entry, .fixedvalue = 0 };
191 lmt_interface.command_names[dimension_cmd] = (command_item) { .id = dimension_cmd, .lua = lua_key_index(dimension), .name = lua_key(dimension), .kind = data_command_item, .min = min_dimension, .max = max_dimension, .base = direct_entry, .fixedvalue = 0 };
192 lmt_interface.command_names[gluespec_cmd] = (command_item) { .id = gluespec_cmd, .lua = lua_key_index(gluespec), .name = lua_key(gluespec), .kind = regular_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
193 lmt_interface.command_names[mugluespec_cmd] = (command_item) { .id = mugluespec_cmd, .lua = lua_key_index(mugluespec), .name = lua_key(mugluespec), .kind = regular_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
194 lmt_interface.command_names[mathspec_cmd] = (command_item) { .id = mathspec_cmd, .lua = lua_key_index(mathspec), .name = lua_key(fontspec), .kind = regular_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
195 lmt_interface.command_names[fontspec_cmd] = (command_item) { .id = fontspec_cmd, .lua = lua_key_index(fontspec), .name = lua_key(fontspec), .kind = regular_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
196 lmt_interface.command_names[register_cmd] = (command_item) { .id = register_cmd, .lua = lua_key_index(register), .name = lua_key(register), .kind = regular_command_item, .min = first_value_level, .max = last_value_level, .base = 0, .fixedvalue = 0 };
197 lmt_interface.command_names[combine_toks_cmd] = (command_item) { .id = combine_toks_cmd, .lua = lua_key_index(combine_toks), .name = lua_key(combine_toks), .kind = regular_command_item, .min = 0, .max = last_combine_toks_code, .base = 0, .fixedvalue = 0 };
198 lmt_interface.command_names[arithmic_cmd] = (command_item) { .id = arithmic_cmd, .lua = lua_key_index(arithmic), .name = lua_key(arithmic), .kind = regular_command_item, .min = 0, .max = last_arithmic_code, .base = 0, .fixedvalue = 0 };
199 lmt_interface.command_names[prefix_cmd] = (command_item) { .id = prefix_cmd, .lua = lua_key_index(prefix), .name = lua_key(prefix), .kind = regular_command_item, .min = 0, .max = last_prefix_code, .base = 0, .fixedvalue = 0 };
200 lmt_interface.command_names[let_cmd] = (command_item) { .id = let_cmd, .lua = lua_key_index(let), .name = lua_key(let), .kind = regular_command_item, .min = 0, .max = last_let_code, .base = 0, .fixedvalue = 0 };
201 lmt_interface.command_names[shorthand_def_cmd] = (command_item) { .id = shorthand_def_cmd, .lua = lua_key_index(shorthand_def), .name = lua_key(shorthand_def), .kind = regular_command_item, .min = 0, .max = last_shorthand_def_code, .base = 0, .fixedvalue = 0 };
202 lmt_interface.command_names[association_cmd] = (command_item) { .id = association_cmd, .lua = lua_key_index(association), .name = lua_key(association), .kind = regular_command_item, .min = 0, .max = last_association_code, .base = 0, .fixedvalue = 0 };
203 lmt_interface.command_names[def_cmd] = (command_item) { .id = def_cmd, .lua = lua_key_index(def), .name = lua_key(def), .kind = regular_command_item, .min = 0, .max = last_def_code, .base = 0, .fixedvalue = 0 };
204 lmt_interface.command_names[set_box_cmd] = (command_item) { .id = set_box_cmd, .lua = lua_key_index(set_box), .name = lua_key(set_box), .kind = regular_command_item, .min = 0, .max = 0, .base = 0, .fixedvalue = 0 };
205 lmt_interface.command_names[hyphenation_cmd] = (command_item) { .id = hyphenation_cmd, .lua = lua_key_index(hyphenation), .name = lua_key(hyphenation), .kind = regular_command_item, .min = 0, .max = last_hyphenation_code, .base = 0, .fixedvalue = 0 };
206 lmt_interface.command_names[interaction_cmd] = (command_item) { .id = interaction_cmd, .lua = lua_key_index(interaction), .name = lua_key(interaction), .kind = regular_command_item, .min = 0, .max = last_interaction_level, .base = 0, .fixedvalue = 0 };
207 lmt_interface.command_names[undefined_cs_cmd] = (command_item) { .id = undefined_cs_cmd, .lua = lua_key_index(undefined_cs), .name = lua_key(undefined_cs), .kind = regular_command_item, .min = 0, .max = 0, .base = 0, .fixedvalue = 0 };
208 lmt_interface.command_names[expand_after_cmd] = (command_item) { .id = expand_after_cmd, .lua = lua_key_index(expand_after), .name = lua_key(expand_after), .kind = regular_command_item, .min = 0, .max = last_expand_after_code, .base = 0, .fixedvalue = 0 };
209 lmt_interface.command_names[no_expand_cmd] = (command_item) { .id = no_expand_cmd, .lua = lua_key_index(no_expand), .name = lua_key(no_expand), .kind = regular_command_item, .min = 0, .max = 0, .base = 0, .fixedvalue = 0 };
210 lmt_interface.command_names[input_cmd] = (command_item) { .id = input_cmd, .lua = lua_key_index(input), .name = lua_key(input), .kind = regular_command_item, .min = 0, .max = last_input_code, .base = 0, .fixedvalue = 0 };
211 lmt_interface.command_names[lua_call_cmd] = (command_item) { .id = lua_call_cmd, .lua = lua_key_index(lua_call), .name = lua_key(lua_call), .kind = reference_command_item, .min = 0, .max = max_function_reference, .base = 0, .fixedvalue = 0 };
212 lmt_interface.command_names[lua_local_call_cmd] = (command_item) { .id = lua_local_call_cmd, .lua = lua_key_index(lua_local_call), .name = lua_key(lua_local_call), .kind = reference_command_item, .min = 0, .max = max_function_reference, .base = 0, .fixedvalue = 0 };
213 lmt_interface.command_names[begin_local_cmd] = (command_item) { .id = begin_local_cmd, .lua = lua_key_index(begin_local), .name = lua_key(begin_local), .kind = regular_command_item, .min = 0, .max = 0, .base = 0, .fixedvalue = 0 };
214 lmt_interface.command_names[if_test_cmd] = (command_item) { .id = if_test_cmd, .lua = lua_key_index(if_test), .name = lua_key(if_test), .kind = regular_command_item, .min = first_if_test_code, .max = last_if_test_code, .base = 0, .fixedvalue = 0 };
215 lmt_interface.command_names[cs_name_cmd] = (command_item) { .id = cs_name_cmd, .lua = lua_key_index(cs_name), .name = lua_key(cs_name), .kind = regular_command_item, .min = 0, .max = last_cs_name_code, .base = 0, .fixedvalue = 0 };
216 lmt_interface.command_names[convert_cmd] = (command_item) { .id = convert_cmd, .lua = lua_key_index(convert), .name = lua_key(convert), .kind = regular_command_item, .min = 0, .max = last_convert_code, .base = 0, .fixedvalue = 0 };
217 lmt_interface.command_names[the_cmd] = (command_item) { .id = the_cmd, .lua = lua_key_index(the), .name = lua_key(the), .kind = regular_command_item, .min = 0, .max = last_the_code, .base = 0, .fixedvalue = 0 };
218 lmt_interface.command_names[get_mark_cmd] = (command_item) { .id = get_mark_cmd, .lua = lua_key_index(get_mark), .name = lua_key(get_mark), .kind = regular_command_item, .min = 0, .max = last_get_mark_code, .base = 0, .fixedvalue = 0 };
219 lmt_interface.command_names[call_cmd] = (command_item) { .id = call_cmd, .lua = lua_key_index(call), .name = lua_key(call), .kind = token_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
220 lmt_interface.command_names[protected_call_cmd] = (command_item) { .id = protected_call_cmd, .lua = lua_key_index(protected_call), .name = lua_key(protected_call), .kind = token_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
221 lmt_interface.command_names[semi_protected_call_cmd] = (command_item) { .id = semi_protected_call_cmd, .lua = lua_key_index(semi_protected_call), .name = lua_key(semi_protected_call), .kind = token_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
222 lmt_interface.command_names[constant_call_cmd] = (command_item) { .id = constant_call_cmd, .lua = lua_key_index(constant_call), .name = lua_key(constant_call), .kind = token_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
223 lmt_interface.command_names[tolerant_call_cmd] = (command_item) { .id = tolerant_call_cmd, .lua = lua_key_index(tolerant_call), .name = lua_key(tolerant_call), .kind = token_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
224 lmt_interface.command_names[tolerant_protected_call_cmd] = (command_item) { .id = tolerant_protected_call_cmd, .lua = lua_key_index(tolerant_protected_call), .name = lua_key(tolerant_protected_call), .kind = token_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
225 lmt_interface.command_names[tolerant_semi_protected_call_cmd] = (command_item) { .id = tolerant_semi_protected_call_cmd, .lua = lua_key_index(tolerant_semi_protected_call), .name = lua_key(tolerant_semi_protected_call), .kind = token_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
226 lmt_interface.command_names[deep_frozen_end_template_cmd] = (command_item) { .id = deep_frozen_end_template_cmd, .lua = lua_key_index(deep_frozen_end_template), .name = lua_key(deep_frozen_end_template), .kind = token_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
227 lmt_interface.command_names[deep_frozen_dont_expand_cmd] = (command_item) { .id = deep_frozen_dont_expand_cmd, .lua = lua_key_index(deep_frozen_dont_expand), .name = lua_key(deep_frozen_dont_expand), .kind = token_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
228 lmt_interface.command_names[deep_frozen_keep_constant_cmd] = (command_item) { .id = deep_frozen_keep_constant_cmd, .lua = lua_key_index(deep_frozen_keep_constant), .name = lua_key(deep_frozen_keep_constant), .kind = token_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
229 lmt_interface.command_names[internal_glue_reference_cmd] = (command_item) { .id = internal_glue_reference_cmd, .lua = lua_key_index(internal_glue_reference), .name = lua_key(internal_glue_reference), .kind = token_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
230 lmt_interface.command_names[register_glue_reference_cmd] = (command_item) { .id = register_glue_reference_cmd, .lua = lua_key_index(register_glue_reference), .name = lua_key(register_glue_reference), .kind = token_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
231 lmt_interface.command_names[internal_muglue_reference_cmd] = (command_item) { .id = internal_muglue_reference_cmd, .lua = lua_key_index(internal_muglue_reference), .name = lua_key(internal_muglue_reference), .kind = token_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
232 lmt_interface.command_names[register_muglue_reference_cmd] = (command_item) { .id = register_muglue_reference_cmd, .lua = lua_key_index(register_muglue_reference), .name = lua_key(register_muglue_reference), .kind = token_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
233 lmt_interface.command_names[internal_box_reference_cmd] = (command_item) { .id = internal_box_reference_cmd, .lua = lua_key_index(specification_reference), .name = lua_key(specification_reference), .kind = token_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
234 lmt_interface.command_names[register_box_reference_cmd] = (command_item) { .id = register_box_reference_cmd, .lua = lua_key_index(internal_box_reference), .name = lua_key(internal_box_reference), .kind = token_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
235 lmt_interface.command_names[internal_toks_reference_cmd] = (command_item) { .id = internal_toks_reference_cmd, .lua = lua_key_index(internal_toks_reference), .name = lua_key(register_box_reference), .kind = token_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
236 lmt_interface.command_names[register_toks_reference_cmd] = (command_item) { .id = register_toks_reference_cmd, .lua = lua_key_index(register_toks_reference), .name = lua_key(register_toks_reference), .kind = token_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
237 lmt_interface.command_names[specification_reference_cmd] = (command_item) { .id = specification_reference_cmd, .lua = lua_key_index(specification_reference), .name = lua_key(specification_reference), .kind = token_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
238 lmt_interface.command_names[unit_reference_cmd] = (command_item) { .id = unit_reference_cmd, .lua = lua_key_index(unit_reference), .name = lua_key(unit_reference), .kind = token_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
239 lmt_interface.command_names[internal_integer_reference_cmd] = (command_item) { .id = internal_integer_reference_cmd, .lua = lua_key_index(internal_integer_reference), .name = lua_key(internal_integer_reference), .kind = regular_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
240 lmt_interface.command_names[register_integer_reference_cmd] = (command_item) { .id = register_integer_reference_cmd, .lua = lua_key_index(register_integer_reference), .name = lua_key(register_integer_reference), .kind = regular_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
241 lmt_interface.command_names[internal_attribute_reference_cmd] = (command_item) { .id = internal_attribute_reference_cmd, .lua = lua_key_index(internal_attribute_reference), .name = lua_key(internal_attribute_reference), .kind = regular_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
242 lmt_interface.command_names[register_attribute_reference_cmd] = (command_item) { .id = register_attribute_reference_cmd, .lua = lua_key_index(register_attribute_reference), .name = lua_key(register_attribute_reference), .kind = regular_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
243 lmt_interface.command_names[internal_posit_reference_cmd] = (command_item) { .id = internal_posit_reference_cmd, .lua = lua_key_index(internal_posit_reference), .name = lua_key(internal_posit_reference), .kind = regular_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
244 lmt_interface.command_names[register_posit_reference_cmd] = (command_item) { .id = register_posit_reference_cmd, .lua = lua_key_index(register_posit_reference), .name = lua_key(register_posit_reference), .kind = regular_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
245 lmt_interface.command_names[internal_dimension_reference_cmd] = (command_item) { .id = internal_dimension_reference_cmd, .lua = lua_key_index(internal_dimension_reference), .name = lua_key(internal_dimension_reference), .kind = regular_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
246 lmt_interface.command_names[register_dimension_reference_cmd] = (command_item) { .id = register_dimension_reference_cmd, .lua = lua_key_index(register_dimension_reference), .name = lua_key(register_dimension_reference), .kind = regular_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
247 lmt_interface.command_names[register_dimension_reference_cmd + 1] = (command_item) { .id = unknown_value, .lua = 0, .name = NULL, .kind = unused_command_item, .min = ignore_entry, .max = ignore_entry, .base = ignore_entry, .fixedvalue = 0 };
248
249 if (lmt_interface.command_names[last_cmd].id != last_cmd) {
250 tex_fatal_error("mismatch between tex and lua command name tables");
251 }
252}
253
254typedef struct saved_tex_scanner {
255 int cmd;
256 int chr;
257 int cs;
258 int tok;
259} saved_tex_scanner;
260
261inline static saved_tex_scanner tokenlib_aux_save_tex_scanner(void) {
262 return (saved_tex_scanner) {
263 .cmd = cur_cmd,
264 .chr = cur_chr,
265 .cs = cur_cs,
266 .tok = cur_tok
267 };
268}
269
270inline static void tokenlib_aux_unsave_tex_scanner(saved_tex_scanner a)
271{
272 cur_cmd = a.cmd;
273 cur_chr = a.chr;
274 cur_cs = a.cs;
275 cur_tok = a.tok;
276}
277
278static int tokenlib_aux_get_command_id(const char *s)
279{
280 for (int i = 0; lmt_interface.command_names[i].id != -1; i++) {
281 if (s == lmt_interface.command_names[i].name) {
282 return i;
283 }
284 }
285 return -1;
286}
287
288
296
297
303
304inline static int tokenlib_aux_valid_chr(int cmd, int chr)
305{
306 command_item item = lmt_interface.command_names[cmd];
307 if (chr > 0) {
308 switch (item.base) {
309 case ignore_entry:
310 case direct_entry:
311 break;
312 default:
313 if (chr >= item.min && chr <= item.max) {
314 return item.base + chr;
315 }
316 }
317 } else if (chr == item.fixedvalue) {
318 return chr;
319 }
320 return 0;
321}
322
323inline static int tokenlib_aux_valid_cs(int cs)
324{
325 return (cs >= 0 && cs <= lmt_token_memory_state.tokens_data.allocated) ? cs : -1;
326}
327
328
329
330inline static int tokenlib_aux_valid_token(int cmd, int chr, int cs)
331{
332 if (cs) {
333 cs = tokenlib_aux_valid_cs(cs);
334 if (cs >= 0) {
335 return cs_token_flag + cs;
336 }
337 } if (cmd >= first_cmd && cmd <= last_cmd) {
338 chr = tokenlib_aux_valid_chr(cmd, chr);
339 if (chr >= 0) {
340 return token_val(cmd, chr);
341 }
342 }
343 return -1;
344}
345
346inline static int tokenlib_aux_to_valid_index(int cmd, int chr)
347{
348 if (cmd >= 0 && cmd <= last_cmd) {
349 command_item item = lmt_interface.command_names[cmd];
350 switch (item.kind) {
351 case unused_command_item:
352 return 0;
353 case regular_command_item:
354 case character_command_item:
355 return chr;
356 case register_command_item:
357 case internal_command_item:
358 case reference_command_item:
359 case data_command_item:
360 switch (item.base) {
361 case ignore_entry:
362 return 0;
363 case direct_entry:
364 break;
365 default:
366 chr -= item.base;
367 break;
368 }
369 return (chr >= item.min && chr <= item.max) ? chr : item.min;
370 case token_command_item:
371 case node_command_item:
372 return item.fixedvalue;
373 }
374 }
375 return 0;
376}
377
378inline static void tokenlib_aux_make_token_table(lua_State *L, int cmd, int chr, int cs)
379{
380 lua_createtable(L, 3, 0);
381 lua_pushinteger(L, cmd);
382 lua_rawseti(L, -2, 1);
383 lua_pushinteger(L, tokenlib_aux_to_valid_index(cmd, chr));
384 lua_rawseti(L, -2, 2);
385 lua_pushinteger(L, cs);
386 lua_rawseti(L, -2, 3);
387}
388
389
395
396inline static int lmt_token_from_lua(lua_State *L)
397{
398 int cmd, chr, cs;
399 lua_rawgeti(L, -1, 1);
400 cmd = lmt_tointeger(L, -1);
401 lua_rawgeti(L, -2, 2);
402 chr = lmt_optinteger(L, -1, 0);
403 lua_rawgeti(L, -3, 3);
404 cs = lmt_optinteger(L, -1, 0);
405 lua_pop(L, 3);
406 return tokenlib_aux_valid_token(cmd, chr, cs);
407}
408
409void lmt_token_list_to_lua(lua_State *L, halfword p)
410{
411 int i = 1;
412 int v = p;
413 int max = lmt_token_memory_state.tokens_data.top;
414 while (v && v < max) {
415 i++;
416 v = token_link(v);
417 }
418 lua_createtable(L, i, 0);
419 i = 1;
420 while (p && p < max) {
421 int cmd, chr, cs;
422 if (token_info(p) >= cs_token_flag) {
423 cs = token_info(p) - cs_token_flag;
424 cmd = eq_type(cs);
425 chr = eq_value(cs);
426 } else {
427 cs = 0;
428 cmd = token_cmd(token_info(p));
429 chr = token_chr(token_info(p));
430 }
431 tokenlib_aux_make_token_table(L, cmd, chr, cs);
432 lua_rawseti(L, -2, i++);
433 p = token_link(p);
434 }
435}
436
437void lmt_token_list_to_luastring(lua_State *L, halfword p, int nospace, int strip, int wipe)
438{
439 int l;
440
441 char *s = tex_tokenlist_to_tstring(p, 1, &l, 0, nospace, strip, wipe, 1);
442 if (l) {
443 lua_pushlstring(L, s, (size_t) l);
444 } else {
445 lua_pushliteral(L, "");
446 }
447}
448
449static lua_token *tokenlib_aux_check_istoken(lua_State *L, int ud);
450
451halfword lmt_token_list_from_lua(lua_State *L, int slot)
452{
453 halfword h = tex_get_available_token(null);
454 halfword p = h;
455 token_link(h) = null;
456 switch (lua_type(L, slot)) {
457 case LUA_TTABLE:
458 {
459 int j = (int) lua_rawlen(L, slot);
460 if (j > 0) {
461 for (int i = 1; i <= j; i++) {
462 int tok;
463 lua_rawgeti(L, slot, (int) i);
464 tok = lmt_token_from_lua(L);
465 if (tok >= 0) {
466 p = tex_store_new_token(p, tok);
467 }
468 lua_pop(L, 1);
469 };
470 }
471 return h;
472 }
473 case LUA_TSTRING:
474 {
475 size_t j;
476 const char *s = lua_tolstring(L, slot, &j);
477 for (size_t i = 0; i < j; i++) {
478 int tok;
479 if (s[i] == ascii_space) {
480 tok = token_val(spacer_cmd, s[i]);
481 } else {
482 int kl;
483 int k = (int) aux_str2uni_len((const unsigned char *) (s + i), &kl);
484 i = i + kl - 1;
485 tok = token_val(other_char_cmd, k);
486 }
487 p = tex_store_new_token(p, tok);
488 }
489 return h;
490 }
491 case LUA_TUSERDATA:
492 {
493 lua_token *t = tokenlib_aux_check_istoken(L, slot);
494 p = tex_store_new_token(p, t->token);
495 return h;
496 }
497 default:
498 {
499 tex_put_available_token(h);
500 return null;
501 }
502 }
503}
504
505halfword lmt_token_code_from_lua(lua_State *L, int slot)
506{
507 lua_token *t = tokenlib_aux_check_istoken(L, slot);
508 return t->token;
509}
510
511# define DEFAULT_SCAN_CODE_SET (2048 + 4096)
512
513
514
515# define is_active_string(s) (strlen(s) > 3 && *s == 0xEF && *(s+1) == 0xBF && *(s+2) == 0xBF)
516
517static unsigned char *tokenlib_aux_get_cs_text(int cs, int *allocated)
518{
519 if (cs == null_cs) {
520 return (unsigned char *) "\\csname\\endcsname";
521 } else if ((cs_text(cs) < 0) || (cs_text(cs) >= lmt_string_pool_state.string_pool_data.ptr)) {
522 return (unsigned char *) "";
523
524
525 } else if (cs_text(cs) < cs_offset_value) {
526 *allocated = 1;
527 return (unsigned char *) aux_uni2str((unsigned) cs_text(cs));
528 } else {
529 return (unsigned char *) (str_length(cs_text(cs)) > 0 ? (unsigned char *) str_string(cs_text(cs)) : (unsigned char *) "");
530 }
531}
532
533static lua_token *tokenlib_aux_maybe_istoken(lua_State *L, int ud)
534{
535 lua_token *t = lua_touserdata(L, ud);
536 if (t && lua_getmetatable(L, ud)) {
537 lua_get_metatablelua(token_instance);
538 if (! lua_rawequal(L, -1, -2)) {
539 t = NULL;
540 }
541 lua_pop(L, 2);
542 }
543 return t;
544}
545
546static lua_token_package *tokenlib_aux_maybe_ispackage(lua_State *L, int ud)
547{
548 lua_token_package *t = lua_touserdata(L, ud);
549 if (t && lua_getmetatable(L, ud)) {
550 lua_get_metatablelua(token_package);
551 if (! lua_rawequal(L, -1, -2)) {
552 t = NULL;
553 }
554 lua_pop(L, 2);
555 }
556 return t;
557}
558
559
560
561lua_token *tokenlib_aux_check_istoken(lua_State *L, int ud)
562{
563 lua_token *t = tokenlib_aux_maybe_istoken(L, ud);
564 if (! t) {
565 tex_formatted_error("token lib", "lua <token> expected, not an object with type %s", luaL_typename(L, ud));
566 }
567 return t;
568}
569
570static lua_token_package *tokenlib_aux_check_ispackage(lua_State *L, int ud)
571{
572 lua_token_package *t = tokenlib_aux_maybe_ispackage(L, ud);
573 if (! t) {
574 tex_formatted_error("token lib", "lua <token package> expected, not an object with type %s", luaL_typename(L, ud));
575 }
576 return t;
577}
578
579
580
581static void tokenlib_aux_make_new_token(lua_State *L, int cmd, int chr, int cs)
582{
583 int tok = tokenlib_aux_valid_token(cmd, chr, cs);
584 if (tok >= 0) {
585 lua_token *thetok = (lua_token *) lua_newuserdatauv(L, sizeof(lua_token), 0);
586 thetok->token = tex_get_available_token(tok);
587 thetok->origin = token_origin_lua;
588 lua_get_metatablelua(token_instance);
589 lua_setmetatable(L, -2);
590 } else {
591 lua_pushnil(L);
592 }
593}
594
595static void tokenlib_aux_make_new_token_tok(lua_State *L, int tok)
596{
597 if (tok >= 0) {
598 lua_token *thetok = (lua_token *) lua_newuserdatauv(L, sizeof(lua_token), 0);
599 thetok->token = tex_get_available_token(tok);
600 thetok->origin = token_origin_lua;
601 lua_get_metatablelua(token_instance);
602 lua_setmetatable(L, -2);
603 } else {
604 lua_pushnil(L);
605 }
606}
607
608static void tokenlib_aux_make_new_package(lua_State *L, singleword cmd, singleword flag, int chr, int cs, quarterword how)
609{
610 lua_token_package *package = (lua_token_package *) lua_newuserdatauv(L, sizeof(lua_token_package), 0);
611 package->cmd = cmd;
612 package->flag = flag;
613 package->chr = chr;
614 package->cs = cs;
615 package->how = how;
616 lua_get_metatablelua(token_package);
617 lua_setmetatable(L, -2);
618}
619
620static void tokenlib_aux_push_token(lua_State *L, int tok)
621{
622 lua_token *thetok = (lua_token *) lua_newuserdatauv(L, sizeof(lua_token), 0);
623 thetok->token = tok;
624 thetok->origin = token_origin_lua;
625 lua_get_metatablelua(token_instance);
626 lua_setmetatable(L, -2);
627}
628
629static int tokenlib_getcommandid(lua_State *L)
630{
631 int id = -1;
632 switch (lua_type(L, 1)) {
633 case LUA_TSTRING:
634 id = tokenlib_aux_get_command_id(lua_tostring(L, 1));
635 break;
636 case LUA_TNUMBER:
637 id = lmt_tointeger(L, 1);
638 break;
639 }
640 if (id >= 0 && id < number_glue_pars) {
641 lua_pushinteger(L, id);
642 } else {
643 lua_pushnil(L);
644 }
645 return 1;
646}
647
648static int tokenlib_scan_next(lua_State *L)
649{
650 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
651 halfword tok = tex_get_token();
652 tokenlib_aux_make_new_token_tok(L, tok);
653 tokenlib_aux_unsave_tex_scanner(texstate);
654 return 1;
655}
656
657static int tokenlib_scan_next_expanded(lua_State *L)
658{
659 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
660 halfword tok = tex_get_x_token();
661 tokenlib_aux_make_new_token_tok(L, tok);
662 tokenlib_aux_unsave_tex_scanner(texstate);
663 return 1;
664}
665
666static int tokenlib_skip_next(lua_State *L)
667{
668 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
669 (void) L;
670 tex_get_token();
671 tokenlib_aux_unsave_tex_scanner(texstate);
672 return 0;
673}
674
675static int tokenlib_skip_next_expanded(lua_State *L)
676{
677 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
678 (void) L;
679 tex_get_x_token();
680 tokenlib_aux_unsave_tex_scanner(texstate);
681 return 0;
682}
683
684
706
707inline static int tokenlib_aux_to_token_val(int chr)
708{
709 switch (chr) {
710 case '\n':
711 case '\r':
712 case ' ':
713 return token_val(spacer_cmd, ' ');
714 default:
715 {
716 int cmd = tex_get_cat_code(cat_code_table_par, chr);
717 switch (cmd) {
718 case escape_cmd:
719 case ignore_cmd:
720 case comment_cmd:
721 case invalid_char_cmd:
722 case active_char_cmd:
723 cmd = other_char_cmd;
724 break;
725 }
726 return token_val(cmd, chr);
727 }
728 }
729}
730
731
740
741static void tokenlib_aux_to_token(lua_State *L, int i, int m, int *head, int *tail)
742{
743 switch (lua_type(L, i)) {
744 case LUA_TSTRING:
745
746 {
747 size_t l = 0;
748 const char *s = lua_tolstring(L, i, &l);
749 const unsigned char *p = (const unsigned char *) s;
750 size_t n = aux_utf8len(s, l);
751 for (size_t j = 0; j < n; j++) {
752 int xl;
753 halfword x = tex_get_available_token(tokenlib_aux_to_token_val(aux_str2uni_len(p, &xl)));
754 if (*head) {
755 token_link(*tail) = x;
756 } else {
757 *head = x;
758 }
759 *tail = x;
760 p += xl;
761 }
762 break;
763 }
764 case LUA_TNUMBER:
765 {
766 halfword t = tex_get_available_token(tokenlib_aux_to_token_val((int) lua_tointeger(L, i)));
767 if (*head) {
768 token_link(*tail) = t;
769 } else {
770 *head = t;
771 }
772 *tail = t;
773 break;
774 }
775 case LUA_TTABLE:
776 {
777 size_t n = lua_rawlen(L, i);
778 for (size_t j = 1; j <= n; j++) {
779 lua_rawgeti(L, i, j);
780 tokenlib_aux_to_token(L, -1, m, head, tail);
781 lua_pop(L, 1);
782 }
783 break;
784 }
785 case LUA_TUSERDATA:
786 {
787
788 lua_token *p = lua_touserdata(L, i);
789 halfword t, q;
790 if (p && lua_getmetatable(L, i)) {
791 t = lua_rawequal(L, m, -1) ? token_info(p->token) : tokenlib_aux_to_token_val(0xFFFD);
792 lua_pop(L, 1);
793 } else {
794 t = tokenlib_aux_to_token_val(0xFFFD);
795 }
796 q = tex_get_available_token(t);
797 if (*head) {
798 token_link(*tail) = q;
799 } else {
800 *head = q;
801 }
802 *tail = q;
803 break;
804 }
805 default:
806
807 break;
808 }
809}
810
811inline static int tokenlib_put_next(lua_State *L)
812{
813 int top = lua_gettop(L);
814 if (top > 0) {
815 halfword h = null;
816 halfword t = null;
817 int m = top + 1;
818 lua_get_metatablelua(token_instance);
819 for (int i = 1; i <= top; i++) {
820 tokenlib_aux_to_token(L, i, m, &h, &t);
821 }
822 if (h) {
823 tex_begin_inserted_list(h);
824 }
825 lua_settop(L, top);
826 }
827 return 0;
828}
829
830inline static int tokenlib_put_back(lua_State *L)
831{
832 lua_token *t = tokenlib_aux_check_istoken(L, 1);
833 if (t) {
834 tex_back_input(token_info(t->token));
835 }
836 return 0;
837}
838
839static int tokenlib_scan_keyword(lua_State *L)
840{
841 const char *s = lua_tostring(L, 1);
842 int v = 0;
843 if (s) {
844 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
845 v = tex_scan_keyword(s);
846 tokenlib_aux_unsave_tex_scanner(texstate);
847 }
848 lua_pushboolean(L, v);
849 return 1;
850}
851
852static int tokenlib_scan_keyword_cs(lua_State *L)
853{
854 const char *s = lua_tostring(L, 1);
855 int v = 0;
856 if (s) {
857 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
858 v = tex_scan_keyword_case_sensitive(s);
859 tokenlib_aux_unsave_tex_scanner(texstate);
860 }
861 lua_pushboolean(L, v);
862 return 1;
863}
864
865static int tokenlib_scan_csname(lua_State *L)
866{
867 int t;
868 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
869 if (lua_toboolean(L, 1)) {
870
871 do {
872 tex_get_token();
873 } while (cur_tok == space_token);
874 } else {
875
876 tex_get_next();
877 }
878 t = cur_cs ? cs_token_flag + cur_cs : token_val(cur_cmd, cur_chr);
879 if (t >= cs_token_flag) {
880 int allocated = 0;
881 unsigned char *s = tokenlib_aux_get_cs_text(t - cs_token_flag, &allocated);
882 if (s) {
883 if (tex_is_active_cs(cs_text(t - cs_token_flag))) {
884 lua_pushstring(L, (char *) (s + 3));
885 } else {
886 lua_pushstring(L, (char *) s);
887 }
888 if (allocated) {
889 lmt_memory_free(s);
890 }
891 } else {
892 lua_pushnil(L);
893 }
894 } else {
895 lua_pushnil(L);
896 }
897 tokenlib_aux_unsave_tex_scanner(texstate);
898 return 1;
899}
900
901static int tokenlib_scan_integer(lua_State *L)
902{
903 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
904 int eq = lua_toboolean(L, 1);
905 halfword v = tex_scan_integer(eq, NULL);
906 lua_pushinteger(L, (int) v);
907 tokenlib_aux_unsave_tex_scanner(texstate);
908 return 1;
909}
910
911static int tokenlib_scan_cardinal(lua_State *L)
912{
913 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
914 int eq = lua_toboolean(L, 1);
915 unsigned int v = 0;
916 tex_scan_cardinal(eq, &v, 0);
917 lua_pushinteger(L, (unsigned int) v);
918 tokenlib_aux_unsave_tex_scanner(texstate);
919 return 1;
920}
921
922static int tokenlib_gobble_integer(lua_State *L)
923{
924 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
925 int eq = lua_toboolean(L, 1);
926 lmt_error_state.intercept = 1;
927 lmt_error_state.last_intercept = 0;
928 tex_scan_integer(eq, NULL);
929 lua_pushboolean(L, ! lmt_error_state.last_intercept);
930 lmt_error_state.intercept = 0;
931 lmt_error_state.last_intercept = 0;
932 tokenlib_aux_unsave_tex_scanner(texstate);
933 return 1;
934}
935
936inline static void tokenlib_aux_goto_first_candidate(void)
937{
938 do {
939 tex_get_token();
940 } while (cur_cmd == spacer_cmd);
941}
942
943inline static void tokenlib_aux_goto_first_candidate_x(void)
944{
945 do {
946 tex_get_x_token();
947 } while (cur_cmd == spacer_cmd);
948}
949
950inline static void tokenlib_aux_add_utf_char_to_buffer(luaL_Buffer *b, halfword chr)
951{
952 if (chr <= ascii_max) {
953 luaL_addchar(b, (unsigned char) chr);
954 } else {
955
961 unsigned char word[5 + 1];
962 aux_uni2string((char *) word, (unsigned int) chr);
963 luaL_addlstring(b, (char *) word, utf8_size(chr));
964 }
965}
966
967
975
976static int tokenlib_scan_float_indeed(lua_State *L, int exponent, int hexadecimal)
977{
978 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
979 int negative = 0;
980 luaL_Buffer b;
981 luaL_buffinit(L, &b);
982 tokenlib_aux_goto_first_candidate_x();
983 if (lua_toboolean(L, 1) && (cur_tok == equal_token)) {
984 tokenlib_aux_goto_first_candidate_x();
985 }
986
987 while(1) {
988 if (cur_tok == minus_token) {
989 negative = ! negative;
990 } else if (cur_tok != plus_token) {
991 break;
992 }
993 tokenlib_aux_goto_first_candidate_x();
994 }
995 if (negative) {
996 luaL_addchar(&b, '-');
997 }
998
999 if (hexadecimal && (cur_tok == zero_token)) {
1000 luaL_addchar(&b, '0');
1001 tex_get_x_token();
1002 if (tex_token_is_hexadecimal(cur_tok)) {
1003 luaL_addchar(&b, 'x');
1004 goto SCANHEXADECIMAL;
1005 } else {
1006 goto PICKUPDECIMAL;
1007 }
1008 } else {
1009 goto SCANDECIMAL;
1010 }
1011 SCANDECIMAL:
1012 if (tex_token_is_seperator(cur_tok)) {
1013 luaL_addchar(&b, '.');
1014 while (1) {
1015 tex_get_x_token();
1016 if (tex_token_is_digit(cur_tok)) {
1017 luaL_addchar(&b, (unsigned char) cur_chr);
1018 } else if (exponent) {
1019 goto DECIMALEXPONENT;
1020 } else {
1021 tex_back_input(cur_tok);
1022 goto DONE;
1023 }
1024 }
1025 } else {
1026 goto PICKUPDECIMAL;
1027 }
1028 while (1) {
1029 tex_get_x_token();
1030 PICKUPDECIMAL:
1031 if (tex_token_is_digit(cur_tok)) {
1032 luaL_addchar(&b, (unsigned char) cur_chr);
1033 } else if (tex_token_is_seperator(cur_tok)) {
1034 luaL_addchar(&b, '.');
1035 while (1) {
1036 tex_get_x_token();
1037 if (tex_token_is_digit(cur_tok)) {
1038 luaL_addchar(&b, (unsigned char) cur_chr);
1039 } else {
1040 tex_back_input(cur_tok);
1041 break;
1042 }
1043 }
1044 } else if (exponent) {
1045 goto DECIMALEXPONENT;
1046 } else {
1047 tex_back_input(cur_tok);
1048 goto DONE;
1049 }
1050 }
1051 DECIMALEXPONENT:
1052 if (tex_token_is_exponent(cur_tok)) {
1053 luaL_addchar(&b, (unsigned char) cur_chr);
1054 tex_get_x_token();
1055 if (tex_token_is_sign(cur_tok)) {
1056 luaL_addchar(&b, (unsigned char) cur_chr);
1057 } else if (tex_token_is_digit(cur_tok)) {
1058 luaL_addchar(&b, (unsigned char) cur_chr);
1059 }
1060 while (1) {
1061 tex_get_x_token();
1062 if (tex_token_is_digit(cur_tok)) {
1063 luaL_addchar(&b, (unsigned char) cur_chr);
1064 } else {
1065 break;
1066 }
1067 }
1068 }
1069 tex_back_input(cur_tok);
1070 goto DONE;
1071 SCANHEXADECIMAL:
1072 tex_get_x_token();
1073 if (tex_token_is_seperator(cur_tok)) {
1074 luaL_addchar(&b, '.');
1075 while (1) {
1076 tex_get_x_token();
1077 if (tex_token_is_xdigit(cur_tok)) {
1078 luaL_addchar(&b, (unsigned char) cur_chr);
1079 } else if (exponent) {
1080 goto HEXADECIMALEXPONENT;
1081 } else {
1082 tex_back_input(cur_tok);
1083 goto DONE;
1084 }
1085 }
1086 } else {
1087
1088 tex_back_input(cur_tok);
1089 while (1) {
1090 tex_get_x_token();
1091 if (tex_token_is_xdigit(cur_tok)) {
1092 luaL_addchar(&b, (unsigned char) cur_chr);
1093 } else if (tex_token_is_seperator(cur_tok)) {
1094 luaL_addchar(&b, '.');
1095 while (1) {
1096 tex_get_x_token();
1097 if (tex_token_is_xdigit(cur_tok)) {
1098 luaL_addchar(&b, (unsigned char) cur_chr);
1099 } else {
1100 tex_back_input(cur_tok);
1101 break;
1102 }
1103 }
1104 } else if (exponent) {
1105 goto HEXADECIMALEXPONENT;
1106 } else {
1107 tex_back_input(cur_tok);
1108 goto DONE;
1109 }
1110 }
1111 }
1112 HEXADECIMALEXPONENT:
1113 if (tex_token_is_xexponent(cur_tok)) {
1114 luaL_addchar(&b, (unsigned char) cur_chr);
1115 tex_get_x_token();
1116 if (tex_token_is_sign(cur_tok)) {
1117
1120 luaL_addchar(&b, (unsigned char) cur_chr);
1121 } else if (tex_token_is_xdigit(cur_tok)) {
1122 luaL_addchar(&b, (unsigned char) cur_chr);
1123 }
1124 while (1) {
1125 tex_get_x_token();
1126 if (tex_token_is_xdigit(cur_tok)) {
1127 luaL_addchar(&b, (unsigned char) cur_chr);
1128 } else {
1129 break;
1130 }
1131 }
1132 }
1133 tex_back_input(cur_tok);
1134 DONE:
1135 luaL_pushresult(&b);
1136 {
1137 int ok = 0;
1138 double d = lua_tonumberx(L, -1, &ok);
1139 if (ok) {
1140 lua_pushnumber(L, d);
1141 } else {
1142 lua_pushnil(L);
1143 }
1144 }
1145 tokenlib_aux_unsave_tex_scanner(texstate);
1146 return 1;
1147}
1148
1149static int tokenlib_scan_integer_indeed(lua_State *L, int cardinal)
1150{
1151 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
1152 int negative = 0;
1153 luaL_Buffer b;
1154 luaL_buffinit(L, &b);
1155 tokenlib_aux_goto_first_candidate_x();
1156 if (lua_toboolean(L, 1) && (cur_tok == equal_token)) {
1157 tokenlib_aux_goto_first_candidate_x();
1158 }
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176 while(1) {
1177 if (cur_tok == minus_token) {
1178 negative = ! negative;
1179 } else if (cur_tok != plus_token) {
1180 break;
1181 }
1182 tokenlib_aux_goto_first_candidate_x();
1183 }
1184 if (negative) {
1185 if (cardinal) {
1186 tex_normal_warning("scanner", "positive number expected, ignoring minus sign");
1187 } else {
1188 luaL_addchar(&b, '-');
1189 }
1190 tokenlib_aux_goto_first_candidate_x();
1191 }
1192 if (cur_tok == zero_token) {
1193 luaL_addchar(&b, '0');
1194 tex_get_x_token();
1195 if (tex_token_is_hexadecimal(cur_tok)) {
1196 luaL_addchar(&b, 'x');
1197 goto HEXADECIMAL;
1198 } else {
1199 goto PICKUPDECIMAL;
1200 }
1201 } else {
1202 goto PICKUPDECIMAL;
1203 }
1204 while (1) {
1205 tex_get_x_token();
1206 PICKUPDECIMAL:
1207 if (tex_token_is_digit(cur_tok)) {
1208 luaL_addchar(&b, (unsigned char) cur_chr);
1209 } else {
1210 tex_back_input(cur_tok);
1211 goto DONE;
1212 }
1213 }
1214 HEXADECIMAL:
1215 while (1) {
1216 tex_get_x_token();
1217 if (tex_token_is_xdigit(cur_tok)) {
1218 luaL_addchar(&b, (unsigned char) cur_chr);
1219 } else {
1220 tex_back_input(cur_tok);
1221 goto DONE;
1222 }
1223 }
1224 DONE:
1225 luaL_pushresult(&b);
1226 if (cardinal) {
1227 int ok = 0;
1228 lua_Unsigned c = lua_tointegerx(L, -1, &ok);
1229 if (ok) {
1230 lua_pushinteger(L, c);
1231 } else {
1232 lua_pushnil(L);
1233 }
1234 } else {
1235 int ok = 0;
1236 lua_Integer i = lua_tointegerx(L, -1, &ok);
1237 if (ok) {
1238 lua_pushinteger(L, i);
1239 } else {
1240 lua_pushnil(L);
1241 }
1242 }
1243 tokenlib_aux_unsave_tex_scanner(texstate);
1244 return 1;
1245}
1246
1247static int tokenlib_scan_float(lua_State *L)
1248{
1249 return tokenlib_scan_float_indeed(L, 1, 0);
1250}
1251
1252static int tokenlib_scan_real(lua_State *L)
1253{
1254 return tokenlib_scan_float_indeed(L, 0, 0);
1255}
1256
1257static int tokenlib_scan_luanumber(lua_State* L)
1258{
1259 return tokenlib_scan_float_indeed(L, 1, 1);
1260}
1261
1262static int tokenlib_scan_luainteger(lua_State* L)
1263{
1264 return tokenlib_scan_integer_indeed(L, 0);
1265}
1266
1267static int tokenlib_scan_luacardinal(lua_State* L)
1268{
1269 return tokenlib_scan_integer_indeed(L, 1);
1270}
1271
1272static int tokenlib_scan_scale(lua_State *L)
1273{
1274 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
1275 int eq = lua_toboolean(L, 1);
1276 halfword val = tex_scan_scale(eq);
1277 lua_pushinteger(L, val);
1278 tokenlib_aux_unsave_tex_scanner(texstate);
1279 return 1;
1280}
1281
1282static int tokenlib_scan_dimension(lua_State *L)
1283{
1284 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
1285 int inf = lua_toboolean(L, 1);
1286 int mu = lua_toboolean(L, 2);
1287 int eq = lua_toboolean(L, 3);
1288 halfword order;
1289 halfword val = tex_scan_dimension(mu, inf, 0, eq, &order);
1290 lua_pushinteger(L, val);
1291 tokenlib_aux_unsave_tex_scanner(texstate);
1292 if (inf) {
1293 lua_pushinteger(L, order);
1294 return 2;
1295 } else {
1296 return 1;
1297 }
1298}
1299
1300static int tokenlib_scan_posit(lua_State *L)
1301{
1302 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
1303 int eq = lua_toboolean(L, 1);
1304 int fl = lua_toboolean(L, 1);
1305 halfword val = tex_scan_posit(eq);
1306 if (fl) {
1307 lua_pushnumber(L, tex_posit_to_double(val));
1308 } else {
1309 lua_pushinteger(L, val);
1310 }
1311 tokenlib_aux_unsave_tex_scanner(texstate);
1312 return 1;
1313}
1314
1315static int tokenlib_gobble_dimension(lua_State *L)
1316{
1317 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
1318 int inf = lua_toboolean(L, 1);
1319 int mu = lua_toboolean(L, 2);
1320 int eq = lua_toboolean(L, 3);
1321 lmt_error_state.intercept = 1;
1322 lmt_error_state.last_intercept = 0;
1323 tex_scan_dimension(mu, inf, 0, eq, NULL);
1324 lua_pushboolean(L, ! lmt_error_state.last_intercept);
1325 lmt_error_state.intercept = 0;
1326 lmt_error_state.last_intercept = 0;
1327 tokenlib_aux_unsave_tex_scanner(texstate);
1328 return 1;
1329}
1330
1331static int tokenlib_scan_skip(lua_State *L)
1332{
1333 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
1334 int mu = lua_toboolean(L, 1) ? muglue_val_level : glue_val_level;
1335 int eq = lua_toboolean(L, 2);
1336 halfword v = tex_scan_glue(mu, eq, 0);
1337 lmt_push_node_fast(L, v);
1338 tokenlib_aux_unsave_tex_scanner(texstate);
1339 return 1;
1340}
1341
1342static int tokenlib_scan_glue(lua_State *L)
1343{
1344 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
1345 int mu = lua_toboolean(L, 1) ? muglue_val_level : glue_val_level;
1346 int eq = lua_toboolean(L, 2);
1347 int t = lua_toboolean(L, 3);
1348 halfword v = tex_scan_glue(mu, eq, 0);
1349 tokenlib_aux_unsave_tex_scanner(texstate);
1350 if (t) {
1351 lua_createtable(L, 5, 0);
1352 lua_pushinteger(L, glue_amount(v));
1353 lua_rawseti(L, -2, 1);
1354 lua_pushinteger(L, glue_stretch(v));
1355 lua_rawseti(L, -2, 2);
1356 lua_pushinteger(L, glue_shrink(v));
1357 lua_rawseti(L, -2, 3);
1358 lua_pushinteger(L, glue_stretch_order(v));
1359 lua_rawseti(L, -2, 4);
1360 lua_pushinteger(L, glue_shrink_order(v));
1361 lua_rawseti(L, -2, 5);
1362 return 1;
1363 } else {
1364 lua_pushinteger(L, glue_amount(v));
1365 lua_pushinteger(L, glue_stretch(v));
1366 lua_pushinteger(L, glue_shrink(v));
1367 lua_pushinteger(L, glue_stretch_order(v));
1368 lua_pushinteger(L, glue_shrink_order(v));
1369 return 5;
1370 }
1371}
1372
1373inline static void lmt_token_list_to_lua_tokens(lua_State *L, halfword t)
1374{
1375 int i = 1;
1376 lua_newtable(L);
1377 while (t) {
1378 halfword n = token_link(t);
1379 token_link(t) = null;
1380 tokenlib_aux_push_token(L, t);
1381 lua_rawseti(L, -2, i++);
1382 t = n;
1383 }
1384}
1385
1386void lmt_token_register_to_lua(lua_State *L, halfword h, int originals)
1387{
1388 int i = 1;
1389 lua_newtable(L);
1390 if (h) {
1391 halfword t = token_link(h);
1392 while (t) {
1393 halfword m = tex_get_available_token(token_info(t));
1394 tokenlib_aux_push_token(L, m);
1395 lua_rawseti(L, -2, i++);
1396 t = token_link(t);
1397 }
1398 }
1399 if (originals) {
1400 lua_createtable(L, i, 0);
1401 if (h) {
1402 halfword t = token_link(h);
1403 i = 1;
1404 while (t) {
1405 lua_push_integer(L, t);
1406 lua_rawseti(L, -2, i++);
1407 t = token_link(t);
1408 }
1409 } else {
1410 lua_newtable(L);
1411 }
1412 }
1413}
1414
1415static int tokenlib_scan_toks(lua_State *L)
1416{
1417 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
1418 int macro = lua_toboolean(L, 1);
1419 int expand = lua_toboolean(L, 2);
1420 halfword defref = lmt_input_state.def_ref;
1421 halfword result, t;
1422 if (macro) {
1423 result = expand ? tex_scan_macro_expand() : tex_scan_macro_normal();
1424 } else {
1425 result = expand ? tex_scan_toks_expand(0, NULL, 0, 0) : tex_scan_toks_normal(0, NULL);
1426 }
1427 tokenlib_aux_unsave_tex_scanner(texstate);
1428 lmt_input_state.def_ref = defref;
1429 t = token_link(result);
1430 token_link(result) = null;
1431 tex_put_available_token(result);
1432 lmt_token_list_to_lua_tokens(L, t);
1433 return 1;
1434}
1435
1436static int tokenlib_scan_tokenlist(lua_State *L)
1437{
1438 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
1439 int macro = lua_toboolean(L, 1);
1440 int expand = lua_toboolean(L, 2);
1441 halfword result;
1442 halfword defref = lmt_input_state.def_ref;
1443 if (macro) {
1444 result = expand ? tex_scan_macro_expand() : tex_scan_macro_normal();
1445 } else {
1446 result = expand ? tex_scan_toks_expand(0, NULL, 0, 0) : tex_scan_toks_normal(0, NULL);
1447 }
1448 tokenlib_aux_push_token(L, result);
1449 tokenlib_aux_unsave_tex_scanner(texstate);
1450 lmt_input_state.def_ref = defref;
1451 return 1;
1452}
1453
1454static int tokenlib_scan_detokened(lua_State *L)
1455{
1456 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
1457 int expand = lua_toboolean(L, 1);
1458 halfword defref = lmt_input_state.def_ref;
1459 halfword result = null;
1460 int macro = 0;
1461 tokenlib_aux_goto_first_candidate();
1462 switch (cur_cmd) {
1463 case left_brace_cmd:
1464 result = expand ? tex_scan_toks_expand(1, NULL, 0, 0) : tex_scan_toks_normal(1, NULL);
1465 break;
1466 case call_cmd:
1467 case protected_call_cmd:
1468 case semi_protected_call_cmd:
1469 case constant_call_cmd:
1470 case tolerant_call_cmd:
1471 case tolerant_protected_call_cmd:
1472 case tolerant_semi_protected_call_cmd:
1473 result = cur_chr;
1474 macro = 1;
1475 break;
1476 default:
1477 tex_back_input(cur_tok);
1478 break;
1479 }
1480 tokenlib_aux_unsave_tex_scanner(texstate);
1481 lmt_input_state.def_ref = defref;
1482 if (result) {
1483 if (token_link(result)) {
1484 tex_detokenize_list(token_link(result));
1485 if (lmt_string_pool_state.string_temp && lmt_string_pool_state.string_temp_top) {
1486 lua_pushlstring(L, (char *) lmt_string_pool_state.string_temp, lmt_string_pool_state.string_temp_top);
1487 } else {
1488 lua_pushliteral(L,"");
1489 }
1490 tex_reset_cur_string();
1491 } else {
1492 lua_pushliteral(L,"");
1493 }
1494 if (! macro) {
1495 tex_flush_token_list(result);
1496 }
1497 } else {
1498 lua_pushnil(L);
1499 }
1500 return 1;
1501}
1502
1503
1504
1505static int tokenlib_scan_tokenstring(lua_State *L)
1506{
1507
1508 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
1509 halfword defref = lmt_input_state.def_ref;
1510 halfword result = lua_toboolean(L, 1) ? tex_scan_toks_normal(0, NULL) : tex_scan_toks_expand(0, NULL, ! lua_toboolean(L, 2), ! lua_toboolean(L, 3));
1511
1512 lmt_token_list_to_luastring(L, result, 0, 0, 1);
1513 lmt_input_state.def_ref = defref;
1514 tokenlib_aux_unsave_tex_scanner(texstate);
1515 return 1;
1516}
1517
1518static int tokenlib_scan_string(lua_State *L)
1519{
1520
1521 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
1522 tokenlib_aux_goto_first_candidate_x();
1523 switch (cur_cmd) {
1524 case left_brace_cmd:
1525 {
1526 halfword defref = lmt_input_state.def_ref;
1527 halfword result = tex_scan_toks_expand(1, NULL, 0, 0);
1528 lmt_token_list_to_luastring(L, result, 0, 0, 1);
1529 lmt_input_state.def_ref = defref;
1530 break;
1531 }
1532 case call_cmd:
1533 case protected_call_cmd:
1534 case semi_protected_call_cmd:
1535 case constant_call_cmd:
1536 case tolerant_call_cmd:
1537 case tolerant_protected_call_cmd:
1538 case tolerant_semi_protected_call_cmd:
1539 {
1540
1541 halfword t = token_link(cur_chr);
1542 lmt_token_list_to_luastring(L, t, 0, 0, 1);
1543 break;
1544 }
1545 case letter_cmd:
1546 case other_char_cmd:
1547 {
1548 luaL_Buffer b;
1549 luaL_buffinit(L, &b);
1550 while (1) {
1551 tokenlib_aux_add_utf_char_to_buffer(&b, cur_chr);
1552 tex_get_x_token();
1553 if (cur_cmd != letter_cmd && cur_cmd != other_char_cmd ) {
1554 break ;
1555 }
1556 }
1557 tex_back_input(cur_tok);
1558 luaL_pushresult(&b);
1559 break;
1560 }
1561 default:
1562 {
1563 tex_back_input(cur_tok);
1564 lua_pushnil(L);
1565 break;
1566 }
1567 }
1568 tokenlib_aux_unsave_tex_scanner(texstate);
1569 return 1;
1570}
1571
1572static int tokenlib_scan_argument(lua_State *L)
1573{
1574
1575 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
1576 tokenlib_aux_goto_first_candidate();
1577 switch (cur_cmd) {
1578 case left_brace_cmd:
1579 {
1580 halfword defref = lmt_input_state.def_ref;
1581 int expand = lua_type(L, 1) == LUA_TBOOLEAN ? lua_toboolean(L, 1) : 1;
1582 halfword result = expand ? tex_scan_toks_expand(1, NULL, 0, 0) : tex_scan_toks_normal(1, NULL);
1583 lmt_token_list_to_luastring(L, result, 0, 0, 1);
1584 lmt_input_state.def_ref = defref;
1585 break;
1586 }
1587 case call_cmd:
1588 case protected_call_cmd:
1589 case semi_protected_call_cmd:
1590
1591 case tolerant_call_cmd:
1592 case tolerant_protected_call_cmd:
1593 case tolerant_semi_protected_call_cmd:
1594 {
1595 halfword result;
1596 halfword defref = lmt_input_state.def_ref;
1597 tex_back_input(right_brace_token + '}');
1598 if (lua_type(L, 1) == LUA_TBOOLEAN && ! lua_toboolean(L, 1)) {
1599 tex_expand_current_token();
1600 result = tex_scan_toks_normal(1, NULL);
1601 } else {
1602 tex_back_input(cur_tok);
1603 result = tex_scan_toks_expand(1, NULL, 0, 0);
1604 }
1605 lmt_token_list_to_luastring(L, result, 0, 0, 1);
1606 lmt_input_state.def_ref = defref;
1607 break;
1608 }
1609 case constant_call_cmd:
1610 {
1611 halfword h = token_link(cur_chr);
1612 if (h) {
1613 luaL_Buffer b;
1614 luaL_buffinit(L, &b);
1615 while (h) {
1616 tokenlib_aux_add_utf_char_to_buffer(&b, token_chr(token_info(h)));
1617 h = token_link(h);
1618 }
1619 luaL_pushresult(&b);
1620 } else {
1621 lua_pushliteral(L, "");
1622 }
1623 break;
1624 }
1625 case letter_cmd:
1626 case other_char_cmd:
1627 {
1628 luaL_Buffer b;
1629 luaL_buffinit(L, &b);
1630
1631 tokenlib_aux_add_utf_char_to_buffer(&b, cur_chr);
1632
1633
1634
1635
1636
1637
1638 luaL_pushresult(&b);
1639 break;
1640 }
1641 default:
1642 {
1643 tex_back_input(cur_tok);
1644 lua_pushnil(L);
1645 break;
1646 }
1647 }
1648 tokenlib_aux_unsave_tex_scanner(texstate);
1649 return 1;
1650}
1651
1652static void show_right_brace_error(void)
1653{
1654 tex_handle_error(
1655 normal_error_type,
1656 "Unbalanced value parsing (in Lua call)",
1657 "A { has to be matched by a }."
1658 );
1659}
1660
1661static int tokenlib_scan_integer_argument(lua_State *L)
1662{
1663 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
1664 int wrapped = 0;
1665 tokenlib_aux_goto_first_candidate();
1666 if (cur_cmd != left_brace_cmd) {
1667 tex_back_input(cur_tok);
1668 } else {
1669 wrapped = 1;
1670 }
1671 lua_pushinteger(L, (int) tex_scan_integer(0, NULL));
1672 if (wrapped) {
1673 tokenlib_aux_goto_first_candidate();
1674 if (cur_cmd != right_brace_cmd) {
1675 show_right_brace_error();
1676 }
1677 }
1678 tokenlib_aux_unsave_tex_scanner(texstate);
1679 return 1;
1680}
1681
1682static int tokenlib_scan_dimension_argument(lua_State *L)
1683{
1684 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
1685 int wrapped = 0;
1686 halfword order = 0;
1687 int inf = lua_toboolean(L, 1);
1688 int mu = lua_toboolean(L, 2);
1689 int eq = lua_toboolean(L, 3);
1690 tokenlib_aux_goto_first_candidate();
1691 if (cur_cmd != left_brace_cmd) {
1692 tex_back_input(cur_tok);
1693 } else {
1694 wrapped = 1;
1695 }
1696 lua_pushinteger(L, tex_scan_dimension(mu, inf, 0, eq, &order));
1697 if (wrapped) {
1698 tokenlib_aux_goto_first_candidate();
1699 if (cur_cmd != right_brace_cmd) {
1700 show_right_brace_error();
1701 }
1702 }
1703 tokenlib_aux_unsave_tex_scanner(texstate);
1704 if (inf) {
1705 lua_pushinteger(L, order);
1706 return 2;
1707 } else {
1708 return 1;
1709 }
1710}
1711
1712static int tokenlib_scan_delimited(lua_State *L)
1713{
1714 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
1715 halfword left = lua_type(L, 1) == LUA_TNUMBER ? lmt_tohalfword(L, 1) : 0;
1716 halfword right = lua_type(L, 2) == LUA_TNUMBER ? lmt_tohalfword(L, 2) : 0;
1717 int expand = (lua_type(L, 3) == LUA_TBOOLEAN) ? expand = lua_toboolean(L, 3) : 1;
1718
1719 if (left) {
1720 left = token_val(left == 32 ? spacer_cmd : other_char_cmd, left);
1721 }
1722 if (right) {
1723 right = token_val(right == 32 ? spacer_cmd : other_char_cmd, right);
1724 } else {
1725
1726 }
1727 if (expand) {
1728 tokenlib_aux_goto_first_candidate_x();
1729 } else {
1730 tokenlib_aux_goto_first_candidate();
1731 }
1732 if (! left || cur_tok == left) {
1733 halfword defref = lmt_input_state.def_ref;
1734 halfword result = get_reference_token();
1735 halfword unbalance = 0;
1736 halfword p = result;
1737 lmt_input_state.def_ref = result;
1738
1739 if (expand) {
1740
1741 if (! left) {
1742 goto INITIAL1;
1743 }
1744 while (1) {
1745 PICKUP:
1746 tex_get_next();
1747 INITIAL1:
1748 switch (cur_cmd) {
1749 case call_cmd:
1750 case tolerant_call_cmd:
1751 case constant_call_cmd:
1752 tex_expand_current_token();
1753 goto PICKUP;
1754 case protected_call_cmd:
1755 case semi_protected_call_cmd:
1756 case tolerant_protected_call_cmd:
1757 case tolerant_semi_protected_call_cmd:
1758 cur_tok = cs_token_flag + cur_cs;
1759 goto APPENDTOKEN;
1760 case the_cmd:
1761 {
1762 halfword t = null;
1763 halfword h = tex_the_toks(cur_chr, &t);
1764 if (h) {
1765 set_token_link(p, h);
1766 p = t;
1767 }
1768 goto PICKUP;
1769 }
1770 default:
1771 if (cur_cmd > max_command_cmd) {
1772 tex_expand_current_token();
1773 goto PICKUP;
1774 } else {
1775 goto DONEEXPANDING;
1776 }
1777 }
1778 DONEEXPANDING:
1779 tex_x_token();
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793 if (cur_tok == right) {
1794 break;
1795 } else if (! cur_cs) {
1796 switch (cur_cmd) {
1797 case left_brace_cmd:
1798 ++unbalance;
1799 break;
1800 case right_brace_cmd:
1801 if (unbalance) {
1802 --unbalance;
1803 break;
1804 } else {
1805 goto FINALYDONE;
1806 }
1807 }
1808 }
1809
1810 APPENDTOKEN:
1811 p = tex_store_new_token(p, cur_tok);
1812 }
1813 } else {
1814
1815 if (! left) {
1816 goto INITIAL2;
1817 }
1818 while (1) {
1819 tex_get_token();
1820 INITIAL2:
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834 if (cur_tok == right) {
1835 break;
1836 } else if (! cur_cs) {
1837 switch (cur_cmd) {
1838 case left_brace_cmd:
1839 ++unbalance;
1840 break;
1841 case right_brace_cmd:
1842 if (unbalance) {
1843 --unbalance;
1844 break;
1845 } else {
1846 goto FINALYDONE;
1847 }
1848 }
1849 }
1850
1851 p = tex_store_new_token(p, cur_tok);
1852 }
1853 }
1854 FINALYDONE:
1855
1856 lmt_input_state.def_ref = defref;
1857 lmt_token_list_to_luastring(L, result, 0, 0, 1);
1858 } else {
1859 tex_back_input(cur_tok);
1860 lua_pushnil(L);
1861 }
1862 tokenlib_aux_unsave_tex_scanner(texstate);
1863 return 1;
1864}
1865
1866static int tokenlib_gobble_until(lua_State *L)
1867{
1868 lua_token *left = tokenlib_aux_check_istoken(L, 1);
1869 lua_token *right = tokenlib_aux_check_istoken(L, 2);
1870 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
1871 int level = 1;
1872 int l = token_info(left->token);
1873 int r = token_info(right->token);
1874 int cmd, chr, lcmd, lchr, rcmd, rchr;
1875 if (l >= cs_token_flag) {
1876 lcmd = eq_type(l - cs_token_flag);
1877 lchr = eq_value(l - cs_token_flag);
1878 } else {
1879 lcmd = token_cmd(l);
1880 lchr = token_chr(l);
1881 }
1882 if (r >= cs_token_flag) {
1883 rcmd = eq_type(r - cs_token_flag);
1884 rchr = eq_value(r - cs_token_flag);
1885 } else {
1886 rcmd = token_cmd(l);
1887 rchr = token_chr(l);
1888 }
1889 while (1) {
1890 tex_get_token();
1891 if (cur_tok >= cs_token_flag) {
1892 cmd = eq_type(cur_cs);
1893 chr = eq_value(cur_cs);
1894 } else {
1895 cmd = cur_cmd;
1896 chr = cur_chr;
1897 }
1898 if (cmd == lcmd && chr == lchr) {
1899 ++level;
1900 } else if (cmd == rcmd && chr == rchr) {
1901 --level;
1902 if (level == 0) {
1903 break;
1904 }
1905 }
1906 }
1907 tokenlib_aux_unsave_tex_scanner(texstate);
1908 return 0;
1909}
1910
1911
1912
1913static int tokenlib_grab_until(lua_State *L)
1914{
1915 lua_token *left = tokenlib_aux_check_istoken(L, 1);
1916 lua_token *right = tokenlib_aux_check_istoken(L, 2);
1917 int l = token_info(left->token);
1918 int r = token_info(right->token);
1919 int lstr = 0;
1920 int rstr = 0;
1921 if (l >= cs_token_flag) {
1922 lstr = cs_text(l - cs_token_flag);
1923 }
1924 if (r >= cs_token_flag) {
1925 rstr = cs_text(r - cs_token_flag);
1926 }
1927 if (lstr && rstr) {
1928 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
1929 halfword defref = lmt_input_state.def_ref;
1930 halfword result = get_reference_token();
1931 halfword p = result;
1932 int level = 1;
1933 int nospace = lua_toboolean(L, 3);
1934 int strip = lmt_optinteger(L, 4, -1);
1935 while (1) {
1936 tex_get_token();
1937 if (cur_tok >= cs_token_flag) {
1938 int str = cs_text(cur_tok - cs_token_flag);
1939 if (str == lstr) {
1940 ++level;
1941 } else if (str == rstr) {
1942 --level;
1943 if (level == 0) {
1944 break;
1945 }
1946 }
1947 }
1948 p = tex_store_new_token(p, cur_tok);
1949 }
1950 tokenlib_aux_unsave_tex_scanner(texstate);
1951 lmt_input_state.def_ref = defref;
1952 lmt_token_list_to_luastring(L, result, nospace, strip, 1);
1953 } else {
1954 lua_pushnil(L);
1955 }
1956 return 1;
1957}
1958
1959static int tokenlib_scan_word(lua_State *L)
1960{
1961 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
1962 tokenlib_aux_goto_first_candidate_x();
1963 if (cur_cmd == letter_cmd || cur_cmd == other_char_cmd) {
1964 luaL_Buffer b;
1965 luaL_buffinit(L, &b);
1966 while (1) {
1967 tokenlib_aux_add_utf_char_to_buffer(&b, cur_chr);
1968 tex_get_x_token();
1969 if (cur_cmd != letter_cmd && cur_cmd != other_char_cmd) {
1970 break;
1971 }
1972 }
1973 if (! (lua_toboolean(L, 1) && ((cur_cmd == spacer_cmd) || (cur_cmd == relax_cmd)))) {
1974 tex_back_input(cur_tok);
1975 }
1976 luaL_pushresult(&b);
1977 } else {
1978 tex_back_input(cur_tok);
1979 lua_pushnil(L);
1980 }
1981 tokenlib_aux_unsave_tex_scanner(texstate);
1982 return 1;
1983}
1984
1985static int tokenlib_scan_letters(lua_State *L)
1986{
1987 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
1988 tokenlib_aux_goto_first_candidate_x();
1989 if (cur_cmd == letter_cmd) {
1990 luaL_Buffer b;
1991 luaL_buffinit(L, &b);
1992 while (1) {
1993 tokenlib_aux_add_utf_char_to_buffer(&b, cur_chr);
1994 tex_get_x_token();
1995 if (cur_cmd != letter_cmd) {
1996 break ;
1997 }
1998 }
1999 if (! (lua_toboolean(L, 1) && ((cur_cmd == spacer_cmd) || (cur_cmd == relax_cmd)))) {
2000 tex_back_input(cur_tok);
2001 }
2002 luaL_pushresult(&b);
2003 } else {
2004 tex_back_input(cur_tok);
2005 lua_pushnil(L);
2006 }
2007 tokenlib_aux_unsave_tex_scanner(texstate);
2008 return 1;
2009}
2010
2011static int tokenlib_scan_char(lua_State *L)
2012{
2013 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
2014 tokenlib_aux_goto_first_candidate();
2015 if (cur_cmd == letter_cmd || cur_cmd == other_char_cmd) {
2016 int c = lmt_tointeger(L, 1);
2017 if (c == cur_chr) {
2018 lua_pushboolean(L, 1);
2019 } else {
2020 lua_pushboolean(L, 0);
2021 tex_back_input(cur_tok);
2022 }
2023 } else {
2024 lua_pushboolean(L, 0);
2025 tex_back_input(cur_tok);
2026 }
2027 tokenlib_aux_unsave_tex_scanner(texstate);
2028 return 1;
2029}
2030
2031static const char *token_cmd_to_string[15] = {
2032 "\\",
2033 "{",
2034 "}",
2035 "$",
2036 "&",
2037 "\n",
2038 "#",
2039 "^",
2040 "_",
2041 "",
2042 " ",
2043 "",
2044 "",
2045 "",
2046 "%"
2047};
2048
2049static int tokenlib_scan_next_char(lua_State *L)
2050{
2051 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
2052 tex_get_token();
2053 switch (cur_cmd) {
2054 case escape_cmd:
2055 case left_brace_cmd:
2056 case right_brace_cmd:
2057 case math_shift_cmd:
2058 case alignment_tab_cmd:
2059 case end_line_cmd:
2060 case parameter_cmd:
2061 case superscript_cmd:
2062 case subscript_cmd:
2063 case ignore_cmd:
2064 case spacer_cmd:
2065 case comment_cmd:
2066 lua_pushstring(L, token_cmd_to_string[cur_cmd]);
2067 break;
2068 case letter_cmd:
2069 case other_char_cmd:
2070 case active_char_cmd:
2071 {
2072 char buffer[6];
2073 char *uindex = aux_uni2string((char *) buffer, (unsigned int) cur_chr);
2074 *uindex = '\0';
2075 lua_pushstring(L, buffer);
2076 break;
2077 }
2078 default:
2079 lua_pushstring(L, "");
2080 break;
2081 }
2082 tokenlib_aux_unsave_tex_scanner(texstate);
2083 return 1;
2084}
2085
2086static int tokenlib_is_next_char(lua_State *L)
2087{
2088 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
2089 tokenlib_aux_goto_first_candidate();
2090 if (cur_cmd == letter_cmd || cur_cmd == other_char_cmd ) {
2091 int c = lmt_tointeger(L, 1);
2092 lua_pushboolean(L, c == cur_chr);
2093 } else {
2094 lua_pushboolean(L, 0);
2095 }
2096 tex_back_input(cur_tok);
2097 tokenlib_aux_unsave_tex_scanner(texstate);
2098 return 1;
2099}
2100
2101static int tokenlib_peek_next(lua_State *L)
2102{
2103 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
2104 if (lua_toboolean(L, 1)) {
2105 tokenlib_aux_goto_first_candidate();
2106 } else {
2107 tex_get_token();
2108 }
2109
2110 tokenlib_aux_make_new_token_tok(L, cur_tok);
2111 tex_back_input(cur_tok);
2112 tokenlib_aux_unsave_tex_scanner(texstate);
2113 return 1;
2114}
2115
2116static int tokenlib_peek_next_expanded(lua_State *L)
2117{
2118 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
2119 if (lua_toboolean(L, 1)) {
2120 tokenlib_aux_goto_first_candidate_x();
2121 } else {
2122 tex_get_x_token();
2123 }
2124
2125 tokenlib_aux_make_new_token_tok(L, cur_tok);
2126 tex_back_input(cur_tok);
2127 tokenlib_aux_unsave_tex_scanner(texstate);
2128 return 1;
2129}
2130
2131static int tokenlib_peek_next_char(lua_State *L)
2132{
2133 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
2134 tokenlib_aux_goto_first_candidate();
2135 if (cur_cmd == letter_cmd || cur_cmd == other_char_cmd ) {
2136 lua_pushinteger(L, cur_chr);
2137 } else {
2138 lua_pushnil(L);
2139 }
2140 tex_back_input(cur_tok);
2141 tokenlib_aux_unsave_tex_scanner(texstate);
2142 return 1;
2143}
2144
2145
2152
2153static int tokenlib_scan_key(lua_State *L)
2154{
2155 int c1 = lmt_optinteger(L, 1, '\0');
2156 int c2 = lmt_optinteger(L, 2, '\0');
2157 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
2158 tokenlib_aux_goto_first_candidate_x();
2159 if ((cur_cmd == letter_cmd || cur_cmd == other_char_cmd) && (cur_chr != c1) && (cur_chr != c2)) {
2160 luaL_Buffer b;
2161 luaL_buffinit(L, &b);
2162 while (1) {
2163 tokenlib_aux_add_utf_char_to_buffer(&b, cur_chr);
2164 tex_get_x_token();
2165 if ((cur_cmd != letter_cmd && cur_cmd != other_char_cmd) || (cur_chr == c1) || (cur_chr == c2)) {
2166 break ;
2167 }
2168 }
2169
2174 tex_back_input(cur_tok);
2175 luaL_pushresult(&b);
2176 } else {
2177 tex_back_input(cur_tok);
2178 lua_pushnil(L);
2179 }
2180 tokenlib_aux_unsave_tex_scanner(texstate);
2181 return 1;
2182}
2183
2184
2185
2186
2187static int tokenlib_scan_value(lua_State *L)
2188{
2189
2190 int c1 = lmt_optinteger(L, 1, '\0');
2191 int c2 = lmt_optinteger(L, 2, '\0');
2192 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
2193 tokenlib_aux_goto_first_candidate_x();
2194 switch (cur_cmd) {
2195 case left_brace_cmd:
2196 {
2197 halfword result;
2198 halfword defref = lmt_input_state.def_ref;
2199 result = tex_scan_toks_expand(1, NULL, 0, 0);
2200 lmt_input_state.def_ref = defref;
2201 lmt_token_list_to_luastring(L, result, 0, 0, 1);
2202 }
2203 break;
2204
2227 case letter_cmd:
2228 case other_char_cmd:
2229 {
2230 luaL_Buffer b;
2231 luaL_buffinit(L, &b);
2232 while (1) {
2233 switch (cur_cmd) {
2234 case left_brace_cmd:
2235 {
2236 halfword result;
2237 halfword defref = lmt_input_state.def_ref;
2238 result = tex_scan_toks_expand(1, NULL, 0, 0);
2239 lmt_input_state.def_ref = defref;
2240 lmt_token_list_to_luastring(L, result, 0, 0, 1);
2241 luaL_addchar(&b, '{');
2242 luaL_addvalue(&b);
2243 luaL_addchar(&b, '}');
2244 }
2245 break;
2246 case call_cmd:
2247 case protected_call_cmd:
2248 case semi_protected_call_cmd:
2249 case constant_call_cmd:
2250 case tolerant_call_cmd:
2251 case tolerant_protected_call_cmd:
2252 case tolerant_semi_protected_call_cmd:
2253 {
2254
2255 halfword t = cur_cs ? cs_token_flag + cur_cs : token_val(cur_cmd, cur_chr);
2256 if (t >= cs_token_flag) {
2257 int allocated = 0;
2258 unsigned char *s = tokenlib_aux_get_cs_text(t - cs_token_flag, &allocated);
2259 if (s) {
2260 if (tex_is_active_cs(cs_text(t - cs_token_flag))) {
2261 lua_pushstring(L, (char *) (s + 3));
2262 luaL_addvalue(&b);
2263 } else {
2264 luaL_addchar(&b, '\\');
2265 lua_pushstring(L, (char *) s);
2266 luaL_addvalue(&b);
2267 luaL_addchar(&b, ' ');
2268 }
2269 if (allocated) {
2270 lmt_memory_free(s);
2271 }
2272 }
2273 }
2274 }
2275 break;
2276 case letter_cmd:
2277 case other_char_cmd:
2278 if (cur_chr == c1 || cur_chr == c2) {
2279 goto DONE;
2280 } else {
2281 tokenlib_aux_add_utf_char_to_buffer(&b, cur_chr);
2282 }
2283 break;
2284 default:
2285
2286 tokenlib_aux_add_utf_char_to_buffer(&b, cur_chr);
2287 break;
2288 }
2289 tex_get_x_token();
2290 }
2291 DONE:
2292 tex_back_input(cur_tok);
2293 luaL_pushresult(&b);
2294 }
2295 break;
2296 default:
2297 {
2298 tex_back_input(cur_tok);
2299 lua_pushnil(L);
2300 }
2301 break;
2302 }
2303 tokenlib_aux_unsave_tex_scanner(texstate);
2304 return 1;
2305}
2306
2307
2308
2309static int tokenlib_future_expand(lua_State *L)
2310{
2311 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
2312 halfword spa = null;
2313 halfword yes = tex_get_token();
2314 halfword nop = tex_get_token();
2315 while (1) {
2316 halfword t = tex_get_token();
2317 switch (t) {
2318 case spacer_cmd:
2319 spa = t;
2320 break;
2321 case letter_cmd:
2322 case other_char_cmd:
2323 if (lua_tointeger(L, 1) == cur_chr) {
2324 tex_back_input(t);
2325 tex_back_input(yes);
2326 tokenlib_aux_unsave_tex_scanner(texstate);
2327 return 0;
2328 }
2329 default:
2330 tex_back_input(t);
2331 if (spa && lua_toboolean(L, 2)) {
2332 tex_back_input(spa);
2333 }
2334 tex_back_input(nop);
2335 tokenlib_aux_unsave_tex_scanner(texstate);
2336 return 0;
2337 }
2338 }
2339
2340}
2341
2342static int tokenlib_scan_code(lua_State *L)
2343{
2344 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
2345 tex_get_x_token();
2346 if (cur_cmd <= max_char_code_cmd) {
2347 int cc = lmt_optinteger(L, 1, DEFAULT_SCAN_CODE_SET);
2348 if (cc & (1 << (cur_cmd))) {
2349 lua_pushinteger(L, (int) cur_chr);
2350 } else {
2351 lua_pushnil(L);
2352 tex_back_input(cur_tok);
2353 }
2354 } else {
2355 lua_pushnil(L);
2356 tex_back_input(cur_tok);
2357 }
2358 tokenlib_aux_unsave_tex_scanner(texstate);
2359 return 1;
2360}
2361
2362static int tokenlib_scan_token_code(lua_State *L)
2363{
2364 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
2365 halfword t = tex_get_token();
2366
2367 if (cur_cmd <= max_char_code_cmd) {
2368 if (DEFAULT_SCAN_CODE_SET & (1 << (cur_cmd))) {
2369 lua_pushinteger(L, (int) cur_chr);
2370 } else {
2371 lua_pushnil(L);
2372 tex_back_input(t);
2373 }
2374 } else {
2375 lua_pushnil(L);
2376 tex_back_input(t);
2377 }
2378 tokenlib_aux_unsave_tex_scanner(texstate);
2379 return 1;
2380}
2381
2382static int tokenlib_is_token(lua_State *L)
2383{
2384 lua_pushboolean(L, tokenlib_aux_maybe_istoken(L, 1) ? 1 : 0);
2385 return 1;
2386}
2387
2388static int tokenlib_expand(lua_State *L)
2389{
2390 (void) L;
2391 tex_expand_current_token();
2392
2393 return 0;
2394}
2395
2396static int tokenlib_is_defined(lua_State *L)
2397{
2398 int b = 0;
2399 if (lua_type(L, 1) == LUA_TSTRING) {
2400 size_t l;
2401 const char *s = lua_tolstring(L, 1, &l);
2402 if (l > 0) {
2403 int cs = tex_string_locate_only(s, l);
2404 b = (cs != undefined_control_sequence) && (eq_type(cs) != undefined_cs_cmd);
2405 }
2406 }
2407 lua_pushboolean(L, b);
2408 return 1;
2409}
2410
2411
2415
2416static int tokenlib_create(lua_State *L)
2417{
2418 switch (lua_type(L, 1)) {
2419 case LUA_TNUMBER:
2420 {
2421 int cs = 0;
2422 int chr = (int) lua_tointeger(L, 1);
2423 int cmd = (int) luaL_optinteger(L, 2, tex_get_cat_code(cat_code_table_par, chr));
2424 switch (cmd) {
2425 case escape_cmd:
2426 case ignore_cmd:
2427 case comment_cmd:
2428 case invalid_char_cmd:
2429
2430 cmd = other_char_cmd;
2431 break;
2432 case active_char_cmd:
2433 cs = tex_active_to_cs(chr, ! lmt_hash_state.no_new_cs);
2434 cmd = eq_type(cs);
2435 chr = eq_value(cs);
2436 break;
2437 }
2438 tokenlib_aux_make_new_token(L, cmd, chr, cs);
2439 break;
2440 }
2441 case LUA_TSTRING:
2442 {
2443 size_t l;
2444 const char *s = lua_tolstring(L, 1, &l);
2445 if (l > 0) {
2446 int cs = tex_string_locate(s, l, lua_toboolean(L, 2));
2447 int cmd = eq_type(cs);
2448 int chr = eq_value(cs);
2449 tokenlib_aux_make_new_token(L, cmd, chr, cs);
2450 } else {
2451 lua_pushnil(L);
2452 }
2453 break;
2454 }
2455 default:
2456 {
2457 lua_pushnil(L);
2458 break;
2459 }
2460 }
2461 return 1;
2462}
2463
2464
2467
2468static int tokenlib_new(lua_State *L)
2469{
2470 int chr = 0;
2471 int cmd = 0;
2472 switch (lua_type(L, 1)) {
2473 case LUA_TSTRING:
2474 cmd = (int) tokenlib_aux_get_command_id(lua_tostring(L, 1));
2475 chr = (int) luaL_optinteger(L, 2, 0);
2476 break;
2477 case LUA_TNUMBER:
2478 chr = (int) lua_tointeger(L, 1);
2479 cmd = (int) luaL_optinteger(L, 2, 0);
2480 break;
2481 default:
2482 break;
2483 }
2484 tokenlib_aux_make_new_token(L, cmd, chr, 0);
2485 return 1;
2486}
2487
2488
2492
2493static int tokenlib_get_cmdchrcs(lua_State* L)
2494{
2495 size_t l;
2496 const char *s = lua_tolstring(L, 1, &l);
2497 if (l > 0) {
2498 int cs = tex_string_locate_only(s, l);
2499 int cmd = eq_type(cs);
2500 int chr = eq_value(cs);
2501 if (! lua_toboolean(L, 2)) {
2502
2503 chr = tokenlib_aux_to_valid_index(cmd, chr);
2504 }
2505 lua_pushinteger(L, cmd);
2506 lua_pushinteger(L, chr);
2507 lua_pushinteger(L, cs);
2508 return 3;
2509 }
2510 return 0;
2511}
2512
2513static int tokenlib_scan_cmdchr(lua_State *L)
2514{
2515 int cmd, chr;
2516 halfword tok = tex_get_token();
2517 if (tok >= cs_token_flag) {
2518 tok -= cs_token_flag;
2519 cmd = eq_type(tok);
2520 chr = eq_value(tok);
2521 } else {
2522 cmd = token_cmd(tok);
2523 chr = token_chr(tok);
2524 }
2525 lua_pushinteger(L, cmd);
2526 lua_pushinteger(L, tokenlib_aux_to_valid_index(cmd, chr));
2527 return 2;
2528}
2529
2530static int tokenlib_scan_cmdchr_expanded(lua_State *L)
2531{
2532 int cmd, chr;
2533 halfword tok = tex_get_x_token();
2534 if (tok >= cs_token_flag) {
2535 tok -= cs_token_flag;
2536 cmd = eq_type(tok);
2537 chr = eq_value(tok);
2538 } else {
2539 cmd = token_cmd(tok);
2540 chr = token_chr(tok);
2541 }
2542 lua_pushinteger(L, cmd);
2543 lua_pushinteger(L, tokenlib_aux_to_valid_index(cmd, chr));
2544 return 2;
2545}
2546
2547
2548static int tokenlib_get_cstoken(lua_State* L)
2549{
2550 size_t l;
2551 const char *s = lua_tolstring(L, 1, &l);
2552 if (l > 0) {
2553 lua_pushinteger(L, (lua_Integer) tex_string_locate_only(s, l) + cs_token_flag);
2554 return 1;
2555 }
2556 return 0;
2557}
2558
2559static int tokenlib_getprimitives(lua_State *L)
2560{
2561 int cs = 0;
2562 int nt = 0;
2563 int raw = lua_toboolean(L, 1);
2564 lua_createtable(L, prim_size, 0);
2565 while (cs < prim_size) {
2566 strnumber s = get_prim_text(cs);
2567 if (s > 0 && (get_prim_origin(cs) != no_command)) {
2568 const char *ss = tex_to_cstring(s);
2569 int cmd = prim_eq_type(cs);
2570 int chr = prim_equiv(cs);
2571 if (! raw) {
2572 chr = tokenlib_aux_to_valid_index(cmd, chr);
2573 }
2574 lua_createtable(L, 4, 0);
2575 lua_pushinteger(L, cmd);
2576 lua_rawseti(L, -2, 1);
2577 lua_pushinteger(L, chr);
2578 lua_rawseti(L, -2, 2);
2579 lua_pushstring(L, ss);
2580 lua_rawseti(L, -2, 3);
2581 lua_pushinteger(L, prim_origin(cs));
2582 lua_rawseti(L, -2, 4);
2583 lua_rawseti(L, -2, ++nt);
2584 }
2585 cs++;
2586 }
2587 return 1;
2588}
2589
2590
2591
2592static int tokenlib_free(lua_State *L)
2593{
2594
2595 lua_token *n = lua_touserdata(L, 1);
2596 if (n->origin == token_origin_lua) {
2597 if (token_link(n->token)) {
2598 tex_flush_token_list(n->token);
2599 } else {
2600 tex_put_available_token(n->token);
2601 }
2602 } else {
2603
2604 }
2605 return 1;
2606}
2607
2608
2609
2610inline static int tokenlib_get_command(lua_State *L)
2611{
2612 lua_token *n = tokenlib_aux_check_istoken(L, 1);
2613 halfword t = token_info(n->token);
2614 lua_pushinteger(L, (t >= cs_token_flag) ? (int) eq_type(t - cs_token_flag) : token_cmd(t));
2615 return 1;
2616}
2617
2618inline static int tokenlib_get_index(lua_State *L)
2619{
2620 int cmd, chr;
2621 lua_token *n = tokenlib_aux_check_istoken(L, 1);
2622 halfword tok = token_info(n->token);
2623 if (tok >= cs_token_flag) {
2624 tok -= cs_token_flag;
2625 cmd = eq_type(tok);
2626 chr = eq_value(tok);
2627 } else {
2628 cmd = token_cmd(tok);
2629 chr = token_chr(tok);
2630 }
2631 lua_pushinteger(L, tokenlib_aux_to_valid_index(cmd, chr));
2632 return 1;
2633}
2634
2635inline static int tokenlib_get_range(lua_State *L)
2636{
2637 int cmd;
2638 if (lua_type(L, 1) == LUA_TNUMBER) {
2639 cmd = (int) lua_tointeger(L, 1);
2640 } else {
2641 lua_token *n = tokenlib_aux_check_istoken(L, 1);
2642 halfword tok = token_info(n->token);
2643 cmd = (tok >= cs_token_flag) ? eq_type(tok - cs_token_flag) : token_cmd(tok);
2644 }
2645 if (cmd >= 0 && cmd <= last_cmd) {
2646 command_item item = lmt_interface.command_names[cmd];
2647 lua_pushinteger(L, item.kind);
2648 switch (item.kind) {
2649 case unused_command_item:
2650 lua_pushboolean(L, 0);
2651 lua_pushboolean(L, 0);
2652 break;
2653 case regular_command_item:
2654 case character_command_item:
2655 case register_command_item:
2656 case internal_command_item:
2657 case reference_command_item:
2658 case data_command_item:
2659 lua_pushinteger(L, item.min);
2660 lua_pushinteger(L, item.max);
2661 break;
2662 case token_command_item:
2663 case node_command_item:
2664 lua_pushboolean(L, 0);
2665 lua_pushboolean(L, 0);
2666 break;
2667 }
2668 lua_pushinteger(L, item.fixedvalue);
2669 return 4;
2670 } else {
2671 return 0;
2672 }
2673}
2674
2675inline static int tokenlib_get_cmdname(lua_State *L)
2676{
2677 lua_token *n = tokenlib_aux_check_istoken(L, 1);
2678 halfword tok = token_info(n->token);
2679 int cmd = (tok >= cs_token_flag) ? eq_type(tok - cs_token_flag) : token_cmd(tok);
2680 lua_push_key_by_index(lmt_interface.command_names[cmd].lua);
2681 return 1;
2682}
2683
2684void lmt_push_cmd_name(lua_State *L, int cmd)
2685{
2686 if (cmd >= 0) {
2687 lua_push_key_by_index(lmt_interface.command_names[cmd].lua);
2688 } else {
2689 lua_pushnil(L);
2690 }
2691}
2692
2693inline static int tokenlib_get_csname(lua_State *L)
2694{
2695 lua_token *n = tokenlib_aux_check_istoken(L, 1);
2696 halfword tok = token_info(n->token);
2697 if (tok >= cs_token_flag) {
2698 int allocated = 0;
2699 unsigned char *s = tokenlib_aux_get_cs_text(tok - cs_token_flag, &allocated);
2700 if (s) {
2701 if (tex_is_active_cs(cs_text(tok - cs_token_flag))) {
2702 lua_pushstring(L, (char *) (s + 3));
2703 } else {
2704 lua_pushstring(L, (char *) s);
2705 }
2706 if (allocated) {
2707 lmt_memory_free(s);
2708 }
2709 return 1;
2710 }
2711 }
2712 lua_pushnil(L);
2713 return 1;
2714}
2715
2716inline static int tokenlib_get_id(lua_State *L)
2717{
2718 lua_token *n = tokenlib_aux_check_istoken(L, 1);
2719 lua_pushinteger(L, n->token);
2720 return 1;
2721}
2722
2723inline static int tokenlib_get_tok(lua_State *L)
2724{
2725 lua_token *n = tokenlib_aux_check_istoken(L, 1);
2726 halfword tok = token_info(n->token);
2727 lua_pushinteger(L, tok);
2728 return 1;
2729}
2730
2731inline static int tokenlib_get_active(lua_State *L)
2732{
2733 lua_token *n = tokenlib_aux_check_istoken(L, 1);
2734 halfword tok = token_info(n->token);
2735 int result = 0;
2736 if (tok >= cs_token_flag) {
2737 int allocated = 0;
2738 unsigned char *s = tokenlib_aux_get_cs_text(tok - cs_token_flag, &allocated);
2739 if (s) {
2740 result = tex_is_active_cs(cs_text(tok - cs_token_flag));
2741 if (allocated) {
2742 lmt_memory_free(s);
2743 }
2744 }
2745 }
2746 lua_pushboolean(L, result);
2747 return 1;
2748}
2749
2750inline static int tokenlib_get_expandable(lua_State *L)
2751{
2752 lua_token *n = tokenlib_aux_check_istoken(L, 1);
2753 halfword tok = token_info(n->token);
2754 halfword cmd = (tok >= cs_token_flag) ? eq_type(tok - cs_token_flag) : token_cmd(tok);
2755 lua_pushboolean(L, cmd > max_command_cmd);
2756 return 1;
2757}
2758
2759inline static int tokenlib_get_protected(lua_State *L)
2760{
2761 lua_token *n = tokenlib_aux_check_istoken(L, 1);
2762 halfword tok = token_info(n->token);
2763 halfword cmd = (tok >= cs_token_flag) ? eq_type(tok - cs_token_flag) : token_cmd(tok);
2764 lua_pushboolean(L, is_protected_cmd(cmd));
2765 return 1;
2766}
2767
2768inline static int tokenlib_get_semiprotected(lua_State *L)
2769{
2770 lua_token *n = tokenlib_aux_check_istoken(L, 1);
2771 halfword tok = token_info(n->token);
2772 halfword cmd = (tok >= cs_token_flag) ? eq_type(tok - cs_token_flag) : token_cmd(tok);
2773 lua_pushboolean(L, is_semi_protected_cmd(cmd));
2774 return 1;
2775}
2776inline static int tokenlib_get_tolerant(lua_State *L)
2777{
2778 lua_token *n = tokenlib_aux_check_istoken(L, 1);
2779 halfword tok = token_info(n->token);
2780 halfword cmd = (tok >= cs_token_flag) ? eq_type(tok - cs_token_flag) : token_cmd(tok);
2781 lua_pushboolean(L, is_tolerant_cmd(cmd));
2782 return 1;
2783}
2784
2785inline static int tokenlib_get_noaligned(lua_State *L)
2786{
2787 lua_token *n = tokenlib_aux_check_istoken(L, 1);
2788 halfword tok = token_info(n->token);
2789 lua_pushboolean(L, tok >= cs_token_flag && has_eq_flag_bits(tok - cs_token_flag, noaligned_flag_bit));
2790 return 1;
2791}
2792
2793inline static int tokenlib_get_primitive(lua_State *L)
2794{
2795 lua_token *n = tokenlib_aux_check_istoken(L, 1);
2796 halfword tok = token_info(n->token);
2797 lua_pushboolean(L, tok >= cs_token_flag && has_eq_flag_bits(tok - cs_token_flag, primitive_flag_bit));
2798 return 1;
2799}
2800
2801inline static int tokenlib_get_permanent(lua_State *L)
2802{
2803 lua_token *n = tokenlib_aux_check_istoken(L, 1);
2804 halfword tok = token_info(n->token);
2805 lua_pushboolean(L, tok >= cs_token_flag && has_eq_flag_bits(tok - cs_token_flag, permanent_flag_bit));
2806 return 1;
2807}
2808
2809inline static int tokenlib_get_immutable(lua_State *L)
2810{
2811 lua_token *n = tokenlib_aux_check_istoken(L, 1);
2812 halfword tok = token_info(n->token);
2813 lua_pushboolean(L, tok >= cs_token_flag && has_eq_flag_bits(tok - cs_token_flag, immutable_flag_bit));
2814 return 1;
2815}
2816
2817inline static int tokenlib_get_mutable(lua_State *L)
2818{
2819 lua_token *n = tokenlib_aux_check_istoken(L, 1);
2820 halfword tok = token_info(n->token);
2821 lua_pushboolean(L, tok >= cs_token_flag && has_eq_flag_bits(tok - cs_token_flag, mutable_flag_bit));
2822 return 1;
2823}
2824
2825inline static int tokenlib_get_frozen(lua_State *L)
2826{
2827 lua_token *n = tokenlib_aux_check_istoken(L, 1);
2828 halfword tok = token_info(n->token);
2829 lua_pushboolean(L, tok >= cs_token_flag && has_eq_flag_bits(tok - cs_token_flag, frozen_flag_bit));
2830 return 1;
2831}
2832
2833inline static int tokenlib_get_instance(lua_State *L)
2834{
2835 lua_token *n = tokenlib_aux_check_istoken(L, 1);
2836 halfword tok = token_info(n->token);
2837 lua_pushboolean(L, tok >= cs_token_flag && has_eq_flag_bits(tok - cs_token_flag, instance_flag_bit));
2838 return 1;
2839}
2840
2841
2842inline static int tokenlib_get_untraced(lua_State *L)
2843{
2844 lua_token *n = tokenlib_aux_check_istoken(L, 1);
2845 halfword tok = token_info(n->token);
2846 lua_pushboolean(L, tok >= cs_token_flag && has_eq_flag_bits(tok - cs_token_flag, untraced_flag_bit));
2847 return 1;
2848}
2849
2850
2851inline static int tokenlib_get_flags(lua_State *L)
2852{
2853 lua_token *n = tokenlib_aux_check_istoken(L, 1);
2854 halfword tok = token_info(n->token);
2855 lua_pushboolean(L, tok >= cs_token_flag ? eq_flag(tok - cs_token_flag) : 0);
2856 return 1;
2857}
2858
2859inline static int tokenlib_get_parameters(lua_State *L)
2860{
2861 lua_token *n = tokenlib_aux_check_istoken(L, 1);
2862 halfword tok = token_info(n->token);
2863 if (tok >= cs_token_flag && is_call_cmd(eq_type(tok - cs_token_flag))) {
2864 halfword v = eq_value(tok - cs_token_flag);
2865 if (v && token_link(v)) {
2866 lua_pushinteger(L, get_token_parameters(v));
2867 return 1;
2868 }
2869 }
2870 lua_pushnil(L);
2871 return 0;
2872}
2873
2874inline static int tokenlib_get_constant(lua_State *L)
2875{
2876 lua_token *n = tokenlib_aux_check_istoken(L, 1);
2877 halfword tok = token_info(n->token);
2878 lua_pushboolean(L, tok >= cs_token_flag && (eq_type(tok - cs_token_flag) == constant_call_cmd));
2879 return 1;
2880}
2881
2882static int tokenlib_getfield(lua_State *L)
2883{
2884 const char *s = lua_tostring(L, 2);
2885 if (lua_key_eq(s, command)) {
2886 return tokenlib_get_command(L);
2887 } else if (lua_key_eq(s, index)) {
2888 return tokenlib_get_index(L);
2889 } else if (lua_key_eq(s, cmdname)) {
2890 return tokenlib_get_cmdname(L);
2891 } else if (lua_key_eq(s, csname)) {
2892 return tokenlib_get_csname(L);
2893 } else if (lua_key_eq(s, id)) {
2894 return tokenlib_get_id(L);
2895 } else if (lua_key_eq(s, tok)) {
2896 return tokenlib_get_tok(L);
2897 } else if (lua_key_eq(s, active)) {
2898 return tokenlib_get_active(L);
2899 } else if (lua_key_eq(s, expandable)) {
2900 return tokenlib_get_expandable(L);
2901 } else if (lua_key_eq(s, protected)) {
2902 return tokenlib_get_protected(L);
2903 } else if (lua_key_eq(s, semiprotected)) {
2904 return tokenlib_get_semiprotected(L);
2905 } else if (lua_key_eq(s, frozen)) {
2906 return tokenlib_get_frozen(L);
2907 } else if (lua_key_eq(s, tolerant)) {
2908 return tokenlib_get_tolerant(L);
2909 } else if (lua_key_eq(s, noaligned)) {
2910 return tokenlib_get_noaligned(L);
2911 } else if (lua_key_eq(s, permanent)) {
2912 return tokenlib_get_permanent(L);
2913 } else if (lua_key_eq(s, immutable)) {
2914 return tokenlib_get_immutable(L);
2915 } else if (lua_key_eq(s, mutable)) {
2916 return tokenlib_get_mutable(L);
2917 } else if (lua_key_eq(s, primitive)) {
2918 return tokenlib_get_primitive(L);
2919 } else if (lua_key_eq(s, instance)) {
2920 return tokenlib_get_instance(L);
2921 } else if (lua_key_eq(s, untraced)) {
2922 return tokenlib_get_untraced(L);
2923 } else if (lua_key_eq(s, flags)) {
2924 return tokenlib_get_flags(L);
2925 } else if (lua_key_eq(s, parameters)) {
2926 return tokenlib_get_parameters(L);
2927 } else if (lua_key_eq(s, constant)) {
2928 return tokenlib_get_constant(L);
2929 } else {
2930 lua_pushnil(L);
2931 }
2932 return 1;
2933}
2934
2935static int tokenlib_get_fields(lua_State *L)
2936{
2937 halfword cmd = null;
2938 halfword chr = null;
2939 int flags = 0;
2940 int onlyflags = lua_toboolean(L, 2);
2941 switch (lua_type(L, 1)) {
2942 case LUA_TSTRING:
2943 {
2944 size_t l;
2945 const char *str = lua_tolstring(L, 1, &l);
2946 if (l > 0) {
2947 halfword cs;
2948 lua_createtable(L, 0, onlyflags ? 0 : 5);
2949 cs = tex_string_locate_only(str, l);
2950 cmd = eq_type(cs);
2951 chr = eq_value(cs);
2952 flags = eq_flag(cs);
2953 if (! onlyflags) {
2954 lua_push_key(csname);
2955 lua_pushstring(L, str);
2956 lua_rawset(L, -3);
2957 }
2958 break;
2959 } else {
2960 return 0;
2961 }
2962 }
2963 case LUA_TUSERDATA:
2964 {
2965 lua_token *n = tokenlib_aux_check_istoken(L, 1);
2966 halfword tok = token_info(n->token);
2967 lua_createtable(L, 0, onlyflags ? 0 : 5);
2968 if (tok >= cs_token_flag) {
2969 int t = tok - cs_token_flag;
2970 int allocated = 0;
2971 unsigned char* str = tokenlib_aux_get_cs_text(t, &allocated);
2972 if (str) {
2973 if (! onlyflags) {
2974 lua_push_key(csname);
2975 if (tex_is_active_cs(cs_text(t))) {
2976 lua_push_key(active);
2977 lua_pushboolean(L, 1);
2978 lua_rawset(L, -3);
2979 lua_pushstring(L, (char*) (str + 3));
2980 } else {
2981 lua_pushstring(L, (char*) str);
2982 }
2983 lua_rawset(L, -3);
2984 }
2985 if (allocated) {
2986 lmt_memory_free(str);
2987 }
2988 }
2989 cmd = eq_type(t);
2990 chr = eq_value(t);
2991 } else {
2992 cmd = token_cmd(tok);
2993 chr = token_chr(tok);
2994 }
2995 break;
2996 }
2997 default:
2998 return 0;
2999
3000 }
3001 if (flags) {
3002 if (is_frozen (flags)) { lua_push_key(frozen); lua_pushboolean(L, 1); lua_rawset(L, -3); }
3003 if (is_noaligned(flags)) { lua_push_key(noaligned); lua_pushboolean(L, 1); lua_rawset(L, -3); }
3004 if (is_permanent(flags)) { lua_push_key(permanent); lua_pushboolean(L, 1); lua_rawset(L, -3); }
3005 if (is_immutable(flags)) { lua_push_key(immutable); lua_pushboolean(L, 1); lua_rawset(L, -3); }
3006 if (is_mutable (flags)) { lua_push_key(mutable); lua_pushboolean(L, 1); lua_rawset(L, -3); }
3007 if (is_primitive(flags)) { lua_push_key(primitive); lua_pushboolean(L, 1); lua_rawset(L, -3); }
3008 if (is_instance (flags)) { lua_push_key(instance); lua_pushboolean(L, 1); lua_rawset(L, -3); }
3009 if (is_untraced (flags)) { lua_push_key(untraced); lua_pushboolean(L, 1); lua_rawset(L, -3); }
3010 if (flags) { lua_push_key(flags); lua_pushinteger(L, flags); lua_rawset(L, -3); }
3011 if (is_protected(cmd)) { lua_push_key(protected); lua_pushboolean(L, 1); lua_rawset(L, -3); } else {
3012 if (is_semiprotected(cmd)) { lua_push_key(semiprotected); lua_pushboolean(L, 1); lua_rawset(L, -3); } }
3013 if (is_tolerant (cmd)) { lua_push_key(tolerant); lua_pushboolean(L, 1); lua_rawset(L, -3); }
3014 }
3015 if (! onlyflags) {
3016 lua_push_key(command);
3017 lua_pushinteger(L, cmd);
3018 lua_rawset(L, -3);
3019 lua_push_key(cmdname);
3020 lua_push_key_by_index(lmt_interface.command_names[cmd].lua);
3021 lua_rawset(L, -3);
3022 lua_push_key(index);
3023 lua_pushinteger(L, tokenlib_aux_to_valid_index(cmd, chr));
3024 lua_rawset(L, -3);
3025 if (is_call_cmd(cmd) && chr && token_link(chr)) {
3026 lua_push_key(parameters);
3027 lua_pushinteger(L, get_token_parameters(token_link(chr)));
3028 lua_rawset(L, -3);
3029 }
3030 }
3031 return 1;
3032}
3033
3034
3035
3036static int tokenlib_equal(lua_State* L)
3037{
3038 lua_token* n = tokenlib_aux_check_istoken(L, 1);
3039 lua_token* m = tokenlib_aux_check_istoken(L, 2);
3040 lua_pushboolean(L, token_info(n->token) == token_info(m->token));
3041 return 1;
3042}
3043
3044static int tokenlib_tostring(lua_State* L)
3045{
3046 lua_token* n = tokenlib_aux_maybe_istoken(L, 1);
3047 if (n) {
3048 halfword id = n->token;
3049 halfword tok = token_info(id);
3050 halfword lnk = token_link(id);
3051 char* ori = (n->origin == token_origin_lua) ? "lua" : "tex";
3052 halfword cmd, chr;
3053 unsigned char* csn = NULL;
3054 unsigned char* csp = NULL;
3055 const char* cmn = NULL;
3056 if (tok >= cs_token_flag) {
3057 int allocated = 0;
3058 tok -= cs_token_flag;
3059 csn = tokenlib_aux_get_cs_text(tok, &allocated);
3060 if (allocated) {
3061 csp = csn;
3062 }
3063 if (csn && tex_is_active_cs(cs_text(tok))) {
3064 csn += 3;
3065 }
3066 cmd = eq_type(tok);
3067 chr = eq_value(tok);
3068 } else {
3069 cmd = token_cmd(tok);
3070 chr = token_chr(tok);
3071 }
3072 if (! cmn) {
3073 if (cmd >= first_cmd && cmd <= last_cmd) {
3074 cmn = lmt_interface.command_names[cmd].name;
3075 switch (lmt_interface.command_names[cmd].base) {
3076 case ignore_entry:
3077 case direct_entry:
3078 break;
3079 default:
3080 chr -= lmt_interface.command_names[cmd].base;
3081 }
3082 } else {
3083 cmn = "bad_token";
3084 }
3085 }
3086 if (csn && csn[0] != '\0') {
3087 if (lnk) {
3088 lua_pushfstring(L, "<%s token : %d => %d : %s : %s %d>", ori, id, lnk, (char *) csn, cmn, chr);
3089 } else {
3090 lua_pushfstring(L, "<%s token : %d == %s : %s %d>", ori, id, (char *) csn, cmn, chr);
3091 }
3092 } else {
3093 if (! lnk) {
3094 lua_pushfstring(L, "<%s token : %d == %s %d>", ori, id, cmn, chr);
3095 } else if (cmd == 0 && chr == 0) {
3096
3097 lua_pushfstring(L, "<%s token : %d => %d : refcount>", ori, id, lnk);
3098 } else {
3099 lua_pushfstring(L, "<%s token : %d => %d : %s %d>", ori, id, lnk, cmn, chr);
3100 }
3101 }
3102 if (csp) {
3103 lmt_memory_free(csp);
3104 }
3105 } else {
3106 lua_pushnil(L);
3107 }
3108 return 1;
3109}
3110
3111static int tokenlib_package_tostring(lua_State *L)
3112{
3113 lua_token_package *n = tokenlib_aux_check_ispackage(L, 1);
3114 if (n) {
3115 if (is_call_cmd(n->cmd)) {
3116 lua_pushfstring(L, "<tex token package %d: %d %d %d>", n->cs, n->cmd, n->chr, get_token_reference(n->chr));
3117 } else {
3118 lua_pushfstring(L, "<tex token package %d: %d %d>", n->cs, n->cmd, n->chr);
3119 }
3120 return 1;
3121 } else {
3122 return 0;
3123 }
3124}
3125
3126static int tokenlib_type(lua_State *L)
3127{
3128 if (tokenlib_aux_maybe_istoken(L, 1)) {
3129 lua_push_key(token);
3130 } else {
3131 lua_pushnil(L);
3132 }
3133 return 1;
3134}
3135
3136static int tokenlib_scan_token(lua_State *L)
3137{
3138 saved_tex_scanner texstate = tokenlib_aux_save_tex_scanner();
3139 tex_get_x_token();
3140
3141 tokenlib_aux_make_new_token_tok(L, cur_tok);
3142 tokenlib_aux_unsave_tex_scanner(texstate);
3143 return 1;
3144}
3145
3146
3147
3148static int tokenlib_scan_box(lua_State *L)
3149{
3150 saved_tex_scanner texstate;
3151 if (lua_gettop(L) > 0) {
3152 const char *s = lua_tostring(L, 1);
3153 halfword code = -1 ;
3154 if (lua_key_eq(s, hbox)) {
3155 code = hbox_code;
3156 } else if (lua_key_eq(s, vbox)) {
3157 code = vbox_code;
3158 } else if (lua_key_eq(s, vtop)) {
3159 code = vtop_code;
3160 } else if (lua_key_eq(s, dbox)) {
3161 code = dbox_code;
3162 }
3163 if (code >= 0) {
3164 tex_back_input(token_val(make_box_cmd, code));
3165 }
3166 }
3167
3170 texstate = tokenlib_aux_save_tex_scanner();
3171 lmt_push_node_fast(L, tex_local_scan_box());
3172 tokenlib_aux_unsave_tex_scanner(texstate);
3173 return 1;
3174}
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184static int tokenlib_get_meaning(lua_State *L)
3185{
3186 if (lua_type(L, 1) == LUA_TSTRING) {
3187 size_t lname = 0;
3188 const char *name = lua_tolstring(L, 1, &lname);
3189 halfword cs = tex_string_locate_only(name, lname);
3190 halfword cmd = eq_type(cs);
3191 if (is_call_cmd(cmd)) {
3192 int chr = eq_value(cs);
3193 if (lua_toboolean(L, 2)) {
3194 if (lua_toboolean(L, 3)) {
3195 lmt_token_list_to_lua(L, token_link(chr));
3196 } else {
3197 int originals = lua_toboolean(L, 4);
3198 lmt_token_register_to_lua(L, chr, originals);
3199 if (originals) {
3200 return 2;
3201 }
3202 }
3203 } else {
3204 char *str = tex_tokenlist_to_tstring(chr, 1, NULL, 0, 0, 0, 0, 0);
3205 lua_pushstring(L, str ? str : "");
3206 }
3207 return 1;
3208 }
3209 }
3210 return 0;
3211}
3212
3213
3222
3223static halfword tokenlib_aux_expand_macros_in_tokenlist(halfword p)
3224{
3225 halfword old_mode;
3226 halfword q = tex_get_available_token(right_brace_token + '}');
3227 halfword r = tex_get_available_token(deep_frozen_end_write_token);
3228 token_link(q) = r;
3229 tex_begin_inserted_list(q);
3230 tex_begin_token_list(p, write_text);
3231
3232 old_mode = cur_list.mode;
3233 cur_list.mode = 0;
3234
3235 cur_cs = 0;
3236
3237 ++lmt_input_state.align_state;
3238 tex_scan_toks_expand(1, NULL, 0, 0);
3239 tex_get_token();
3240 if (cur_tok != deep_frozen_end_write_token) {
3241
3242 tex_handle_error(
3243 normal_error_type,
3244 "Unbalanced token list expansion",
3245 "On this page there's a token list expansion with fewer real {'s than }'s. I can't\n"
3246 "handle that very well; good luck."
3247 );
3248 do {
3249 tex_get_token();
3250 } while (cur_tok != deep_frozen_end_write_token);
3251 }
3252 cur_list.mode = old_mode;
3253
3254 tex_end_token_list();
3255 return lmt_input_state.def_ref;
3256}
3257
3258
3259
3260static int tokenlib_get_macro(lua_State *L)
3261{
3262 if (lua_type(L, 1) == LUA_TSTRING) {
3263 size_t lname = 0;
3264 const char *name = lua_tolstring(L, 1, &lname);
3265 halfword cs = tex_string_locate_only(name, lname);
3266 halfword cmd = eq_type(cs);
3267 if (is_call_cmd(cmd)) {
3268 halfword chr = eq_value(cs);
3269 char *str = NULL;
3270 if (lua_toboolean(L, 2)) {
3271 chr = tokenlib_aux_expand_macros_in_tokenlist(chr);
3272 str = tex_tokenlist_to_tstring(chr, 1, NULL, 0, 0, 0, 1, 0);
3273 } else {
3274 str = tex_tokenlist_to_tstring(chr, 1, NULL, lua_toboolean(L, 3) ? 2 : 1, 0, 0, 0, 0);
3275 }
3276 lua_pushstring(L, str ? str : "");
3277 return 1;
3278 }
3279 }
3280 return 0;
3281}
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291static int tokenlib_push_macro(lua_State *L)
3292{
3293
3299 if (lua_type(L, 1) == LUA_TSTRING) {
3300 size_t lname = 0;
3301 const char *name = lua_tolstring(L, 1, &lname);
3302 if (lname > 0) {
3303 halfword cs = tex_string_locate_only(name, lname);
3304 singleword cmd = eq_type(cs);
3305 halfword chr = eq_value(cs);
3306 quarterword global = lua_toboolean(L, 2) ? add_global_flag(0) : 0;
3307 if (is_call_cmd(cmd)) {
3308 tex_add_token_reference(chr);
3309 }
3310 tokenlib_aux_make_new_package(L, cmd, eq_flag(cs), chr, cs, global);
3311 return 1;
3312 }
3313 }
3314 return 0;
3315}
3316
3317static int tokenlib_pop_macro(lua_State *L)
3318{
3319 lua_token_package *p = tokenlib_aux_check_ispackage(L, 1);
3320 if (p) {
3321 tex_forced_define(p->how, p->cs, p->flag, p->cmd, p->chr);
3322 }
3323 return 0;
3324}
3325
3326char *lmt_get_expansion(halfword head, int *len)
3327{
3328 char *str = NULL;
3329 halfword t;
3330 halfword ref = get_reference_token();
3331 set_token_link(ref, head);
3332 t = tokenlib_aux_expand_macros_in_tokenlist(ref);
3333 str = tex_tokenlist_to_tstring(t, 1, len, 0, 0, 0, 1, 1);
3334 tex_flush_token_list(ref);
3335 return str;
3336}
3337
3338static int tokenlib_get_expansion(lua_State* L)
3339{
3340 const char *str;
3341 size_t len;
3342 int slot = 1;
3343 halfword ct = lua_type(L, slot) == LUA_TNUMBER ? lmt_tohalfword(L, slot++) : cat_code_table_par;
3344 if (! tex_valid_catcode_table(ct)) {
3345 ct = cat_code_table_par;
3346 }
3347 str = lua_tolstring(L, 1, &len);
3348 if (len > 0) {
3349 halfword h = get_reference_token();
3350 halfword t = h;
3351 char *s;
3352 int l;
3353 tex_parse_str_to_tok(h, &t, ct, str, len, 2);
3354 t = tokenlib_aux_expand_macros_in_tokenlist(h);
3355 s = tex_tokenlist_to_tstring(t, 1, &l, 0, 0, 0, 1, 1);
3356 tex_flush_token_list(h);
3357 if (l > 0) {
3358 lua_pushlstring(L, (const char *) s, (size_t) l);
3359 return 1;
3360 }
3361 }
3362 lua_pushliteral(L, "");
3363 return 1;
3364}
3365
3366static int tokenlib_save_lua(lua_State *L)
3367{
3368 halfword f = lmt_tohalfword(L, 1);
3369 if (lua_toboolean(L, 2) && cur_level > 0) {
3370
3371 halfword ptr = lmt_save_state.save_stack_data.ptr;
3372 while (1) {
3373 --ptr;
3374 switch (save_type(ptr)) {
3375 case level_boundary_save_type:
3376 goto SAVE;
3377 case restore_lua_save_type:
3378 if (save_value(ptr) == f) {
3379 return 0;
3380 } else {
3381 break;
3382 }
3383 }
3384 }
3385 }
3386 SAVE:
3387 tex_save_halfword_on_stack(restore_lua_save_type, f);
3388 return 0;
3389}
3390
3391static int tokenlib_set_lua(lua_State *L)
3392{
3393 int top = lua_gettop(L);
3394 if (top >= 2) {
3395 size_t lname = 0;
3396 const char *name = lua_tolstring(L, 1, &lname);
3397 if (name) {
3398 halfword cs;
3399 int flags = 0;
3400 int funct = lmt_tointeger(L, 2);
3401 lmt_check_for_flags(L, 3, &flags, 1, 1);
3402 cs = tex_string_locate(name, lname, 1);
3403 if (tex_define_permitted(cs, flags)) {
3404 if (is_value(flags)) {
3405 tex_define(flags, cs, lua_value_cmd, funct);
3406 } else if (is_conditional(flags)) {
3407 tex_define(flags, cs, if_test_cmd, last_if_test_code + funct);
3408
3409 } else if (is_protected(flags)) {
3410 tex_define(flags, cs, lua_protected_call_cmd, funct);
3411 } else if (is_semiprotected(flags)) {
3412 tex_define(flags, cs, lua_semi_protected_call_cmd, funct);
3413 } else {
3414 tex_define(flags, cs, lua_call_cmd, funct);
3415 }
3416 }
3417 }
3418 }
3419 return 0;
3420}
3421
3422
3423
3424static int tokenlib_undefine_macro(lua_State *L)
3425{
3426 size_t lname = 0;
3427 const char *name = lua_tolstring(L, 1, &lname);
3428 if (name) {
3429 halfword cs = tex_string_locate(name, lname, 1);
3430 int flags = 0;
3431 lmt_check_for_flags(L, 2, &flags, 1, 1);
3432 tex_define(flags, cs, undefined_cs_cmd, null);
3433 }
3434 return 0;
3435}
3436
3437static int tokenlib_set_macro(lua_State *L)
3438{
3439 int top = lua_gettop(L);
3440 if (top > 0) {
3441 const char *name = NULL;
3442 size_t lname = 0;
3443 int slot = 1;
3444 halfword ct = lua_type(L, slot) == LUA_TNUMBER ? lmt_tohalfword(L, slot++) : cat_code_table_par;
3445 if (! tex_valid_catcode_table(ct)) {
3446 ct = cat_code_table_par;
3447 }
3448 name = lua_tolstring(L, slot++, &lname);
3449 if (name) {
3450 size_t lstr = 0;
3451 const char *str = lua_tolstring(L, slot++, &lstr);
3452 halfword cs = tex_string_locate(name, lname, 1);
3453 int flags = 0;
3454 if (slot <= top) {
3455 slot = lmt_check_for_flags(L, slot, &flags, 1, 1);
3456 }
3457 if (tex_define_permitted(cs, flags)) {
3458 halfword h;
3459 if (lstr > 0) {
3460 h = get_reference_token();
3461
3462 tex_parse_str_to_tok(h, null, ct, str, lstr, lua_toboolean(L, slot++) ? 2 : 1);
3463 } else {
3464 h = lmt_token_state.empty;
3465
3466 }
3467 tex_define(flags, cs, tex_flags_to_cmd(flags), h);
3468 }
3469 }
3470 }
3471 return 0;
3472}
3473
3474
3475
3476halfword lmt_macro_to_tok(lua_State *L, int slot, halfword *tail)
3477{
3478 halfword tok = 0;
3479 switch (lua_type(L, slot)) {
3480 case LUA_TSTRING:
3481 {
3482 size_t lname = 0;
3483 const char *name = lua_tolstring(L, slot, &lname);
3484 int cs = tex_string_locate_only(name, lname);
3485 int cmd = eq_type(cs);
3486 if (is_call_cmd(cmd)) {
3487 tok = cs_token_flag + cs;
3488 } else if (cmd != undefined_cs_cmd) {
3489
3490 tok = token_val(cmd, eq_value(cs));
3491 }
3492 break;
3493 }
3494 case LUA_TUSERDATA:
3495 tok = token_info(lmt_token_code_from_lua(L, slot));
3496 if (! is_call_cmd(tok >= cs_token_flag ? eq_type(tok - cs_token_flag) : token_cmd(tok))) {
3497 tok = 0;
3498 }
3499 break;
3500 }
3501 if (tok) {
3502 int top = lua_gettop(L);
3503 halfword m = tex_get_available_token(tok);
3504 halfword a = m;
3505 halfword c = cat_code_table_par;
3506 if (top > slot) {
3507 int arg = 0;
3508 for (int i = slot + 1; i <= top; i++) {
3509 switch (lua_type(L, i)) {
3510 case LUA_TBOOLEAN:
3511 {
3512 arg = lua_toboolean(L, i);
3513 break;
3514 }
3515 case LUA_TSTRING:
3516 {
3517 size_t l;
3518 const char *s = lua_tolstring(L, i, &l);
3519 if (arg) {
3520 a = tex_store_new_token(a, left_brace_token + '{');
3521 }
3522
3523 tex_parse_str_to_tok(a, &a, c, s, l, 1);
3524 if (arg) {
3525 a = tex_store_new_token(a, right_brace_token + '}');
3526 }
3527 break;
3528 }
3529 case LUA_TNUMBER:
3530 {
3531
3532 c = lmt_tohalfword(L, i);
3533 break;
3534 }
3535 case LUA_TTABLE:
3536 {
3537 size_t l;
3538 const char *s ;
3539 int j = (int) lua_rawlen(L, i);
3540 for (int k = 1; k <= j; k++) {
3541 lua_rawgeti(L, i, k);
3542 s = lua_tolstring(L, -1, &l);
3543 a = tex_store_new_token(a, left_brace_token + '{');
3544
3545 tex_parse_str_to_tok(a, &a, c, s, l, 1);
3546 a = tex_store_new_token(a, right_brace_token + '}');
3547 lua_pop(L, 1);
3548 };
3549 break;
3550 }
3551 case LUA_TUSERDATA:
3552 {
3553 a = tex_store_new_token(a, lmt_token_code_from_lua(L, i));
3554 break;
3555 }
3556 }
3557 }
3558 }
3559 if (tail) {
3560 *tail = a;
3561 }
3562 return m;
3563 } else {
3564 if (tail) {
3565 *tail = null;
3566 }
3567 return null;
3568 }
3569}
3570
3571static int tokenlib_expand_macro(lua_State *L)
3572{
3573 halfword tail = null;
3574 halfword tok = lmt_macro_to_tok(L, 1, &tail);
3575 if (tok) {
3576
3577 tex_begin_inserted_list(tex_get_available_token(token_val(end_local_cmd, 0)));
3578 tex_begin_inserted_list(tok);
3579
3580
3581
3582 if (lmt_token_state.luacstrings > 0) {
3583 tex_lua_string_start();
3584 }
3585 if (tracing_nesting_par > 2) {
3586 tex_local_control_message("entering local control via (run) macro");
3587 }
3588 tex_local_control(1);
3589 } else {
3590 tex_local_control_message("invalid (run) macro");
3591 }
3592 return 0;
3593}
3594
3595
3596
3597static int tokenlib_set_char(lua_State *L)
3598{
3599 int top = lua_gettop(L);
3600 if (top >= 2) {
3601 size_t lname = 0;
3602 const char *name = lua_tolstring(L, 1, &lname);
3603 if (name) {
3604 int value = lmt_tointeger(L, 2);
3605 if (value >= 0 && value <= max_character_code) {
3606 int flags = 0;
3607 int cs = tex_string_locate(name, lname, 1);
3608 if (top > 2) {
3609 lmt_check_for_flags(L, 3, &flags, 1, 0);
3610 }
3611 tex_define(flags, cs, char_given_cmd, value);
3612 }
3613 }
3614 }
3615 return 0;
3616}
3617
3618
3619
3620static int tokenlib_set_constant_value(lua_State *L, singleword cmd, halfword min, halfword max)
3621{
3622 int top = lua_gettop(L);
3623 if (top >= 2) {
3624 size_t lname = 0;
3625 const char *name = lua_tolstring(L, 1, &lname);
3626 if (name) {
3627 halfword value = lmt_tohalfword(L, 2);
3628 if (value >= min && value <= max) {
3629 int flags = 0;
3630 int cs = tex_string_locate(name, lname, 1);
3631 if (top > 2) {
3632 lmt_check_for_flags(L, 3, &flags, 1, 0);
3633 }
3634 tex_define(flags, cs, cmd, value);
3635 }
3636 }
3637 }
3638 return 0;
3639}
3640
3641static int tokenlib_get_constant_value(lua_State *L, halfword cmd)
3642{
3643 if (lua_type(L, 1) == LUA_TSTRING) {
3644 size_t l;
3645 const char *s = lua_tolstring(L, 1, &l);
3646 if (l > 0) {
3647 int cs = tex_string_locate_only(s, l);
3648 if (eq_type(cs) == cmd) {
3649 lua_pushinteger(L, eq_value(cs));
3650 return 1;
3651 }
3652 }
3653 }
3654 lua_pushnil(L);
3655 return 1;
3656}
3657
3658static int tokenlib_set_integer(lua_State *L)
3659{
3660 return tokenlib_set_constant_value(L, integer_cmd, min_integer, max_integer);
3661}
3662
3663static int tokenlib_set_dimension(lua_State *L)
3664{
3665 return tokenlib_set_constant_value(L, dimension_cmd, min_dimension, max_dimension);
3666}
3667
3668
3669
3670
3671
3672
3673static int tokenlib_get_integer(lua_State *L)
3674{
3675 return tokenlib_get_constant_value(L, integer_cmd);
3676}
3677
3678static int tokenlib_get_dimension(lua_State *L)
3679{
3680 return tokenlib_get_constant_value(L, dimension_cmd);
3681}
3682
3683
3684
3685
3686
3687
3688
3699
3700static int tokenlib_serialize(lua_State *L)
3701{
3702 lua_token *n = tokenlib_aux_maybe_istoken(L, 1);
3703 if (n) {
3704
3705 halfword t = tokenlib_aux_expand_macros_in_tokenlist(n->token);
3706 char *s = tex_tokenlist_to_tstring(t, 1, NULL, 0, 0, 0, 1, 0);
3707 lua_pushstring(L, s ? s : "");
3708 } else {
3709 lua_pushnil(L);
3710 }
3711 return 1;
3712}
3713
3714static int tokenlib_getcommandvalues(lua_State *L)
3715{
3716 lua_createtable(L, number_tex_commands, 1);
3717 for (int i = 0; i < number_tex_commands; i++) {
3718 lua_rawgeti(L, LUA_REGISTRYINDEX, lmt_interface.command_names[i].lua);
3719 lua_rawseti(L, -2, lmt_interface.command_names[i].id);
3720 }
3721 return 1;
3722}
3723
3724static int tokenlib_getfunctionvalues(lua_State *L)
3725{
3726 return lmt_push_info_values(L, lmt_interface.lua_function_values);
3727}
3728
3729static const struct luaL_Reg tokenlib_function_list[] = {
3730 { "type", tokenlib_type },
3731 { "create", tokenlib_create },
3732 { "new", tokenlib_new },
3733
3734 { "istoken", tokenlib_is_token },
3735 { "isdefined", tokenlib_is_defined },
3736
3737 { "scannext", tokenlib_scan_next },
3738 { "scannextexpanded", tokenlib_scan_next_expanded },
3739 { "scannextchar", tokenlib_scan_next_char },
3740
3741 { "skipnext", tokenlib_skip_next },
3742 { "skipnextexpanded", tokenlib_skip_next_expanded },
3743
3744 { "peeknext", tokenlib_peek_next },
3745 { "peeknextexpanded", tokenlib_peek_next_expanded },
3746 { "peeknextchar", tokenlib_peek_next_char },
3747
3748 { "scancmdchr", tokenlib_scan_cmdchr },
3749 { "scancmdchrexpanded", tokenlib_scan_cmdchr_expanded },
3750 { "scankeyword", tokenlib_scan_keyword },
3751 { "scankeywordcs", tokenlib_scan_keyword_cs },
3752 { "scanint", tokenlib_scan_integer },
3753 { "scaninteger", tokenlib_scan_integer },
3754 { "scanintegerargument", tokenlib_scan_integer_argument },
3755 { "scandimensionargument", tokenlib_scan_dimension_argument },
3756 { "scandimenargument", tokenlib_scan_dimension_argument },
3757 { "scancardinal", tokenlib_scan_cardinal },
3758 { "scanfloat", tokenlib_scan_float },
3759 { "scanreal", tokenlib_scan_real },
3760 { "scanluanumber", tokenlib_scan_luanumber },
3761 { "scanluainteger", tokenlib_scan_luainteger },
3762 { "scanluacardinal", tokenlib_scan_luacardinal },
3763 { "scanscale", tokenlib_scan_scale },
3764 { "scandimen", tokenlib_scan_dimension },
3765 { "scandimension", tokenlib_scan_dimension },
3766 { "scanposit", tokenlib_scan_posit },
3767 { "scanskip", tokenlib_scan_skip },
3768 { "scanglue", tokenlib_scan_glue },
3769 { "scantoks", tokenlib_scan_toks },
3770 { "scantokenlist", tokenlib_scan_tokenlist },
3771 { "scancode", tokenlib_scan_code },
3772 { "scantokencode", tokenlib_scan_token_code },
3773 { "scanstring", tokenlib_scan_string },
3774 { "scantokenstring", tokenlib_scan_tokenstring },
3775 { "scanargument", tokenlib_scan_argument },
3776 { "scandelimited", tokenlib_scan_delimited },
3777 { "scanword", tokenlib_scan_word },
3778 { "scanletters", tokenlib_scan_letters },
3779 { "scankey", tokenlib_scan_key },
3780 { "scanvalue", tokenlib_scan_value },
3781 { "scanchar", tokenlib_scan_char },
3782 { "scancsname", tokenlib_scan_csname },
3783 { "scantoken", tokenlib_scan_token },
3784 { "scanbox", tokenlib_scan_box },
3785 { "scandetokened", tokenlib_scan_detokened },
3786 { "isnextchar", tokenlib_is_next_char },
3787
3788 { "putnext", tokenlib_put_next },
3789 { "putback", tokenlib_put_back },
3790 { "expand", tokenlib_expand },
3791
3792 { "getcommand", tokenlib_get_command },
3793 { "getindex", tokenlib_get_index },
3794 { "getrange", tokenlib_get_range },
3795
3796 { "getcmdname", tokenlib_get_cmdname },
3797 { "getcsname", tokenlib_get_csname },
3798 { "getid", tokenlib_get_id },
3799 { "gettok", tokenlib_get_tok },
3800 { "getactive", tokenlib_get_active },
3801
3802 { "getexpandable", tokenlib_get_expandable },
3803 { "getprotected", tokenlib_get_protected },
3804 { "getfrozen", tokenlib_get_frozen },
3805 { "gettolerant", tokenlib_get_tolerant },
3806 { "getnoaligned", tokenlib_get_noaligned },
3807 { "getprimitive", tokenlib_get_primitive },
3808 { "getpermanent", tokenlib_get_permanent },
3809 { "getimmutable", tokenlib_get_immutable },
3810 { "getinstance", tokenlib_get_instance },
3811
3812 { "getflags", tokenlib_get_flags },
3813 { "getparameters", tokenlib_get_parameters },
3814 { "getconstant", tokenlib_get_constant },
3815 { "getmacro", tokenlib_get_macro },
3816 { "getmeaning", tokenlib_get_meaning },
3817 { "getcmdchrcs", tokenlib_get_cmdchrcs },
3818 { "getcstoken", tokenlib_get_cstoken },
3819 { "getfields", tokenlib_get_fields },
3820
3821 { "setmacro", tokenlib_set_macro },
3822 { "undefinemacro", tokenlib_undefine_macro },
3823 { "expandmacro", tokenlib_expand_macro },
3824 { "setchar", tokenlib_set_char },
3825 { "setlua", tokenlib_set_lua },
3826 { "setinteger", tokenlib_set_integer },
3827 { "getinteger", tokenlib_get_integer },
3828 { "setdimension", tokenlib_set_dimension },
3829 { "getdimension", tokenlib_get_dimension },
3830
3831 { "gobbleinteger", tokenlib_gobble_integer },
3832 { "gobbledimen", tokenlib_gobble_dimension },
3833 { "gobble", tokenlib_gobble_until },
3834 { "grab", tokenlib_grab_until },
3835
3836 { "futureexpand", tokenlib_future_expand },
3837 { "pushmacro", tokenlib_push_macro },
3838 { "popmacro", tokenlib_pop_macro },
3839
3840 { "savelua", tokenlib_save_lua },
3841 { "serialize", tokenlib_serialize },
3842 { "getexpansion", tokenlib_get_expansion },
3843
3844 { "getfunctionvalues", tokenlib_getfunctionvalues },
3845 { "getcommandvalues", tokenlib_getcommandvalues },
3846 { "getcommandid", tokenlib_getcommandid },
3847 { "getprimitives", tokenlib_getprimitives },
3848
3849 { NULL, NULL },
3850};
3851
3852static const struct luaL_Reg tokenlib_instance_metatable[] = {
3853 { "__index", tokenlib_getfield },
3854 { "__tostring", tokenlib_tostring },
3855 { "__gc", tokenlib_free },
3856 { "__eq", tokenlib_equal },
3857 { NULL, NULL },
3858};
3859
3860static const struct luaL_Reg tokenlib_package_metatable[] = {
3861 { "__tostring", tokenlib_package_tostring },
3862 { NULL, NULL },
3863};
3864
3865int luaopen_token(lua_State *L)
3866{
3867 luaL_newmetatable(L, TOKEN_METATABLE_INSTANCE);
3868 luaL_setfuncs(L, tokenlib_instance_metatable, 0);
3869 luaL_newmetatable(L, TOKEN_METATABLE_PACKAGE);
3870 luaL_setfuncs(L, tokenlib_package_metatable, 0);
3871 lua_newtable(L);
3872 luaL_setfuncs(L, tokenlib_function_list, 0);
3873 return 1;
3874}
3875
3876typedef struct LoadS {
3877 char *s;
3878 size_t size;
3879} LoadS;
3880
3881static const char *tokenlib_aux_reader(lua_State *L, void *ud, size_t *size)
3882{
3883 LoadS *ls = (LoadS *) ud;
3884 (void) L;
3885 if (ls->size > 0) {
3886 *size = ls->size;
3887 ls->size = 0;
3888 return ls->s;
3889 } else {
3890 return NULL;
3891 }
3892}
3893
3894void lmt_token_call(int p)
3895{
3896 LoadS ls;
3897 int l = 0;
3898 ls.s = tex_tokenlist_to_tstring(p, 1, &l, 0, 0, 0, 0, 1);
3899 ls.size = (size_t) l;
3900 if (ls.size > 0) {
3901 lua_State *L = lmt_lua_state.lua_instance;
3902 int i;
3903 int top = lua_gettop(L);
3904 lua_pushcfunction(L, lmt_traceback);
3905 i = lua_load(L, tokenlib_aux_reader, &ls, "=[\\directlua]", NULL);
3906 if (i != 0) {
3907 lmt_error(L, "token call, syntax", -1, i == LUA_ERRSYNTAX ? 0 : 1);
3908 } else {
3909 ++lmt_lua_state.direct_callback_count;
3910 i = lua_pcall(L, 0, 0, top + 1);
3911 if (i != 0) {
3912 lua_remove(L, top + 1);
3913 lmt_error(L, "token call, execute", -1, i == LUA_ERRRUN ? 0 : 1);
3914 }
3915 }
3916 lua_settop(L, top);
3917 }
3918}
3919
3920void lmt_function_call(int slot, int prefix)
3921{
3922 lua_State *L = lmt_lua_state.lua_instance;
3923 int stacktop = lua_gettop(L);
3924 lua_rawgeti(L, LUA_REGISTRYINDEX, lmt_lua_state.function_table_id);
3925 lua_pushcfunction(L, lmt_traceback);
3926 if (lua_rawgeti(L, -2, slot) == LUA_TFUNCTION) {
3927 int i = 1;
3928
3929 lua_pushinteger(L, slot);
3930 if (prefix > 0) {
3931 lua_pushinteger(L, prefix);
3932 ++i;
3933 }
3934 ++lmt_lua_state.function_callback_count;
3935 i = lua_pcall(L, i, 0, stacktop + 2);
3936 if (i) {
3937 lua_remove(L, stacktop + 2);
3938 lmt_error(L, "registered function call", slot, i == LUA_ERRRUN ? 0 : 1);
3939 }
3940 }
3941 lua_settop(L, stacktop);
3942}
3943
3944void lmt_local_call(int slot)
3945{
3946 lua_State *L = lmt_lua_state.lua_instance;
3947 int stacktop = lua_gettop(L);
3948 lua_pushcfunction(L, lmt_traceback);
3949 if (lua_rawgeti(L, LUA_REGISTRYINDEX, slot) == LUA_TFUNCTION) {
3950 int i;
3951 ++lmt_lua_state.local_callback_count;
3952 i = lua_pcall(L, 0, 0, stacktop + 1);
3953 if (i) {
3954 lua_remove(L, stacktop + 1);
3955 lmt_error(L, "local function call", slot, i == LUA_ERRRUN ? 0 : 1);
3956 }
3957 }
3958 lua_settop(L, stacktop);
3959}
3960
3961
3962
3963int lmt_function_call_by_category(int slot, int property, halfword *value)
3964{
3965 lua_State *L = lmt_lua_state.lua_instance;
3966 int stacktop = lua_gettop(L);
3967 int category = lua_value_none_code;
3968 lua_pushcfunction(L, lmt_traceback);
3969 lua_rawgeti(L, LUA_REGISTRYINDEX, lmt_lua_state.function_table_id);
3970 if (lua_rawgeti(L, -1, slot) == LUA_TFUNCTION) {
3971 int i;
3972
3973 lua_pushinteger(L, slot);
3974 if (property) {
3975 lua_pushinteger(L, property);
3976 } else {
3977 lua_push_key(value);
3978 }
3979 ++lmt_lua_state.value_callback_count;
3980 i = lua_pcall(L, 2, 2, stacktop + 1);
3981 if (i) {
3982 lua_remove(L, stacktop + 1);
3983 lmt_error(L, "function call", slot, i == LUA_ERRRUN ? 0 : 1);
3984 } else {
3985 if (lua_type(L, -2) == LUA_TNUMBER) {
3986 category = lmt_tointeger(L, -2);
3987 }
3988 switch (category) {
3989 case lua_value_none_code:
3990 {
3991 break;
3992 }
3993 case lua_value_integer_code:
3994 {
3995
3996 *value = lua_type(L, -1) == LUA_TNUMBER ? lmt_tohalfword(L, -1) : 0;
3997 if (*value < - max_integer) {
3998 *value = max_integer;
3999 } else if (*value > max_integer) {
4000 *value = max_integer;
4001 }
4002 break;
4003 }
4004 case lua_value_cardinal_code:
4005 {
4006
4007 lua_Unsigned u = lua_type(L, -1) == LUA_TNUMBER ? (lua_Unsigned) lua_tointeger(L, -1) : 0;
4008 if (u > max_cardinal) {
4009 u = max_cardinal;
4010 }
4011 if (*value > max_integer) {
4012 *value = (halfword) (u - 0x100000000);
4013 } else {
4014 *value = (halfword) u;
4015 }
4016 break;
4017 }
4018 case lua_value_dimension_code:
4019 {
4020
4021 *value = lua_type(L, -1) == LUA_TNUMBER ? lmt_roundnumber(L, -1) : 0;
4022 if (*value < - max_dimension) {
4023 *value = max_dimension;
4024 } else if (*value > max_dimension) {
4025 *value = max_dimension;
4026 }
4027 break;
4028 }
4029 case lua_value_skip_code:
4030 {
4031 halfword n = lmt_check_isnode(L, -1);
4032 if (n && node_type(n) == glue_spec_node) {
4033 *value = n;
4034 } else {
4035 luaL_error(L, "gluespec node expected");
4036 *value = tex_copy_node(zero_glue);
4037 }
4038 break;
4039 }
4040 case lua_value_float_code:
4041 *value = tex_double_to_posit(lua_tonumber(L, -1)).v;
4042 break;
4043 case lua_value_string_code:
4044 category = lua_value_none_code;
4045 break;
4046 case lua_value_boolean_code:
4047 *value = lua_toboolean(L, -1);
4048 break;
4049 case lua_value_node_code:
4050 *value = lmt_check_isnode(L, -1);
4051 break;
4052 case lua_value_direct_code:
4053 *value = lmt_check_isdirect(L, -1);
4054 break;
4055 case lua_value_conditional_code:
4056 break;
4057 default:
4058 category = lua_value_none_code;
4059 break;
4060 }
4061 }
4062 }
4063 lua_settop(L, stacktop);
4064 return category;
4065}
4066
4067
4083
4084int lmt_push_specification(lua_State *L, halfword ptr, int onlycount)
4085{
4086 if (ptr) {
4087 switch (node_subtype(ptr)) {
4088 case par_shape_code:
4089 {
4090 int n = specification_count(ptr);
4091 if (onlycount == 1) {
4092 lua_pushinteger(L, n);
4093 } else {
4094 int r = specification_repeat(ptr);
4095 lua_createtable(L, n, r ? 1 : 0);
4096 if (r) {
4097 lua_push_boolean_at_key(L, repeat, r);
4098 }
4099 for (int m = 1; m <= n; m++) {
4100 lua_createtable(L, 2, 0);
4101 lua_pushinteger(L, tex_get_specification_indent(ptr, m));
4102 lua_rawseti(L, -2, 1);
4103 lua_pushinteger(L, tex_get_specification_width(ptr, m));
4104 lua_rawseti(L, -2, 2);
4105 lua_rawseti(L, -2, m);
4106 }
4107 }
4108 return 1;
4109 }
4110 case par_passes_code:
4111 {
4112 return 0;
4113 }
4114 case inter_line_penalties_code:
4115 case club_penalties_code:
4116 case widow_penalties_code:
4117 case display_widow_penalties_code:
4118 case orphan_penalties_code:
4119 case math_forward_penalties_code:
4120 case math_backward_penalties_code:
4121 {
4122 int n = specification_count(ptr);
4123 if (onlycount == 1) {
4124 lua_pushinteger(L, n);
4125 } else {
4126 lua_createtable(L, n, 0);
4127 for (int m = 1; m <= n; m++) {
4128 lua_pushinteger(L, tex_get_specification_penalty(ptr, m));
4129 lua_rawseti(L, -2, m);
4130 }
4131 }
4132 return 1;
4133 }
4134 }
4135 }
4136 lua_pushnil(L);
4137 return 1;
4138}
4139 |