lmtstatuslib.c /size: 38 Kb    last modification: 2025-02-21 11:03
1/*
2    See license.txt in the root of this project.
3*/
4
5/*tex
6
7    This module has been there from the start and provides some information that doesn't really
8    fit elsewhere. In \LUATEX\ the module got extended ovet time, and in \LUAMETATEX\ most of what
9    is here has been redone, also because we want different statistics.
10
11*/
12# include "luametatex.h"
13
14# define STATS_METATABLE "tex.stats"
15
16typedef struct statistic_entry {
17    const char *name;
18    void       *value;
19    int         type;
20    int         padding;
21} statistic_entry;
22
23typedef const char *(*constfunc) (void);
24typedef char       *(*charfunc)  (void);
25typedef lua_Number  (*numfunc)   (void);
26typedef int         (*intfunc)   (void);
27typedef int         (*luafunc)   (lua_State *L);
28
29static int statslib_callbackstate(lua_State *L)
30{
31    lmt_push_callback_usage(L);
32    return 1;
33}
34
35static int statslib_linebreakstate(lua_State *L)
36{
37    lua_createtable(L, n_of_par_context_codes + 3, 0);
38    for (int i = 0; i < n_of_par_context_codes; i++) {
39        lua_push_key_by_index(lmt_interface.par_context_values[i].lua);
40        lua_createtable(L, 0, 5);
41        lua_set_integer_by_key(L, "calls",         lmt_linebreak_state.passes[i].n_of_break_calls);
42        lua_set_integer_by_key(L, "first",         lmt_linebreak_state.passes[i].n_of_first_passes);
43        lua_set_integer_by_key(L, "second",        lmt_linebreak_state.passes[i].n_of_second_passes);
44        lua_set_integer_by_key(L, "final",         lmt_linebreak_state.passes[i].n_of_final_passes);
45        lua_set_integer_by_key(L, "specification", lmt_linebreak_state.passes[i].n_of_specification_passes);
46        lua_set_integer_by_key(L, "sub",           lmt_linebreak_state.passes[i].n_of_sub_passes);
47        lua_rawset(L, -3);
48    }
49    lua_set_integer_by_key(L, "lefttwins",   lmt_linebreak_state.n_of_left_twins);
50    lua_set_integer_by_key(L, "righttwins",  lmt_linebreak_state.n_of_right_twins);
51    lua_set_integer_by_key(L, "doubletwins", lmt_linebreak_state.n_of_double_twins);
52    return 1;
53}
54
55static int statslib_balancestate(lua_State *L)
56{
57    lua_createtable(L, 9, 0);
58    lua_set_integer_by_key(L, "calls",          lmt_balance_state.passes.n_of_break_calls);
59    lua_set_integer_by_key(L, "first",          lmt_balance_state.passes.n_of_first_passes);
60    lua_set_integer_by_key(L, "second",         lmt_balance_state.passes.n_of_second_passes);
61    lua_set_integer_by_key(L, "final",          lmt_balance_state.passes.n_of_final_passes);
62    lua_set_integer_by_key(L, "specification",  lmt_balance_state.passes.n_of_specification_passes);
63    lua_set_integer_by_key(L, "sub",            lmt_balance_state.passes.n_of_sub_passes);
64    lua_set_integer_by_key(L, "foundinserts",   lmt_balance_state.total_inserts_found);
65    lua_set_integer_by_key(L, "checkedinserts", lmt_balance_state.total_inserts_checked);
66    lua_set_integer_by_key(L, "callbacks",      lmt_balance_state.n_of_callbacks);
67    return 1;
68}
69
70static int statslib_hyphenationstate(lua_State *L)
71{
72    lua_createtable(L, 0, 6);
73    lua_set_integer_by_key(L, "lists",      lmt_language_state.list_count);
74    lua_set_integer_by_key(L, "words",      lmt_language_state.word_count);
75    lua_set_integer_by_key(L, "checked",    lmt_language_state.checked_count);
76    lua_set_integer_by_key(L, "hyphenated", lmt_language_state.hyphenated_count);
77    lua_set_integer_by_key(L, "exceptions", lmt_language_state.exceptions_count);
78    lua_set_integer_by_key(L, "nothing",    lmt_language_state.nothing_count);
79    return 1;
80}
81
82static int statslib_texstate(lua_State *L)
83{
84    lua_Integer approximate = 0
85        + (lua_Integer) lmt_string_pool_state .string_pool_data    .allocated * (lua_Integer) lmt_string_pool_state .string_pool_data    .itemsize + lmt_string_pool_state .string_pool_data    .extra
86        + (lua_Integer) lmt_string_pool_state .string_body_data    .allocated * (lua_Integer) lmt_string_pool_state .string_body_data    .itemsize + lmt_string_pool_state .string_body_data    .extra
87        + (lua_Integer) lmt_node_memory_state .nodes_data          .allocated * (lua_Integer) lmt_node_memory_state .nodes_data          .itemsize + lmt_node_memory_state .nodes_data          .extra
88        + (lua_Integer) lmt_token_memory_state.tokens_data         .allocated * (lua_Integer) lmt_token_memory_state.tokens_data         .itemsize + lmt_token_memory_state.tokens_data         .extra
89        + (lua_Integer) lmt_fileio_state      .io_buffer_data      .allocated * (lua_Integer) lmt_fileio_state      .io_buffer_data      .itemsize + lmt_fileio_state      .io_buffer_data      .extra
90        + (lua_Integer) lmt_input_state       .input_stack_data    .allocated * (lua_Integer) lmt_input_state       .input_stack_data    .itemsize + lmt_input_state       .input_stack_data    .extra
91        + (lua_Integer) lmt_input_state       .in_stack_data       .allocated * (lua_Integer) lmt_input_state       .in_stack_data       .itemsize + lmt_input_state       .in_stack_data       .extra
92        + (lua_Integer) lmt_nest_state        .nest_data           .allocated * (lua_Integer) lmt_nest_state        .nest_data           .itemsize + lmt_nest_state        .nest_data           .extra
93        + (lua_Integer) lmt_input_state       .parameter_stack_data.allocated * (lua_Integer) lmt_input_state       .parameter_stack_data.itemsize + lmt_input_state       .parameter_stack_data.extra
94        + (lua_Integer) lmt_save_state        .save_stack_data     .allocated * (lua_Integer) lmt_save_state        .save_stack_data     .itemsize + lmt_save_state        .save_stack_data     .extra
95        + (lua_Integer) lmt_hash_state        .hash_data           .allocated * (lua_Integer) lmt_hash_state        .hash_data           .itemsize + lmt_hash_state        .hash_data           .extra
96        + (lua_Integer) lmt_fileio_state      .io_buffer_data      .allocated * (lua_Integer) lmt_fileio_state      .io_buffer_data      .itemsize + lmt_fileio_state      .io_buffer_data      .extra
97        + (lua_Integer) lmt_font_state        .font_data           .allocated * (lua_Integer) lmt_font_state        .font_data           .itemsize + lmt_font_state        .font_data           .extra
98        + (lua_Integer) lmt_language_state    .language_data       .allocated * (lua_Integer) lmt_language_state    .language_data       .itemsize + lmt_language_state    .language_data       .extra
99        + (lua_Integer) lmt_mark_state        .mark_data           .allocated * (lua_Integer) lmt_mark_state        .mark_data           .itemsize + lmt_mark_state        .mark_data           .extra
100        + (lua_Integer) lmt_insert_state      .insert_data         .allocated * (lua_Integer) lmt_insert_state      .insert_data         .itemsize + lmt_insert_state      .insert_data         .extra
101        + (lua_Integer) lmt_sparse_state      .sparse_data         .allocated * (lua_Integer) lmt_sparse_state      .sparse_data         .itemsize + lmt_sparse_state      .sparse_data         .extra
102        + (lua_Integer) lmt_mvl_state         .mvl_data            .allocated * (lua_Integer) lmt_mvl_state         .mvl_data            .itemsize + lmt_mvl_state         .mvl_data            .extra
103    ;
104    lua_createtable(L, 0, 4);
105    lua_set_integer_by_key(L, "approximate", (int) approximate);
106    return 1;
107}
108
109static int statslib_luastate(lua_State *L)
110{
111    lua_createtable(L, 0, 6);
112    lua_set_integer_by_key(L, "functionsize",   lmt_lua_state.function_table_size);
113    lua_set_integer_by_key(L, "propertiessize", lmt_node_memory_state.node_properties_table_size);
114    lua_set_integer_by_key(L, "bytecodes",      lmt_lua_state.bytecode_max);
115    lua_set_integer_by_key(L, "bytecodebytes",  lmt_lua_state.bytecode_bytes);
116    lua_set_integer_by_key(L, "statebytes",     lmt_lua_state.used_bytes);
117    lua_set_integer_by_key(L, "statebytesmax",  lmt_lua_state.used_bytes_max);
118    return 1;
119}
120
121static int statslib_errorstate(lua_State* L)
122{
123    lua_createtable(L, 0, 3);
124    lua_set_string_by_key(L, "error",         lmt_error_state.last_error);
125    lua_set_string_by_key(L, "errorcontext",  lmt_error_state.last_error_context);
126    lua_set_string_by_key(L, "luaerror",      lmt_error_state.last_lua_error);
127    return 1;
128}
129
130static int statslib_warningstate(lua_State* L)
131{
132    lua_createtable(L, 0, 2);
133    lua_set_string_by_key(L, "warningtag",    lmt_error_state.last_warning_tag);
134    lua_set_string_by_key(L, "warning",       lmt_error_state.last_warning);
135    return 1;
136}
137
138static int statslib_aux_stats_name_to_id(const char *name, statistic_entry stats[])
139{
140    for (int i = 0; stats[i].name; i++) {
141        if (strcmp (stats[i].name, name) == 0) {
142            return i;
143        }
144    }
145    return -1;
146}
147
148static int statslib_aux_limits_state(lua_State* L, limits_data *data)
149{
150    lua_createtable(L, 0, 4);
151    lua_set_integer_by_key(L, "set", data->size);
152    lua_set_integer_by_key(L, "min", data->minimum);
153    lua_set_integer_by_key(L, "max", data->maximum);
154    lua_set_integer_by_key(L, "top", data->top);
155    return 1;
156}
157
158static int statslib_aux_memory_state(lua_State* L, memory_data *data)
159{
160    lua_createtable(L, 0, 11);
161    lua_set_integer_by_key(L, "set", data->size); /*tex Can |memory_data_unset|. */
162    lua_set_integer_by_key(L, "min", data->minimum);
163    lua_set_integer_by_key(L, "max", data->maximum);
164    lua_set_integer_by_key(L, "mem", data->allocated);
165    lua_set_integer_by_key(L, "ext", data->extra);
166    lua_set_integer_by_key(L, "itm", data->itemsize);
167    lua_set_integer_by_key(L, "all", data->allocated * data->itemsize + data->extra);
168    lua_set_integer_by_key(L, "top", data->top - data->offset);
169    lua_set_integer_by_key(L, "ptr", data->ptr - data->offset);
170    lua_set_integer_by_key(L, "ini", data->initial); /*tex Can |memory_data_unset|. */
171    lua_set_integer_by_key(L, "stp", data->step);
172 // lua_set_integer_by_key(L, "off", data->offset);
173    return 1;
174}
175
176static int statslib_errorlinestate    (lua_State* L) { return statslib_aux_limits_state(L, &lmt_error_state       .line_limits);  }
177static int statslib_halferrorlinestate(lua_State* L) { return statslib_aux_limits_state(L, &lmt_error_state       .half_line_limits); }
178static int statslib_expandstate       (lua_State* L) { return statslib_aux_limits_state(L, &lmt_expand_state      .limits); }
179static int statslib_stringstate       (lua_State* L) { return statslib_aux_memory_state(L, &lmt_string_pool_state .string_pool_data); }
180static int statslib_poolstate         (lua_State* L) { return statslib_aux_memory_state(L, &lmt_string_pool_state .string_body_data); }
181static int statslib_lookupstate       (lua_State* L) { return statslib_aux_memory_state(L, &lmt_hash_state        .eqtb_data); }
182static int statslib_hashstate         (lua_State* L) { return statslib_aux_memory_state(L, &lmt_hash_state        .hash_data); }
183static int statslib_nodestate         (lua_State* L) { return statslib_aux_memory_state(L, &lmt_node_memory_state .nodes_data); }
184static int statslib_tokenstate        (lua_State* L) { return statslib_aux_memory_state(L, &lmt_token_memory_state.tokens_data); }
185static int statslib_inputstate        (lua_State* L) { return statslib_aux_memory_state(L, &lmt_input_state       .input_stack_data); }
186static int statslib_filestate         (lua_State* L) { return statslib_aux_memory_state(L, &lmt_input_state       .in_stack_data); }
187static int statslib_parameterstate    (lua_State* L) { return statslib_aux_memory_state(L, &lmt_input_state       .parameter_stack_data); }
188static int statslib_neststate         (lua_State* L) { return statslib_aux_memory_state(L, &lmt_nest_state        .nest_data); }
189static int statslib_savestate         (lua_State* L) { return statslib_aux_memory_state(L, &lmt_save_state        .save_stack_data); }
190static int statslib_bufferstate       (lua_State* L) { return statslib_aux_memory_state(L, &lmt_fileio_state      .io_buffer_data); }
191static int statslib_fontstate         (lua_State* L) { return statslib_aux_memory_state(L, &lmt_font_state        .font_data); }
192static int statslib_languagestate     (lua_State* L) { return statslib_aux_memory_state(L, &lmt_language_state    .language_data); }
193static int statslib_markstate         (lua_State* L) { return statslib_aux_memory_state(L, &lmt_mark_state        .mark_data); }
194static int statslib_insertstate       (lua_State* L) { return statslib_aux_memory_state(L, &lmt_insert_state      .insert_data); }
195static int statslib_sparsestate       (lua_State* L) { return statslib_aux_memory_state(L, &lmt_sparse_state      .sparse_data); }
196static int statslib_mvlstate          (lua_State* L) { return statslib_aux_memory_state(L, &lmt_mvl_state         .mvl_data); }
197
198static int statslib_readstate(lua_State *L)
199{
200    lua_createtable(L, 0, 4);
201    lua_set_string_by_key (L, "filename",       tex_current_input_file_name());
202    lua_set_integer_by_key(L, "iocode",         lmt_input_state.cur_input.name > io_file_input_code ? io_file_input_code : lmt_input_state.cur_input.name);
203    lua_set_integer_by_key(L, "linenumber",     lmt_input_state.input_line);
204    lua_set_integer_by_key(L, "skiplinenumber", lmt_condition_state.skip_line);
205    return 1;
206}
207
208static int statslib_enginestate(lua_State *L)
209{
210    lua_createtable(L, 0, 15);
211    lua_set_string_by_key (L, "logfilename",     lmt_fileio_state.log_name);
212    lua_set_string_by_key (L, "banner",          lmt_engine_state.luatex_banner);
213    lua_set_number_by_key (L, "version",         lmt_version_state.luatexversion);
214    lua_set_string_by_key (L, "luatex_engine",   lmt_engine_state.engine_name);
215    lua_set_integer_by_key(L, "luatex_version",  lmt_version_state.version);
216    lua_set_integer_by_key(L, "luatex_revision", lmt_version_state.revision);
217    lua_set_integer_by_key(L, "luatex_release",  lmt_version_state.release);
218    lua_set_string_by_key(L,  "luatex_verbose",  lmt_version_state.verbose);
219    lua_set_integer_by_key(L, "development_id",  lmt_version_state.developmentid);
220    lua_set_string_by_key (L, "copyright",       lmt_version_state.copyright);
221    lua_set_integer_by_key(L, "format_id",       lmt_version_state.formatid);
222    lua_set_integer_by_key(L, "tex_hash_size",   hash_size);
223    lua_set_string_by_key (L, "used_compiler",   lmt_version_state.compiler);
224 // lua_set_string_by_key (L, "used_libc",       lmt_version_state.libc);
225    lua_set_integer_by_key(L, "run_state",       lmt_main_state.run_state);
226    lua_set_boolean_by_key(L, "permit_loadlib",  lmt_engine_state.permit_loadlib);
227    return 1;
228}
229
230static int statslib_aux_getstat_indeed(lua_State *L, statistic_entry stats[], int i)
231{
232    switch (stats[i].type) {
233        case 'S':
234            /* string function pointer, no copy */
235            {
236                const char *st = (*(constfunc) stats[i].value)();
237                lua_pushstring(L, st);
238                /* No freeing here! */
239                break;
240            }
241     // case 's':
242     //     /* string function pointer, copy */
243     //     {
244     //         char *st = (*(charfunc) stats[i].value)();
245     //         lua_pushstring(L, st);
246     //         lmt_memory_free(st);
247     //         break;
248     //     }
249     // case 'N':
250     //     /* number function pointer */
251     //     lua_pushnumber(L, (*(numfunc) stats[i].value)());
252     //     break;
253     // case 'G':
254     //     /* integer function pointer */
255     //     lua_pushinteger(L, (*(intfunc) stats[i].value)());
256     //     break;
257        case 'd':
258            /* double pointer */
259            lua_pushnumber(L, *(double *) (stats[i].value));
260            break;
261        case 'g':
262            /* integer pointer */
263            lua_pushinteger(L, *(int *) (stats[i].value));
264            break;
265        case 'c':
266            /* string pointer */
267            lua_pushstring(L, *(const char **) (stats[i].value));
268            break;
269     // case 'n': /* node */
270     //     /* node pointer */
271     //     if (*(halfword*) (stats[i].value)) {
272     //         lmt_push_node_fast(L, *(halfword *) (stats[i].value));
273     //     } else {
274     //         lua_pushnil(L);
275     //     }
276     //     break;
277        case 'b':
278            /* boolean integer pointer */
279            lua_pushboolean(L, *(int *) (stats[i].value));
280            break;
281        case 'f':
282            (*(luafunc) stats[i].value)(L);
283            break;
284        default:
285            /* nothing reasonable */
286            lua_pushnil(L);
287            break;
288    }
289    return 1;
290}
291
292static int statslib_aux_getstats_indeed(lua_State *L, statistic_entry stats[])
293{
294    if (lua_type(L, -1) == LUA_TSTRING) {
295        const char *st = lua_tostring(L, -1);
296        int i = statslib_aux_stats_name_to_id(st, stats);
297        if (i >= 0) {
298            return statslib_aux_getstat_indeed(L, stats, i);
299        }
300    }
301    return 0;
302}
303
304static int statslib_getconstants(lua_State *L)
305{
306    lua_createtable(L, 0, 100);
307
308    lua_set_integer_by_key(L, "no_catcode_table",               no_catcode_table_preset);
309    lua_set_integer_by_key(L, "default_catcode_table",          default_catcode_table_preset);
310                                                                
311    lua_set_cardinal_by_key(L,"max_cardinal",                   max_cardinal);
312    lua_set_cardinal_by_key(L,"min_cardinal",                   min_cardinal);
313    lua_set_integer_by_key(L, "max_integer",                    max_integer);
314    lua_set_integer_by_key(L, "min_integer",                    min_integer);
315    lua_set_integer_by_key(L, "max_dimen",                      max_dimension); /* obsolete */
316    lua_set_integer_by_key(L, "min_dimen",                      min_dimension); /* obsolete */
317    lua_set_integer_by_key(L, "max_dimension",                  max_dimension);
318    lua_set_integer_by_key(L, "min_dimension",                  min_dimension);
319    lua_set_integer_by_key(L, "min_data_value",                 min_data_value);
320    lua_set_integer_by_key(L, "max_data_value",                 max_data_value);
321    lua_set_integer_by_key(L, "max_half_value",                 max_half_value);
322                                                                
323    lua_set_integer_by_key(L, "max_limited_scale",              max_limited_scale);
324    lua_set_integer_by_key(L, "max_math_style_scale",           max_math_style_scale);
325                                                                
326    lua_set_integer_by_key(L, "one_bp",                         one_bp);
327                                                                
328    lua_set_integer_by_key(L, "infinity",                       max_infinity);
329    lua_set_integer_by_key(L, "min_infinity",                   min_infinity);
330    lua_set_integer_by_key(L, "awful_bad",                      awful_bad);
331    lua_set_integer_by_key(L, "infinite_bad",                   infinite_bad);
332    lua_set_integer_by_key(L, "infinite_penalty",               infinite_penalty);
333    lua_set_integer_by_key(L, "eject_penalty",                  eject_penalty);
334    lua_set_integer_by_key(L, "deplorable",                     deplorable);
335    lua_set_integer_by_key(L, "large_width_excess",             large_width_excess);
336    lua_set_integer_by_key(L, "small_stretchability",           small_stretchability);
337    lua_set_integer_by_key(L, "decent_criterion",               decent_criterion);
338    lua_set_integer_by_key(L, "loose_criterion",                loose_criterion);
339                                                                
340    lua_set_integer_by_key(L, "default_rule",                   default_rule);
341    lua_set_integer_by_key(L, "ignore_depth",                   ignore_depth);
342                                                                
343    lua_set_integer_by_key(L, "min_quarterword",                min_quarterword);
344    lua_set_integer_by_key(L, "max_quarterword",                max_quarterword);
345                                                                
346    lua_set_integer_by_key(L, "min_halfword",                   min_halfword);
347    lua_set_integer_by_key(L, "max_halfword",                   max_halfword);
348                                                                
349    lua_set_integer_by_key(L, "null_flag",                      null_flag);
350    lua_set_integer_by_key(L, "zero_glue",                      zero_glue);
351    lua_set_integer_by_key(L, "unity",                          unity);
352    lua_set_integer_by_key(L, "two",                            two);
353    lua_set_integer_by_key(L, "null",                           null);
354    lua_set_integer_by_key(L, "null_font",                      null_font);
355                                                                
356    lua_set_integer_by_key(L, "unused_attribute_value",         unused_attribute_value);
357    lua_set_integer_by_key(L, "unused_state_value",             unused_state_value);
358    lua_set_integer_by_key(L, "unused_script_value",            unused_script_value);
359                                                                
360    lua_set_integer_by_key(L, "preset_rule_thickness",          preset_rule_thickness);
361    lua_set_integer_by_key(L, "running_rule",                   null_flag);
362                                                                
363    lua_set_integer_by_key(L, "min_space_factor",               min_space_factor);
364    lua_set_integer_by_key(L, "max_space_factor",               max_space_factor);
365    lua_set_integer_by_key(L, "min_scale_factor",               min_scale_factor);
366    lua_set_integer_by_key(L, "max_scale_factor",               max_scale_factor);
367    lua_set_integer_by_key(L, "default_space_factor",           default_space_factor);
368    lua_set_integer_by_key(L, "special_space_factor",           special_space_factor);
369    lua_set_integer_by_key(L, "default_tolerance",              default_tolerance);
370    lua_set_integer_by_key(L, "default_hangafter",              default_hangafter);
371    lua_set_integer_by_key(L, "default_deadcycles",             default_deadcycles);
372    lua_set_integer_by_key(L, "default_pre_display_gap",        default_pre_display_gap);
373    lua_set_integer_by_key(L, "default_eqno_gap_step",          default_eqno_gap_step);
374                                                                
375    lua_set_integer_by_key(L, "default_output_box",             default_output_box);
376                                                                
377    lua_set_integer_by_key(L, "max_n_of_fonts",                 max_n_of_fonts);
378    lua_set_integer_by_key(L, "max_n_of_bytecodes",             max_n_of_bytecodes);
379    lua_set_integer_by_key(L, "max_n_of_math_families",         max_n_of_math_families);
380    lua_set_integer_by_key(L, "max_n_of_languages",             max_n_of_languages);
381    lua_set_integer_by_key(L, "max_n_of_catcode_tables",        max_n_of_catcode_tables);
382 /* lua_set_integer_by_key(L, "max_n_of_hjcode_tables",         max_n_of_hjcode_tables); */ /* meaningless */
383    lua_set_integer_by_key(L, "max_n_of_marks",                 max_n_of_marks);
384                                                                
385    lua_set_integer_by_key(L, "max_character_code",             max_character_code);
386    lua_set_integer_by_key(L, "max_mark_index",                 max_mark_index);
387                                                                
388    lua_set_integer_by_key(L, "max_toks_register_index",        max_toks_register_index);
389    lua_set_integer_by_key(L, "max_box_register_index",         max_box_register_index);
390    lua_set_integer_by_key(L, "max_int_register_index",         max_integer_register_index);   /* obsolete */
391    lua_set_integer_by_key(L, "max_integer_register_index",     max_integer_register_index);
392    lua_set_integer_by_key(L, "max_float_register_index",       max_posit_register_index);
393    lua_set_integer_by_key(L, "max_dimension_register_index",   max_dimension_register_index);
394    lua_set_integer_by_key(L, "max_dimen_register_index",       max_dimension_register_index); /* obsolete */
395    lua_set_integer_by_key(L, "max_attribute_register_index",   max_attribute_register_index);
396    lua_set_integer_by_key(L, "max_glue_register_index",        max_glue_register_index);
397    lua_set_integer_by_key(L, "max_muglue_register_index",      max_muglue_register_index);
398                                                                
399    lua_set_integer_by_key(L, "max_bytecode_index",             max_bytecode_index);
400    lua_set_integer_by_key(L, "max_math_family_index",          max_math_family_index);
401    lua_set_integer_by_key(L, "max_math_class_code",            max_math_class_code);
402    lua_set_integer_by_key(L, "max_function_reference",         max_function_reference);
403                                                                
404    lua_set_integer_by_key(L, "min_mvl_index",                  min_mvl_index);
405    lua_set_integer_by_key(L, "max_mvl_index",                  max_mvl_index);
406
407    lua_set_integer_by_key(L, "max_newline_character",          max_newline_character);
408    lua_set_integer_by_key(L, "max_endline_character",          max_endline_character);
409                                                                
410    lua_set_integer_by_key(L, "max_size_of_word",               max_size_of_word);
411                                                                
412    lua_set_integer_by_key(L, "tex_hash_size",                  hash_size);
413    lua_set_integer_by_key(L, "tex_hash_prime",                 hash_prime);
414    lua_set_integer_by_key(L, "tex_eqtb_size",                  eqtb_size);
415                                                                
416    lua_set_integer_by_key(L, "math_first_user_class",          math_first_user_class);
417    lua_set_integer_by_key(L, "math_last_user_class",           math_last_user_class);
418    lua_set_integer_by_key(L, "math_all_class",                 math_all_class);
419    lua_set_integer_by_key(L, "math_begin_class",               math_begin_class);
420    lua_set_integer_by_key(L, "math_end_class",                 math_end_class);
421
422    lua_set_integer_by_key(L, "unused_math_family",             unused_math_family);
423    lua_set_integer_by_key(L, "unused_math_style",              unused_math_style);
424    lua_set_integer_by_key(L, "assumed_math_control",           assumed_math_control);
425                                                                
426    lua_set_integer_by_key(L, "undefined_math_parameter",       undefined_math_parameter);
427                                                                
428    lua_set_integer_by_key(L, "max_calculated_badness",         max_calculated_badness);
429                                                                
430    lua_set_integer_by_key(L, "max_math_scaling_factor",        max_math_scaling_factor);   
431    lua_set_integer_by_key(L, "math_default_penalty",           math_default_penalty);   
432
433    lua_set_integer_by_key(L, "max_font_adjust_step",           max_font_adjust_step);            
434    lua_set_integer_by_key(L, "max_font_adjust_stretch_factor", max_font_adjust_stretch_factor);
435    lua_set_integer_by_key(L, "max_font_adjust_shrink_factor",  max_font_adjust_shrink_factor);
436
437    lua_set_integer_by_key(L, "max_twin_length",                max_twin_length); 
438
439    lua_set_integer_by_key(L, "default_character_control",      default_character_control); 
440
441    lua_set_integer_by_key(L, "min_n_of_fitness_values",        min_n_of_fitness_values);
442    lua_set_integer_by_key(L, "max_n_of_fitness_values",        max_n_of_fitness_values);
443    lua_set_integer_by_key(L, "all_fitness_values",             all_fitness_values);
444
445    return 1;
446}
447
448static struct statistic_entry statslib_entries[] = {
449
450    /*tex But these are now collected in tables: */
451
452    { .name = "enginestate",        .value = &statslib_enginestate,        .type = 'f' },
453    { .name = "errorlinestate",     .value = &statslib_errorlinestate,     .type = 'f' },
454    { .name = "halferrorlinestate", .value = &statslib_halferrorlinestate, .type = 'f' },
455    { .name = "expandstate",        .value = &statslib_expandstate,        .type = 'f' },
456    { .name = "stringstate",        .value = &statslib_stringstate,        .type = 'f' },
457    { .name = "poolstate",          .value = &statslib_poolstate,          .type = 'f' },
458    { .name = "hashstate",          .value = &statslib_hashstate,          .type = 'f' },
459    { .name = "lookupstate",        .value = &statslib_lookupstate,        .type = 'f' },
460    { .name = "nodestate",          .value = &statslib_nodestate,          .type = 'f' },
461    { .name = "tokenstate",         .value = &statslib_tokenstate,         .type = 'f' },
462    { .name = "inputstate",         .value = &statslib_inputstate,         .type = 'f' },
463    { .name = "filestate",          .value = &statslib_filestate,          .type = 'f' },
464    { .name = "parameterstate",     .value = &statslib_parameterstate,     .type = 'f' },
465    { .name = "neststate",          .value = &statslib_neststate,          .type = 'f' },
466    { .name = "savestate",          .value = &statslib_savestate,          .type = 'f' },
467    { .name = "bufferstate",        .value = &statslib_bufferstate,        .type = 'f' },
468    { .name = "texstate",           .value = &statslib_texstate,           .type = 'f' },
469    { .name = "luastate",           .value = &statslib_luastate,           .type = 'f' },
470    { .name = "callbackstate",      .value = &statslib_callbackstate,      .type = 'f' },
471    { .name = "linebreakstate",     .value = &statslib_linebreakstate,     .type = 'f' },
472    { .name = "balancestate",       .value = &statslib_balancestate,       .type = 'f' },
473    { .name = "hyphenationstate",   .value = &statslib_hyphenationstate,   .type = 'f' },
474    { .name = "errorstate",         .value = &statslib_errorstate,         .type = 'f' },
475    { .name = "warningstate",       .value = &statslib_warningstate,       .type = 'f' },
476    { .name = "readstate",          .value = &statslib_readstate,          .type = 'f' },
477    { .name = "fontstate",          .value = &statslib_fontstate,          .type = 'f' },
478    { .name = "languagestate",      .value = &statslib_languagestate,      .type = 'f' },
479    { .name = "markstate",          .value = &statslib_markstate,          .type = 'f' },
480    { .name = "insertstate",        .value = &statslib_insertstate,        .type = 'f' },
481    { .name = "sparsestate",        .value = &statslib_sparsestate,        .type = 'f' },
482    { .name = "mvlstate",           .value = &statslib_mvlstate,           .type = 'f' },
483
484    /*tex Lua keys: */
485
486    { .name = "lua_version_major",   .value = (void *) &lmt_version_state.luaversionmajor,   .type = 'g' },
487    { .name = "lua_version_minor",   .value = (void *) &lmt_version_state.luaversionminor,   .type = 'g' },
488    { .name = "lua_version_release", .value = (void *) &lmt_version_state.luaversionrelease, .type = 'g' },
489    { .name = "lua_version",         .value = (void *) &lmt_version_state.luaversion,        .type = 'd' },
490    { .name = "lua_format",          .value = (void *) &lmt_version_state.luaformat,         .type = 'g' },
491
492    /*tex We keep these as direct accessible keys: */
493
494    { .name = "filename",           .value = (void *) &tex_current_input_file_name,     .type = 'S' },
495    { .name = "logfilename",        .value = (void *) &lmt_fileio_state.log_name,       .type = 'c' },
496    { .name = "banner",             .value = (void *) &lmt_engine_state.luatex_banner,  .type = 'c' },
497    { .name = "copyright",          .value = (void *) &lmt_version_state.copyright,     .type = 'c' },
498    /* */
499    { .name = "majorversion",       .value = (void *) &lmt_version_state.majorversion,  .type = 'g' },
500    { .name = "minorversion",       .value = (void *) &lmt_version_state.minorversion,  .type = 'g' },
501    { .name = "release",            .value = (void *) &lmt_version_state.release,       .type = 'g' },
502    { .name = "development_id",     .value = (void *) &lmt_version_state.developmentid, .type = 'g' },
503    { .name = "format_id",          .value = (void *) &lmt_version_state.formatid,      .type = 'g' },
504    /* */
505    { .name = "version",            .value = (void *) &lmt_version_state.luatexversion, .type = 'd' },
506    /* */
507    { .name = "luatex_engine",      .value = (void *) &lmt_engine_state.engine_name,    .type = 'c' },
508    { .name = "luatex_version",     .value = (void *) &lmt_version_state.version,       .type = 'g' },
509    { .name = "luatex_revision",    .value = (void *) &lmt_version_state.revision,      .type = 'g' },
510    { .name = "luatex_release",     .value = (void *) &lmt_version_state.release,       .type = 'g' },
511    { .name = "luatex_verbose",     .value = (void *) &lmt_version_state.verbose,       .type = 'c' },
512    /* */
513    { .name = "used_compiler",      .value = (void *) &lmt_version_state.compiler,      .type = 'c' },
514    { .name = "run_state",          .value = (void *) &lmt_main_state.run_state,        .type = 'g' },
515    { .name = "permit_loadlib",     .value = (void *) &lmt_engine_state.permit_loadlib, .type = 'b' },
516
517    { .name = NULL,                 .value = NULL,                                      .type = 0   },
518};
519
520static struct statistic_entry statslib_entries_only[] = {
521    { .name = "filename",            .value = (void *) &tex_current_input_file_name,         .type = 'S' },
522    { .name = "banner",              .value = (void *) &lmt_engine_state.luatex_banner,      .type = 'c' },
523    { .name = "copyright",           .value = (void *) &lmt_version_state.copyright,         .type = 'c' },
524    /* */                                                                                    
525    { .name = "majorversion",        .value = (void *) &lmt_version_state.majorversion,      .type = 'g' },
526    { .name = "minorversion",        .value = (void *) &lmt_version_state.minorversion,      .type = 'g' },
527    { .name = "release",             .value = (void *) &lmt_version_state.release,           .type = 'g' },
528    { .name = "development_id",      .value = (void *) &lmt_version_state.developmentid,     .type = 'g' },
529    { .name = "format_id",           .value = (void *) &lmt_version_state.formatid,          .type = 'g' },
530    /* */                                                                                    
531    { .name = "version",             .value = (void *) &lmt_version_state.luatexversion,     .type = 'd' },
532    /* */                                                                                    
533    { .name = "luatex_engine",       .value = (void *) &lmt_engine_state.engine_name,        .type = 'c' },
534    { .name = "luatex_version",      .value = (void *) &lmt_version_state.version,           .type = 'g' },
535    { .name = "luatex_revision",     .value = (void *) &lmt_version_state.revision,          .type = 'g' },
536    { .name = "luatex_release",      .value = (void *) &lmt_version_state.release,           .type = 'g' },
537    { .name = "luatex_verbose",      .value = (void *) &lmt_version_state.verbose,           .type = 'c' },
538    /* */                                                                                    
539    { .name = "used_compiler",       .value = (void *) &lmt_version_state.compiler,          .type = 'c' },
540
541    { .name = "lua_version_major",   .value = (void *) &lmt_version_state.luaversionmajor,   .type = 'g' },
542    { .name = "lua_version_minor",   .value = (void *) &lmt_version_state.luaversionminor,   .type = 'g' },
543    { .name = "lua_version_release", .value = (void *) &lmt_version_state.luaversionrelease, .type = 'g' },
544    { .name = "lua_version",         .value = (void *) &lmt_version_state.luaversion,        .type = 'd' },
545    { .name = "lua_format",          .value = (void *) &lmt_version_state.luaformat,         .type = 'g' },
546
547    { .name = NULL,                  .value = NULL,                                          .type = 0   },
548};
549
550static int statslib_aux_getstats(lua_State *L)
551{
552    return statslib_aux_getstats_indeed(L, statslib_entries);
553}
554
555static int statslib_aux_getstats_only(lua_State *L)
556{
557    return statslib_aux_getstats_indeed(L, statslib_entries_only);
558}
559
560static int statslib_aux_statslist(lua_State *L, statistic_entry stats[])
561{
562    lua_createtable(L, 0, 60);
563    for (int i = 0; stats[i].name; i++) {
564        lua_pushstring(L, stats[i].name);
565        statslib_aux_getstat_indeed(L, stats, i);
566        lua_rawset(L, -3);
567    }
568    return 1;
569}
570
571static int statslib_statslist(lua_State *L)
572{
573    return statslib_aux_statslist(L, statslib_entries);
574}
575
576static int statslib_statslist_only(lua_State *L)
577{
578    return statslib_aux_statslist(L, statslib_entries_only);
579}
580
581static int statslib_resetmessages(lua_State *L)
582{
583    (void) (L);
584    lmt_memory_free(lmt_error_state.last_warning);
585    lmt_memory_free(lmt_error_state.last_warning_tag);
586    lmt_memory_free(lmt_error_state.last_error);
587    lmt_memory_free(lmt_error_state.last_lua_error);
588    lmt_error_state.last_warning = NULL;
589    lmt_error_state.last_warning_tag = NULL;
590    lmt_error_state.last_error = NULL;
591    lmt_error_state.last_lua_error = NULL;
592    return 0;
593}
594
595static const struct luaL_Reg statslib_function_list[] = {
596    { "list",                  statslib_statslist          }, /* for old times sake */
597    { "getconstants",          statslib_getconstants       },
598    { "resetmessages",         statslib_resetmessages      },
599
600    { "gettexstate",           statslib_texstate           },
601    { "getluastate",           statslib_luastate           },
602    { "geterrorstate",         statslib_errorstate         },
603    { "getwarningstate",       statslib_warningstate       },
604    { "getreadstate",          statslib_readstate          },
605    { "getcallbackstate",      statslib_callbackstate      },
606    { "getlinebreakstate",     statslib_linebreakstate     },
607    { "getbalancestate",       statslib_balancestate       },
608    { "gethyphenationstate",   statslib_hyphenationstate   },
609
610    { "geterrorlinestate",     statslib_errorlinestate     },
611    { "gethalferrorlinestate", statslib_halferrorlinestate },
612    { "getexpandstate",        statslib_expandstate        },
613
614    { "getstringstate",        statslib_stringstate        },
615    { "getpoolstate",          statslib_poolstate          },
616    { "gethashstate",          statslib_hashstate          },
617    { "getlookupstate",        statslib_lookupstate        },
618    { "getnodestate",          statslib_nodestate          },
619    { "gettokenstate",         statslib_tokenstate         },
620    { "getinputstate",         statslib_inputstate         },
621    { "getfilestate",          statslib_filestate          },
622    { "getparameterstate",     statslib_parameterstate     },
623    { "getneststate",          statslib_neststate          },
624    { "getsavestate",          statslib_savestate          },
625    { "getbufferstate",        statslib_bufferstate        },
626    { "getfontstate",          statslib_fontstate          },
627    { "getlanguagestate",      statslib_languagestate      },
628    { "getmarkstate",          statslib_markstate          },
629    { "getinsertstate",        statslib_insertstate        },
630    { "getsparsestate",        statslib_sparsestate        },
631    { "getmvlstate",           statslib_mvlstate           },
632
633    { NULL,                    NULL                        },
634};
635
636static const struct luaL_Reg statslib_function_list_only[] = {
637    { "list", statslib_statslist_only },
638    { NULL,   NULL                    },
639};
640
641int luaopen_status(lua_State *L)
642{
643    lua_newtable(L);
644    luaL_setfuncs(L, lmt_engine_state.lua_only ? statslib_function_list_only : statslib_function_list, 0);
645    luaL_newmetatable(L, STATS_METATABLE);
646    lua_pushstring(L, "__index");
647    lua_pushcfunction(L, lmt_engine_state.lua_only ? statslib_aux_getstats_only : statslib_aux_getstats);
648    lua_settable(L, -3);
649    lua_setmetatable(L, -2); /*tex meta to itself */
650    return 1;
651}
652