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