1
4
5
25
26# include "luametatex.h"
27
28
33
34# define TEX_METATABLE_ATTRIBUTE "tex.attribute"
35# define TEX_METATABLE_SKIP "tex.skip"
36# define TEX_METATABLE_GLUE "tex.glue"
37# define TEX_METATABLE_MUSKIP "tex.muskip"
38# define TEX_METATABLE_MUGLUE "tex.muglue"
39# define TEX_METATABLE_DIMEN "tex.dimen"
40# define TEX_METATABLE_FLOAT "tex.float"
41# define TEX_METATABLE_COUNT "tex.count"
42# define TEX_METATABLE_TOKS "tex.toks"
43# define TEX_METATABLE_BOX "tex.box"
44# define TEX_METATABLE_SFCODE "tex.sfcode"
45# define TEX_METATABLE_LCCODE "tex.lccode"
46# define TEX_METATABLE_UCCODE "tex.uccode"
47# define TEX_METATABLE_HCCODE "tex.hccode"
48# define TEX_METATABLE_HMCODE "tex.hmcode"
49# define TEX_METATABLE_AMCODE "tex.amcode"
50# define TEX_METATABLE_CATCODE "tex.catcode"
51# define TEX_METATABLE_MATHCODE "tex.mathcode"
52# define TEX_METATABLE_DELCODE "tex.delcode"
53# define TEX_METATABLE_LISTS "tex.lists"
54# define TEX_METATABLE_NEST "tex.nest"
55
56# define TEX_METATABLE_TEX "tex.tex"
57
58# define TEX_NEST_INSTANCE "tex.nest.instance"
59
60
61
62static void texlib_aux_show_box_index_error(lua_State *L)
63{
64 luaL_error(L, "invalid index passed, range 0.." LMT_TOSTRING(max_box_register_index) " or name expected");
65}
66
67static void texlib_aux_show_character_error(lua_State *L, int i)
68{
69 luaL_error(L, "invalid character value %d passed, range 0.." LMT_TOSTRING(max_character_code), i);
70}
71
72static void texlib_aux_show_catcode_error(lua_State *L, int i)
73{
74 luaL_error(L, "invalid catcode %d passed, range 0.." LMT_TOSTRING(max_category_code), i);
75}
76
77static void texlib_aux_show_family_error(lua_State *L, int i)
78{
79 luaL_error(L, "invalid family %d passed, range 0.." LMT_TOSTRING(max_math_family_index), i);
80}
81
82static void texlib_aux_show_class_error(lua_State *L, int i)
83{
84 luaL_error(L, "invalid class %d passed, range 0.." LMT_TOSTRING(max_math_class_code), i);
85}
86
87static void texlib_aux_show_half_error(lua_State *L, int i)
88{
89 luaL_error(L, "invalid value %d passed, range 0.." LMT_TOSTRING(max_half_value), i);
90}
91
92
130
131typedef enum line_modes {
132 full_line_mode = 0,
133 partial_line_mode = 1,
134} line_modes;
135
136# define PACKED_SIZE 8
137# define INITIAL_SIZE 32
138# define MAX_ROPE_CACHE 5000
139
140typedef union spindle_data {
141 unsigned char c[PACKED_SIZE];
142 halfword h;
143 char *t;
144} spindle_data;
145
146typedef struct spindle_rope {
147
148 void *next;
149 union {
150 unsigned int tsize;
151 halfword tail;
152 };
153 unsigned char kind;
154 unsigned char partial;
155 short cattable;
156 spindle_data data;
157
158
159} spindle_rope;
160
161typedef struct spindle {
162 spindle_rope *head;
163 spindle_rope *tail;
164 int complete;
165
166 int padding;
167} spindle;
168
169typedef struct spindle_state_info {
170 int spindle_size;
171 int spindle_index;
172 spindle *spindles;
173 spindle_rope *rope_cache;
174 int rope_count;
175
176 int padding;
177} spindle_state_info ;
178
179static spindle_state_info lmt_spindle_state = {
180 .spindle_size = 0,
181 .spindle_index = 0,
182 .spindles = NULL,
183 .rope_cache = NULL,
184 .rope_count = 0,
185 .padding = 0
186};
187
188# define write_spindle lmt_spindle_state.spindles[lmt_spindle_state.spindle_index]
189# define read_spindle lmt_spindle_state.spindles[lmt_spindle_state.spindle_index - 1]
190
191inline static void texlib_aux_reset_spindle(int i)
192{
193 lmt_spindle_state.spindles[i].head = NULL;
194 lmt_spindle_state.spindles[i].tail = NULL;
195 lmt_spindle_state.spindles[i].complete = 0;
196}
197
198
204
205inline static spindle_rope *texlib_aux_new_rope(void)
206{
207 spindle_rope *rope;
208 if (lmt_spindle_state.rope_cache) {
209 rope = lmt_spindle_state.rope_cache;
210 lmt_spindle_state.rope_cache = rope->next;
211 } else {
212 rope = (spindle_rope *) lmt_memory_malloc(sizeof(spindle_rope));
213 ++lmt_spindle_state.rope_count;
214 if (rope) {
215 rope->next = NULL;
216 } else {
217 tex_overflow_error("spindle", sizeof(spindle_rope));
218 }
219 }
220 return rope;
221}
222
223inline static void texlib_aux_dispose_rope(spindle_rope *rope)
224{
225 if (rope) {
226 if (lmt_spindle_state.rope_count > MAX_ROPE_CACHE) {
227 lmt_memory_free(rope);
228 --lmt_spindle_state.rope_count;
229 } else {
230 rope->next = lmt_spindle_state.rope_cache;
231 lmt_spindle_state.rope_cache = rope;
232 }
233 }
234}
235
236static void texlib_aux_initialize(void)
237{
238 lmt_spindle_state.spindles = lmt_memory_malloc(INITIAL_SIZE * sizeof(spindle));
239 if (lmt_spindle_state.spindles) {
240 for (int i = 0; i < INITIAL_SIZE; i++) {
241 texlib_aux_reset_spindle(i);
242 }
243 lmt_spindle_state.spindle_index = 0;
244 lmt_spindle_state.spindle_size = INITIAL_SIZE;
245 } else {
246 tex_overflow_error("spindle", sizeof(spindle));
247 }
248}
249
250
253
254static int texlib_aux_store(lua_State *L, int i, int partial, int cattable, int append)
255{
256 size_t tsize = 0;
257 spindle_rope *rope = NULL;
258 unsigned char kind = unset_lua_input;
259 spindle_data data = { .h = 0 };
260 switch (lua_type(L, i)) {
261 case LUA_TNUMBER:
262 case LUA_TSTRING:
263 {
264 const char *sttemp = lua_tolstring(L, i, &tsize);
265 if (! partial) {
266 while (tsize > 0 && sttemp[tsize-1] == ' ') {
267 tsize--;
268 }
269 }
270 if (tsize > PACKED_SIZE) {
271 data.t = lmt_memory_malloc(tsize + 1);
272 kind = string_lua_input;
273 if (data.t) {
274 memcpy(data.t, sttemp, (tsize + 1));
275 break;
276 } else {
277 return 0;
278 }
279 } else {
280
284 (void) append;
285 if (append && write_spindle.tail && partial && partial == write_spindle.tail->partial) {
286 if (write_spindle.tail->kind == packed_lua_input && write_spindle.tail->cattable == cattable) {
287 size_t s = write_spindle.tail->tsize;
288 if (tsize + s <= PACKED_SIZE) {
289 for (unsigned i = 0; i < tsize; i++) {
290 write_spindle.tail->data.c[s++] = (unsigned char) sttemp[i];
291 }
292 write_spindle.tail->tsize += tsize;
293
294
295 return 1;
296 }
297 }
298 }
299 for (unsigned int i = 0; i < tsize; i++) {
300
301 data.c[i] = (unsigned char) sttemp[i];
302 }
303 kind = packed_lua_input;
304 }
305 }
306 break;
307 case LUA_TUSERDATA:
308 {
309 void *p = lua_touserdata(L, i);
310 if (p && lua_getmetatable(L, i)) {
311 lua_get_metatablelua(token_instance);
312 if (lua_rawequal(L, -1, -2)) {
313 halfword token = (*((lua_token *) p)).token;
314 if (token_link(token)) {
315
319 token = token_link(token);
320 if (token) {
321
325 halfword t = null;
326 kind = token_list_lua_input;
327 data.h = tex_copy_token_list(token, &t);
328 tsize = t;
329 } else {
330 lua_pop(L, 2);
331 return 0;
332 }
333 } else {
334
339 if (write_spindle.tail && write_spindle.tail->partial && partial == write_spindle.tail->partial) {
340 switch (write_spindle.tail->kind) {
341 case token_lua_input:
342
346 write_spindle.tail->kind = token_list_lua_input;
347 write_spindle.tail->data.h = tex_store_new_token(null, write_spindle.tail->data.h);
348 write_spindle.tail->tail = tex_store_new_token(write_spindle.tail->data.h, token_info(token));
349 break;
350 case token_list_lua_input:
351
355 write_spindle.tail->tail = tex_store_new_token(write_spindle.tail->tail, token_info(token));
356 break;
357 default:
358 goto SINGLE;
359 }
360 lmt_token_state.luacstrings++;
361 write_spindle.complete = 0;
362 lua_pop(L, 2);
363 return 1;
364 }
365
366 SINGLE:
367 kind = token_lua_input;
368 data.h = token_info(token);
369 }
370 lua_pop(L, 2);
371 } else {
372 lua_get_metatablelua(node_instance);
373 if (lua_rawequal(L, -1, -3)) {
374 kind = node_lua_input;
375 data.h = *((halfword *) p);
376 lua_pop(L, 3);
377 } else {
378 lua_pop(L, 3);
379 return 0;
380 }
381 }
382 } else {
383 return 0;
384 }
385 }
386 break;
387 default:
388 return 0;
389 }
390 lmt_token_state.luacstrings++;
391 rope = texlib_aux_new_rope();
392
393 rope->tsize = (unsigned) tsize;
394 rope->next = NULL;
395 rope->kind = kind;
396 rope->partial = (unsigned char) partial;
397 rope->cattable = (short) cattable;
398 rope->data = data;
399
400 if (write_spindle.head) {
401 write_spindle.tail->next = rope;
402 } else {
403 write_spindle.head = rope;
404 }
405 write_spindle.tail = rope;
406 write_spindle.complete = 0;
407 return 1;
408}
409
410static void texlib_aux_store_token(halfword token, int partial, int cattable)
411{
412 spindle_rope *rope = texlib_aux_new_rope();
413
414 rope->tsize = 0;
415 rope->next = NULL;
416 rope->kind = token_lua_input;
417 rope->partial = (unsigned char) partial;
418 rope->cattable = (short) cattable;
419 rope->data.h = token;
420
421 if (write_spindle.head) {
422 write_spindle.tail->next = rope;
423 } else {
424 write_spindle.head = rope;
425 }
426 write_spindle.tail = rope;
427 write_spindle.complete = 0;
428 lmt_token_state.luacstrings++;
429}
430
431static void lmx_aux_store_string(char *str, int len, int cattable)
432{
433 spindle_rope *rope = texlib_aux_new_rope();
434 rope->data.h = 0;
435 if (len > PACKED_SIZE) {
436 rope->data.t = lmt_memory_malloc((size_t) len + 1);
437 if (rope->data.t) {
438 memcpy(rope->data.t, str, (size_t) len + 1);
439 } else {
440 len = 0;
441 }
442 rope->kind = string_lua_input;
443 } else {
444 for (int i = 0; i < len; i++) {
445
446 rope->data.c[i] = (unsigned char) str[i];
447 }
448 rope->kind = packed_lua_input;
449 }
450
451 rope->tsize = (unsigned) len;
452 rope->next = NULL;
453 rope->partial = full_line_mode,
454 rope->cattable = (unsigned char) cattable;
455
456 if (write_spindle.head) {
457 write_spindle.tail->next = rope;
458 } else {
459 write_spindle.head = rope;
460 }
461 write_spindle.tail = rope;
462 write_spindle.complete = 0;
463 lmt_token_state.luacstrings++;
464}
465
466static int texlib_aux_cprint(lua_State *L, int partial, int cattable, int startstrings)
467{
468 int top = lua_gettop(L);
469 int type = lua_type(L, startstrings);
470 if (top > startstrings && cattable != no_catcode_table_preset && type == LUA_TNUMBER) {
471 cattable = lmt_tointeger(L, startstrings);
472 ++startstrings;
473 if (cattable != default_catcode_table_preset && cattable != no_catcode_table_preset && ! tex_valid_catcode_table(cattable)) {
474 cattable = default_catcode_table_preset;
475 }
476 type = lua_type(L, startstrings);
477 }
478 if (type == LUA_TTABLE) {
479 for (int i = 1;; i++) {
480 lua_rawgeti(L, startstrings, i);
481 if (texlib_aux_store(L, -1, partial, cattable, i > 1)) {
482 lua_pop(L, 1);
483 } else {
484 lua_pop(L, 1);
485 break;
486 }
487 }
488 } else {
489 for (int i = startstrings; i <= top; i++) {
490 texlib_aux_store(L, i, partial, cattable, i > startstrings);
491 }
492 }
493 return 0;
494}
495
496
501
502void lmt_cstring_store(char *str, int len, int cattable)
503{
504 lmx_aux_store_string(str, len, cattable);
505}
506
507void lmt_tstring_store(strnumber s, int cattable)
508{
509 lmx_aux_store_string((char *) str_string(s), (int) str_length(s), cattable);
510}
511
512
515
516void lmt_cstring_print(int cattable, const char *s, int ispartial)
517{
518 lua_State *L = lmt_lua_state.lua_instance;
519 int top = lua_gettop(L);
520 lua_settop(L, 0);
521 lua_pushinteger(L, cattable);
522 lua_pushstring(L, s);
523 texlib_aux_cprint(L, ispartial ? partial_line_mode : full_line_mode, default_catcode_table_preset, 1);
524 lua_settop(L, top);
525}
526
527
528
529static int texlib_write(lua_State *L)
530{
531 return texlib_aux_cprint(L, full_line_mode, no_catcode_table_preset, 1);
532}
533
534
535
536static int texlib_print(lua_State *L)
537{
538 return texlib_aux_cprint(L, full_line_mode, default_catcode_table_preset, 1);
539}
540
541
542
543static int texlib_sprint(lua_State *L)
544{
545 return texlib_aux_cprint(L, partial_line_mode, default_catcode_table_preset, 1);
546}
547
548static int texlib_mprint(lua_State *L)
549{
550 int ini = 1;
551 if (tracing_nesting_par > 2) {
552 tex_local_control_message("entering local control via (run) macro");
553 }
554 texlib_aux_store_token(token_val(end_local_cmd, 0), partial_line_mode, default_catcode_table_preset);
555 if (lmt_token_state.luacstrings > 0) {
556 tex_lua_string_start();
557 }
558 if (lua_type(L, 1) == LUA_TSTRING) {
559 size_t lname = 0;
560 const char *name = lua_tolstring(L, 1, &lname);
561 int cs = tex_string_locate_only(name, lname);
562 int cmd = eq_type(cs);
563 if (is_call_cmd(cmd)) {
564 texlib_aux_store_token(cs_token_flag + cs, partial_line_mode, default_catcode_table_preset);
565 ++ini;
566 } else {
567 tex_local_control_message("invalid (mprint) macro");
568 }
569 }
570 if (lua_gettop(L) >= ini) {
571 texlib_aux_cprint(L, partial_line_mode, default_catcode_table_preset, ini);
572 }
573 if (tracing_nesting_par > 2) {
574 tex_local_control_message("entering local control via mprint");
575 }
576 tex_local_control(1);
577 return 0;
578}
579
580
581
582static int texlib_pushlocal(lua_State *L)
583{
584 (void) L;
585 if (tracing_nesting_par > 2) {
586 tex_local_control_message("pushing local control");
587 }
588 texlib_aux_store_token(token_val(end_local_cmd, 0), partial_line_mode, default_catcode_table_preset);
589 if (lmt_token_state.luacstrings > 0) {
590 tex_lua_string_start();
591 }
592 return 0;
593}
594
595static int texlib_poplocal(lua_State *L)
596{
597 (void) L;
598 if (tracing_nesting_par > 2) {
599 tex_local_control_message("entering local control via pop");
600 }
601 tex_local_control(1);
602 return 0;
603}
604
605
606
607static int texlib_cprint(lua_State *L)
608{
609
612 int cattable = lmt_tointeger(L, 1);
613 if (cattable < 0 || cattable > 15) {
614 cattable = - 12 - 0xFF ;
615 } else {
616 cattable = - cattable - 0xFF;
617 }
618 if (lua_type(L, 2) == LUA_TTABLE) {
619 for (int i = 1; ; i++) {
620 lua_rawgeti(L, 2, i);
621 if (texlib_aux_store(L, -1, partial_line_mode, cattable, i > 1)) {
622 lua_pop(L, 1);
623 } else {
624 lua_pop(L, 1);
625 break;
626 }
627 }
628 } else {
629 int n = lua_gettop(L);
630 for (int i = 2; i <= n; i++) {
631 texlib_aux_store(L, i, partial_line_mode, cattable, i > 2);
632 }
633 }
634 return 0;
635}
636
637
638
639static int texlib_tprint(lua_State *L)
640{
641 int n = lua_gettop(L);
642 for (int i = 1; i <= n; i++) {
643 int cattable = default_catcode_table_preset;
644 int startstrings = 1;
645 if (lua_type(L, i) != LUA_TTABLE) {
646 luaL_error(L, "no string to print");
647 }
648 lua_pushvalue(L, i);
649 lua_pushinteger(L, 1);
650 lua_gettable(L, -2);
651 if (lua_type(L, -1) == LUA_TNUMBER) {
652 cattable = lmt_tointeger(L, -1);
653 startstrings = 2;
654 if (cattable != default_catcode_table_preset && cattable != no_catcode_table_preset && ! tex_valid_catcode_table(cattable)) {
655 cattable = default_catcode_table_preset;
656 }
657 }
658 lua_pop(L, 1);
659 for (int j = startstrings; ; j++) {
660 lua_pushinteger(L, j);
661 lua_gettable(L, -2);
662 if (texlib_aux_store(L, -1, partial_line_mode, cattable, j > startstrings)) {
663 lua_pop(L, 1);
664 } else {
665 lua_pop(L, 1);
666 break;
667 }
668 }
669 lua_pop(L, 1);
670 }
671 return 0;
672}
673
674static int texlib_isprintable(lua_State* L)
675{
676 halfword okay = 0;
677 switch (lua_type(L, 1)) {
678 case LUA_TSTRING :
679 okay = 1;
680 break;
681 case LUA_TUSERDATA :
682 if (lua_getmetatable(L, 1)) {
683 lua_get_metatablelua(token_instance);
684 if (lua_rawequal(L, -1, -2)) {
685 okay = 1;
686
687 } else {
688 lua_get_metatablelua(node_instance);
689 if (lua_rawequal(L, -1, -3)) {
690 okay = 1;
691 }
692
693 }
694 }
695 break;
696 }
697 lua_pushboolean(L, okay);
698 return 1;
699}
700
701
702
703int lmt_cstring_input(halfword *result, int *cattable, int *partial, int *finalline)
704{
705 spindle_rope *rope = read_spindle.head;
706 int type = eof_tex_input ;
707 if (! read_spindle.complete) {
708 read_spindle.complete = 1;
709 read_spindle.tail = NULL;
710 }
711 if (rope) {
712 switch (rope->kind) {
713 case string_lua_input:
714 {
715 if (rope->data.t) {
716
717 int strsize = (int) rope->tsize;
718 int newlast = lmt_fileio_state.io_first + strsize;
719 lmt_fileio_state.io_last = lmt_fileio_state.io_first;
720 if (tex_room_in_buffer(newlast)) {
721 memcpy(&lmt_fileio_state.io_buffer[lmt_fileio_state.io_last], &rope->data.t[0], sizeof(unsigned char) * strsize);
722 lmt_fileio_state.io_last = newlast;
723 lmt_memory_free(rope->data.t);
724 rope->data.t = NULL;
725 } else {
726 return type;
727 }
728 }
729 *cattable = rope->cattable;
730 *partial = rope->partial;
731 *finalline = (rope->next == NULL);
732 type = string_tex_input;
733 break;
734 }
735 case packed_lua_input:
736 {
737 unsigned strsize = rope->tsize;
738 int newlast = lmt_fileio_state.io_first + strsize;
739 lmt_fileio_state.io_last = lmt_fileio_state.io_first;
740 if (tex_room_in_buffer(newlast)) {
741 memcpy(&lmt_fileio_state.io_buffer[lmt_fileio_state.io_last], &rope->data.c[0], sizeof(unsigned char) * strsize);
742
743
744
745
746 lmt_fileio_state.io_last = newlast;
747 *cattable = rope->cattable;
748 *partial = rope->partial;
749 *finalline = (rope->next == NULL);
750 type = string_tex_input;
751 } else {
752 return type;
753 }
754 break;
755 }
756 case token_lua_input:
757 {
758 *result = rope->data.h;
759 type = token_tex_input;
760 break;
761 }
762 case token_list_lua_input:
763 {
764 *result = rope->data.h;
765 type = token_list_tex_input;
766 break;
767 }
768 case node_lua_input:
769 {
770 *result = rope->data.h;
771 type = node_tex_input;
772 break;
773 }
774 }
775 texlib_aux_dispose_rope(read_spindle.tail);
776 read_spindle.tail = rope;
777 read_spindle.head = rope->next;
778 } else {
779 texlib_aux_dispose_rope(read_spindle.tail);
780 read_spindle.tail = NULL;
781 }
782 return type;
783}
784
785
786
787void lmt_cstring_start(void)
788{
789 lmt_spindle_state.spindle_index++;
790 if (lmt_spindle_state.spindle_size == lmt_spindle_state.spindle_index) {
791 int size = (lmt_spindle_state.spindle_size + 1) * sizeof(spindle);
792 spindle *spindles = lmt_memory_realloc(lmt_spindle_state.spindles, (size_t) size);
793 if (spindles) {
794 lmt_spindle_state.spindles = spindles;
795 texlib_aux_reset_spindle(lmt_spindle_state.spindle_index);
796 lmt_spindle_state.spindle_size++;
797 } else {
798 tex_overflow_error("spindle", size);
799 }
800 }
801}
802
803
804
805void lmt_cstring_close(void)
806{
807 spindle_rope *rope;
808 spindle_rope *next = read_spindle.head;
809 while (next) {
810 if (next->kind == string_tex_input && next->data.t) {
811 lmt_memory_free(next->data.t);
812 next->data.t = NULL;
813 }
814 rope = next;
815 next = next->next;
816 if (rope == read_spindle.tail) {
817 read_spindle.tail = NULL;
818 }
819 texlib_aux_dispose_rope(rope);
820 }
821 read_spindle.head = NULL;
822 texlib_aux_dispose_rope(read_spindle.tail);
823 read_spindle.tail = NULL;
824 read_spindle.complete = 0;
825 lmt_spindle_state.spindle_index--;
826}
827
828
832
833static const char *texlib_aux_scan_integer_part(lua_State *L, const char *ss, int *ret, int *radix_ret)
834{
835 int negative = 0;
836 int vacuous = 1;
837 int overflow = 0;
838 int chr = 0;
839 const char *str = ss;
840 long long result = 0;
841 while (1) {
842 chr = *str++;
843 switch (chr) {
844 case ' ':
845 case '+':
846 break;
847 case '-':
848 negative = ! negative;
849 break;
850 case '\'':
851 {
852 int digit;
853 *radix_ret = 8;
854 chr = *str++;
855 while (chr) {
856 if ((chr >= '0') && (chr <= '0' + 7)) {
857 digit = chr - '0';
858 } else {
859 break;
860 }
861 if (! overflow) {
862 vacuous = 0;
863 result = result * 8 + digit;
864 if (result > max_integer) {
865 overflow = 1;
866 }
867 }
868 chr = *str++;
869 }
870 goto DONE;
871 }
872 case '"':
873 {
874 int digit;
875 *radix_ret = 16;
876 chr = *str++;
877 while (chr) {
878 if ((chr >= '0') && (chr <= '0' + 9)) {
879 digit = chr - '0';
880 } else if ((chr <= 'A' + 5) && (chr >= 'A')) {
881 digit = chr - 'A' + 10;
882 } else if ((chr <= 'a' + 5) && (chr >= 'a')) {
883
884 digit = chr - 'a' + 10;
885 } else {
886 goto DONE;
887 }
888 if (! overflow) {
889 vacuous = 0;
890 result = result * 16 + digit;
891 if (result > max_integer) {
892 overflow = 1;
893 }
894 }
895 chr = *str++;
896 }
897 goto DONE;
898 }
899 default:
900 {
901 int digit;
902 *radix_ret = 10;
903 while (chr) {
904 if ((chr >= '0') && (chr <= '0' + 9)) {
905 digit = chr - '0';
906 } else {
907 goto DONE;
908 }
909 if (! overflow) {
910 vacuous = 0;
911 result = result * 10 + digit;
912 if (result > max_integer) {
913 overflow = 1;
914 }
915 }
916 chr = *str++;
917 }
918 goto DONE;
919 }
920 }
921 }
922 DONE:
923 if (overflow) {
924 luaL_error(L, "number too big");
925 result = max_integer;
926 } else if (vacuous) {
927 luaL_error(L, "missing number, treated as zero") ;
928 }
929 if (negative) {
930 result = -result;
931 }
932 *ret = (int) result;
933 if (chr != ' ' && str > ss) {
934 str--;
935 }
936 return str;
937}
938
939
944
945# define unit_hashes(a,b,c,d) \
946 unit_parameter_hash(a,c): \
947 case unit_parameter_hash(b,d): \
948 case unit_parameter_hash(a,d): \
949 case unit_parameter_hash(b,c)
950
951static const char *texlib_aux_scan_dimension_part(lua_State * L, const char *ss, int *ret)
952{
953 int negative = 0;
954 int fraction = 0;
955 int numerator;
956 int denominator;
957 scaled special;
958 int result = 0;
959 int radix = 0;
960 int remainder = 0;
961 int saved_error = lmt_scanner_state.arithmic_error;
962 const char *str = NULL;
963 if (ss && (*ss == '.' || *ss == ',')) {
964 str = ss;
965 goto FRACTION;
966 } else {
967 str = texlib_aux_scan_integer_part(L, ss, &result, &radix);
968 }
969 if (! (char) *str) {
970
974 goto ATTACH_FRACTION;
975 }
976 if (result < 0) {
977 negative = ! negative;
978 result = -result;
979 }
980 FRACTION:
981 if ((radix == 0 || radix == 10) && (*str == '.' || *str == ',')) {
982 unsigned k = 0;
983 unsigned char digits[18];
984 str++;
985 while (1) {
986 unsigned char chr = *str++;
987 if ((chr > '0' + 9) || (chr < '0')) {
988 break;
989 } else if (k < 17) {
990 digits[k++] = (unsigned char) chr - '0';
991 }
992 }
993 fraction = tex_round_decimals_digits(digits, k);
994 if (*str != ' ') {
995 --str;
996 }
997 }
998
1001 while ((char) *str == ' ') {
1002 str++;
1003 }
1004
1008 if ((char) *str) {
1009 int index = unit_parameter_index(str[0], str[1]);
1010 if (index >= 0) {
1011 switch (index) {
1012 case unit_hashes('p','P','t','T'):
1013 str += 2;
1014 goto ATTACH_FRACTION;
1015 case unit_hashes('c','C','m','M'):
1016 str += 2;
1017 numerator = 7227;
1018 denominator = 254;
1019 goto CONVERSION;
1020 case unit_hashes('m','M','m','M'):
1021 str += 2;
1022 numerator = 7227;
1023 denominator = 2540;
1024 goto CONVERSION;
1025 case unit_hashes('e','E','m','M'):
1026 str += 2;
1027 special = tex_get_font_em_width(cur_font_par);
1028 goto SPECIAL;
1029 case unit_hashes('e','E','x','X'):
1030 str += 2;
1031 special = tex_get_font_ex_height(cur_font_par);
1032 goto SPECIAL;
1033 case unit_hashes('s','S','p','P'):
1034 str += 2;
1035 goto DONE;
1036 case unit_hashes('b','B','p','P'):
1037 str += 2;
1038 numerator = 7227;
1039 denominator = 7200;
1040 goto CONVERSION;
1041 case unit_hashes('t','T','s','S'):
1042 str += 2;
1043 numerator = 4588;
1044 denominator = 645;
1045 goto CONVERSION;
1046 case unit_hashes('e','E','s','S'):
1047 str += 2;
1048 numerator = 9176;
1049 denominator = 129;
1050 goto CONVERSION;
1051 case unit_hashes('e','E','u','U'):
1052 str += 2;
1053 numerator = 9176 * eu_factor_par;
1054 denominator = 129 * 10;
1055 goto CONVERSION;
1056 case unit_hashes('d','D','k','K'):
1057 str += 2;
1058 numerator = 49838;
1059 denominator = 7739;
1060 goto CONVERSION;
1061 case unit_hashes('m','M','u','U'):
1062 str += 2;
1063 goto ATTACH_FRACTION;
1064 case unit_hashes('d','D','d','D'):
1065 str += 2;
1066 numerator = 1238;
1067 denominator = 1157;
1068 goto CONVERSION;
1069 case unit_hashes('c','C','c','C'):
1070 str += 2;
1071 numerator = 14856;
1072 denominator = 1157;
1073 goto CONVERSION;
1074 case unit_hashes('p','P','c','C'):
1075 str += 2;
1076 numerator = 12;
1077 denominator = 1;
1078 goto CONVERSION;
1079 case unit_hashes('p','P','x','X'):
1080 str += 2;
1081 special = px_dimension_par;
1082 goto SPECIAL;
1083 case unit_hashes('i','I','n','N'):
1084 str += 2;
1085 numerator = 7227;
1086 denominator = 100;
1087 goto CONVERSION;
1088 default:
1089 if (tex_get_userunit(index, &special)) {
1090 str += 2;
1091 goto SPECIAL;
1092 }
1093 {
1094 halfword cs = unit_parameter(index);
1095 if (cs > 0) {
1096 halfword cmd = eq_type(cs);
1097 halfword chr = eq_value(cs);
1098 switch (cmd) {
1099 case internal_dimension_cmd:
1100 case register_dimension_cmd:
1101 str += 2;
1102 special = eq_value(chr);
1103 goto SPECIAL;
1104 case dimension_cmd:
1105 str += 2;
1106 special = chr;
1107 goto SPECIAL;
1108 }
1109 }
1110 }
1111 }
1112 }
1113 }
1114 goto ATTACH_FRACTION;
1115 SPECIAL:
1116 result = tex_nx_plus_y(result, special, tex_xn_over_d_r(special, fraction, 0x10000, &remainder));
1117 goto DONE;
1118 CONVERSION:
1119 result = tex_xn_over_d_r(result, numerator, denominator, &remainder);
1120 fraction = (numerator * fraction + 0x10000 * remainder) / denominator;
1121 result = result + (fraction / 0x10000);
1122 fraction = fraction % 0x10000;
1123 ATTACH_FRACTION:
1124 if (result >= 0x4000) {
1125 lmt_scanner_state.arithmic_error = 1;
1126 } else {
1127 result = result * 0x10000 + fraction;
1128 }
1129 DONE:
1130 if (lmt_scanner_state.arithmic_error || (abs(result) >= 0x40000000)) {
1131 result = max_dimension;
1132 luaL_error(L, "dimension too large");
1133 }
1134 *ret = negative ? - result : result;
1135 lmt_scanner_state.arithmic_error = saved_error;
1136
1137 while ((char) *str == ' ') {
1138 str++;
1139 }
1140 return str;
1141}
1142
1143static int texlib_aux_dimension_to_number(lua_State *L, const char *s)
1144{
1145 int result = 0;
1146 const char *d = texlib_aux_scan_dimension_part(L, s, &result);
1147 if (*d) {
1148 return luaL_error(L, "conversion failed (trailing junk?)");
1149 } else {
1150 return result;
1151 }
1152}
1153
1154static int texlib_aux_integer_to_number(lua_State *L, const char *s)
1155{
1156 int result = 0;
1157 int radix = 10;
1158 const char *d = texlib_aux_scan_integer_part(L, s, &result, &radix);
1159 if (*d) {
1160 return luaL_error(L, "conversion failed (trailing junk?)");
1161 } else {
1162 return result;
1163 }
1164}
1165
1166static int texlib_toscaled(lua_State *L)
1167{
1168 int sp;
1169 switch (lua_type(L, 1)) {
1170 case LUA_TNUMBER:
1171 sp = lmt_toroundnumber(L, 1);
1172 break;
1173 case LUA_TSTRING:
1174 sp = texlib_aux_dimension_to_number(L, lua_tostring(L, 1));
1175 break;
1176 default:
1177 return luaL_error(L, "string or a number expected");
1178 }
1179 lua_pushinteger(L, sp);
1180 return 1;
1181}
1182
1183static int texlib_tonumber(lua_State *L)
1184{
1185 int i;
1186 switch (lua_type(L, 1)) {
1187 case LUA_TNUMBER:
1188 i = lmt_toroundnumber(L, 1);
1189 break;
1190 case LUA_TSTRING:
1191 i = texlib_aux_integer_to_number(L, lua_tostring(L, 1));
1192 break;
1193 default:
1194 return luaL_error(L, "string or a number expected");
1195 }
1196 lua_pushinteger(L, i);
1197 return 1;
1198}
1199
1200static int texlib_error(lua_State *L)
1201{
1202 const char *error = luaL_checkstring(L, 1);
1203 const char *help = lua_type(L, 2) == LUA_TSTRING ? luaL_checkstring(L, 2) : NULL;
1204 tex_handle_error(normal_error_type, error, help);
1205 return 0;
1206}
1207
1208
1215
1216inline static int texlib_aux_valid_register_index(lua_State *L, int slot, int cmd, int base, int max, int constant_cmd)
1217{
1218 int index = -1;
1219 switch (lua_type(L, slot)) {
1220 case LUA_TSTRING:
1221 {
1222 size_t len;
1223 const char *str = lua_tolstring(L, 1, &len);
1224 int cs = tex_string_locate_only(str, len);
1225 if (eq_type(cs) == cmd) {
1226 index = eq_value(cs) - base;
1227 } else if (eq_type(cs) == constant_cmd) {
1228 return 0xFFFF + cs;
1229 }
1230 }
1231 break;
1232 case LUA_TNUMBER:
1233 index = lmt_tointeger(L, slot);
1234 break;
1235 default:
1236 luaL_error(L, "string or a number expected");
1237 break;
1238 }
1239 if (index >= 0 && index <= max) {
1240 return index;
1241 } else if (index < (eqtb_size + lmt_hash_state.hash_data.ptr + 1) && eq_type(index) == constant_cmd) {
1242 return index;
1243 } else {
1244 return -1;
1245 }
1246}
1247
1248static int texlib_get_register_index(lua_State *L)
1249{
1250 size_t len;
1251 const char *str = lua_tolstring(L, 1, &len);
1252 int cs = tex_string_locate_only(str, len);
1253 int index = -1;
1254 switch (eq_type(cs)) {
1255 case register_toks_cmd : index = eq_value(cs) - register_toks_base; break;
1256 case register_integer_cmd : index = eq_value(cs) - register_integer_base; break;
1257 case register_attribute_cmd : index = eq_value(cs) - register_attribute_base; break;
1258 case register_dimension_cmd : index = eq_value(cs) - register_dimension_base; break;
1259 case register_glue_cmd : index = eq_value(cs) - register_glue_base; break;
1260 case register_muglue_cmd : index = eq_value(cs) - register_muglue_base; break;
1261 }
1262 if (index >= 0) {
1263 lua_pushinteger(L, index);
1264 } else {
1265 lua_pushnil(L);
1266 }
1267 return 1;
1268}
1269
1270inline static int texlib_aux_checked_register(lua_State *L, int cmd, int base, int max, int constant_cmd)
1271{
1272 int index = texlib_aux_valid_register_index(L, 1, cmd, base, max, constant_cmd);
1273 if (index >= 0) {
1274 lua_pushinteger(L, index);
1275 } else {
1276 lua_pushboolean(L, 0);
1277 }
1278 return 1;
1279}
1280
1281typedef void (*setfunc) (int, halfword, int, int);
1282typedef halfword (*getfunc) (int, int);
1283
1284
1285
1286int lmt_check_for_flags(lua_State *L, int slot, int *flags, int prefixes, int numeric)
1287{
1288
1289
1290
1291 if (prefixes) {
1292 while (1) {
1293 switch (lua_type(L, slot)) {
1294 case LUA_TSTRING:
1295 {
1296 const char *str = lua_tostring(L, slot);
1297 if (! str || lua_key_eq(str, macro)) {
1298
1299 slot += 1;
1300 } else if (lua_key_eq(str, global)) {
1301 slot += 1;
1302 *flags = add_global_flag(*flags);
1303 } else if (lua_key_eq(str, frozen)) {
1304 slot += 1;
1305 *flags = add_frozen_flag(*flags);
1306 } else if (lua_key_eq(str, permanent)) {
1307 slot += 1;
1308 *flags = add_permanent_flag(*flags);
1309 } else if (lua_key_eq(str, protected)) {
1310 slot += 1;
1311 *flags = add_protected_flag(*flags);
1312 } else if (lua_key_eq(str, semiprotected)) {
1313 slot += 1;
1314 *flags = add_semiprotected_flag(*flags);
1315 } else if (lua_key_eq(str, untraced)) {
1316 slot += 1;
1317 *flags = add_untraced_flag(*flags);
1318 } else if (lua_key_eq(str, immutable)) {
1319 slot += 1;
1320 *flags = add_immutable_flag(*flags);
1321 } else if (lua_key_eq(str, overloaded)) {
1322 slot += 1;
1323 *flags = add_overloaded_flag(*flags);
1324 } else if (lua_key_eq(str, value)) {
1325 slot += 1;
1326 *flags = add_value_flag(*flags);
1327 } else if (lua_key_eq(str, constant)) {
1328 slot += 1;
1329 *flags = add_constant_flag(*flags);
1330 } else if (lua_key_eq(str, conditional) || lua_key_eq(str, condition)) {
1331
1332 slot += 1;
1333 *flags = add_conditional_flag(*flags);
1334 } else {
1335
1336 return slot;
1337 }
1338 break;
1339 }
1340 case LUA_TNUMBER:
1341 if (numeric) {
1342 *flags |= lua_tointeger(L, slot);
1343 slot += 1;
1344 break;
1345 } else {
1346 return slot;
1347 }
1348 case LUA_TNIL:
1349
1350 slot += 1;
1351 break;
1352 default:
1353 return slot;
1354 }
1355 }
1356 }
1357 return slot;
1358}
1359
1360int lmt_check_for_level(lua_State *L, int slot, quarterword *level, quarterword defaultlevel)
1361{
1362 if (lua_type(L, slot) == LUA_TSTRING) {
1363 const char *str = lua_tostring(L, slot);
1364 *level = lua_key_eq(str, global) ? level_one : defaultlevel;
1365 ++slot;
1366 } else {
1367 *level = defaultlevel;
1368 }
1369 return slot;
1370}
1371
1372
1373
1374static int texlib_aux_check_for_index(
1375 lua_State *L,
1376 int slot,
1377 const char *what,
1378 int *index,
1379 int internal_cmd,
1380 int register_cmd,
1381 int internal_base,
1382 int register_base,
1383 int max_index,
1384 int constant_cmd
1385) {
1386 *index = -1;
1387 switch (lua_type(L, slot)) {
1388 case LUA_TSTRING:
1389 {
1390 size_t len;
1391 const char *str = lua_tolstring(L, slot, &len);
1392 int cs = tex_string_locate_only(str, len);
1393 if (eq_type(cs) == internal_cmd) {
1394 *index = eq_value(cs) - internal_base;
1395 return 1;
1396 } else if (eq_type(cs) == register_cmd) {
1397 *index = eq_value(cs) - register_base;
1398 return 0;
1399 } else if (eq_type(cs) == constant_cmd) {
1400 *index = cs;
1401 return 2;
1402 } else {
1403 luaL_error(L, "incorrect %s name", what);
1404 return -1;
1405 }
1406 }
1407 case LUA_TNUMBER:
1408 *index = lmt_tointeger(L, slot);
1409 if (*index >= 0 && *index <= max_index) {
1410 return 0;
1411 } else {
1412 halfword i = *index - 0xFFFF;
1413 if (i < (eqtb_size + lmt_hash_state.hash_data.ptr + 1) && eq_type(i) == constant_cmd) {
1414 *index = i;
1415 return 2;
1416 }
1417 }
1418 return -1;
1419 default:
1420 luaL_error(L, "%s name or valid index expected", what);
1421 return -1;
1422 }
1423}
1424
1425static int texlib_get(lua_State *L);
1426
1427
1434
1435static int texlib_isdimen(lua_State *L)
1436{
1437 return texlib_aux_checked_register(L, register_dimension_cmd, register_dimension_base, max_dimension_register_index, dimension_cmd);
1438}
1439
1440
1441
1442static int texlib_setdimen(lua_State *L)
1443{
1444 int flags = 0;
1445 int index = 0;
1446 int slot = lmt_check_for_flags(L, 1, &flags, 1, 0);
1447 int state = texlib_aux_check_for_index(L, slot++, "dimen", &index, internal_dimension_cmd, register_dimension_cmd, internal_dimension_base, register_dimension_base, max_dimension_register_index, dimension_cmd);
1448 if (state >= 0) {
1449 halfword value = 0;
1450 switch (lua_type(L, slot)) {
1451 case LUA_TNUMBER:
1452 value = lmt_toroundnumber(L, slot++);
1453 break;
1454 case LUA_TSTRING:
1455 value = texlib_aux_dimension_to_number(L, lua_tostring(L, slot++));
1456 break;
1457 case LUA_TBOOLEAN:
1458 if (lua_toboolean(L, slot++)) {
1459
1460 return 0;
1461 }
1462 break;
1463 case LUA_TNONE:
1464 case LUA_TNIL:
1465 break;
1466 default:
1467 luaL_error(L, "unsupported dimen value type");
1468 break;
1469 }
1470 if (state == 2) {
1471 tex_define(flags, index, dimension_cmd, value);
1472 } else {
1473 tex_set_tex_dimension_register(index, value, flags, state);
1474 if (state == 1 && lua_toboolean(L, slot)) {
1475 tex_update_par_par(internal_dimension_cmd, index);
1476 }
1477 }
1478 }
1479 return 0;
1480}
1481
1482static int texlib_getdimen(lua_State *L)
1483{
1484 int index;
1485 int state = texlib_aux_check_for_index(L, 1, "dimen", &index, internal_dimension_cmd, register_dimension_cmd, internal_dimension_base, register_dimension_base, max_dimension_register_index, dimension_cmd);
1486 lua_pushinteger(L, state >= 0 ? (state == 2 ? eq_value(index) : tex_get_tex_dimension_register(index, state)) : 0);
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501 return 1;
1502}
1503
1504static halfword texlib_aux_make_glue(lua_State *L, int top, int slot)
1505{
1506 halfword value = tex_copy_node(zero_glue);
1507 if (slot <= top) {
1508 glue_amount(value) = lmt_toroundnumber(L, slot++);
1509 if (slot <= top) {
1510 glue_stretch(value) = lmt_toroundnumber(L, slot++);
1511 if (slot <= top) {
1512 glue_shrink(value) = lmt_toroundnumber(L, slot++);
1513 if (slot <= top) {
1514 glue_stretch_order(value) = tex_checked_glue_order(lmt_tohalfword(L, slot++));
1515 if (slot <= top) {
1516 glue_shrink_order(value) = tex_checked_glue_order(lmt_tohalfword(L, slot++));
1517 }
1518 }
1519 }
1520 }
1521 }
1522 return value;
1523}
1524
1525inline static int texlib_aux_push_glue(lua_State* L, halfword g)
1526{
1527 if (g) {
1528 lua_pushinteger(L, glue_amount(g));
1529 lua_pushinteger(L, glue_stretch(g));
1530 lua_pushinteger(L, glue_shrink(g));
1531 lua_pushinteger(L, glue_stretch_order(g));
1532 lua_pushinteger(L, glue_shrink_order(g));
1533 } else {
1534 lua_pushinteger(L, 0);
1535 lua_pushinteger(L, 0);
1536 lua_pushinteger(L, 0);
1537 lua_pushinteger(L, 0);
1538 lua_pushinteger(L, 0);
1539 }
1540 return 5;
1541}
1542
1543static halfword texlib_aux_get_glue_spec(lua_State *L, int slot)
1544{
1545 halfword value = null;
1546 switch (lua_type(L, slot + 1)) {
1547 case LUA_TBOOLEAN:
1548
1549
1550
1551 break;
1552 case LUA_TNIL:
1553 case LUA_TNONE:
1554 break;
1555 default:
1556 value = lmt_check_isnode(L, slot + 1);
1557 if (node_type(value) != glue_spec_node) {
1558 value = null;
1559 luaL_error(L, "glue_spec expected");
1560 }
1561 }
1562 return value;
1563}
1564
1565static int texlib_isskip(lua_State *L)
1566{
1567 return texlib_aux_checked_register(L, register_glue_cmd, register_glue_base, max_glue_register_index, gluespec_cmd);
1568}
1569
1570
1571
1572static int texlib_setskip(lua_State *L)
1573{
1574 int flags = 0;
1575 int index = 0;
1576 int slot = lmt_check_for_flags(L, 1, &flags, 1, 0);
1577 int state = texlib_aux_check_for_index(L, slot++, "skip", &index, internal_glue_cmd, register_glue_cmd, internal_glue_base, register_glue_base, max_glue_register_index, gluespec_cmd);
1578 if (state >= 0) {
1579 halfword value = texlib_aux_get_glue_spec(L, slot++);
1580 if (state == 2) {
1581 tex_define(flags, index, gluespec_cmd, value);
1582 } else {
1583 tex_set_tex_skip_register(index, value, flags, state);
1584 if (state == 1 && lua_toboolean(L, slot)) {
1585 tex_update_par_par(internal_glue_cmd, index);
1586 }
1587 }
1588 }
1589 return 0;
1590}
1591
1592static int texlib_getskip(lua_State *L)
1593{
1594 int index;
1595 int state = texlib_aux_check_for_index(L, 1, "skip", &index, internal_glue_cmd, register_glue_cmd, internal_glue_base, register_glue_base, max_glue_register_index, gluespec_cmd);
1596 halfword value = state >= 0 ? (state == 2 ? eq_value(index) : tex_get_tex_skip_register(index, state)) : null;
1597 lmt_push_node_fast(L, tex_copy_node(value ? value : zero_glue));
1598 return 1;
1599}
1600
1601static int texlib_isglue(lua_State *L)
1602{
1603 return texlib_aux_checked_register(L, register_glue_cmd, register_glue_base, max_glue_register_index, gluespec_cmd);
1604}
1605
1606
1607
1608static int texlib_setglue(lua_State *L)
1609{
1610 int flags = 0;
1611 int index = 0;
1612 int slot = lmt_check_for_flags(L, 1, &flags, 1, 0);
1613 int state = texlib_aux_check_for_index(L, slot++, "skip", &index, internal_glue_cmd, register_glue_cmd, internal_glue_base, register_glue_base, max_glue_register_index, gluespec_cmd);
1614 if (state >= 0) {
1615 halfword value = texlib_aux_make_glue(L, lua_gettop(L), slot);
1616 if (state == 2) {
1617 tex_define(flags, index, gluespec_cmd, value);
1618 } else {
1619 tex_set_tex_skip_register(index, value, flags, state);
1620 }
1621 }
1622 return 0;
1623}
1624
1625static int texlib_getglue(lua_State *L)
1626{
1627 int index;
1628 int all = (lua_type(L, 2) == LUA_TBOOLEAN) ? lua_toboolean(L, 2) : 1;
1629 int state = texlib_aux_check_for_index(L, 1, "skip", &index, internal_glue_cmd, register_glue_cmd, internal_glue_base, register_glue_base, max_glue_register_index, gluespec_cmd);
1630 halfword value = state >= 0 ? (state == 2 ? eq_value(index) : tex_get_tex_skip_register(index, state)) : null;
1631 if (! value) {
1632 lua_pushinteger(L, 0);
1633 if (all) {
1634
1635 lua_pushinteger(L, 0);
1636 lua_pushinteger(L, 0);
1637 return 3;
1638 } else {
1639 return 1;
1640 }
1641 } else if (all) {
1642 return texlib_aux_push_glue(L, value);
1643 } else {
1644
1645 lua_pushinteger(L, value ? glue_amount(value) : 0);
1646 return 1;
1647 }
1648}
1649
1650static int texlib_ismuskip(lua_State *L)
1651{
1652 return texlib_aux_checked_register(L, register_muglue_cmd, register_muglue_base, max_muglue_register_index, mugluespec_cmd);
1653}
1654
1655static int texlib_setmuskip(lua_State *L)
1656{
1657 int flags = 0;
1658 int index = 0;
1659 int slot = lmt_check_for_flags(L, 1, &flags, 1, 0);
1660 int state = texlib_aux_check_for_index(L, slot++, "muskip", &index, internal_muglue_cmd, register_muglue_cmd, internal_muglue_base, register_muglue_base, max_muglue_register_index, mugluespec_cmd);
1661 if (state >= 0) {
1662 halfword value =texlib_aux_get_glue_spec(L, slot);
1663 if (state == 2) {
1664 tex_define(flags, index, mugluespec_cmd, value);
1665 } else {
1666 tex_set_tex_muskip_register(index, value, flags, state);
1667 }
1668 }
1669 return 0;
1670}
1671
1672static int texlib_getmuskip(lua_State *L)
1673{
1674 int index;
1675 int state = texlib_aux_check_for_index(L, 1, "muskip", &index, internal_muglue_cmd, register_muglue_cmd, internal_muglue_base, register_muglue_base, max_muglue_register_index, mugluespec_cmd);
1676 halfword value = state >= 0 ? (state == 2 ? eq_value(index) : tex_get_tex_muskip_register(index, state)) : null;
1677 lmt_push_node_fast(L, tex_copy_node(value ? value : zero_glue));
1678 return 1;
1679}
1680
1681static int texlib_ismuglue(lua_State *L)
1682{
1683 return texlib_aux_checked_register(L, register_muglue_cmd, register_muglue_base, max_muglue_register_index, mugluespec_cmd);
1684}
1685
1686static int texlib_setmuglue(lua_State *L)
1687{
1688 int flags = 0;
1689 int index = 0;
1690 int slot = lmt_check_for_flags(L, 1, &flags, 1, 0);
1691 int state = texlib_aux_check_for_index(L, slot++, "muskip", &index, internal_muglue_cmd, register_muglue_cmd, internal_muglue_base, register_muglue_base, max_muglue_register_index, mugluespec_cmd);
1692 if (state >= 0) {
1693 halfword value = texlib_aux_make_glue(L, lua_gettop(L), slot);
1694 if (state == 2) {
1695 tex_define(flags, index, mugluespec_cmd, value);
1696 } else {
1697 tex_set_tex_muskip_register(index, value, flags, state);
1698 }
1699 }
1700 return 0;
1701}
1702
1703static int texlib_getmuglue(lua_State *L)
1704{
1705 int index;
1706 int all = (lua_type(L, 2) == LUA_TBOOLEAN) ? lua_toboolean(L, 2) : 1;
1707 int state = texlib_aux_check_for_index(L, 1, "muskip", &index, internal_muglue_cmd, register_muglue_cmd, internal_muglue_base, register_muglue_base, max_muglue_register_index, mugluespec_cmd);
1708 halfword value = state >= 0 ? (state == 2 ? eq_value(index) : tex_get_tex_muskip_register(index, state)) : null;
1709 if (! value) {
1710 lua_pushinteger(L, 0);
1711 return 1;
1712 } else if (all) {
1713 return texlib_aux_push_glue(L, value);
1714 } else {
1715
1716 lua_pushinteger(L, value ? glue_amount(value) : 0);
1717 return 1;
1718 }
1719}
1720
1721static int texlib_iscount(lua_State *L)
1722{
1723 return texlib_aux_checked_register(L, register_integer_cmd, register_integer_base, max_integer_register_index, integer_cmd);
1724}
1725
1726static int texlib_setcount(lua_State *L)
1727{
1728 int flags = 0;
1729 int index = 0;
1730 int slot = lmt_check_for_flags(L, 1, &flags, 1, 0);
1731 int state = texlib_aux_check_for_index(L, slot++, "count", &index, internal_integer_cmd, register_integer_cmd, internal_integer_base, register_integer_base, max_integer_register_index, integer_cmd);
1732 if (state >= 0) {
1733 halfword value = lmt_optinteger(L, slot++, 0);
1734 if (state == 2) {
1735 tex_define(flags, index, integer_cmd, value);
1736 } else {
1737 tex_set_tex_count_register(index, value, flags, state);
1738 if (state == 1 && lua_toboolean(L, slot)) {
1739 tex_update_par_par(internal_integer_cmd, index);
1740 }
1741 }
1742 }
1743 return 0;
1744}
1745
1746static int texlib_getcount(lua_State *L)
1747{
1748 int index;
1749 int state = texlib_aux_check_for_index(L, 1, "count", &index, internal_integer_cmd, register_integer_cmd, internal_integer_base, register_integer_base, max_integer_register_index, integer_cmd);
1750 lua_pushinteger(L, state >= 0 ? (state == 2 ? eq_value(index) : tex_get_tex_count_register(index, state)) : 0);
1751 return 1;
1752}
1753
1754static int texlib_isfloat(lua_State *L)
1755{
1756 return texlib_aux_checked_register(L, register_posit_cmd, register_posit_base, max_posit_register_index, posit_cmd);
1757}
1758
1759static int texlib_setfloat(lua_State *L)
1760{
1761 int flags = 0;
1762 int index = 0;
1763 int slot = lmt_check_for_flags(L, 1, &flags, 1, 0);
1764 int state = texlib_aux_check_for_index(L, slot++, "float", &index, internal_posit_cmd, register_posit_cmd, internal_posit_base, register_posit_base, max_posit_register_index, posit_cmd);
1765 if (state >= 0) {
1766 halfword value = tex_double_to_posit(luaL_optnumber(L, slot++, 0)).v;
1767 if (state == 2) {
1768 tex_define(flags, index, posit_cmd, value);
1769 } else {
1770 tex_set_tex_count_register(index, value, flags, state);
1771 if (state == 1 && lua_toboolean(L, slot)) {
1772 tex_update_par_par(internal_posit_cmd, index);
1773 }
1774 }
1775 }
1776 return 0;
1777}
1778
1779static int texlib_getfloat(lua_State *L)
1780{
1781 int index;
1782 int state = texlib_aux_check_for_index(L, 1, "float", &index, internal_posit_cmd, register_posit_cmd, internal_posit_base, register_posit_base, max_posit_register_index, posit_cmd);
1783 lua_pushnumber(L, tex_posit_to_double((state >= 0) ? (state == 2 ? eq_value(index) : tex_get_tex_posit_register(index, state)) : 0));
1784 return 1;
1785}
1786
1787static int texlib_isattribute(lua_State *L)
1788{
1789 return texlib_aux_checked_register(L, register_attribute_cmd, register_attribute_base, max_attribute_register_index, -1);
1790}
1791
1792
1793
1794static int texlib_setattribute(lua_State *L)
1795{
1796 int flags = 0;
1797 int index = 0;
1798 int slot = lmt_check_for_flags(L, 1, &flags, 1, 0);
1799 int state = texlib_aux_check_for_index(L, slot++, "attribute", &index, internal_attribute_cmd, register_attribute_cmd, internal_attribute_base, register_attribute_base, max_attribute_register_index, 0);
1800 if (state >= 0) {
1801 halfword value = lmt_optinteger(L, slot++, unused_attribute_value);
1802 tex_set_tex_attribute_register(index, value, flags, state);
1803 }
1804 return 0;
1805}
1806
1807static int texlib_getattribute(lua_State *L)
1808{
1809 int index;
1810 int state = texlib_aux_check_for_index(L, 1, "attribute", &index, internal_attribute_cmd, register_attribute_cmd, internal_attribute_base, register_attribute_base, max_attribute_register_index, 0);
1811 lua_pushinteger(L, state >= 0 ? tex_get_tex_attribute_register(index, state) : 0);
1812 return 1;
1813}
1814
1815
1816
1817
1818
1819static int texlib_istoks(lua_State *L)
1820{
1821 return texlib_aux_checked_register(L, register_toks_cmd, register_toks_base, max_toks_register_index, -1);
1822}
1823
1824
1825
1826static int texlib_settoks(lua_State *L)
1827{
1828 int flags = 0;
1829 int index = 0;
1830 int slot = lmt_check_for_flags(L, 1, &flags, 1, 0);
1831 int state = texlib_aux_check_for_index(L, slot++, "toks", &index, internal_toks_cmd, register_toks_cmd, internal_toks_base, register_toks_base,max_toks_register_index, 0);
1832 if (state >= 0) {
1833 lstring value = { .c = NULL, .l = 0 };
1834 switch (lua_type(L, slot)) {
1835 case LUA_TSTRING:
1836 value.c = lua_tolstring(L, slot, &value.l);
1837 break;
1838 case LUA_TNIL:
1839 case LUA_TNONE:
1840 break;
1841 default:
1842 return luaL_error(L, "string or nil expected");
1843 }
1844 tex_set_tex_toks_register(index, value, flags, state);
1845 }
1846 return 0;
1847}
1848
1849
1850
1851static int texlib_scantoks(lua_State *L)
1852{
1853 int index = 0;
1854 int flags = 0;
1855 int slot = lmt_check_for_flags(L, 1, &flags, 1, 0);
1856 int state = texlib_aux_check_for_index(L, slot++, "toks", &index, internal_toks_cmd, register_toks_cmd, internal_toks_base, register_toks_base,max_toks_register_index, 0);
1857 if (state >= 0) {
1858 lstring value = { .c = NULL, .l = 0 };
1859 int cattable = lmt_checkinteger(L, slot++);
1860 switch (lua_type(L, slot)) {
1861 case LUA_TSTRING:
1862 value.c = lua_tolstring(L, slot, &value.l);
1863 break;
1864 case LUA_TNIL:
1865 case LUA_TNONE:
1866 break;
1867 default:
1868 return luaL_error(L, "string or nil expected");
1869 }
1870 tex_scan_tex_toks_register(index, cattable, value, flags, state);
1871 }
1872 return 0;
1873}
1874
1875static int texlib_gettoks(lua_State *L)
1876{
1877 int index;
1878 int slot = 1;
1879 int state = texlib_aux_check_for_index(L, slot++, "toks", &index, internal_toks_cmd, register_toks_cmd, internal_toks_base, register_toks_base, max_toks_register_index, 0);
1880 if (state >= 0) {
1881 if (lua_toboolean(L, slot)) {
1882 lmt_token_register_to_lua(L, state ? toks_parameter(index) : toks_register(index), 0);
1883 } else {
1884
1885 strnumber value = tex_get_tex_toks_register(index, state);
1886 lua_pushstring(L, tex_to_cstring(value));
1887 tex_flush_str(value);
1888 }
1889 } else {
1890 lua_pushnil(L);
1891 return 1;
1892 }
1893 return 1;
1894}
1895
1896static int texlib_getmark(lua_State *L)
1897{
1898 if (lua_gettop(L) == 0) {
1899 lua_pushinteger(L, lmt_mark_state.mark_data.ptr);
1900 return 1;
1901 } else if (lua_type(L, 1) == LUA_TSTRING) {
1902 int mark = -1;
1903 const char *s = lua_tostring(L, 1);
1904 if (lua_key_eq(s, top)) {
1905 mark = top_marks_code;
1906 } else if (lua_key_eq(s, first)) {
1907 mark = first_marks_code;
1908 } else if (lua_key_eq(s, bottom)) {
1909 mark = bot_marks_code;
1910 } else if (lua_key_eq(s, splitfirst)) {
1911 mark = split_first_marks_code;
1912 } else if (lua_key_eq(s, splitbottom)) {
1913 mark = split_bot_marks_code;
1914 } else if (lua_key_eq(s, current)) {
1915 mark = current_marks_code;
1916 }
1917 if (mark >= 0) {
1918 int index = lmt_optinteger(L, 2, 0);
1919 if (index >= 0 && index <= lmt_mark_state.mark_data.ptr) {
1920 halfword ptr = tex_get_some_mark(mark, index);
1921 if (ptr) {
1922 char *str = tex_tokenlist_to_tstring(ptr, 1, NULL, 0, 0, 0, 0, 1);
1923 if (str) {
1924 lua_pushstring(L, str);
1925 } else {
1926 lua_pushliteral(L, "");
1927 }
1928 return 1;
1929 }
1930 } else {
1931 luaL_error(L, "valid mark class expected");
1932 }
1933 }
1934 }
1935 lua_pushnil(L);
1936 return 1;
1937}
1938
1939int lmt_get_box_id(lua_State *L, int i, int report)
1940{
1941 int index = -1;
1942 switch (lua_type(L, i)) {
1943 case LUA_TSTRING:
1944 {
1945 size_t len = 0;
1946 const char *str = lua_tolstring(L, i, &len);
1947 int cs = tex_string_locate_only(str, len);
1948 int cmd = eq_type(cs);
1949 switch (cmd) {
1950 case char_given_cmd:
1951 case integer_cmd:
1952 index = eq_value(cs);
1953 break;
1954 case register_integer_cmd:
1955 index = register_integer_number(eq_value(cs));
1956 break;
1957 default:
1958
1959 break;
1960 }
1961 break;
1962 }
1963 case LUA_TNUMBER:
1964 index = lmt_tointeger(L, i);
1965 default:
1966 break;
1967 }
1968 if (index >= 0 && index <= max_box_register_index) {
1969 return index;
1970 } else {
1971 if (report) {
1972 luaL_error(L, "string or a number within range expected");
1973 }
1974 return -1;
1975 }
1976}
1977
1978static int texlib_getbox(lua_State *L)
1979{
1980 halfword index = lmt_get_box_id(L, 1, 1);
1981 lmt_node_list_to_lua(L, index >= 0 ? tex_get_tex_box_register(index, 0) : null);
1982 return 1;
1983}
1984
1985static int texlib_splitbox(lua_State *L)
1986{
1987 int index = lmt_get_box_id(L, 1, 1);
1988 if (index >= 0) {
1989 if (lua_isnumber(L, 2)) {
1990 int packing = packing_additional;
1991 switch (lua_type(L, 3)) {
1992 case LUA_TSTRING:
1993 {
1994 const char *str = lua_tostring(L, 3);
1995 if (lua_key_eq(str, exactly)) {
1996 packing = packing_exactly;
1997 } else if (lua_key_eq(str, additional)) {
1998 packing = packing_additional;
1999 }
2000 break;
2001 }
2002 case LUA_TNUMBER:
2003 {
2004 packing = lmt_tointeger(L, 3);
2005 if (packing != packing_exactly && packing != packing_additional) {
2006 packing = packing_exactly;
2007 luaL_error(L, "wrong mode in splitbox");
2008 }
2009 break;
2010 }
2011 }
2012 lmt_node_list_to_lua(L, tex_vsplit(index, lmt_toroundnumber(L, 2), packing));
2013 } else {
2014
2015 lua_pushnil(L);
2016 }
2017 } else {
2018 lua_pushnil(L);
2019 }
2020 return 1;
2021}
2022
2023
2024
2025static int texlib_isbox(lua_State *L)
2026{
2027 lua_pushboolean(L, lmt_get_box_id(L, 1, 0) >= 0);
2028 return 1;
2029}
2030
2031static int texlib_setbox(lua_State *L)
2032{
2033 int flags = 0;
2034 int slot = lmt_check_for_flags(L, 1, &flags, 1, 0);
2035 int index = lmt_get_box_id(L, slot++, 1);
2036 if (index >= 0) {
2037 halfword box = null;
2038 switch (lua_type(L, slot)) {
2039 case LUA_TBOOLEAN:
2040 if (lua_toboolean(L, slot)) {
2041 return 0;
2042 } else {
2043 box = null;
2044 break;
2045 }
2046 case LUA_TNIL:
2047 case LUA_TNONE:
2048 break;
2049 default:
2050 box = lmt_node_list_from_lua(L, slot);
2051 if (box) {
2052 switch (node_type(box)) {
2053 case hlist_node:
2054 case vlist_node:
2055 break;
2056 default:
2057 return luaL_error(L, "invalid node type %s passed", get_node_name(node_type(box)));
2058 }
2059 }
2060 break;
2061 }
2062 tex_set_tex_box_register(index, box, flags, 0);
2063 }
2064 return 0;
2065}
2066
2067
2068
2069static int texlib_setlccode(lua_State *L)
2070{
2071 int top = lua_gettop(L);
2072 if (top >= 2) {
2073 quarterword level;
2074 int slot = lmt_check_for_level(L, 1, &level, cur_level);
2075 int ch1 = lmt_checkinteger(L, slot++);
2076 if (character_in_range(ch1)) {
2077 halfword ch2 = lmt_checkhalfword(L, slot++);
2078 if (character_in_range(ch2)) {
2079 tex_set_lc_code(ch1, ch2, level);
2080 if (slot <= top) {
2081 halfword ch3 = lmt_checkhalfword(L, slot);
2082 if (character_in_range(ch3)) {
2083 tex_set_uc_code(ch1, ch3, level);
2084 } else {
2085 texlib_aux_show_character_error(L, ch3);
2086 }
2087 }
2088 } else {
2089 texlib_aux_show_character_error(L, ch2);
2090 }
2091 } else {
2092 texlib_aux_show_character_error(L, ch1);
2093 }
2094 }
2095 return 0;
2096}
2097
2098static int texlib_setuccode(lua_State *L)
2099{
2100 int top = lua_gettop(L);
2101 if (top >= 2) {
2102 quarterword level;
2103 int slot = lmt_check_for_level(L, 1, &level, cur_level);
2104 int ch1 = lmt_checkinteger(L, slot++);
2105 if (character_in_range(ch1)) {
2106 halfword ch2 = lmt_checkhalfword(L, slot++);
2107 if (character_in_range(ch2)) {
2108 tex_set_uc_code(ch1, ch2, level);
2109 if (slot <= top) {
2110 halfword ch3 = lmt_checkhalfword(L, slot);
2111 if (character_in_range(ch3)) {
2112 tex_set_lc_code(ch1, ch3, level);
2113 } else {
2114 texlib_aux_show_character_error(L, ch3);
2115 }
2116 }
2117 } else {
2118 texlib_aux_show_character_error(L, ch2);
2119 }
2120 } else {
2121 texlib_aux_show_character_error(L, ch1);
2122 }
2123 }
2124 return 0;
2125}
2126
2127static int texlib_setsfcode(lua_State *L)
2128{
2129 int top = lua_gettop(L);
2130 if (top >= 2) {
2131 quarterword level;
2132 int slot = lmt_check_for_level(L, 1, &level, cur_level);
2133 int ch = lmt_checkinteger(L, slot++);
2134 if (character_in_range(ch)) {
2135 halfword val = lmt_checkhalfword(L, slot);
2136 if (half_in_range(val)) {
2137 tex_set_sf_code(ch, val, level);
2138 } else {
2139 texlib_aux_show_half_error(L, val);
2140 }
2141 } else {
2142 texlib_aux_show_character_error(L, ch);
2143 }
2144 }
2145 return 0;
2146}
2147
2148static int texlib_sethccode(lua_State *L)
2149{
2150 int top = lua_gettop(L);
2151 if (top >= 2) {
2152 quarterword level;
2153 int slot = lmt_check_for_level(L, 1, &level, cur_level);
2154 int ch = lmt_checkinteger(L, slot++);
2155 if (character_in_range(ch)) {
2156 halfword val = lmt_checkhalfword(L, slot);
2157 if (half_in_range(val)) {
2158 tex_set_hc_code(ch, val, level);
2159 } else {
2160 texlib_aux_show_half_error(L, val);
2161 }
2162 } else {
2163 texlib_aux_show_character_error(L, ch);
2164 }
2165 }
2166 return 0;
2167}
2168
2169static int texlib_sethmcode(lua_State *L)
2170{
2171 int top = lua_gettop(L);
2172 if (top >= 2) {
2173 quarterword level;
2174 int slot = lmt_check_for_level(L, 1, &level, cur_level);
2175 int ch = lmt_checkinteger(L, slot++);
2176 if (character_in_range(ch)) {
2177 halfword val = lmt_checkhalfword(L, slot);
2178 tex_set_hm_code(ch, val, level);
2179 } else {
2180 texlib_aux_show_character_error(L, ch);
2181 }
2182 }
2183 return 0;
2184}
2185
2186static int texlib_setamcode(lua_State *L)
2187{
2188 int top = lua_gettop(L);
2189 if (top >= 2) {
2190 quarterword level;
2191 int slot = lmt_check_for_level(L, 1, &level, cur_level);
2192 int ch = lmt_checkinteger(L, slot++);
2193 if (character_in_range(ch)) {
2194 halfword val = lmt_checkhalfword(L, slot);
2195 tex_set_am_code(ch, val, level);
2196 } else {
2197 texlib_aux_show_character_error(L, ch);
2198 }
2199 }
2200 return 0;
2201}
2202
2203static int texlib_getlccode(lua_State *L)
2204{
2205 int ch = lmt_checkinteger(L, 1);
2206 if (character_in_range(ch)) {
2207 lua_pushinteger(L, tex_get_lc_code(ch));
2208 } else {
2209 texlib_aux_show_character_error(L, ch);
2210 lua_pushinteger(L, 0);
2211 }
2212 return 1;
2213}
2214
2215static int texlib_getuccode(lua_State *L)
2216{
2217 int ch = lmt_checkinteger(L, 1);
2218 if (character_in_range(ch)) {
2219 lua_pushinteger(L, tex_get_uc_code(ch));
2220 } else {
2221 texlib_aux_show_character_error(L, ch);
2222 lua_pushinteger(L, 0);
2223 }
2224 return 1;
2225}
2226
2227static int texlib_getsfcode(lua_State *L)
2228{
2229 int ch = lmt_checkinteger(L, 1);
2230 if (character_in_range(ch)) {
2231 lua_pushinteger(L, tex_get_sf_code(ch));
2232 } else {
2233 texlib_aux_show_character_error(L, ch);
2234 lua_pushinteger(L, 0);
2235 }
2236 return 1;
2237}
2238
2239static int texlib_gethccode(lua_State *L)
2240{
2241 int ch = lmt_checkinteger(L, 1);
2242 if (character_in_range(ch)) {
2243 lua_pushinteger(L, tex_get_hc_code(ch));
2244 } else {
2245 texlib_aux_show_character_error(L, ch);
2246 lua_pushinteger(L, 0);
2247 }
2248 return 1;
2249}
2250
2251static int texlib_gethmcode(lua_State *L)
2252{
2253 int ch = lmt_checkinteger(L, 1);
2254 if (character_in_range(ch)) {
2255 lua_pushinteger(L, tex_get_hm_code(ch));
2256 } else {
2257 texlib_aux_show_character_error(L, ch);
2258 lua_pushinteger(L, 0);
2259 }
2260 return 1;
2261}
2262
2263static int texlib_getamcode(lua_State *L)
2264{
2265 int ch = lmt_checkinteger(L, 1);
2266 if (character_in_range(ch)) {
2267 lua_pushinteger(L, tex_get_am_code(ch));
2268 } else {
2269 texlib_aux_show_character_error(L, ch);
2270 lua_pushinteger(L, 0);
2271 }
2272 return 1;
2273}
2274
2275
2276
2277static int texlib_setcatcode(lua_State *L)
2278{
2279 int top = lua_gettop(L);
2280 if (top >= 2) {
2281 quarterword level;
2282 int slot = lmt_check_for_level(L, 1, &level, cur_level);
2283 int cattable = ((top - slot + 1) >= 3) ? lmt_checkinteger(L, slot++) : cat_code_table_par;
2284 int ch = lmt_checkinteger(L, slot++);
2285 if (character_in_range(ch)) {
2286 halfword val = lmt_checkhalfword(L, slot);
2287 if (catcode_in_range(val)) {
2288 tex_set_cat_code(cattable, ch, val, level);
2289 } else {
2290 texlib_aux_show_catcode_error(L, val);
2291 }
2292 } else {
2293 texlib_aux_show_character_error(L, ch);
2294 }
2295 }
2296 return 0;
2297}
2298
2299
2300
2301static int texlib_getcatcode(lua_State *L)
2302{
2303 int slot = 1;
2304 int cattable = (lua_gettop(L) > 1) ? lmt_checkinteger(L, slot++) : cat_code_table_par;
2305 int ch = lmt_checkinteger(L, slot);
2306 if (character_in_range(ch)) {
2307 lua_pushinteger(L, tex_get_cat_code(cattable, ch));
2308 } else {
2309 texlib_aux_show_character_error(L, ch);
2310 lua_pushinteger(L, 12);
2311 }
2312 return 1;
2313}
2314
2315
2319
2320static int texlib_setmathcode(lua_State *L)
2321{
2322 quarterword level;
2323 int slot = lmt_check_for_level(L, 1, &level, cur_level);
2324 int ch = lmt_checkinteger(L, slot++);
2325 if (character_in_range(ch)) {
2326 halfword cval, fval, chval;
2327 switch (lua_type(L, slot)) {
2328 case LUA_TNUMBER:
2329 cval = lmt_checkhalfword(L, slot++);
2330 fval = lmt_checkhalfword(L, slot++);
2331 chval = lmt_checkhalfword(L, slot);
2332 break;
2333 case LUA_TTABLE:
2334 lua_rawgeti(L, slot, 1);
2335 cval = lmt_checkhalfword(L, -1);
2336 lua_rawgeti(L, slot, 2);
2337 fval = lmt_checkhalfword(L, -1);
2338 lua_rawgeti(L, slot, 3);
2339 chval = lmt_checkhalfword(L, -1);
2340 lua_pop(L, 3);
2341 break;
2342 default:
2343 return luaL_error(L, "number of table expected");
2344 }
2345 if (class_in_range(cval)) {
2346 if (family_in_range(fval)) {
2347 if (character_in_range(chval)) {
2348 mathcodeval m;
2349 m.character_value = chval;
2350 m.class_value = (short) cval;
2351 m.family_value = (short) fval;
2352 tex_set_math_code(ch, m, (quarterword) (level));
2353 } else {
2354 texlib_aux_show_character_error(L, chval);
2355 }
2356 } else {
2357 texlib_aux_show_family_error(L, fval);
2358 }
2359 } else {
2360 texlib_aux_show_class_error(L, cval);
2361 }
2362 } else {
2363 texlib_aux_show_character_error(L, ch);
2364 }
2365return 0;
2366}
2367
2368static int texlib_getmathcode(lua_State* L)
2369{
2370 mathcodeval mval = tex_no_math_code();
2371 int ch = lmt_checkinteger(L, -1);
2372 if (character_in_range(ch)) {
2373 mval = tex_get_math_code(ch);
2374 } else {
2375 texlib_aux_show_character_error(L, ch);
2376 }
2377 lua_createtable(L, 3, 0);
2378 lua_pushinteger(L, mval.class_value);
2379 lua_rawseti(L, -2, 1);
2380 lua_pushinteger(L, mval.family_value);
2381 lua_rawseti(L, -2, 2);
2382 lua_pushinteger(L, mval.character_value);
2383 lua_rawseti(L, -2, 3);
2384 return 1;
2385}
2386
2387static int texlib_getmathcodes(lua_State* L)
2388{
2389 mathcodeval mval = tex_no_math_code();
2390 int ch = lmt_checkinteger(L, -1);
2391 if (character_in_range(ch)) {
2392 mval = tex_get_math_code(ch);
2393 } else {
2394 texlib_aux_show_character_error(L, ch);
2395 }
2396 lua_pushinteger(L, mval.class_value);
2397 lua_pushinteger(L, mval.family_value);
2398 lua_pushinteger(L, mval.character_value);
2399 return 3;
2400}
2401
2402
2406
2407static int texlib_setdelcode(lua_State* L)
2408{
2409 quarterword level;
2410 int slot = lmt_check_for_level(L, 1, &level, cur_level);
2411
2412 int ch = lmt_checkinteger(L, slot++);
2413 if (character_in_range(ch)) {
2414 halfword sfval, scval, lfval, lcval;
2415 switch (lua_type(L, slot)) {
2416 case LUA_TNUMBER:
2417 sfval = lmt_checkhalfword(L, slot++);
2418 scval = lmt_checkhalfword(L, slot++);
2419 lfval = lmt_checkhalfword(L, slot++);
2420 lcval = lmt_checkhalfword(L, slot);
2421 break;
2422 case LUA_TTABLE:
2423 lua_rawgeti(L, slot, 1);
2424 sfval = lmt_checkhalfword(L, -1);
2425 lua_rawgeti(L, slot, 2);
2426 scval = lmt_checkhalfword(L, -1);
2427 lua_rawgeti(L, slot, 3);
2428 lfval = lmt_checkhalfword(L, -1);
2429 lua_rawgeti(L, slot, 4);
2430 lcval = lmt_checkhalfword(L, -1);
2431 lua_pop(L, 4);
2432 break;
2433 default:
2434 return luaL_error(L, "number of table expected");
2435 }
2436 if (family_in_range(sfval)) {
2437 if (character_in_range(scval)) {
2438 if (family_in_range(lfval)) {
2439 if (character_in_range(lcval)) {
2440 delcodeval d;
2441 d.small.class_value = 0;
2442 d.small.family_value = (short) sfval;
2443 d.small.character_value = scval;
2444 d.large.class_value = 0;
2445 d.large.family_value = (short) lfval;
2446 d.large.character_value = lcval;
2447 tex_set_del_code(ch, d, (quarterword) (level));
2448 }
2449 else {
2450 texlib_aux_show_character_error(L, lcval);
2451 }
2452 }
2453 else {
2454 texlib_aux_show_family_error(L, lfval);
2455 }
2456 }
2457 else {
2458 texlib_aux_show_character_error(L, scval);
2459 }
2460 }
2461 else {
2462 texlib_aux_show_family_error(L, sfval);
2463 }
2464 }
2465 else {
2466 texlib_aux_show_character_error(L, ch);
2467 }
2468 return 0;
2469}
2470
2471static int texlib_getdelcode(lua_State* L)
2472{
2473 delcodeval dval = tex_no_del_code();
2474 int ch = lmt_checkinteger(L, -1);
2475 if (character_in_range(ch)) {
2476 dval = tex_get_del_code(ch);
2477 } else {
2478 texlib_aux_show_character_error(L, ch);
2479 }
2480 if (tex_has_del_code(dval)) {
2481 lua_createtable(L, 4, 0);
2482 lua_pushinteger(L, dval.small.family_value);
2483 lua_rawseti(L, -2, 1);
2484 lua_pushinteger(L, dval.small.character_value);
2485 lua_rawseti(L, -2, 2);
2486 lua_pushinteger(L, dval.large.family_value);
2487 lua_rawseti(L, -2, 3);
2488 lua_pushinteger(L, dval.large.character_value);
2489 lua_rawseti(L, -2, 4);
2490 } else {
2491 lua_pushnil(L);
2492 }
2493 return 1;
2494}
2495
2496static int texlib_getdelcodes(lua_State* L)
2497{
2498 delcodeval dval = tex_no_del_code();
2499 int ch = lmt_checkinteger(L, -1);
2500 if (character_in_range(ch)) {
2501 dval = tex_get_del_code(ch);
2502 } else {
2503 texlib_aux_show_character_error(L, ch);
2504 }
2505 if (tex_has_del_code(dval)) {
2506 lua_pushinteger(L, dval.small.family_value);
2507 lua_pushinteger(L, dval.small.character_value);
2508 lua_pushinteger(L, dval.large.family_value);
2509 lua_pushinteger(L, dval.large.character_value);
2510 } else {
2511 lua_pushnil(L);
2512 }
2513 return 4;
2514}
2515
2516static halfword texlib_aux_getdimension(lua_State* L, int index)
2517{
2518 switch (lua_type(L, index)) {
2519 case LUA_TNUMBER:
2520 return lmt_toroundnumber(L, index);
2521 case LUA_TSTRING:
2522 return texlib_aux_dimension_to_number(L, lua_tostring(L, index));
2523 default:
2524 luaL_error(L, "string or number expected (dimension)");
2525 return 0;
2526 }
2527}
2528
2529static halfword texlib_aux_getinteger(lua_State* L, int index)
2530{
2531 switch (lua_type(L, index)) {
2532 case LUA_TNUMBER:
2533 return lmt_toroundnumber(L, index);
2534 default:
2535 luaL_error(L, "number expected (integer)");
2536 return 0;
2537 }
2538}
2539
2540static halfword texlib_toparshape(lua_State *L, int i)
2541{
2542 if (lua_type(L, i) == LUA_TTABLE) {
2543 halfword n = (halfword) luaL_len(L, i);
2544 if (n > 0) {
2545 halfword p = tex_new_specification_node(n, par_shape_code, 0);
2546 lua_push_key(repeat);
2547 if (lua_rawget(L, -2) == LUA_TBOOLEAN && lua_toboolean(L, -1)) {
2548 tex_set_specification_option(p, specification_option_repeat);
2549 }
2550 lua_pop(L, 1);
2551
2552 for (int j = 1; j <= n; j++) {
2553 halfword indent = 0;
2554 halfword width = 0;
2555 if (lua_rawgeti(L, i, j) == LUA_TTABLE) {
2556 if (lua_rawgeti(L, -1, 1) == LUA_TNUMBER) {
2557 indent = lmt_toroundnumber(L, -1);
2558 if (lua_rawgeti(L, -2, 2) == LUA_TNUMBER) {
2559 width = lmt_toroundnumber(L, -1);
2560 }
2561 lua_pop(L, 1);
2562 }
2563 lua_pop(L, 1);
2564 }
2565 lua_pop(L, 1);
2566 tex_set_specification_indent(p, j, indent);
2567 tex_set_specification_width(p, j, width);
2568 }
2569 return p;
2570 }
2571 }
2572 return null;
2573}
2574
2575static int texlib_shiftparshape(lua_State *L)
2576{
2577 if (par_shape_par) {
2578 tex_shift_specification_list(par_shape_par, lmt_tointeger(L, 1), lua_toboolean(L, 2));
2579 }
2580 return 0;
2581}
2582
2583static int texlib_snapshotpar(lua_State *L)
2584{
2585 halfword par = tex_find_par_par(cur_list.head);
2586 if (par) {
2587 if (lua_type(L, 1) == LUA_TNUMBER) {
2588 tex_snapshot_par(par, lmt_tointeger(L, 1));
2589 }
2590 lua_pushinteger(L, par_state(par));
2591 return 1;
2592 } else {
2593 return 0;
2594 }
2595}
2596
2597static int texlib_getparstate(lua_State *L)
2598{
2599 lua_createtable(L, 0, 7);
2600 lua_push_integer_at_key(L, hsize, hsize_par);
2601 lua_push_integer_at_key(L, leftskip, left_skip_par ? glue_amount(left_skip_par) : 0);
2602 lua_push_integer_at_key(L, rightskip, right_skip_par ? glue_amount(right_skip_par) : 0);
2603 lua_push_integer_at_key(L, hangindent, hang_indent_par);
2604 lua_push_integer_at_key(L, hangafter, hang_after_par);
2605 lua_push_integer_at_key(L, parindent, par_indent_par);
2606 lua_push_specification_at_key(L, parshape, par_shape_par);
2607 return 1;
2608}
2609
2610static int texlib_set_item(lua_State* L, int index, int prefixes)
2611{
2612 int flags = 0;
2613 int slot = lmt_check_for_flags(L, index, &flags, prefixes, 0);
2614 size_t sl;
2615 const char *st = lua_tolstring(L, slot++, &sl);
2616 if (sl > 0) {
2617 int cs = tex_string_locate_only(st, sl);
2618 if (cs != undefined_control_sequence && has_eq_flag_bits(cs, primitive_flag_bit)) {
2619 int cmd = eq_type(cs);
2620 switch (cmd) {
2621 case internal_integer_cmd:
2622 case register_integer_cmd:
2623 switch (lua_type(L, slot)) {
2624 case LUA_TNUMBER:
2625 {
2626 int n = lmt_tointeger(L, slot++);
2627 if (cmd == register_integer_cmd) {
2628 tex_word_define(flags, eq_value(cs), n);
2629 } else {
2630 tex_assign_internal_integer_value(lua_toboolean(L, slot) ? add_frozen_flag(flags) : flags, eq_value(cs), n);
2631 }
2632 break;
2633 }
2634 default:
2635 luaL_error(L, "number expected");
2636 break;
2637 }
2638 return 1;
2639 case internal_posit_cmd:
2640 case register_posit_cmd:
2641 switch (lua_type(L, slot)) {
2642 case LUA_TNUMBER:
2643 {
2644 int n = tex_double_to_posit(lua_tonumber(L, slot++)).v;
2645 if (cmd == register_posit_cmd) {
2646 tex_word_define(flags, eq_value(cs), n);
2647 } else {
2648 tex_assign_internal_posit_value(lua_toboolean(L, slot) ? add_frozen_flag(flags) : flags, eq_value(cs), n);
2649 }
2650 break;
2651 }
2652
2653
2654
2655
2656
2657 default:
2658 luaL_error(L, "number expected");
2659 break;
2660 }
2661 return 1;
2662 case internal_dimension_cmd:
2663 case register_dimension_cmd:
2664 {
2665 halfword n = texlib_aux_getdimension(L, slot);
2666 if (cmd == register_dimension_cmd) {
2667 tex_word_define(flags, eq_value(cs), n);
2668 } else {
2669 tex_assign_internal_dimension_value(lua_toboolean(L, slot) ? add_frozen_flag(flags) : flags, eq_value(cs), n);
2670 }
2671 return 1;
2672 }
2673 case internal_glue_cmd:
2674 case register_glue_cmd:
2675 switch (lua_type(L, slot)) {
2676 case LUA_TNUMBER:
2677 {
2678 int top = lua_gettop(L);
2679 halfword value = tex_copy_node(zero_glue);
2680 glue_amount(value) = lmt_toroundnumber(L, slot++);
2681 if (slot <= top) {
2682 glue_stretch(value) = lmt_toroundnumber(L, slot++);
2683 if (slot <= top) {
2684 glue_shrink(value) = lmt_toroundnumber(L, slot++);
2685 if (slot <= top) {
2686 glue_stretch_order(value) = tex_checked_glue_order(lmt_tohalfword(L, slot++));
2687 if (slot <= top) {
2688 glue_shrink_order(value) = tex_checked_glue_order(lmt_tohalfword(L, slot));
2689 }
2690 }
2691 }
2692 }
2693 if (cmd == register_glue_cmd) {
2694 tex_word_define(flags, eq_value(cs), value);
2695 } else {
2696 tex_assign_internal_skip_value(lua_toboolean(L, slot) ? add_frozen_flag(flags) : flags, eq_value(cs), value);
2697 }
2698 break;
2699 }
2700 case LUA_TUSERDATA:
2701 {
2702 halfword n = lmt_check_isnode(L, slot);
2703 if (node_type(n) == glue_spec_node) {
2704 if (cmd == register_glue_cmd) {
2705 tex_word_define(flags, eq_value(cs), n);
2706 } else {
2707 tex_assign_internal_skip_value(lua_toboolean(L, slot) ? add_frozen_flag(flags) : flags, eq_value(cs), n);
2708 }
2709 } else {
2710 luaL_error(L, "gluespec node expected");
2711 }
2712 break;
2713 }
2714 default:
2715 luaL_error(L, "number or node expected");
2716 break;
2717 }
2718 return 1;
2719 case internal_toks_cmd:
2720 case register_toks_cmd:
2721 switch (lua_type(L, slot)) {
2722 case LUA_TSTRING:
2723 {
2724 int t = lmt_token_list_from_lua(L, slot);
2725
2726 tex_define(flags, eq_value(cs), cmd == internal_toks_cmd ? internal_toks_reference_cmd : register_toks_reference_cmd, t);
2727 break;
2728 }
2729 default:
2730 luaL_error(L, "string expected");
2731 break;
2732 }
2733 return 1;
2734 case page_property_cmd:
2735
2736 switch (eq_value(cs)) {
2737
2738
2739
2740
2741
2742 case page_depth_code:
2743 lmt_page_builder_state.depth = texlib_aux_getdimension(L, slot);
2744 break;
2745
2746
2747
2748
2749
2750 case insert_storing_code:
2751 lmt_insert_state.storing = texlib_aux_getinteger(L, slot);
2752 break;
2753
2754
2755
2756 default:
2757 return 0;
2758 }
2759 case auxiliary_cmd:
2760
2761 switch (eq_value(cs)) {
2762 case space_factor_code:
2763 cur_list.space_factor = texlib_aux_getinteger(L, slot);
2764 return 1;
2765 case prev_depth_code:
2766 cur_list.prev_depth = texlib_aux_getdimension(L, slot);
2767 return 1;
2768 case prev_graf_code:
2769 cur_list.prev_graf = texlib_aux_getinteger(L, slot);
2770 return 1;
2771 default:
2772 return 0;
2773 }
2774 case box_property_cmd:
2775
2776 return 0;
2777 case specification_cmd:
2778 {
2779 int chr = internal_specification_number(eq_value(cs));
2780 switch (chr) {
2781 case par_shape_code:
2782 {
2783 halfword p = texlib_toparshape(L, slot);
2784 tex_define(flags, eq_value(cs), specification_reference_cmd, p);
2785
2786 if (is_frozen(flags) && cur_mode == hmode) {
2787 tex_update_par_par(specification_reference_cmd, chr);
2788 }
2789 break;
2790 }
2791 }
2792 return 0;
2793 }
2794 }
2795 }
2796 }
2797 return 0;
2798}
2799
2800static int texlib_set(lua_State *L)
2801{
2802 texlib_set_item(L, 1, 1);
2803 return 0;
2804}
2805
2806static int texlib_newindex(lua_State *L)
2807{
2808 if (! texlib_set_item(L, 2, 0)) {
2809 lua_rawset(L, 1);
2810 }
2811 return 0;
2812}
2813
2814static int texlib_aux_convert(lua_State *L, int code)
2815{
2816 int classification = some_convert_classification[code];
2817 int value = classification == classification_integer ? lmt_checkinteger(L, 2) : 0;
2818 int texstr = tex_the_convert_string(code, value);
2819 if (texstr) {
2820 lua_pushstring(L, tex_to_cstring(texstr));
2821 tex_flush_str(texstr);
2822 } else {
2823 lua_pushnil(L);
2824 }
2825 return 1;
2826}
2827
2828
2829
2830static int texlib_aux_scan_internal(lua_State *L, int cmd, int code, int values)
2831{
2832 int retval = 1 ;
2833 int save_cur_val = cur_val;
2834 int save_cur_val_level = cur_val_level;
2835 tex_scan_something_simple(cmd, code);
2836 switch (cur_val_level) {
2837 case integer_val_level:
2838 case attribute_val_level:
2839 case dimension_val_level:
2840 lua_pushinteger(L, cur_val);
2841 break;
2842 case posit_val_level:
2843 lua_pushnumber(L, tex_posit_to_double(cur_val));
2844 break;
2845 case glue_val_level:
2846 case muglue_val_level:
2847 switch (values) {
2848 case 0:
2849 lua_pushinteger(L, glue_amount(cur_val));
2850 tex_flush_node(cur_val);
2851 break;
2852 case 1:
2853 lua_pushinteger(L, glue_amount(cur_val));
2854 lua_pushinteger(L, glue_stretch(cur_val));
2855 lua_pushinteger(L, glue_shrink(cur_val));
2856 lua_pushinteger(L, glue_stretch_order(cur_val));
2857 lua_pushinteger(L, glue_shrink_order(cur_val));
2858 tex_flush_node(cur_val);
2859 retval = 5;
2860 break;
2861 default:
2862 lmt_push_node_fast(L, cur_val);
2863 break;
2864 }
2865 break;
2866 case list_val_level:
2867 lmt_push_node_fast(L, cur_val);
2868 break;
2869 default:
2870 {
2871 int texstr = tex_the_scanned_result();
2872 const char *str = tex_to_cstring(texstr);
2873 if (str) {
2874 lua_pushstring(L, str);
2875 } else {
2876 lua_pushnil(L);
2877 }
2878 tex_flush_str(texstr);
2879 }
2880 break;
2881 }
2882 cur_val = save_cur_val;
2883 cur_val_level = save_cur_val_level;
2884 return retval;
2885}
2886
2887static int texlib_aux_item(lua_State *L, int code, int all)
2888{
2889 if (some_item_classification[code] == classification_no_arguments) {
2890 return texlib_aux_scan_internal(L, convert_cmd, code, all);
2891 } else {
2892 return 0;
2893 }
2894}
2895
2896static int texlib_setmath(lua_State *L)
2897{
2898 int top = lua_gettop(L);
2899 if (top >= 3) {
2900 quarterword level;
2901 int slot = lmt_check_for_level(L, 1, &level, cur_level);
2902 int param = lmt_get_math_parameter(L, slot++, -1);
2903 int style = lmt_get_math_style(L, slot++, -1);
2904 if (param < 0 || style < 0) {
2905
2906 } else {
2907 switch (math_parameter_value_type(param)) {
2908 case math_integer_parameter:
2909 case math_dimension_parameter:
2910 case math_style_parameter:
2911 tex_def_math_parameter(style, param, (scaled) lmt_optroundnumber(L, slot, 0), level, indirect_math_regular, 0);
2912 break;
2913 case math_muglue_parameter:
2914 {
2915 halfword p = tex_copy_node(zero_glue);
2916 glue_amount(p) = lmt_optroundnumber(L, slot++, 0);
2917 glue_stretch(p) = lmt_optroundnumber(L, slot++, 0);
2918 glue_shrink(p) = lmt_optroundnumber(L, slot++, 0);
2919 glue_stretch_order(p) = tex_checked_glue_order(lmt_optroundnumber(L, slot++, 0));
2920 glue_shrink_order(p) = tex_checked_glue_order(lmt_optroundnumber(L, slot, 0));
2921 tex_def_math_parameter(style, param, (scaled) p, level, indirect_math_regular, 0);
2922 break;
2923 }
2924 }
2925 }
2926 }
2927 return 0;
2928}
2929
2930static int texlib_getmath(lua_State *L)
2931{
2932 if (lua_gettop(L) == 2) {
2933 int param = lmt_get_math_parameter(L, 1, -1);
2934 int style = lmt_get_math_style(L, 2, -1);
2935 if (param >= 0 && style >= 0) {
2936 scaled value = tex_get_math_parameter(style, param, NULL);
2937 if (value != undefined_math_parameter) {
2938 switch (math_parameter_value_type(param)) {
2939 case math_integer_parameter:
2940 case math_dimension_parameter:
2941 case math_style_parameter:
2942 lua_pushinteger(L, value);
2943 return 1;
2944 case math_muglue_parameter:
2945 if (value <= thick_muskip_code) {
2946 value = glue_parameter(value);
2947 }
2948 lua_pushinteger(L, glue_amount(value));
2949 lua_pushinteger(L, glue_stretch(value));
2950 lua_pushinteger(L, glue_shrink(value));
2951 lua_pushinteger(L, glue_stretch_order(value));
2952 lua_pushinteger(L, glue_shrink_order(value));
2953 return 5;
2954 }
2955 }
2956 }
2957 }
2958 lua_pushnil(L);
2959 return 1;
2960}
2961
2962
2968
2969static int texlib_getfontname(lua_State *L)
2970{
2971 return texlib_aux_convert(L, font_name_code);
2972}
2973
2974static int texlib_getfontidentifier(lua_State *L)
2975{
2976 return texlib_aux_convert(L, font_identifier_code);
2977}
2978
2979static int texlib_getfontoffamily(lua_State *L)
2980{
2981 int f = lmt_checkinteger(L, 1);
2982 int s = lmt_optinteger(L, 2, 0);
2983 lua_pushinteger(L, tex_fam_fnt(f, s));
2984 return 1;
2985}
2986
2987static int texlib_getnumber(lua_State *L)
2988{
2989 return texlib_aux_convert(L, number_code);
2990}
2991
2992
2993
2994
2995
2996
2997static int texlib_getromannumeral(lua_State *L)
2998{
2999 return texlib_aux_convert(L, roman_numeral_code);
3000}
3001
3002
3007
3008static int texlib_get_internal(lua_State *L, int index, int all)
3009{
3010 if (lua_type(L, index) == LUA_TSTRING) {
3011 size_t l;
3012 const char *s = lua_tolstring(L, index, &l);
3013 if (l == 0) {
3014 return 0;
3015 } else if (lua_key_eq(s, prevdepth)) {
3016 lua_pushinteger(L, cur_list.prev_depth);
3017 return 1;
3018 } else if (lua_key_eq(s, prevgraf)) {
3019 lua_pushinteger(L, cur_list.prev_graf);
3020 return 1;
3021 } else if (lua_key_eq(s, spacefactor)) {
3022 lua_pushinteger(L, cur_list.space_factor);
3023 return 1;
3024 } else {
3025 int cs = tex_string_locate_only(s, l);
3026 if (cs != undefined_control_sequence && has_eq_flag_bits(cs, primitive_flag_bit)) {
3027 int cmd = eq_type(cs);
3028 int code = eq_value(cs);
3029
3033 switch (cmd) {
3034
3038 case some_item_cmd:
3039 return texlib_aux_item(L, code, all);
3040 case convert_cmd:
3041 return texlib_aux_convert(L, code);
3042 case specification_cmd:
3043 return lmt_push_specification(L, specification_parameter(internal_specification_number(code)), all);
3044
3049 case font_property_cmd:
3050 case hyphenation_cmd:
3051 case box_property_cmd:
3052 case define_family_cmd:
3053 case math_parameter_cmd:
3054 case association_cmd:
3055 case register_cmd:
3056 break;
3057
3060 default:
3061 return texlib_aux_scan_internal(L, cmd, code, all);
3062 }
3063 }
3064 }
3065
3066 }
3067 return 0;
3068}
3069
3070static int texlib_get(lua_State *L)
3071{
3072
3073 int ret = texlib_get_internal(L, 1, (lua_type(L, 2) == LUA_TBOOLEAN) ? lua_toboolean(L, 2) : -1);
3074 if (ret) {
3075 return ret;
3076 } else {
3077 lua_pushnil(L);
3078 return 1;
3079 }
3080}
3081
3082static int texlib_index(lua_State *L)
3083{
3084
3085 int ret = texlib_get_internal(L, 2, -1);
3086 if (ret) {
3087 return ret;
3088 } else {
3089 lua_rawget(L, 1);
3090 return 1;
3091 }
3092}
3093
3094static int texlib_getlist(lua_State *L)
3095{
3096 const char *s = lua_tostring(L, 1);
3097 if (! s) {
3098 lua_pushnil(L);
3099 } else if (lua_key_eq(s, pageinserthead)) {
3100 lmt_push_node_fast(L, tex_get_special_node_list(page_insert_list_type, NULL));
3101 } else if (lua_key_eq(s, contributehead)) {
3102 lmt_push_node_fast(L, tex_get_special_node_list(contribute_list_type, NULL));
3103 } else if (lua_key_eq(s, pagehead)) {
3104 lmt_push_node_fast(L, tex_get_special_node_list(page_list_type, NULL));
3105 } else if (lua_key_eq(s, temphead)) {
3106 lmt_push_node_fast(L, tex_get_special_node_list(temp_list_type, NULL));
3107 } else if (lua_key_eq(s, holdhead)) {
3108 lmt_push_node_fast(L, tex_get_special_node_list(hold_list_type, NULL));
3109 } else if (lua_key_eq(s, postadjusthead)) {
3110 lmt_push_node_fast(L, tex_get_special_node_list(post_adjust_list_type, NULL));
3111 } else if (lua_key_eq(s, preadjusthead)) {
3112 lmt_push_node_fast(L, tex_get_special_node_list(pre_adjust_list_type, NULL));
3113 } else if (lua_key_eq(s, postmigratehead)) {
3114 lmt_push_node_fast(L, tex_get_special_node_list(post_migrate_list_type, NULL));
3115 } else if (lua_key_eq(s, premigratehead)) {
3116 lmt_push_node_fast(L, tex_get_special_node_list(pre_migrate_list_type, NULL));
3117 } else if (lua_key_eq(s, alignhead)) {
3118 lmt_push_node_fast(L, tex_get_special_node_list(align_list_type, NULL));
3119 } else if (lua_key_eq(s, pagediscardshead)) {
3120 lmt_push_node_fast(L, tex_get_special_node_list(page_discards_list_type, NULL));
3121 } else if (lua_key_eq(s, splitdiscardshead)) {
3122 lmt_push_node_fast(L, tex_get_special_node_list(split_discards_list_type, NULL));
3123 } else if (lua_key_eq(s, bestpagebreak)) {
3124 lmt_push_node_fast(L, lmt_page_builder_state.best_break);
3125 } else if (lua_key_eq(s, leastpagecost)) {
3126 lua_pushinteger(L, lmt_page_builder_state.least_cost);
3127 } else if (lua_key_eq(s, bestsize)) {
3128 lua_pushinteger(L, lmt_page_builder_state.best_size);
3129 } else if (lua_key_eq(s, insertpenalties)) {
3130 lua_pushinteger(L, lmt_page_builder_state.insert_penalties);
3131 } else if (lua_key_eq(s, insertheights)) {
3132 lua_pushinteger(L, lmt_page_builder_state.insert_heights);
3133 } else {
3134 lua_pushnil(L);
3135 }
3136 return 1;
3137}
3138
3139
3140
3141static int texlib_setlist(lua_State *L)
3142{
3143 const char *s = lua_tostring(L, 1);
3144 if (! s) {
3145
3146 } else if (lua_key_eq(s, bestsize)) {
3147 lmt_page_builder_state.best_size = lmt_toscaled(L, 2);
3148 } else if (lua_key_eq(s, leastpagecost)) {
3149 lmt_page_builder_state.least_cost = lmt_tointeger(L, 2);
3150 } else if (lua_key_eq(s, insertpenalties)) {
3151 lmt_page_builder_state.insert_penalties = lmt_tointeger(L, 2);
3152 } else if (lua_key_eq(s, insertheights)) {
3153 lmt_page_builder_state.insert_heights = lmt_tointeger(L, 2);
3154 } else {
3155 halfword n = null;
3156 if (! lua_isnil(L, 2)) {
3157 n = lmt_check_isnode(L, 2);
3158 }
3159 if (lua_key_eq(s, pageinserthead)) {
3160 tex_set_special_node_list(page_insert_list_type, n);
3161 } else if (lua_key_eq(s, contributehead)) {
3162 tex_set_special_node_list(contribute_list_type, n);
3163 } else if (lua_key_eq(s, pagehead)) {
3164 tex_set_special_node_list(page_list_type, n);
3165 } else if (lua_key_eq(s, temphead)) {
3166 tex_set_special_node_list(temp_list_type, n);
3167 } else if (lua_key_eq(s, pagediscardshead)) {
3168 tex_set_special_node_list(page_discards_list_type, n);
3169 } else if (lua_key_eq(s, splitdiscardshead)) {
3170 tex_set_special_node_list(split_discards_list_type, n);
3171 } else if (lua_key_eq(s, holdhead)) {
3172 tex_set_special_node_list(hold_list_type, n);
3173 } else if (lua_key_eq(s, postadjusthead)) {
3174 tex_set_special_node_list(post_adjust_list_type, n);
3175 } else if (lua_key_eq(s, preadjusthead)) {
3176 tex_set_special_node_list(pre_adjust_list_type, n);
3177 } else if (lua_key_eq(s, postmigratehead)) {
3178 tex_set_special_node_list(post_migrate_list_type, n);
3179 } else if (lua_key_eq(s, premigratehead)) {
3180 tex_set_special_node_list(pre_migrate_list_type, n);
3181 } else if (lua_key_eq(s, alignhead)) {
3182 tex_set_special_node_list(align_list_type, n);
3183 } else if (lua_key_eq(s, bestpagebreak)) {
3184 lmt_page_builder_state.best_break = n;
3185 }
3186 }
3187 return 0;
3188}
3189
3190static void texlib_get_nest_field(lua_State *L, const char *field, list_state_record *r)
3191{
3192
3193 if (lua_key_eq(field, mode)) {
3194 lua_pushinteger(L, r->mode);
3195 } else if (lua_key_eq(field, head) || lua_key_eq(field, list)) {
3196
3197 lmt_push_node_fast(L, r->head);
3198 } else if (lua_key_eq(field, tail)) {
3199
3200 lmt_push_node_fast(L, r->tail);
3201 } else if (lua_key_eq(field, delimiter)) {
3202 lmt_push_node_fast(L, r->delimiter);
3203 } else if (lua_key_eq(field, prevgraf)) {
3204 lua_pushinteger(L, r->prev_graf);
3205 } else if (lua_key_eq(field, modeline)) {
3206 lua_pushinteger(L, r->mode_line);
3207 } else if (lua_key_eq(field, prevdepth)) {
3208 lua_pushinteger(L, r->prev_depth);
3209 } else if (lua_key_eq(field, spacefactor)) {
3210 lua_pushinteger(L, r->space_factor);
3211 } else if (lua_key_eq(field, noad)) {
3212 lmt_push_node_fast(L, r->incomplete_noad);
3213 } else if (lua_key_eq(field, direction)) {
3214 lmt_push_node_fast(L, r->direction_stack);
3215 } else if (lua_key_eq(field, mathdir)) {
3216 lua_pushboolean(L, r->math_dir);
3217 } else if (lua_key_eq(field, mathstyle)) {
3218 lua_pushinteger(L, r->math_style);
3219 } else {
3220 lua_pushnil(L);
3221 }
3222}
3223
3224static void texlib_set_nest_field(lua_State *L, int n, const char *field, list_state_record *r)
3225{
3226 if (lua_key_eq(field, mode)) {
3227 r->mode = lmt_tointeger(L, n);
3228 } else if (lua_key_eq(field, head) || lua_key_eq(field, list)) {
3229 r->head = lmt_check_isnode(L, n);
3230 } else if (lua_key_eq(field, tail)) {
3231 r->tail = lmt_check_isnode(L, n);
3232 } else if (lua_key_eq(field, delimiter)) {
3233 r->delimiter = lmt_check_isnode(L, n);
3234 } else if (lua_key_eq(field, prevgraf)) {
3235 r->prev_graf = lmt_tointeger(L, n);
3236 } else if (lua_key_eq(field, modeline)) {
3237 r->mode_line = lmt_tointeger(L, n);
3238 } else if (lua_key_eq(field, prevdepth)) {
3239 r->prev_depth = lmt_toroundnumber(L, n);
3240 } else if (lua_key_eq(field, spacefactor)) {
3241 r->space_factor = lmt_toroundnumber(L, n);
3242 } else if (lua_key_eq(field, noad)) {
3243 r->incomplete_noad = lmt_check_isnode(L, n);
3244 } else if (lua_key_eq(field, direction)) {
3245 r->direction_stack = lmt_check_isnode(L, n);
3246 } else if (lua_key_eq(field, mathdir)) {
3247 r->math_dir = lua_toboolean(L, n);
3248 } else if (lua_key_eq(field, mathstyle)) {
3249 r->math_style = lmt_tointeger(L, n);
3250 }
3251}
3252
3253static int texlib_aux_nest_getfield(lua_State *L)
3254{
3255 list_state_record **rv = lua_touserdata(L, -2);
3256 list_state_record *r = *rv;
3257 const char *field = lua_tostring(L, -1);
3258 texlib_get_nest_field(L, field, r);
3259 return 1;
3260}
3261
3262static int texlib_aux_nest_setfield(lua_State *L)
3263{
3264 list_state_record **rv = lua_touserdata(L, -3);
3265 list_state_record *r = *rv;
3266 const char *field = lua_tostring(L, -2);
3267 texlib_set_nest_field(L, -1, field, r);
3268 return 0;
3269}
3270
3271static const struct luaL_Reg texlib_nest_metatable[] = {
3272 { "__index", texlib_aux_nest_getfield },
3273 { "__newindex", texlib_aux_nest_setfield },
3274 { NULL, NULL },
3275};
3276
3277static void texlib_aux_init_nest_lib(lua_State *L)
3278{
3279 luaL_newmetatable(L, TEX_NEST_INSTANCE);
3280 luaL_setfuncs(L, texlib_nest_metatable, 0);
3281 lua_pop(L, 1);
3282}
3283
3284
3285
3286static int texlib_getnestlevel(lua_State *L)
3287{
3288 lua_pushinteger(L, lmt_nest_state.nest_data.ptr);
3289 return 1;
3290}
3291
3292static int texlib_getnest(lua_State *L)
3293{
3294 int p = -1 ;
3295 int t = lua_gettop(L);
3296 if (t == 0) {
3297 p = lmt_nest_state.nest_data.ptr;
3298 } else {
3299 switch (lua_type(L, 1)) {
3300 case LUA_TNUMBER:
3301 {
3302 int ptr = lmt_tointeger(L, 1);
3303 if (ptr >= 0 && ptr <= lmt_nest_state.nest_data.ptr) {
3304 p = ptr;
3305 }
3306 }
3307 break;
3308 case LUA_TSTRING:
3309 {
3310 const char *s = lua_tostring(L, 1);
3311 if (lua_key_eq(s, top)) {
3312 p = lmt_nest_state.nest_data.ptr;
3313 } else if (lua_key_eq(s, ptr) || lua_key_eq(s, level)) {
3314 lua_pushinteger(L, lmt_nest_state.nest_data.ptr);
3315 return 1;
3316 }
3317 }
3318 break;
3319 }
3320 }
3321 if (p > -1) {
3322 if (t > 1) {
3323 const char *field = lua_tostring(L, 2);
3324 if (field) {
3325 texlib_get_nest_field(L, field, &lmt_nest_state.nest[p]);
3326 } else {
3327 lua_pushnil(L);
3328 }
3329 } else {
3330 list_state_record **nestitem = lua_newuserdatauv(L, sizeof(list_state_record *), 0);
3331 *nestitem = &lmt_nest_state.nest[p];
3332 luaL_getmetatable(L, TEX_NEST_INSTANCE);
3333 lua_setmetatable(L, -2);
3334 }
3335 } else {
3336 lua_pushnil(L);
3337 }
3338 return 1;
3339}
3340
3341
3342
3343static int texlib_setnest(lua_State *L)
3344{
3345 if (lua_gettop(L) > 2) {
3346 int p = -1 ;
3347 switch (lua_type(L, 1)) {
3348 case LUA_TNUMBER:
3349 {
3350 int ptr = lmt_tointeger(L, 1);
3351 if (ptr >= 0 && ptr <= lmt_nest_state.nest_data.ptr) {
3352 p = ptr;
3353 }
3354 }
3355 break;
3356 case LUA_TSTRING:
3357 {
3358 const char *s = lua_tostring(L, 1);
3359 if (lua_key_eq(s, top)) {
3360 p = lmt_nest_state.nest_data.ptr;
3361 }
3362 }
3363 break;
3364 }
3365 if (p > -1) {
3366 const char *field = lua_tostring(L, 2);
3367 if (field) {
3368 texlib_set_nest_field(L, 3, field, &lmt_nest_state.nest[p]);
3369 }
3370 }
3371 }
3372 return 0;
3373}
3374
3375static int texlib_round(lua_State *L)
3376{
3377
3378 lua_pushinteger(L, clippedround((double) lua_tonumber(L, 1)));
3379 return 1;
3380}
3381
3382static int texlib_scale(lua_State *L)
3383{
3384 double delta = luaL_checknumber(L, 2);
3385 switch (lua_type(L, 1)) {
3386 case LUA_TTABLE:
3387 {
3388
3392 lua_newtable(L);
3393 lua_pushnil(L);
3394 while (lua_next(L, 1)) {
3395
3396 lua_pushvalue(L, -2);
3397 lua_insert(L, -2);
3398 if (lua_type(L, -2) == LUA_TNUMBER) {
3399 double m = (double) lua_tonumber(L, -1) * delta;
3400 lua_pop(L, 1);
3401
3402 lua_pushinteger(L, clippedround(m));
3403 }
3404 lua_rawset(L, 3);
3405 }
3406 }
3407 break;
3408 case LUA_TNUMBER:
3409
3410 lua_pushinteger(L, clippedround((double) lua_tonumber(L, 1) * delta));
3411 break;
3412 default:
3413 lua_pushnil(L);
3414 break;
3415 }
3416 return 1;
3417}
3418
3419
3424
3425static int texlib_definefont(lua_State *L)
3426{
3427 size_t len;
3428 int slot = 1;
3429 int flags = (lua_isboolean(L, slot) && lua_toboolean(L, slot++)) ? add_global_flag(0) : 0;
3430 const char *csname = lua_tolstring(L, slot++, &len);
3431 halfword id = lmt_tohalfword(L, slot++);
3432 int cs = tex_string_locate(csname, len, 1);
3433 lmt_check_for_flags(L, slot, &flags, 1, 1);
3434 tex_define(flags, cs, set_font_cmd, id);
3435 return 0;
3436}
3437
3438static int texlib_hashtokens(lua_State *L)
3439{
3440 int cs = 1;
3441 int nt = 0;
3442 int nx = 0;
3443 int all = lua_toboolean(L, 1);
3444 lua_createtable(L, hash_size, 0);
3445
3446 if (all) {
3447 while (cs <= hash_size) {
3448 strnumber s = cs_text(cs);
3449 if (s > 0) {
3450 halfword n = cs_next(cs);
3451 if (n) {
3452 int mt = 0;
3453 lua_createtable(L, 2, 0);
3454 lua_pushstring(L, tex_to_cstring(s));
3455 ++nt;
3456 lua_rawseti(L, -2, ++mt);
3457 while (n) {
3458 s = cs_text(n);
3459 if (s) {
3460 lua_pushstring(L, tex_to_cstring(s));
3461 lua_rawseti(L, -2, ++mt);
3462 ++nt;
3463 ++nx;
3464 }
3465 n = cs_next(n);
3466 }
3467 } else {
3468 lua_pushstring(L, tex_to_cstring(s));
3469 ++nt;
3470 }
3471 } else {
3472 lua_pushboolean(L, 0);
3473 }
3474 lua_rawseti(L, -2, cs);
3475 cs++;
3476 }
3477 } else {
3478 while (cs < hash_size) {
3479 strnumber s = cs_text(cs);
3480 if (s > 0) {
3481 halfword n = cs_next(cs);
3482 lua_pushstring(L, tex_to_cstring(s));
3483 lua_rawseti(L, -2, ++nt);
3484 while (n) {
3485 s = cs_text(n);
3486 if (s) {
3487 lua_pushstring(L, tex_to_cstring(s));
3488 lua_rawseti(L, -2, ++nt);
3489 ++nx;
3490 }
3491 n = cs_next(n);
3492 }
3493 }
3494 cs++;
3495 }
3496 }
3497 lua_pushinteger(L, --cs);
3498 lua_pushinteger(L, nt);
3499 lua_pushinteger(L, nx);
3500 return 4;
3501}
3502
3503static int texlib_primitives(lua_State *L)
3504{
3505 int cs = 0;
3506 int nt = 0;
3507 lua_createtable(L, prim_size, 0);
3508 while (cs < prim_size) {
3509 strnumber s = get_prim_text(cs);
3510 if (s > 0 && (get_prim_origin(cs) != no_command)) {
3511 lua_pushstring(L, tex_to_cstring(s));
3512 lua_rawseti(L, -2, ++nt);
3513 }
3514 cs++;
3515 }
3516 return 1;
3517}
3518
3519static int texlib_extraprimitives(lua_State *L)
3520{
3521 int mask = 0;
3522 int cs = 0;
3523 int nt = 0;
3524 int n = lua_gettop(L);
3525 if (n == 0) {
3526 mask = tex_command + etex_command + luatex_command;
3527 } else {
3528 for (int i = 1; i <= n; i++) {
3529 if (lua_type(L, i) == LUA_TSTRING) {
3530 const char *s = lua_tostring(L, i);
3531 if (lua_key_eq(s, tex)) {
3532 mask |= tex_command;
3533 } else if (lua_key_eq(s, etex)) {
3534 mask |= etex_command;
3535 } else if (lua_key_eq(s, luatex)) {
3536 mask |= luatex_command;
3537 }
3538 }
3539 }
3540 }
3541 lua_createtable(L, prim_size, 0);
3542 while (cs < prim_size) {
3543 strnumber s = get_prim_text(cs);
3544 if (s > 0 && (get_prim_origin(cs) & mask)) {
3545 lua_pushstring(L, tex_to_cstring(s));
3546 lua_rawseti(L, -2, ++nt);
3547 }
3548 cs++;
3549 }
3550 return 1;
3551}
3552
3553static void texlib_aux_enableprimitive(const char *pre, size_t prel, const char *prm)
3554{
3555 strnumber s = tex_maketexstring(prm);
3556 halfword prm_val = tex_prim_lookup(s);
3557 tex_flush_str(s);
3558 if (prm_val != undefined_primitive && get_prim_origin(prm_val) != no_command) {
3559 char *newprm;
3560 size_t newlen;
3561 halfword cmd = get_prim_eq_type(prm_val);
3562 halfword chr = get_prim_equiv(prm_val);
3563 if (strncmp(pre, prm, prel) != 0) {
3564
3565 newlen = strlen(prm) + prel;
3566 newprm = (char *) lmt_memory_malloc((size_t) newlen + 1);
3567 if (newprm) {
3568 strcpy(newprm, pre);
3569 strcat(newprm + prel, prm);
3570 } else {
3571 tex_overflow_error("primitives", (int) newlen + 1);
3572 }
3573 } else {
3574 newlen = strlen(prm);
3575 newprm = (char *) lmt_memory_malloc((size_t) newlen + 1);
3576 if (newprm) {
3577 strcpy(newprm, prm);
3578 } else {
3579 tex_overflow_error("primitives", (int) newlen + 1);
3580 }
3581 }
3582 if (newprm) {
3583 halfword val = tex_string_locate(newprm, newlen, 1);
3584 if (val == undefined_control_sequence || eq_type(val) == undefined_cs_cmd) {
3585 tex_primitive_def(newprm, newlen, (singleword) cmd, chr);
3586 }
3587 lmt_memory_free(newprm);
3588 }
3589 }
3590}
3591
3592static int texlib_enableprimitives(lua_State *L)
3593{
3594 if (lua_gettop(L) == 2) {
3595 size_t prelen;
3596 const char *prefix = luaL_checklstring(L, 1, &prelen);
3597 switch (lua_type(L, 2)) {
3598 case LUA_TTABLE:
3599 {
3600 int i = 1;
3601 while (1) {
3602 if (lua_rawgeti(L, 2, i) == LUA_TSTRING) {
3603 const char *primitive = lua_tostring(L, 3);
3604 texlib_aux_enableprimitive(prefix, prelen, primitive);
3605 } else {
3606 lua_pop(L, 1);
3607 break;
3608 }
3609 lua_pop(L, 1);
3610 i++;
3611 }
3612 }
3613 break;
3614 case LUA_TBOOLEAN:
3615 if (lua_toboolean(L, 2)) {
3616 for (int cs = 0; cs < prim_size; cs++) {
3617 strnumber s = get_prim_text(cs);
3618 if (s > 0) {
3619 const char *primitive = tex_to_cstring(s);
3620 texlib_aux_enableprimitive(prefix, prelen, primitive);
3621 }
3622 }
3623 }
3624 break;
3625 default:
3626 luaL_error(L, "array of names or 'true' expected");
3627 }
3628 } else {
3629 luaL_error(L, "wrong number of arguments");
3630 }
3631 return 0;
3632}
3633
3634
3635
3636static halfword texlib_topenalties(lua_State *L, int i, quarterword s)
3637{
3638 int n = 0;
3639 lua_pushnil(L);
3640 while (lua_next(L, i)) {
3641 n++;
3642 lua_pop(L, 1);
3643 }
3644 if (n > 0) {
3645 int j = 0;
3646 halfword p = tex_new_specification_node(n, s, 0);
3647 lua_pushnil(L);
3648 while (lua_next(L, i)) {
3649 j++;
3650 if (lua_type(L, -1) == LUA_TNUMBER) {
3651 tex_set_specification_penalty(p, j, lmt_tohalfword(L, -1));
3652 }
3653 lua_pop(L, 1);
3654 }
3655 return p;
3656 } else {
3657 return null;
3658 }
3659}
3660
3661
3662
3663# define get_dimension_par(P,A,B) \
3664 lua_push_key(A); \
3665 P = (lua_rawget(L, -2) == LUA_TNUMBER) ? lmt_roundnumber(L, -1) : B; \
3666 lua_pop(L, 1);
3667
3668# define get_glue_par(P,A,B) \
3669 lua_push_key(A); \
3670 P = (lua_rawget(L, -2) == LUA_TUSERDATA) ? lmt_check_isnode(L, -1) : B; \
3671 lua_pop(L, 1);
3672
3673# define get_integer_par(P,A,B) \
3674 lua_push_key(A); \
3675 P = (lua_rawget(L, -2) == LUA_TNUMBER) ? lmt_tohalfword(L, -1) : B; \
3676 lua_pop(L, 1);
3677
3678# define get_penalties_par(P,A,B,C) \
3679 lua_push_key(A); \
3680 P = (lua_rawget(L, -2) == LUA_TTABLE) ? texlib_topenalties(L, lua_gettop(L), C) : B; \
3681 lua_pop(L, 1);
3682
3683# define get_shape_par(P,A,B) \
3684 lua_push_key(A); \
3685 P = (lua_rawget(L, -2) == LUA_TTABLE) ? texlib_toparshape(L, lua_gettop(L)) : B; \
3686 lua_pop(L, 1);
3687
3688
3692
3693
3694
3695
3696static int texlib_preparelinebreak(lua_State *L)
3697{
3698 halfword direct;
3699 halfword par = lmt_check_isdirectornode(L, 1, &direct);
3700 if (node_type(par) == par_node) {
3701 halfword tail = tex_tail_of_node_list(par);
3702 if (node_type(tail) == glue_node && node_subtype(tail) == par_fill_right_skip_glue) {
3703 tex_formatted_warning("linebreak", "list seems already prepared");
3704 } else {
3705 halfword parinit_left_skip_glue = null;
3706 halfword parinit_right_skip_glue = null;
3707 halfword parfill_left_skip_glue = null;
3708 halfword parfill_right_skip_glue = null;
3709 halfword final_line_penalty = null;
3710 tex_line_break_prepare(par, &tail, &parinit_left_skip_glue, &parinit_right_skip_glue, &parfill_left_skip_glue, &parfill_right_skip_glue, &final_line_penalty);
3711 lmt_push_directornode(L, par, direct);
3712 lmt_push_directornode(L, tail, direct);
3713 lmt_push_directornode(L, parinit_left_skip_glue, direct);
3714 lmt_push_directornode(L, parinit_right_skip_glue, direct);
3715 lmt_push_directornode(L, parfill_left_skip_glue , direct);
3716 lmt_push_directornode(L, parfill_right_skip_glue, direct);
3717
3718 return 6;
3719 }
3720 }
3721 lua_pushnil(L);
3722 return 1;
3723}
3724
3725static int texlib_linebreak(lua_State *L)
3726{
3727
3728 halfword direct;
3729 halfword par = lmt_check_isdirectornode(L, 1, &direct);
3730 if (node_type(par) == par_node) {
3731 line_break_properties properties;
3732 halfword tail = par;
3733 halfword has_indent = null;
3734 halfword has_penalty = 0;
3735 halfword prepared = 0;
3736 properties.initial_par = par;
3737 properties.display_math = 0;
3738 properties.paragraph_dir = par_dir(par);
3739 properties.parfill_left_skip = null;
3740 properties.parfill_right_skip = null;
3741 properties.parinit_left_skip = null;
3742 properties.parinit_right_skip = null;
3743 properties.extra_hyphen_penalty = 0;
3744 properties.optional_found = 0;
3745 while (tail) {
3746 switch (node_type(tail)) {
3747 case glue_node:
3748 switch (node_subtype(tail)) {
3749 case indent_skip_glue:
3750 if (has_indent) {
3751 tex_formatted_warning("linebreak", "duplicate %s glue in tex.linebreak", "indent");
3752 goto NOTHING;
3753 } else {
3754 has_indent = 1;
3755 }
3756 break;
3757 case par_fill_left_skip_glue:
3758 if (properties.parfill_left_skip) {
3759 tex_formatted_warning("linebreak", "duplicate %s glue in tex.linebreak", "leftskip");
3760 goto NOTHING;
3761 } else {
3762 properties.parfill_left_skip = tail;
3763 }
3764 break;
3765 case par_fill_right_skip_glue:
3766 if (properties.parfill_right_skip) {
3767 tex_formatted_warning("linebreak", "duplicate %s glue in tex.linebreak", "rightskip");
3768 goto NOTHING;
3769 } else {
3770 properties.parfill_right_skip = tail;
3771 }
3772 break;
3773 case par_init_left_skip_glue:
3774 if (properties.parinit_left_skip) {
3775 tex_formatted_warning("linebreak", "duplicate %s glue in tex.linebreak", "leftinit");
3776 goto NOTHING;
3777 } else {
3778 properties.parinit_left_skip = tail;
3779 }
3780 break;
3781 case par_init_right_skip_glue:
3782 if (properties.parinit_right_skip) {
3783 tex_formatted_warning("linebreak", "duplicate %s glue in tex.linebreak", "rightinit");
3784 goto NOTHING;
3785 } else {
3786 properties.parinit_right_skip = tail;
3787 }
3788 break;
3789 }
3790 break;
3791 case penalty_node:
3792 if (node_subtype(tail) == line_penalty_subtype && penalty_amount(tail) == infinite_penalty && ! (properties.parfill_left_skip && properties.parfill_right_skip)) {
3793 has_penalty = 1;
3794 }
3795 }
3796 if (node_next(tail)) {
3797 tail = node_next(tail);
3798 } else {
3799 break;
3800 }
3801 }
3802 {
3803 int has_init = properties.parinit_left_skip && properties.parinit_right_skip;
3804 int has_fill = properties.parfill_left_skip && properties.parfill_right_skip;
3805 if (lmt_linebreak_state.calling_back) {
3806 if (has_indent && ! (has_init && has_fill && has_penalty)) {
3807 tex_formatted_warning("linebreak", "[ par + leftinit + rightinit + indentglue + ... + penalty + leftfill + righfill ] expected");
3808 goto NOTHING;
3809 } else if (! (has_fill && has_penalty)) {
3810 tex_formatted_warning("linebreak", "[ par + indentbox + ... + penalty + leftfill + righfill ] expected");
3811 goto NOTHING;
3812 } else {
3813 prepared = 1;
3814 }
3815 } else {
3816 if (! (has_indent && has_init && has_fill)) {
3817 tex_formatted_warning("linebreak", "[ leftinit | rightinit | leftfill | rigthfill ] expected");
3818 goto NOTHING;
3819 } else {
3820
3821 prepared = has_init && has_fill;
3822 }
3823 }
3824 }
3825 tex_push_nest();
3826 node_next(temp_head) = par;
3827
3828 if (lua_gettop(L) != 2 || lua_type(L, 2) != LUA_TTABLE) {
3829 lua_newtable(L);
3830 }
3831 lua_push_key(direction);
3832 if (lua_rawget(L, -2) == LUA_TNUMBER) {
3833 properties.paragraph_dir = checked_direction_value(lmt_tointeger(L, -1));
3834 }
3835 lua_pop(L, 1);
3836 get_integer_par (properties.tracing_paragraphs, tracingparagraphs, tracing_paragraphs_par);
3837 get_integer_par (properties.pretolerance, pretolerance, tex_get_par_par(par, par_pre_tolerance_code));
3838 get_integer_par (properties.tolerance, tolerance, tex_get_par_par(par, par_tolerance_code));
3839 get_dimension_par(properties.emergency_stretch, emergencystretch, tex_get_par_par(par, par_emergency_stretch_code));
3840 get_dimension_par(properties.emergency_extra_stretch, emergencyextrastretch, tex_get_par_par(par, par_emergency_extra_stretch_code));
3841 get_integer_par (properties.looseness, looseness, tex_get_par_par(par, par_looseness_code));
3842 get_integer_par (properties.adjust_spacing, adjustspacing, tex_get_par_par(par, par_adjust_spacing_code));
3843 get_integer_par (properties.protrude_chars, protrudechars, tex_get_par_par(par, par_protrude_chars_code));
3844 get_integer_par (properties.adj_demerits, adjdemerits, tex_get_par_par(par, par_adj_demerits_code));
3845 get_integer_par (properties.double_adj_demerits, doubleadjdemerits, tex_get_par_par(par, par_double_adj_demerits_code));
3846 get_integer_par (properties.line_penalty, linepenalty, tex_get_par_par(par, par_line_penalty_code));
3847 get_integer_par (properties.last_line_fit, lastlinefit, tex_get_par_par(par, par_last_line_fit_code));
3848 get_integer_par (properties.double_hyphen_demerits, doublehyphendemerits, tex_get_par_par(par, par_double_hyphen_demerits_code));
3849 get_integer_par (properties.final_hyphen_demerits, finalhyphendemerits, tex_get_par_par(par, par_final_hyphen_demerits_code));
3850 get_dimension_par(properties.hsize, hsize, tex_get_par_par(par, par_hsize_code));
3851 get_glue_par (properties.left_skip, leftskip, tex_get_par_par(par, par_left_skip_code));
3852 get_glue_par (properties.right_skip, rightskip, tex_get_par_par(par, par_right_skip_code));
3853 get_glue_par (properties.emergency_left_skip, emergencyleftskip, tex_get_par_par(par, par_emergency_left_skip_code));
3854 get_glue_par (properties.emergency_right_skip, emergencyrightskip, tex_get_par_par(par, par_emergency_right_skip_code));
3855 get_dimension_par(properties.hang_indent, hangindent, tex_get_par_par(par, par_hang_indent_code));
3856 get_integer_par (properties.hang_after, hangafter, tex_get_par_par(par, par_hang_after_code));
3857 get_integer_par (properties.inter_line_penalty, interlinepenalty, tex_get_par_par(par, par_inter_line_penalty_code));
3858 get_integer_par (properties.club_penalty, clubpenalty, tex_get_par_par(par, par_club_penalty_code));
3859 get_integer_par (properties.widow_penalty, widowpenalty, tex_get_par_par(par, par_widow_penalty_code));
3860 get_integer_par (properties.display_widow_penalty, displaywidowpenalty, tex_get_par_par(par, par_display_widow_penalty_code));
3861 get_integer_par (properties.orphan_penalty, orphanpenalty, tex_get_par_par(par, par_orphan_penalty_code));
3862 get_integer_par (properties.single_line_penalty, singlelinepenalty, tex_get_par_par(par, par_single_line_penalty_code));
3863 get_integer_par (properties.broken_penalty, brokenpenalty, tex_get_par_par(par, par_broken_penalty_code));
3864 get_glue_par (properties.baseline_skip, baselineskip, tex_get_par_par(par, par_baseline_skip_code));
3865 get_glue_par (properties.line_skip, lineskip, tex_get_par_par(par, par_line_skip_code));
3866 get_dimension_par(properties.line_skip_limit, lineskiplimit, tex_get_par_par(par, par_line_skip_limit_code));
3867 get_integer_par (properties.adjust_spacing, adjustspacing, tex_get_par_par(par, par_adjust_spacing_code));
3868 get_integer_par (properties.adjust_spacing_step, adjustspacingstep, tex_get_par_par(par, par_adjust_spacing_step_code));
3869 get_integer_par (properties.adjust_spacing_shrink, adjustspacingshrink, tex_get_par_par(par, par_adjust_spacing_shrink_code));
3870 get_integer_par (properties.adjust_spacing_stretch, adjustspacingstretch, tex_get_par_par(par, par_adjust_spacing_stretch_code));
3871 get_integer_par (properties.hyphenation_mode, hyphenationmode, tex_get_par_par(par, par_hyphenation_mode_code));
3872 get_integer_par (properties.shaping_penalties_mode, shapingpenaltiesmode, tex_get_par_par(par, par_shaping_penalties_mode_code));
3873 get_integer_par (properties.shaping_penalty, shapingpenalty, tex_get_par_par(par, par_shaping_penalty_code));
3874 get_shape_par (properties.par_shape, parshape, tex_get_par_par(par, par_par_shape_code));
3875 get_penalties_par(properties.inter_line_penalties, interlinepenalties, tex_get_par_par(par, par_inter_line_penalties_code), inter_line_penalties_code);
3876 get_penalties_par(properties.club_penalties, clubpenalties, tex_get_par_par(par, par_club_penalties_code), club_penalties_code);
3877 get_penalties_par(properties.widow_penalties, widowpenalties, tex_get_par_par(par, par_widow_penalties_code), widow_penalties_code);
3878 get_penalties_par(properties.display_widow_penalties, displaywidowpenalties, tex_get_par_par(par, par_display_widow_penalties_code), display_widow_penalties_code);
3879 get_penalties_par(properties.orphan_penalties, orphanpenalties, tex_get_par_par(par, par_orphan_penalties_code), orphan_penalties_code);
3880 get_penalties_par(properties.par_passes, parpasses, tex_get_par_par(par, par_par_passes_code), par_passes_code);
3881 get_integer_par (properties.tracing_passes, tracingpasses, tracing_passes_par);
3882 get_integer_par (properties.line_break_criterion, linebreakcriterion, line_break_criterion_par);
3883 get_integer_par (properties.line_break_optional, linebreakoptional, line_break_optional_par);
3884 if (! prepared) {
3885 halfword attr_template = tail;
3886 halfword final_line_penalty = tex_new_penalty_node(infinite_penalty, line_penalty_subtype);
3887
3888 get_glue_par(properties.parfill_left_skip, parfillleftskip, tex_get_par_par(par, par_par_fill_left_skip_code));
3889 get_glue_par(properties.parfill_right_skip, parfillrightskip, tex_get_par_par(par, par_par_fill_right_skip_code));
3890 get_glue_par(properties.parinit_left_skip, parinitleftskip, tex_get_par_par(par, par_par_init_left_skip_code));
3891 get_glue_par(properties.parinit_right_skip, parinitrightskip, tex_get_par_par(par, par_par_init_right_skip_code));
3892
3893 properties.parfill_left_skip = tex_new_glue_node(properties.parfill_left_skip, par_fill_left_skip_glue);
3894 properties.parfill_right_skip = tex_new_glue_node(properties.parfill_right_skip, par_fill_right_skip_glue);
3895 tex_attach_attribute_list_copy(final_line_penalty, attr_template);
3896 tex_attach_attribute_list_copy(properties.parfill_left_skip, attr_template);
3897 tex_attach_attribute_list_copy(properties.parfill_right_skip, attr_template);
3898 tex_couple_nodes(tail, final_line_penalty);
3899 tex_couple_nodes(final_line_penalty, properties.parfill_left_skip);
3900 tex_couple_nodes(properties.parfill_left_skip, properties.parfill_right_skip);
3901 if (node_next(par)) {
3902 halfword n = node_next(par);
3903 while (n) {
3904 if (node_type(n) == glue_node && node_subtype(n) == indent_skip_glue) {
3905 properties.parinit_left_skip = tex_new_glue_node(properties.parinit_left_skip, par_init_left_skip_glue);
3906 properties.parinit_right_skip = tex_new_glue_node(properties.parinit_right_skip, par_init_right_skip_glue);
3907 tex_attach_attribute_list_copy(properties.parinit_left_skip, attr_template);
3908 tex_attach_attribute_list_copy(properties.parinit_right_skip, attr_template);
3909 tex_try_couple_nodes(properties.parinit_right_skip, n);
3910 tex_try_couple_nodes(properties.parinit_left_skip, properties.parinit_right_skip);
3911 tex_try_couple_nodes(par, properties.parinit_left_skip);
3912 break;
3913 } else {
3914 n = node_next(n);
3915 }
3916 }
3917 }
3918 }
3919 lmt_linebreak_state.last_line_fill = properties.parfill_right_skip;
3920 tex_do_line_break(&properties);
3921 {
3922 halfword fewest_demerits = 0;
3923 halfword actual_looseness = 0;
3924
3925 tex_get_linebreak_info(&fewest_demerits, &actual_looseness) ;
3926 lmt_push_directornode(L, node_next(cur_list.head), direct);
3927 lua_createtable(L, 0, 4);
3928
3929 lua_push_key(demerits);
3930 lua_pushinteger(L, fewest_demerits);
3931 lua_settable(L, -3);
3932
3933 lua_push_key(looseness);
3934 lua_pushinteger(L, actual_looseness);
3935 lua_settable(L, -3);
3936
3937 lua_push_key(prevdepth);
3938 lua_pushinteger(L, cur_list.prev_depth);
3939 lua_settable(L, -3);
3940
3941 lua_push_key(prevgraf);
3942 lua_pushinteger(L, cur_list.prev_graf);
3943 lua_settable(L, -3);
3944 }
3945 tex_pop_nest();
3946 if (properties.par_shape != tex_get_par_par(par, par_par_shape_code)) { tex_flush_node(properties.par_shape); }
3947 if (properties.inter_line_penalties != tex_get_par_par(par, par_inter_line_penalties_code)) { tex_flush_node(properties.inter_line_penalties); }
3948 if (properties.club_penalties != tex_get_par_par(par, par_club_penalties_code)) { tex_flush_node(properties.club_penalties); }
3949 if (properties.widow_penalties != tex_get_par_par(par, par_widow_penalties_code)) { tex_flush_node(properties.widow_penalties); }
3950 if (properties.display_widow_penalties != tex_get_par_par(par, par_display_widow_penalties_code)) { tex_flush_node(properties.display_widow_penalties); }
3951 if (properties.orphan_penalties != tex_get_par_par(par, par_orphan_penalties_code)) { tex_flush_node(properties.orphan_penalties); }
3952 return 2;
3953 } else {
3954 tex_formatted_warning("linebreak", "[ par ... ] expected");
3955 }
3956 NOTHING:
3957 lmt_push_directornode(L, par, direct);
3958 return 1;
3959}
3960
3961static int texlib_resetparagraph(lua_State *L)
3962{
3963 (void) L;
3964 tex_normal_paragraph(reset_par_context);
3965 return 0;
3966}
3967
3968static int texlib_shipout(lua_State *L)
3969{
3970 int boxnum = lmt_get_box_id(L, 1, 1);
3971 if (box_register(boxnum)) {
3972 tex_flush_node_list(box_register(boxnum));
3973 box_register(boxnum) = null;
3974 }
3975 return 0;
3976}
3977
3978static int texlib_badness(lua_State *L)
3979{
3980 scaled t = lmt_roundnumber(L, 1);
3981 scaled s = lmt_roundnumber(L, 2);
3982 lua_pushinteger(L, tex_badness(t, s));
3983 return 1;
3984}
3985
3986static int texlib_showcontext(lua_State *L)
3987{
3988 (void) L;
3989 tex_show_context();
3990 return 0;
3991}
3992
3993
3997
3998static int texlib_triggerbuildpage(lua_State *L)
3999{
4000 if (lua_toboolean(L, 1) && cur_list.mode != vmode) {
4001 return 0;
4002 }
4003 tex_build_page(triggered_page_context, 0);
4004 return 0;
4005}
4006
4007static int texlib_getpagestate(lua_State *L)
4008{
4009 lua_pushinteger(L, lmt_page_builder_state.contents);
4010 return 1;
4011}
4012
4013static int texlib_getlocallevel(lua_State *L)
4014{
4015 lua_pushinteger(L, lmt_main_control_state.local_level);
4016 return 1;
4017}
4018
4019
4020
4021static int texlib_setinputstatemode(lua_State *L)
4022{
4023 input_file_state.mode = lmt_tohalfword(L, 1);
4024 return 0;
4025}
4026static int texlib_getinputstatemode(lua_State *L)
4027{
4028 lua_pushinteger(L, input_file_state.mode);
4029 return 1;
4030}
4031
4032static int texlib_setinputstatefile(lua_State *L)
4033{
4034 lmt_input_state.cur_input.state_file = lmt_tointeger(L, 1);
4035 return 0;
4036}
4037
4038static int texlib_getinputstatefile(lua_State *L)
4039{
4040 lua_pushinteger(L, lmt_input_state.cur_input.state_file);
4041 return 1;
4042}
4043
4044static int texlib_forceinputstatefile(lua_State *L)
4045{
4046 input_file_state.forced_file = lmt_tointeger(L, 1);
4047 return 0;
4048}
4049
4050static int texlib_forceinputstateline(lua_State *L)
4051{
4052 input_file_state.forced_line = lmt_tointeger(L, 1);
4053 return 0;
4054}
4055
4056static int texlib_setinputstateline(lua_State *L)
4057{
4058 input_file_state.line = lmt_tohalfword(L, 1);
4059 return 0;
4060}
4061
4062static int texlib_getinputstateline(lua_State *L)
4063{
4064 lua_pushinteger(L, input_file_state.line);
4065 return 1;
4066}
4067
4068
4073
4074
4075
4076
4080
4081static int texlib_forcehmode(lua_State *L)
4082{
4083 if (is_v_mode(cur_list.mode)) {
4084 if (lua_type(L, 1) == LUA_TBOOLEAN) {
4085 tex_begin_paragraph(lua_toboolean(L, 1), force_par_trigger);
4086 } else {
4087 tex_begin_paragraph(1, force_par_trigger);
4088 }
4089 }
4090 return 0;
4091}
4092
4093
4101
4102static int texlib_runlocal(lua_State *L)
4103{
4104
4105 int obeymode = 1;
4106 halfword token = -1;
4107 int ismacro = 0 ;
4108 switch (lua_type(L, 1)) {
4109 case LUA_TFUNCTION:
4110 {
4111
4112 int reference;
4113 halfword c, e;
4114 lua_pushvalue(L, 1);
4115 reference = luaL_ref(L, LUA_REGISTRYINDEX);
4116 c = tex_get_available_token(token_val(lua_local_call_cmd, reference));
4117 e = tex_get_available_token(token_val(end_local_cmd, 0));
4118 token_link(c) = e;
4119 tex_begin_inserted_list(c);
4120 if (lmt_token_state.luacstrings > 0) {
4121 tex_lua_string_start();
4122 }
4123 if (tracing_nesting_par > 2) {
4124 tex_local_control_message("entering token scanner via function");
4125 }
4126 tex_local_control(obeymode);
4127 luaL_unref(L, LUA_REGISTRYINDEX, reference);
4128 return 0;
4129 }
4130 case LUA_TNUMBER:
4131 {
4132 halfword k = lmt_checkhalfword(L, 1);
4133 if (k >= 0 && k <= 65535) {
4134 token = toks_register(k);
4135 goto WRAPUP;
4136 } else {
4137 tex_local_control_message("invalid token register number");
4138 return 0;
4139 }
4140 }
4141 case LUA_TSTRING:
4142 {
4143 size_t lname = 0;
4144 const char *name = lua_tolstring(L, 1, &lname);
4145 int cs = tex_string_locate_only(name, lname);
4146 int cmd = eq_type(cs);
4147 if (cmd < call_cmd) {
4148
4149 switch (cmd) {
4150 case register_toks_cmd:
4151 token = toks_register(register_toks_number(eq_value(cs)));
4152 goto WRAPUP;
4153 case undefined_cs_cmd:
4154 tex_local_control_message("undefined macro or token register");
4155 return 0;
4156 default:
4157
4158 tex_local_control_message("invalid macro or token register");
4159 return 0;
4160 }
4161 } else {
4162 halfword ref = eq_value(cs);
4163 halfword head = token_link(ref);
4164 if (head && get_token_preamble(ref)) {
4165 tex_local_control_message("macro takes arguments and is ignored");
4166 return 0;
4167 } else {
4168 token = cs_token_flag + cs;
4169 ismacro = 1 ;
4170 goto WRAPUP;
4171 }
4172 }
4173 }
4174 case LUA_TUSERDATA:
4175
4176 token = token_info(lmt_token_code_from_lua(L, 1));
4177 ismacro = 1;
4178 goto WRAPUP;
4179 default:
4180 return 0;
4181 }
4182 WRAPUP:
4183 if (token < 0) {
4184
4185 } else if (lmt_input_state.scanner_status != scanner_is_defining || lua_toboolean(L, 2)) {
4186
4187 int grouped = lua_toboolean(L, 3);
4188 if (grouped) {
4189 tex_begin_inserted_list(tex_get_available_token(token_val(right_brace_cmd, 0)));
4190 }
4191 tex_begin_inserted_list(tex_get_available_token(token_val(end_local_cmd, 0)));
4192 if (ismacro) {
4193 tex_begin_inserted_list(tex_get_available_token(token));
4194 } else {
4195 tex_begin_token_list(token, local_text);
4196 }
4197 if (grouped) {
4198 tex_begin_inserted_list(tex_get_available_token(token_val(left_brace_cmd, 0)));
4199 }
4200
4201 if (lmt_token_state.luacstrings > 0) {
4202 tex_lua_string_start();
4203 }
4204 if (tracing_nesting_par > 2) {
4205 if (ismacro) {
4206 tex_local_control_message("entering token scanner via macro");
4207 } else {
4208 tex_local_control_message("entering token scanner via register");
4209 }
4210 }
4211 tex_local_control(obeymode);
4212 } else if (ismacro) {
4213 tex_back_input(token);
4214 } else {
4215 halfword h = null;
4216 halfword t = null;
4217 halfword r = token_link(token);
4218 while (r) {
4219 t = tex_store_new_token(t, token_info(r));
4220 if (! h) {
4221 h = t;
4222 }
4223 r = token_link(r);
4224 }
4225 tex_begin_inserted_list(h);
4226 }
4227 return 0;
4228}
4229
4230static int texlib_quitlocal(lua_State *L)
4231{
4232 (void) L;
4233 if (tracing_nesting_par > 2) {
4234 tex_local_control_message("quitting token scanner");
4235 }
4236 tex_end_local_control();
4237 return 0;
4238}
4239
4240
4241
4242static int texlib_expandasvalue(lua_State *L)
4243{
4244 int kind = lmt_tointeger(L, 1);
4245 halfword tail = null;
4246 halfword head = lmt_macro_to_tok(L, 2, &tail);
4247 if (head) {
4248 switch (kind) {
4249 case lua_value_none_code:
4250 case lua_value_dimension_code:
4251 {
4252 halfword value = 0;
4253 halfword space = tex_get_available_token(space_token);
4254 halfword relax = tex_get_available_token(deep_frozen_relax_token);
4255 token_link(tail) = space;
4256 token_link(space) = relax;
4257 tex_begin_inserted_list(head);
4258 lmt_error_state.intercept = 1;
4259 lmt_error_state.last_intercept = 0;
4260 value = tex_scan_dimension(0, 0, 0, 0, NULL);
4261 lmt_error_state.intercept = 0;
4262 while (cur_tok != deep_frozen_relax_token) {
4263 tex_get_token();
4264 }
4265 if (! lmt_error_state.last_intercept) {
4266 lua_pushinteger(L, value);
4267 break;
4268 } else if (kind == lua_value_none_code) {
4269 head = lmt_macro_to_tok(L, 2, &tail);
4270 goto TRYAGAIN;
4271 } else {
4272 head = lmt_macro_to_tok(L, 2, &tail);
4273 goto JUSTINCASE;
4274 }
4275 }
4276 case lua_value_integer_code:
4277 case lua_value_cardinal_code:
4278 case lua_value_boolean_code:
4279 TRYAGAIN:
4280 {
4281 halfword value = 0;
4282 halfword space = tex_get_available_token(space_token);
4283 halfword relax = tex_get_available_token(deep_frozen_relax_token);
4284 token_link(tail) = space;
4285 token_link(space) = relax;
4286 tex_begin_inserted_list(head);
4287 lmt_error_state.intercept = 1;
4288 lmt_error_state.last_intercept = 0;
4289 value = tex_scan_integer(0, NULL);
4290 lmt_error_state.intercept = 0;
4291 while (cur_tok != deep_frozen_relax_token) {
4292 tex_get_token();
4293 }
4294 if (lmt_error_state.last_intercept) {
4295 head = lmt_macro_to_tok(L, 2, &tail);
4296 goto JUSTINCASE;
4297 } else if (kind == lua_value_boolean_code) {
4298 lua_pushboolean(L, value);
4299 break;
4300 } else {
4301 lua_pushinteger(L, value);
4302 break;
4303 }
4304 }
4305 case lua_value_conditional_code:
4306
4307 default:
4308 JUSTINCASE:
4309 {
4310 int len = 0;
4311 const char *str = (const char *) lmt_get_expansion(head, &len);
4312 lua_pushlstring(L, str, str ? len : 0);
4313 break;
4314 }
4315 }
4316 return 1;
4317 } else {
4318 return 0;
4319 }
4320}
4321
4322
4323
4324static int texlib_runstring(lua_State *L)
4325{
4326 int top = lua_gettop(L);
4327 if (top > 0) {
4328 size_t lstr = 0;
4329 const char *str = NULL;
4330 int slot = 1;
4331 halfword ct = lua_type(L, slot) == LUA_TNUMBER ? lmt_tohalfword(L, slot++) : cat_code_table_par;
4332 if (! tex_valid_catcode_table(ct)) {
4333 ct = cat_code_table_par;
4334 }
4335 str = lua_tolstring(L, slot++, &lstr);
4336 if (lstr > 0) {
4337 int obeymode = 1;
4338 int expand = lua_toboolean(L, slot++);
4339 int grouped = lua_toboolean(L, slot++);
4340 int ignore = lua_toboolean(L, slot++);
4341 halfword h = get_reference_token();
4342 halfword t = h;
4343 if (grouped) {
4344
4345 t = tex_store_new_token(t, token_val(right_brace_cmd, 0));
4346 }
4347
4348 tex_parse_str_to_tok(h, &t, ct, str, lstr, ignore ? 2 : 1);
4349 if (grouped) {
4350
4351 t = tex_store_new_token(t, token_val(left_brace_cmd, 0));
4352 }
4353 if (lmt_input_state.scanner_status != scanner_is_defining || expand) {
4354
4355 tex_begin_inserted_list(tex_get_available_token(token_val(end_local_cmd, 0)));
4356 tex_begin_token_list(h, local_text);
4357 if (lmt_token_state.luacstrings > 0) {
4358 tex_lua_string_start();
4359 }
4360 if (tracing_nesting_par > 2) {
4361 tex_local_control_message("entering token scanner via register");
4362 }
4363 tex_local_control(obeymode);
4364 } else {
4365 tex_begin_inserted_list(h);
4366 }
4367 }
4368 }
4369 return 0;
4370}
4371
4372
4373
4374static int texlib_getmathdir(lua_State *L)
4375{
4376 lua_pushinteger(L, math_direction_par);
4377 return 1;
4378}
4379
4380static int texlib_setmathdir(lua_State *L)
4381{
4382 tex_set_math_dir(lmt_tohalfword(L, 1));
4383 return 0;
4384}
4385
4386static int texlib_getpardir(lua_State *L)
4387{
4388 lua_pushinteger(L, par_direction_par);
4389 return 1;
4390}
4391
4392static int texlib_setpardir(lua_State *L)
4393{
4394 tex_set_par_dir(lmt_tohalfword(L, 1));
4395 return 0;
4396}
4397
4398static int texlib_gettextdir(lua_State *L)
4399{
4400 lua_pushinteger(L, text_direction_par);
4401 return 1;
4402}
4403
4404static int texlib_settextdir(lua_State *L)
4405{
4406 tex_set_text_dir(lmt_tohalfword(L, 1));
4407 return 0;
4408}
4409
4410
4411
4412static int texlib_setlinedir(lua_State *L)
4413{
4414 tex_set_line_dir(lmt_tohalfword(L, 1));
4415 return 0;
4416}
4417
4418static int texlib_getboxdir(lua_State *L)
4419{
4420 int index = lmt_tointeger(L, 1);
4421 if (index >= 0 && index <= max_box_register_index) {
4422 if (box_register(index)) {
4423 lua_pushinteger(L, box_dir(box_register(index)));
4424 } else {
4425 lua_pushnil(L);
4426 }
4427 return 1;
4428 } else {
4429 texlib_aux_show_box_index_error(L);
4430 }
4431 return 0;
4432}
4433
4434static int texlib_setboxdir(lua_State *L)
4435{
4436 int index = lmt_tointeger(L, 1);
4437 if (index >= 0 && index <= max_box_register_index) {
4438 tex_set_box_dir(index, lmt_tosingleword(L, 2));
4439 } else {
4440 texlib_aux_show_box_index_error(L);
4441 }
4442 return 0;
4443}
4444
4445static int texlib_gethelptext(lua_State *L)
4446{
4447 if (lmt_error_state.help_text) {
4448 lua_pushstring(L, lmt_error_state.help_text);
4449 } else {
4450 lua_pushnil(L);
4451 }
4452 return 1;
4453}
4454
4455static int texlib_setinteraction(lua_State *L)
4456{
4457 if (lua_type(L,1) == LUA_TNUMBER) {
4458 int i = lmt_tointeger(L, 1);
4459 if (i >= 0 && i <= 3) {
4460 lmt_error_state.interaction = i;
4461 }
4462 }
4463 return 0;
4464}
4465
4466static int texlib_getinteraction(lua_State *L)
4467{
4468 lua_pushinteger(L, lmt_error_state.interaction);
4469 return 1;
4470}
4471
4472static int texlib_setglyphdata(lua_State *L)
4473{
4474 update_tex_glyph_data(0, lmt_opthalfword(L, 1, unused_attribute_value));
4475 return 0;
4476}
4477
4478static int texlib_getglyphdata(lua_State *L)
4479{
4480 lua_pushinteger(L, glyph_data_par);
4481 return 1;
4482}
4483
4484static int texlib_setglyphstate(lua_State *L)
4485{
4486 update_tex_glyph_state(0, lmt_opthalfword(L, 1, unused_state_value));
4487 return 0;
4488}
4489
4490static int texlib_getglyphstate(lua_State *L)
4491{
4492 lua_pushinteger(L, glyph_state_par);
4493 return 1;
4494}
4495
4496static int texlib_setglyphscript(lua_State *L)
4497{
4498 update_tex_glyph_script(0, lmt_opthalfword(L, 1, unused_script_value));
4499 return 0;
4500}
4501
4502static int texlib_getglyphscript(lua_State *L)
4503{
4504 lua_pushinteger(L, glyph_script_par);
4505 return 1;
4506}
4507
4508static int texlib_getglyphscales(lua_State *L)
4509{
4510 lua_pushinteger(L, glyph_scale_par);
4511 lua_pushinteger(L, glyph_x_scale_par);
4512 lua_pushinteger(L, glyph_y_scale_par);
4513 lua_pushinteger(L, glyph_data_par);
4514 return 4;
4515}
4516
4517static int texlib_fatalerror(lua_State *L)
4518{
4519 const char *s = lua_tostring(L, 1);
4520 tex_fatal_error(s);
4521 return 1;
4522}
4523
4524static int texlib_lastnodetype(lua_State *L)
4525{
4526 halfword tail = cur_list.tail;
4527 int type = -1;
4528 int subtype = -1;
4529 if (tail) {
4530 halfword mode = cur_list.mode;
4531 if (mode != nomode && tail != contribute_head && node_type(tail) != glyph_node) {
4532 type = node_type(tail);
4533 subtype = node_subtype(tail);
4534 } else if (mode == vmode && tail == cur_list.head) {
4535 type = lmt_page_builder_state.last_node_type;
4536 subtype = lmt_page_builder_state.last_node_subtype;
4537 } else if (mode == nomode || tail == cur_list.head) {
4538
4539 } else {
4540 type = node_type(tail);
4541 subtype = node_subtype(tail);
4542 }
4543 }
4544 if (type >= 0) {
4545 lua_pushinteger(L, type);
4546 lua_pushinteger(L, subtype);
4547 } else {
4548 lua_pushnil(L);
4549 lua_pushnil(L);
4550 }
4551 return 2;
4552}
4553
4554
4555
4556static int texlib_chardef(lua_State *L)
4557{
4558 size_t len;
4559 const char *str = lua_tolstring(L, 1, &len);
4560 if (len > 0) {
4561 int cs = tex_string_locate(str, len, 1);
4562 int flags = 0;
4563 lmt_check_for_flags(L, 3, &flags, 1, 0);
4564 if (tex_define_permitted(cs, flags)) {
4565 int code = lmt_tointeger(L, 2);
4566 if (code >= 0 && code <= max_character_code) {
4567 tex_define(flags, cs, (quarterword) char_given_cmd, code);
4568 } else {
4569 tex_formatted_error("lua", "chardef only accepts codes in the range 0-%i", max_character_code);
4570 }
4571 }
4572 }
4573 return 0;
4574}
4575
4576
4577
4578static int texlib_mathchardef(lua_State *L)
4579{
4580 size_t len;
4581 const char *str = lua_tolstring(L, 1, &len);
4582 if (len > 0) {
4583 int cs = tex_string_locate(str, len, 1);
4584 int flags = 0;
4585 lmt_check_for_flags(L, 5, &flags, 1, 0);
4586 if (tex_define_permitted(cs, flags)) {
4587 mathcodeval mval;
4588 mathdictval dval;
4589 mval.class_value = (short) lmt_tointeger(L, 2);
4590 mval.family_value = (short) lmt_tointeger(L, 3);
4591 mval.character_value = lmt_tointeger(L, 4);
4592 dval.properties = lmt_optquarterword(L, 6, 0);
4593 dval.group = lmt_optquarterword(L, 7, 0);
4594 dval.index = lmt_optinteger(L, 8, 0);
4595 if (class_in_range(mval.class_value) && family_in_range(mval.family_value) && character_in_range(mval.character_value)) {
4596 tex_define(flags, cs, mathspec_cmd, tex_new_math_dict_spec(dval, mval, umath_mathcode));
4597 } else {
4598 tex_normal_error("lua", "mathchardef needs proper class, family and character codes");
4599 }
4600 } else {
4601
4602 }
4603 }
4604 return 0;
4605}
4606
4607static int texlib_setintegervalue(lua_State *L)
4608{
4609 size_t len;
4610 const char *str = lua_tolstring(L, 1, &len);
4611 if (len > 0) {
4612 int cs = tex_string_locate(str, len, 1);
4613 int flags = 0;
4614 lmt_check_for_flags(L, 3, &flags, 1, 0);
4615 if (tex_define_permitted(cs, flags)) {
4616 int value = lmt_optroundnumber(L, 2, 0);
4617 if (value >= min_integer && value <= max_integer) {
4618 tex_define(flags, cs, (quarterword) integer_cmd, value);
4619 } else {
4620 tex_formatted_error("lua", "integer only accepts values in the range %i-%i", min_integer, max_integer);
4621 }
4622 }
4623 }
4624 return 0;
4625}
4626
4627static int texlib_setfloatvalue(lua_State *L)
4628{
4629 size_t len;
4630 const char *str = lua_tolstring(L, 1, &len);
4631 if (len > 0) {
4632 int cs = tex_string_locate(str, len, 1);
4633 int flags = 0;
4634 lmt_check_for_flags(L, 3, &flags, 1, 0);
4635 if (tex_define_permitted(cs, flags)) {
4636 unsigned value = tex_double_to_posit(luaL_optnumber(L, 2, 0)).v;
4637
4638
4639 tex_define(flags, cs, (quarterword) posit_cmd, value);
4640
4641
4642
4643 }
4644 }
4645 return 0;
4646}
4647
4648static int texlib_setcardinalvalue(lua_State *L)
4649{
4650 size_t len;
4651 const char *str = lua_tolstring(L, 1, &len);
4652 if (len > 0) {
4653 int cs = tex_string_locate(str, len, 1);
4654 int flags = 0;
4655 lmt_check_for_flags(L, 3, &flags, 1, 0);
4656 if (tex_define_permitted(cs, flags)) {
4657 unsigned value = lmt_opturoundnumber(L, 2, 0);
4658
4659
4660 tex_define(flags, cs, (quarterword) integer_cmd, value);
4661
4662
4663
4664 }
4665 }
4666 return 0;
4667}
4668
4669static int texlib_setdimensionvalue(lua_State *L)
4670{
4671 size_t len;
4672 const char *str = lua_tolstring(L, 1, &len);
4673 if (len > 0) {
4674 int cs = tex_string_locate(str, len, 1);
4675 int flags = 0;
4676 lmt_check_for_flags(L, 3, &flags, 1, 0);
4677 if (tex_define_permitted(cs, flags)) {
4678 int value = lmt_optroundnumber(L, 2, 0);
4679 if (value >= min_dimension && value <= max_dimension) {
4680 tex_define(flags, cs, (quarterword) dimension_cmd, value);
4681 } else {
4682 tex_formatted_error("lua", "dimension only accepts values in the range %i-%i", min_dimension, max_dimension);
4683 }
4684 }
4685 }
4686 return 0;
4687}
4688
4689
4690
4691
4692
4693
4694static int texlib_aux_getvalue(lua_State *L, halfword level, halfword cs)
4695{
4696 halfword chr = eq_value(cs);
4697 if (chr && ! get_token_preamble(chr)) {
4698 halfword value = 0;
4699 tex_begin_inserted_list(tex_get_available_token(cs_token_flag + cs));
4700 if (tex_scan_tex_value(level, &value)) {
4701 if (level == posit_val_level) {
4702 lua_pushnumber(L, tex_posit_to_double(value));
4703 } else {
4704 lua_pushinteger(L, value);
4705 }
4706 return 1;
4707 }
4708 }
4709 lua_pushnil(L);
4710 return 1;
4711}
4712
4713static int texlib_getintegervalue(lua_State *L)
4714{
4715 switch (lua_type(L, 1)) {
4716 case LUA_TSTRING:
4717 {
4718 size_t len;
4719 const char *str = lua_tolstring(L, 1, &len);
4720 if (len > 0) {
4721 int cs = tex_string_locate_only(str, len);
4722 switch (eq_type(cs)) {
4723 case integer_cmd:
4724 lua_pushinteger(L, eq_value(cs));
4725 return 1;
4726 case call_cmd:
4727 case protected_call_cmd:
4728 case semi_protected_call_cmd:
4729 case constant_call_cmd:
4730 return texlib_aux_getvalue(L, integer_val_level, cs);
4731 default:
4732
4733 return texlib_getcount(L);
4734 }
4735 } else {
4736 break;
4737 }
4738 }
4739 case LUA_TNUMBER:
4740 {
4741 halfword i = lmt_tohalfword(L, 1) - 0xFFFF;
4742 if (i < (eqtb_size + lmt_hash_state.hash_data.ptr + 1) && eq_type(i) == integer_cmd) {
4743 lua_pushinteger(L, eq_value(i));
4744 return 1;
4745 } else {
4746 break;
4747 }
4748 }
4749 }
4750 lua_pushnil(L);
4751 return 1;
4752}
4753
4754static int texlib_getfloatvalue(lua_State *L)
4755{
4756 if (lua_type(L, 1) == LUA_TSTRING) {
4757 size_t len;
4758 const char *str = lua_tolstring(L, 1, &len);
4759 if (len > 0) {
4760 int cs = tex_string_locate_only(str, len);
4761 switch (eq_type(cs)) {
4762 case posit_cmd:
4763 lua_pushnumber(L, tex_posit_to_double(eq_value(cs)));
4764 return 1;
4765 case call_cmd:
4766 case protected_call_cmd:
4767 case semi_protected_call_cmd:
4768 case constant_call_cmd:
4769 return texlib_aux_getvalue(L, posit_val_level, cs);
4770 default:
4771
4772 return texlib_getfloat(L);
4773 }
4774 }
4775 }
4776 lua_pushnil(L);
4777 return 1;
4778}
4779
4780static int texlib_getdimensionvalue(lua_State *L)
4781{
4782 switch (lua_type(L, 1)) {
4783 case LUA_TSTRING:
4784 {
4785 size_t len;
4786 const char *str = lua_tolstring(L, 1, &len);
4787 if (len > 0) {
4788 int cs = tex_string_locate_only(str, len);
4789 switch (eq_type(cs)) {
4790 case dimension_cmd:
4791 lua_pushinteger(L, eq_value(cs));
4792 return 1;
4793 case posit_cmd:
4794 lua_pushinteger(L, tex_posit_to_dimension(eq_value(cs)));
4795 return 1;
4796 case call_cmd:
4797 case protected_call_cmd:
4798 case semi_protected_call_cmd:
4799 case constant_call_cmd:
4800 return texlib_aux_getvalue(L, dimension_val_level, cs);
4801 default:
4802
4803 return texlib_getdimen(L);
4804 }
4805 } else {
4806 break;
4807 }
4808 }
4809 case LUA_TNUMBER:
4810 {
4811 halfword i = lmt_tohalfword(L, 1) - 0xFFFF;
4812 if (i < (eqtb_size + lmt_hash_state.hash_data.ptr + 1) && eq_type(i) == dimension_cmd) {
4813 lua_pushinteger(L, eq_value(i));
4814 return 1;
4815 } else {
4816 break;
4817 }
4818 }
4819 }
4820 lua_pushnil(L);
4821 return 1;
4822}
4823
4824
4825
4826
4827
4828
4829
4835
4836static int texlib_getmodevalues(lua_State *L)
4837{
4838 lua_createtable(L, 4, 1);
4839 lua_push_key_at_index(L, unset, nomode);
4840 lua_push_key_at_index(L, vertical, vmode);
4841 lua_push_key_at_index(L, horizontal, hmode);
4842 lua_push_key_at_index(L, math, mmode);
4843 return 1;
4844}
4845
4846static int texlib_getmode(lua_State *L)
4847{
4848 lua_pushinteger(L, tex_normalized_mode(cur_list.mode));
4849 return 1;
4850}
4851
4852static int texlib_getrunstatevalues(lua_State *L)
4853{
4854 lua_createtable(L, 2, 1);
4855 lua_set_string_by_index(L, initializing_state, "initializing");
4856 lua_set_string_by_index(L, updating_state, "updating");
4857 lua_set_string_by_index(L, production_state, "production");
4858 return 1;
4859}
4860
4861static int texlib_setrunstate(lua_State *L)
4862{
4863 int state = lmt_tointeger(L, 1);
4864 if (state == updating_state || state == production_state) {
4865 lmt_main_state.run_state = state;
4866 }
4867 return 0;
4868}
4869
4870
4874
4875
4876static int texlib_gethyphenationvalues(lua_State *L)
4877{
4878 lua_createtable(L, 2, 17);
4879 lua_push_key_at_index(L, normal, normal_hyphenation_mode);
4880 lua_push_key_at_index(L, automatic, automatic_hyphenation_mode);
4881 lua_push_key_at_index(L, explicit, explicit_hyphenation_mode);
4882 lua_push_key_at_index(L, syllable, syllable_hyphenation_mode);
4883 lua_push_key_at_index(L, uppercase, uppercase_hyphenation_mode);
4884 lua_push_key_at_index(L, compound, compound_hyphenation_mode);
4885 lua_push_key_at_index(L, strictstart, strict_start_hyphenation_mode);
4886 lua_push_key_at_index(L, strictend, strict_end_hyphenation_mode);
4887 lua_push_key_at_index(L, automaticpenalty, automatic_penalty_hyphenation_mode);
4888 lua_push_key_at_index(L, explicitpenalty, explicit_penalty_hyphenation_mode);
4889 lua_push_key_at_index(L, permitglue, permit_glue_hyphenation_mode);
4890 lua_push_key_at_index(L, permitall, permit_all_hyphenation_mode);
4891 lua_push_key_at_index(L, permitmathreplace, permit_math_replace_hyphenation_mode);
4892 lua_push_key_at_index(L, forcecheck, force_check_hyphenation_mode);
4893 lua_push_key_at_index(L, lazyligatures, lazy_ligatures_hyphenation_mode);
4894 lua_push_key_at_index(L, forcehandler, force_handler_hyphenation_mode);
4895 lua_push_key_at_index(L, feedbackcompound, feedback_compound_hyphenation_mode);
4896 lua_push_key_at_index(L, ignorebounds, ignore_bounds_hyphenation_mode);
4897 lua_push_key_at_index(L, collapse, collapse_hyphenation_mode);
4898 return 1;
4899}
4900
4901static int texlib_getglyphoptionvalues(lua_State *L)
4902{
4903 lua_createtable(L, 3, 12);
4904 lua_set_string_by_index(L, glyph_option_normal_glyph, "normal");
4905 lua_set_string_by_index(L, glyph_option_no_left_ligature, "noleftligature");
4906 lua_set_string_by_index(L, glyph_option_no_right_ligature, "norightligature");
4907 lua_set_string_by_index(L, glyph_option_no_left_kern, "noleftkern");
4908 lua_set_string_by_index(L, glyph_option_no_right_kern, "norightkern");
4909 lua_set_string_by_index(L, glyph_option_no_expansion, "noexpansion");
4910 lua_set_string_by_index(L, glyph_option_no_protrusion, "noprotrusion");
4911 lua_set_string_by_index(L, glyph_option_apply_x_offset, "applyxoffset");
4912 lua_set_string_by_index(L, glyph_option_apply_y_offset, "applyyoffset");
4913 lua_set_string_by_index(L, glyph_option_no_italic_correction, "noitaliccorrection");
4914 lua_set_string_by_index(L, glyph_option_no_zero_italic_correction, "nozeroitaliccorrection");
4915 lua_set_string_by_index(L, glyph_option_math_discretionary, "mathdiscretionary");
4916 lua_set_string_by_index(L, glyph_option_math_italics_too, "mathsitalicstoo");
4917 lua_set_string_by_index(L, glyph_option_user_first, "userfirst");
4918 lua_set_string_by_index(L, glyph_option_user_last, "userlast");
4919 return 1;
4920}
4921
4922static int texlib_getglueoptionvalues(lua_State *L)
4923{
4924 lua_createtable(L, 3, 2);
4925 lua_set_string_by_index(L, glue_option_normal, "normal");
4926 lua_set_string_by_index(L, glue_option_no_auto_break, "noautobreak");
4927 lua_set_string_by_index(L, glue_option_has_factor, "hasfactor");
4928 lua_set_string_by_index(L, glue_option_is_limited, "islimited");
4929 lua_set_string_by_index(L, glue_option_limit, "limit");
4930 return 1;
4931}
4932
4933static int texlib_getmathoptionvalues(lua_State *L)
4934{
4935 lua_createtable(L, 3, 0);
4936 lua_set_string_by_index(L, math_option_normal, "normal");
4937 lua_set_string_by_index(L, math_option_short, "short");
4938 lua_set_string_by_index(L, math_option_orphaned, "orphaned");
4939 return 1;
4940}
4941
4942static int texlib_getpenaltyoptionvalues(lua_State *L)
4943{
4944 lua_createtable(L, 3, 1);
4945 lua_set_string_by_index(L, penalty_option_normal, "normal");
4946 lua_set_string_by_index(L, penalty_option_math_forward, "mathforward");;
4947 lua_set_string_by_index(L, penalty_option_math_backward, "mathbackward");
4948 lua_set_string_by_index(L, penalty_option_orphaned, "orphaned");
4949 return 1;
4950}
4951
4952static int texlib_getnoadoptionvalues(lua_State *L)
4953{
4954 lua_createtable(L, 2, 37);
4955 lua_push_key_at_index(L, axis, noad_option_axis);
4956 lua_push_key_at_index(L, noaxis, noad_option_no_axis);
4957 lua_push_key_at_index(L, exact, noad_option_exact);
4958 lua_push_key_at_index(L, left, noad_option_left);
4959 lua_push_key_at_index(L, middle, noad_option_middle);
4960 lua_push_key_at_index(L, right, noad_option_right);
4961 lua_push_key_at_index(L, adapttoleftsize, noad_option_adapt_to_left_size);
4962 lua_push_key_at_index(L, adapttorightsize, noad_option_adapt_to_right_size);
4963 lua_push_key_at_index(L, nosubscript, noad_option_no_sub_script);
4964 lua_push_key_at_index(L, nosuperscript, noad_option_no_super_script);
4965 lua_push_key_at_index(L, nosubprescript, noad_option_no_sub_pre_script);
4966 lua_push_key_at_index(L, nosuperprescript, noad_option_no_super_pre_script);
4967 lua_push_key_at_index(L, noscript, noad_option_no_script);
4968 lua_push_key_at_index(L, nooverflow, noad_option_no_overflow);
4969 lua_push_key_at_index(L, void, noad_option_void);
4970 lua_push_key_at_index(L, phantom, noad_option_phantom);
4971 lua_push_key_at_index(L, openupheight, noad_option_openup_height);
4972 lua_push_key_at_index(L, openupdepth, noad_option_openup_depth);
4973 lua_push_key_at_index(L, limits, noad_option_limits);
4974 lua_push_key_at_index(L, nolimits, noad_option_no_limits);
4975 lua_push_key_at_index(L, preferfontthickness, noad_option_prefer_font_thickness);
4976 lua_push_key_at_index(L, noruling, noad_option_no_ruling);
4977 lua_push_key_at_index(L, shiftedsubscript, noad_option_shifted_sub_script);
4978 lua_push_key_at_index(L, shiftedsuperscript, noad_option_shifted_super_script);
4979 lua_push_key_at_index(L, shiftedsubprescript, noad_option_shifted_sub_pre_script);
4980 lua_push_key_at_index(L, shiftedsuperprescript, noad_option_shifted_super_pre_script);
4981 lua_push_key_at_index(L, unpacklist, noad_option_unpack_list);
4982 lua_push_key_at_index(L, nocheck, noad_option_no_check);
4983 lua_push_key_at_index(L, auto, noad_option_auto);
4984 lua_push_key_at_index(L, unrolllist, noad_option_unroll_list);
4985 lua_push_key_at_index(L, followedbyspace, noad_option_followed_by_space);
4986 lua_push_key_at_index(L, proportional, noad_option_proportional);
4987 lua_push_key_at_index(L, sourceonnucleus, noad_option_source_on_nucleus);
4988 lua_push_key_at_index(L, fixedsuperorsubscript, noad_option_fixed_super_or_sub_script);
4989 lua_push_key_at_index(L, fixedsuperandsubscript, noad_option_fixed_super_and_sub_script);
4990 lua_push_key_at_index(L, autobase, noad_option_auto_base);
4991 lua_push_key_at_index(L, shrink, noad_option_shrink);
4992 lua_push_key_at_index(L, stretch, noad_option_stretch);
4993 lua_push_key_at_index(L, center, noad_option_center);
4994 lua_push_key_at_index(L, scale, noad_option_scale);
4995 lua_push_key_at_index(L, keepbase, noad_option_keep_base);
4996 lua_push_key_at_index(L, single, noad_option_single);
4997 lua_push_key_at_index(L, norule, noad_option_no_rule);
4998 lua_push_key_at_index(L, automiddle, noad_option_auto_middle);
4999
5000
5001 lua_set_string_by_index(L, noad_option_reflected, "reflected");
5002 return 1;
5003}
5004
5005static int texlib_getdiscoptionvalues(lua_State *L)
5006{
5007 lua_createtable(L, 2, 7);
5008 lua_set_string_by_index(L, disc_option_normal_word, "normalword");
5009 lua_set_string_by_index(L, disc_option_pre_word, "preword");
5010 lua_set_string_by_index(L, disc_option_post_word, "postword");
5011 lua_set_string_by_index(L, disc_option_prefer_break, "preferbreak");
5012 lua_set_string_by_index(L, disc_option_prefer_nobreak, "prefernobreak");
5013 lua_set_string_by_index(L, disc_option_no_italic_correction, "noitaliccorrection");
5014 lua_set_string_by_index(L, disc_option_no_zero_italic_correction, "nozeroitaliccorrection");
5015 lua_set_string_by_index(L, disc_option_user_first, "userfirst");
5016 lua_set_string_by_index(L, disc_option_user_last, "userlast");
5017 return 1;
5018}
5019
5020static int texlib_getmathsurroundvalues(lua_State *L)
5021{
5022 lua_createtable(L, 2, 6);
5023 lua_set_string_by_index(L, math_skip_surround_when_zero, "zero");
5024 lua_set_string_by_index(L, math_skip_always_left, "left");
5025 lua_set_string_by_index(L, math_skip_always_right, "right");
5026 lua_set_string_by_index(L, math_skip_always_both, "both");
5027 lua_set_string_by_index(L, math_skip_always_surround, "surround");
5028 lua_set_string_by_index(L, math_skip_ignore, "ignore");
5029 lua_set_string_by_index(L, math_skip_only_when_skip, "skip");
5030 lua_set_string_by_index(L, math_skip_only_when_no_skip, "noskip");
5031 return 1;
5032}
5033
5034static int texlib_getlistanchorvalues(lua_State *L)
5035{
5036 lua_createtable(L, 14, 0);
5037 lua_set_string_by_index(L, left_origin_anchor, "leftorigin");
5038 lua_set_string_by_index(L, left_height_anchor, "leftheight");
5039 lua_set_string_by_index(L, left_depth_anchor, "leftdepth");
5040 lua_set_string_by_index(L, right_origin_anchor, "rightorigin");
5041 lua_set_string_by_index(L, right_height_anchor, "rightheight");
5042 lua_set_string_by_index(L, right_depth_anchor, "rightdepth");
5043 lua_set_string_by_index(L, center_origin_anchor, "centerorigin");
5044 lua_set_string_by_index(L, center_height_anchor, "centerheight");
5045 lua_set_string_by_index(L, center_depth_anchor, "centerdepth");
5046 lua_set_string_by_index(L, halfway_total_anchor, "halfwaytotal");
5047 lua_set_string_by_index(L, halfway_height_anchor, "halfwayheight");
5048 lua_set_string_by_index(L, halfway_depth_anchor, "halfwaydepth");
5049 lua_set_string_by_index(L, halfway_left_anchor, "halfwayleft");
5050 lua_set_string_by_index(L, halfway_right_anchor, "halfwayright");
5051 return 1;
5052}
5053
5054static int texlib_getlistsignvalues(lua_State *L)
5055{
5056 lua_createtable(L, 0, 2);
5057 lua_set_string_by_index(L, negate_x_anchor, "negatex");
5058 lua_set_string_by_index(L, negate_y_anchor, "negatey");
5059 return 1;
5060}
5061
5062static int texlib_getlistgeometryvalues(lua_State *L)
5063{
5064 lua_createtable(L, 2, 1);
5065 lua_set_string_by_index(L, offset_geometry, "offset");
5066 lua_set_string_by_index(L, orientation_geometry, "orientation");
5067 lua_set_string_by_index(L, anchor_geometry, "anchor");
5068 return 1;
5069}
5070
5071
5072static int texlib_getmathgluevalues(lua_State *L)
5073{
5074 lua_createtable(L, 2, 1);
5075 lua_set_string_by_index(L, math_glue_stretch_code, "stretch");
5076 lua_set_string_by_index(L, math_glue_shrink_code, "shrink");
5077 lua_set_string_by_index(L, math_glue_limit_code, "limit");
5078 return 1;
5079}
5080
5081
5082static int texlib_getautomigrationvalues(lua_State *L)
5083{
5084 lua_createtable(L, 2, 3);
5085 lua_push_key_at_index(L, mark, auto_migrate_mark);
5086 lua_push_key_at_index(L, insert, auto_migrate_insert);
5087 lua_push_key_at_index(L, adjust, auto_migrate_adjust);
5088 lua_push_key_at_index(L, pre, auto_migrate_pre);
5089 lua_push_key_at_index(L, post, auto_migrate_post);
5090 return 1;
5091}
5092
5093static int texlib_getprotrusionboundaryvalues(lua_State *L)
5094{
5095 lua_createtable(L, 3, 1);
5096 lua_set_string_by_index(L, protrusion_skip_none, "skipnone");
5097 lua_set_string_by_index(L, protrusion_skip_next, "skipnext");
5098 lua_set_string_by_index(L, protrusion_skip_previous, "skipprevious");
5099 lua_set_string_by_index(L, protrusion_skip_both, "skipboth");
5100 return 1;
5101}
5102
5103static int texlib_getflagvalues(lua_State *L)
5104{
5105 lua_createtable(L, 2, 18);
5106
5107 lua_push_key_at_index(L, frozen, frozen_flag_bit);
5108 lua_push_key_at_index(L, permanent, permanent_flag_bit);
5109 lua_push_key_at_index(L, immutable, immutable_flag_bit);
5110 lua_push_key_at_index(L, primitive, primitive_flag_bit);
5111 lua_push_key_at_index(L, mutable, mutable_flag_bit);
5112 lua_push_key_at_index(L, noaligned, noaligned_flag_bit);
5113 lua_push_key_at_index(L, instance, instance_flag_bit);
5114 lua_push_key_at_index(L, untraced, untraced_flag_bit);
5115 lua_push_key_at_index(L, global, global_flag_bit);
5116 lua_push_key_at_index(L, tolerant, tolerant_flag_bit);
5117 lua_push_key_at_index(L, protected, protected_flag_bit);
5118 lua_push_key_at_index(L, overloaded, overloaded_flag_bit);
5119 lua_push_key_at_index(L, aliased, aliased_flag_bit);
5120 lua_push_key_at_index(L, immediate, immediate_flag_bit);
5121 lua_push_key_at_index(L, conditional, conditional_flag_bit);
5122 lua_push_key_at_index(L, value, value_flag_bit);
5123 lua_push_key_at_index(L, semiprotected, semiprotected_flag_bit);
5124 lua_push_key_at_index(L, inherited, inherited_flag_bit);
5125 lua_push_key_at_index(L, constant, constant_flag_bit);
5126 lua_push_key_at_index(L, deferred, deferred_flag_bit);
5127 return 1;
5128}
5129
5130static int texlib_getspecialmathclassvalues(lua_State *L)
5131{
5132 lua_createtable(L, 0, 3);
5133 lua_set_string_by_index(L, math_all_class, "all");
5134 lua_set_string_by_index(L, math_begin_class, "begin");
5135 lua_set_string_by_index(L, math_end_class, "end");
5136 return 1;
5137}
5138
5139static int texlib_getmathclassoptionvalues(lua_State *L)
5140{
5141 lua_createtable(L, 2, 25);
5142 lua_set_string_by_index(L, no_pre_slack_class_option, "nopreslack");
5143 lua_set_string_by_index(L, no_post_slack_class_option, "nopostslack");
5144 lua_set_string_by_index(L, left_top_kern_class_option, "lefttopkern");
5145 lua_set_string_by_index(L, right_top_kern_class_option, "righttopkern");
5146 lua_set_string_by_index(L, left_bottom_kern_class_option, "leftbottomkern");
5147 lua_set_string_by_index(L, right_bottom_kern_class_option, "rightbottomkern");
5148 lua_set_string_by_index(L, look_ahead_for_end_class_option, "lookaheadforend");
5149 lua_set_string_by_index(L, no_italic_correction_class_option, "noitaliccorrection");
5150 lua_set_string_by_index(L, check_ligature_class_option, "checkligature");
5151 lua_set_string_by_index(L, check_kern_pair_class_option, "checkkernpair");
5152 lua_set_string_by_index(L, check_italic_correction_class_option, "checkitaliccorrection");
5153 lua_set_string_by_index(L, flatten_class_option, "flatten");
5154 lua_set_string_by_index(L, omit_penalty_class_option, "omitpenalty");
5155
5156
5157
5158 lua_set_string_by_index(L, unpack_class_option, "unpack");
5159 lua_set_string_by_index(L, raise_prime_option, "raiseprime");
5160 lua_set_string_by_index(L, carry_over_left_top_kern_class_option, "carryoverlefttopkern");
5161 lua_set_string_by_index(L, carry_over_left_bottom_kern_class_option, "carryoverleftbottomkern");
5162 lua_set_string_by_index(L, carry_over_right_top_kern_class_option, "carryoverrighttopkern");
5163 lua_set_string_by_index(L, carry_over_right_bottom_kern_class_option, "carryoverrightbottomkern");
5164 lua_set_string_by_index(L, prefer_delimiter_dimensions_class_option, "preferdelimiterdimensions");
5165 lua_set_string_by_index(L, auto_inject_class_option, "autoinject");
5166 lua_set_string_by_index(L, remove_italic_correction_class_option, "removeitaliccorrection");
5167 lua_set_string_by_index(L, operator_italic_correction_class_option, "operatoritaliccorrection");
5168 lua_set_string_by_index(L, short_inline_class_option, "shortinline");
5169 lua_set_string_by_index(L, push_nesting_class_option, "pushnesting");
5170 lua_set_string_by_index(L, pop_nesting_class_option, "popnesting");
5171 lua_set_string_by_index(L, obey_nesting_class_option, "obeynesting");
5172 return 1;
5173}
5174
5175static int texlib_getnormalizelinevalues(lua_State *L)
5176{
5177 lua_createtable(L, 2, 7);
5178 lua_set_string_by_index(L, normalize_line_mode, "normalizeline");
5179 lua_set_string_by_index(L, parindent_skip_mode, "parindentskip");
5180 lua_set_string_by_index(L, swap_hangindent_mode, "swaphangindent");
5181 lua_set_string_by_index(L, swap_parshape_mode, "swapparshape");
5182 lua_set_string_by_index(L, break_after_dir_mode, "breakafterdir");
5183 lua_set_string_by_index(L, remove_margin_kerns_mode, "removemarginkerns");
5184 lua_set_string_by_index(L, clip_width_mode, "clipwidth");
5185 lua_set_string_by_index(L, flatten_discretionaries_mode, "flattendiscretionaries");
5186 lua_set_string_by_index(L, discard_zero_tab_skips_mode, "discardzerotabskips");
5187 lua_set_string_by_index(L, flatten_h_leaders_mode, "flattenhleaders");
5188 return 1;
5189}
5190
5191static int texlib_getnormalizeparvalues(lua_State *L)
5192{
5193 lua_createtable(L, 2, 0);
5194 lua_set_string_by_index(L, normalize_par_mode, "normalizepar");
5195 lua_set_string_by_index(L, flatten_v_leaders_mode, "flattenvleaders");
5196 lua_set_string_by_index(L, limit_prev_graf_mode, "limitprevgraf");
5197 return 1;
5198}
5199
5200static int texlib_getunitclassvalues(lua_State *L)
5201{
5202 lua_createtable(L, 4, 1);
5203 lua_set_string_by_index(L, unset_unit_class, "unset");
5204 lua_set_string_by_index(L, tex_unit_class, "tex");
5205 lua_set_string_by_index(L, pdftex_unit_class, "pdftex");
5206 lua_set_string_by_index(L, luametatex_unit_class, "luametatex");
5207 lua_set_string_by_index(L, user_unit_class, "user");
5208 return 1;
5209}
5210
5211static int texlib_geterrorvalues(lua_State *L)
5212{
5213 lua_createtable(L, 7, 1);
5214 lua_set_string_by_index(L, normal_error_type, "normal");
5215 lua_set_string_by_index(L, back_error_type, "back");
5216 lua_set_string_by_index(L, insert_error_type, "insert");
5217 lua_set_string_by_index(L, succumb_error_type, "succumb");
5218 lua_set_string_by_index(L, eof_error_type, "eof");
5219 lua_set_string_by_index(L, condition_error_type,"condition");
5220 lua_set_string_by_index(L, runaway_error_type, "runaway");
5221 lua_set_string_by_index(L, warning_error_type, "warning");
5222 return 1;
5223}
5224
5225static int texlib_getiovalues(lua_State *L)
5226{
5227 lua_createtable(L, 5, 1);
5228 lua_set_string_by_index(L, io_initial_input_code, "initial");
5229 lua_set_string_by_index(L, io_lua_input_code, "lua print");
5230 lua_set_string_by_index(L, io_token_input_code, "scan token");
5231 lua_set_string_by_index(L, io_token_eof_input_code, "scan token eof");
5232 lua_set_string_by_index(L, io_tex_macro_code, "tex macro");
5233 lua_set_string_by_index(L, io_file_input_code, "file");
5234 return 1;
5235}
5236
5237static int texlib_getfrozenparvalues(lua_State *L)
5238{
5239 lua_createtable(L, 2, 22);
5240 lua_set_string_by_index(L, par_hsize_category, "hsize");
5241 lua_set_string_by_index(L, par_skip_category, "skip");
5242 lua_set_string_by_index(L, par_hang_category, "hang");
5243 lua_set_string_by_index(L, par_indent_category, "indent");
5244 lua_set_string_by_index(L, par_par_fill_category, "parfill");
5245 lua_set_string_by_index(L, par_adjust_category, "adjust");
5246 lua_set_string_by_index(L, par_protrude_category, "protrude");
5247 lua_set_string_by_index(L, par_tolerance_category, "tolerance");
5248 lua_set_string_by_index(L, par_stretch_category, "stretch");
5249 lua_set_string_by_index(L, par_looseness_category, "looseness");
5250 lua_set_string_by_index(L, par_last_line_category, "lastline");
5251 lua_set_string_by_index(L, par_line_penalty_category, "linepenalty");
5252 lua_set_string_by_index(L, par_club_penalty_category, "clubpenalty");
5253 lua_set_string_by_index(L, par_widow_penalty_category, "widowpenalty");
5254 lua_set_string_by_index(L, par_display_penalty_category, "displaypenalty");
5255 lua_set_string_by_index(L, par_broken_penalty_category, "brokenpenalty");
5256 lua_set_string_by_index(L, par_demerits_category, "demerits");
5257 lua_set_string_by_index(L, par_shape_category, "shape");
5258 lua_set_string_by_index(L, par_line_category, "line");
5259 lua_set_string_by_index(L, par_hyphenation_category, "hyphenation");
5260 lua_set_string_by_index(L, par_shaping_penalty_category, "shapingpenalty");
5261 lua_set_string_by_index(L, par_orphan_penalty_category, "orphanpenalty");
5262 lua_set_string_by_index(L, par_emergency_category, "emergency");
5263 lua_set_string_by_index(L, par_par_passes_category, "parpasses");
5264 lua_set_string_by_index(L, par_par_single_line_penalty_category, "singlelinepenalty");
5265
5266 return 1;
5267}
5268
5269static int texlib_getkerneloptionvalues(lua_State *L)
5270{
5271 lua_createtable(L, 2, 6);
5272 lua_set_string_by_index(L, math_kernel_no_italic_correction, "noitaliccorrection");
5273 lua_set_string_by_index(L, math_kernel_no_left_pair_kern, "noleftpairkern");
5274 lua_set_string_by_index(L, math_kernel_no_right_pair_kern, "norightpairkern");
5275 lua_set_string_by_index(L, math_kernel_auto_discretionary, "autodiscretionary");
5276 lua_set_string_by_index(L, math_kernel_full_discretionary, "fulldiscretionary");
5277 lua_set_string_by_index(L, math_kernel_ignored_character, "ignoredcharacter");
5278 lua_set_string_by_index(L, math_kernel_is_large_operator, "islargeoperator");
5279 lua_set_string_by_index(L, math_kernel_has_italic_shape, "hasitalicshape");
5280 return 1;
5281}
5282
5283static int texlib_getcharactertagvalues(lua_State *L)
5284{
5285 lua_createtable(L, 2, 21);
5286 lua_set_string_by_index(L, no_tag, "normal");
5287 lua_set_string_by_index(L, ligatures_tag, "ligatures");
5288 lua_set_string_by_index(L, kerns_tag, "kerns");
5289 lua_set_string_by_index(L, list_tag, "list");
5290 lua_set_string_by_index(L, callback_tag, "callback");
5291 lua_set_string_by_index(L, extensible_tag, "extensible");
5292 lua_set_string_by_index(L, horizontal_tag, "horizontal");
5293 lua_set_string_by_index(L, vertical_tag, "vertical");
5294 lua_set_string_by_index(L, inner_left_tag, "innerleft");
5295 lua_set_string_by_index(L, inner_right_tag, "innerright");
5296 lua_set_string_by_index(L, inner_top_tag, "innertop");
5297 lua_set_string_by_index(L, inner_bottom_tag, "innerbottom");
5298 lua_set_string_by_index(L, extend_last_tag, "extendlast");
5299 lua_set_string_by_index(L, italic_tag, "italic");
5300 lua_set_string_by_index(L, n_ary_tag, "nary");
5301 lua_set_string_by_index(L, radical_tag, "radical");
5302 lua_set_string_by_index(L, punctuation_tag, "punctuation");
5303 lua_set_string_by_index(L, keep_base_tag, "keepbase");
5304 lua_set_string_by_index(L, expansion_tag, "expansion");
5305 lua_set_string_by_index(L, protrusion_tag, "protrusion");
5306 lua_set_string_by_index(L, above_baseline_tag, "abovebaseline");
5307 lua_set_string_by_index(L, below_baseline_tag, "belowbaseline");
5308 lua_set_string_by_index(L, force_extensible_tag, "forceextensible");
5309 return 1;
5310}
5311
5312static int texlib_getshapingpenaltiesvalues(lua_State *L)
5313{
5314 lua_createtable(L, 2, 2);
5315 lua_push_key_at_index(L, interlinepenalty, inter_line_penalty_shaping);
5316 lua_push_key_at_index(L, widowpenalty, widow_penalty_shaping);
5317 lua_push_key_at_index(L, clubpenalty, club_penalty_shaping);
5318 lua_push_key_at_index(L, brokenpenalty, broken_penalty_shaping);
5319 return 1;
5320}
5321
5322static int texlib_getautoparagraphvalues(lua_State *L)
5323{
5324 lua_createtable(L, 2, 1);
5325 lua_set_string_by_index(L, auto_paragraph_text, "text");
5326 lua_set_string_by_index(L, auto_paragraph_macro, "macro");
5327 lua_set_string_by_index(L, auto_paragraph_go_on, "continue");
5328 return 1;
5329}
5330
5331static int texlib_getprimitiveorigins(lua_State *L)
5332{
5333 lua_createtable(L, 2, 1);
5334 lua_push_key_at_index(L, tex, tex_command);
5335 lua_push_key_at_index(L, etex, etex_command);
5336 lua_push_key_at_index(L, luatex, luatex_command);
5337 return 1;
5338}
5339
5340static int texlib_getinteractionmodes(lua_State *L)
5341{
5342 lua_createtable(L, 4, 0);
5343 lua_set_string_by_index(L, batch_mode, "batch");
5344 lua_set_string_by_index(L, error_stop_mode, "errorstop");
5345 lua_set_string_by_index(L, nonstop_mode, "nonstop");
5346 lua_set_string_by_index(L, scroll_mode, "scroll");
5347 return 1;
5348}
5349
5350static int texlib_getiftypes(lua_State *L)
5351{
5352 lua_createtable(L, 70, 0);
5353 lua_set_string_by_index(L, if_char_code - first_real_if_test_code, "char");
5354 lua_set_string_by_index(L, if_cat_code - first_real_if_test_code, "cat");
5355 lua_set_string_by_index(L, if_int_code - first_real_if_test_code, "num");
5356 lua_set_string_by_index(L, if_abs_int_code - first_real_if_test_code, "absnum");
5357 lua_set_string_by_index(L, if_zero_int_code - first_real_if_test_code, "zeronum");
5358 lua_set_string_by_index(L, if_interval_int_code - first_real_if_test_code, "intervalnum");
5359 lua_set_string_by_index(L, if_posit_code - first_real_if_test_code, "float");
5360 lua_set_string_by_index(L, if_abs_posit_code - first_real_if_test_code, "absfloat");
5361 lua_set_string_by_index(L, if_zero_posit_code - first_real_if_test_code, "zerofloat");
5362 lua_set_string_by_index(L, if_interval_posit_code - first_real_if_test_code, "intervalfloat");
5363 lua_set_string_by_index(L, if_dim_code - first_real_if_test_code, "dim");
5364 lua_set_string_by_index(L, if_abs_dim_code - first_real_if_test_code, "absdim");
5365 lua_set_string_by_index(L, if_zero_dim_code - first_real_if_test_code, "zerodim");
5366 lua_set_string_by_index(L, if_interval_dim_code - first_real_if_test_code, "intervaldim");
5367 lua_set_string_by_index(L, if_odd_code - first_real_if_test_code, "odd");
5368 lua_set_string_by_index(L, if_vmode_code - first_real_if_test_code, "vmode");
5369 lua_set_string_by_index(L, if_hmode_code - first_real_if_test_code, "hmode");
5370 lua_set_string_by_index(L, if_mmode_code - first_real_if_test_code, "mmode");
5371 lua_set_string_by_index(L, if_inner_code - first_real_if_test_code, "inner");
5372 lua_set_string_by_index(L, if_void_code - first_real_if_test_code, "void");
5373 lua_set_string_by_index(L, if_hbox_code - first_real_if_test_code, "hbox");
5374 lua_set_string_by_index(L, if_vbox_code - first_real_if_test_code, "vbox");
5375 lua_set_string_by_index(L, if_cstok_code - first_real_if_test_code, "cstoken");
5376 lua_set_string_by_index(L, if_tok_code - first_real_if_test_code, "tok");
5377 lua_set_string_by_index(L, if_x_code - first_real_if_test_code, "x");
5378
5379 lua_set_string_by_index(L, if_true_code - first_real_if_test_code, "true");
5380 lua_set_string_by_index(L, if_false_code - first_real_if_test_code, "false");
5381 lua_set_string_by_index(L, if_chk_int_code - first_real_if_test_code, "chknum");
5382 lua_set_string_by_index(L, if_chk_integer_code - first_real_if_test_code, "chknunber");
5383 lua_set_string_by_index(L, if_val_int_code - first_real_if_test_code, "numval");
5384 lua_set_string_by_index(L, if_cmp_int_code - first_real_if_test_code, "cmpnum");
5385 lua_set_string_by_index(L, if_chk_dim_code - first_real_if_test_code, "chkdim");
5386 lua_set_string_by_index(L, if_chk_dimension_code - first_real_if_test_code, "chkdimension");
5387 lua_set_string_by_index(L, if_val_dim_code - first_real_if_test_code, "dimval");
5388 lua_set_string_by_index(L, if_cmp_dim_code - first_real_if_test_code, "cmpdim");
5389 lua_set_string_by_index(L, if_case_code - first_real_if_test_code, "case");
5390 lua_set_string_by_index(L, if_defined_code - first_real_if_test_code, "defined");
5391 lua_set_string_by_index(L, if_csname_code - first_real_if_test_code, "csname");
5392 lua_set_string_by_index(L, if_font_char_code - first_real_if_test_code, "fontchar");
5393 lua_set_string_by_index(L, if_posit_code - first_real_if_test_code, "float");
5394 lua_set_string_by_index(L, if_tok_code - first_real_if_test_code, "tok");
5395 lua_set_string_by_index(L, if_in_csname_code - first_real_if_test_code, "incsname");
5396 lua_set_string_by_index(L, if_font_char_code - first_real_if_test_code, "fontchar");
5397 lua_set_string_by_index(L, if_condition_code - first_real_if_test_code, "condition");
5398 lua_set_string_by_index(L, if_flags_code - first_real_if_test_code, "flags");
5399 lua_set_string_by_index(L, if_empty_code - first_real_if_test_code, "empty");
5400 lua_set_string_by_index(L, if_relax_code - first_real_if_test_code, "relax");
5401 lua_set_string_by_index(L, if_boolean_code - first_real_if_test_code, "boolean");
5402 lua_set_string_by_index(L, if_numexpression_code - first_real_if_test_code, "numexpression");
5403 lua_set_string_by_index(L, if_dimexpression_code - first_real_if_test_code, "dimexpression");
5404 lua_set_string_by_index(L, if_math_parameter_code - first_real_if_test_code, "mathparameter");
5405 lua_set_string_by_index(L, if_math_style_code - first_real_if_test_code, "mathstyle");
5406 lua_set_string_by_index(L, if_arguments_code - first_real_if_test_code, "arguments");
5407 lua_set_string_by_index(L, if_parameters_code - first_real_if_test_code, "parameters");
5408 lua_set_string_by_index(L, if_parameter_code - first_real_if_test_code, "parameter");
5409 lua_set_string_by_index(L, if_has_tok_code - first_real_if_test_code, "hastok");
5410 lua_set_string_by_index(L, if_has_toks_code - first_real_if_test_code, "hastoks");
5411 lua_set_string_by_index(L, if_has_xtoks_code - first_real_if_test_code, "hasxtoks");
5412 lua_set_string_by_index(L, if_has_char_code - first_real_if_test_code, "haschar");
5413 lua_set_string_by_index(L, if_insert_code - first_real_if_test_code, "insert");
5414 lua_set_string_by_index(L, if_in_alignment_code - first_real_if_test_code, "inalignment");
5415
5416 return 1;
5417}
5418
5419static int texlib_getlargestusedmark(lua_State* L)
5420{
5421 lua_pushinteger(L, lmt_mark_state.mark_data.ptr);
5422 return 1;
5423}
5424
5425static int texlib_getoutputactive(lua_State* L)
5426{
5427 lua_pushboolean(L, lmt_page_builder_state.output_active);
5428 return 1;
5429}
5430
5431
5432
5433int lmt_push_info_keys(lua_State *L, value_info *values)
5434{
5435 lua_newtable(L);
5436 for (int i = 0; values[i].name; i++) {
5437 lua_rawgeti(L, LUA_REGISTRYINDEX, values[i].lua);
5438 lua_rawseti(L, -2, i);
5439 }
5440 return 1;
5441}
5442
5443int lmt_push_info_values(lua_State *L, value_info *values)
5444{
5445 lua_newtable(L);
5446 for (int i = 0; values[i].name; i++) {
5447 lua_rawgeti(L, LUA_REGISTRYINDEX, values[i].lua);
5448 lua_rawseti(L, -2, values[i].value);
5449 }
5450 return 1;
5451}
5452
5453static int texlib_getgroupvalues(lua_State *L)
5454{
5455 return lmt_push_info_values(L, lmt_interface.group_code_values);
5456}
5457
5458static int texlib_getmathparametervalues(lua_State *L)
5459{
5460 return lmt_push_info_keys(L, lmt_interface.math_parameter_values);
5461}
5462
5463static int texlib_getmathstylevalues(lua_State* L)
5464{
5465 return lmt_push_info_values(L, lmt_interface.math_style_values);
5466}
5467
5468static int texlib_getpacktypevalues(lua_State *L)
5469{
5470 return lmt_push_info_values(L, lmt_interface.pack_type_values);
5471}
5472
5473static int texlib_getparcontextvalues(lua_State *L)
5474{
5475 return lmt_push_info_values(L, lmt_interface.par_context_values);
5476}
5477
5478static int texlib_getpagecontextvalues(lua_State *L)
5479{
5480 return lmt_push_info_values(L, lmt_interface.page_context_values);
5481}
5482
5483static int texlib_getappendlinecontextvalues(lua_State *L)
5484{
5485 return lmt_push_info_values(L, lmt_interface.append_line_context_values);
5486}
5487
5488static int texlib_getalignmentcontextvalues(lua_State *L)
5489{
5490 return lmt_push_info_values(L, lmt_interface.alignment_context_values);
5491}
5492
5493static int texlib_getbreakcontextvalues(lua_State *L)
5494{
5495 return lmt_push_info_values(L, lmt_interface.break_context_values);
5496}
5497
5498static int texlib_getbuildcontextvalues(lua_State *L)
5499{
5500 return lmt_push_info_values(L, lmt_interface.build_context_values);
5501}
5502
5503static int texlib_getpartriggervalues(lua_State *L)
5504{
5505 return lmt_push_info_values(L, lmt_interface.par_trigger_values);
5506}
5507
5508static int texlib_getparmodevalues(lua_State *L)
5509{
5510 return lmt_push_info_values(L, lmt_interface.par_mode_values);
5511}
5512
5513static int texlib_getmathstylenamevalues(lua_State *L)
5514{
5515 return lmt_push_info_values(L, lmt_interface.math_style_name_values);
5516}
5517
5518static int texlib_getmathvariantvalues(lua_State *L)
5519{
5520 return lmt_push_info_values(L, lmt_interface.math_style_variant_values);
5521}
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534static int texlib_getdiscstatevalues(lua_State *L)
5535{
5536 lua_createtable(L, 4, 1);
5537 lua_set_string_by_index(L, glyph_discpart_unset, "unset");
5538 lua_set_string_by_index(L, glyph_discpart_pre, "pre");
5539 lua_set_string_by_index(L, glyph_discpart_post, "post");
5540 lua_set_string_by_index(L, glyph_discpart_replace, "replace");
5541 lua_set_string_by_index(L, glyph_discpart_always, "always");
5542 return 1;
5543}
5544
5545static int texlib_getmathcontrolvalues(lua_State *L)
5546{
5547 lua_createtable(L, 2, 24);
5548 lua_set_string_by_index(L, math_control_use_font_control, "usefontcontrol");
5549 lua_set_string_by_index(L, math_control_over_rule, "overrule");
5550 lua_set_string_by_index(L, math_control_under_rule, "underrule");
5551 lua_set_string_by_index(L, math_control_radical_rule, "radicalrule");
5552 lua_set_string_by_index(L, math_control_fraction_rule, "fractionrule");
5553 lua_set_string_by_index(L, math_control_accent_skew_half, "accentskewhalf");
5554 lua_set_string_by_index(L, math_control_accent_skew_apply, "accentskewapply");
5555 lua_set_string_by_index(L, math_control_apply_ordinary_kern_pair, "applyordinarykernpair");
5556 lua_set_string_by_index(L, math_control_apply_vertical_italic_kern, "applyverticalitalickern");
5557 lua_set_string_by_index(L, math_control_apply_ordinary_italic_kern, "applyordinaryitalickern");
5558 lua_set_string_by_index(L, math_control_apply_char_italic_kern, "applycharitalickern");
5559 lua_set_string_by_index(L, math_control_rebox_char_italic_kern, "reboxcharitalickern");
5560 lua_set_string_by_index(L, math_control_apply_boxed_italic_kern, "applyboxeditalickern");
5561 lua_set_string_by_index(L, math_control_staircase_kern, "staircasekern");
5562 lua_set_string_by_index(L, math_control_apply_text_italic_kern, "applytextitalickern");
5563 lua_set_string_by_index(L, math_control_check_text_italic_kern, "checktextitalickern");
5564 lua_set_string_by_index(L, math_control_check_space_italic_kern, "checkspaceitalickern");
5565 lua_set_string_by_index(L, math_control_apply_script_italic_kern, "applyscriptitalickern");
5566 lua_set_string_by_index(L, math_control_analyze_script_nucleus_char, "analyzescriptnucleuschar");
5567 lua_set_string_by_index(L, math_control_analyze_script_nucleus_list, "analyzescriptnucleuslist");
5568 lua_set_string_by_index(L, math_control_analyze_script_nucleus_box, "analyzescriptnucleusbox");
5569 lua_set_string_by_index(L, math_control_accent_top_skew_with_offset, "accenttopskewwithoffset");
5570 lua_set_string_by_index(L, math_control_ignore_kern_dimensions, "ignorekerndimensions");
5571 lua_set_string_by_index(L, math_control_ignore_flat_accents, "ignoreflataccents");
5572 lua_set_string_by_index(L, math_control_extend_accents, "extendaccents");
5573 lua_set_string_by_index(L, math_control_extend_delimiters, "extenddelimiters");
5574 return 1;
5575}
5576
5577static int texlib_gettextcontrolvalues(lua_State *L)
5578{
5579 lua_createtable(L, 2, 4);
5580 lua_set_string_by_index(L, text_control_collapse_hyphens, "collapsehyphens");
5581 lua_set_string_by_index(L, text_control_base_ligaturing, "baseligaturing");
5582 lua_set_string_by_index(L, text_control_base_kerning, "basekerning");
5583 lua_set_string_by_index(L, text_control_none_protected, "noneprotected");
5584 lua_set_string_by_index(L, text_control_has_italics, "hasitalics");
5585 lua_set_string_by_index(L, text_control_auto_italics, "autoitalics");
5586 return 1;
5587}
5588
5589static int texlib_getfitnessvalues(lua_State *L)
5590{
5591 lua_createtable(L, 5, 1);
5592 lua_set_string_by_index(L, very_loose_fit, "veryloose");
5593 lua_set_string_by_index(L, loose_fit, "loose");
5594 lua_set_string_by_index(L, semi_loose_fit, "semiloose");
5595 lua_set_string_by_index(L, decent_fit, "decent");
5596 lua_set_string_by_index(L, semi_tight_fit, "semitight");
5597 lua_set_string_by_index(L, tight_fit, "tight");
5598 return 1;
5599}
5600
5601
5602static int texlib_getparpassclassvalues(lua_State *L)
5603{
5604 lua_createtable(L, 4, 2);
5605 lua_set_string_by_index(L, very_loose_class, "veryloose");
5606 lua_set_string_by_index(L, loose_fit_class, "loose");
5607 lua_set_string_by_index(L, semi_loose_fit_class, "semiloose");
5608 lua_set_string_by_index(L, decent_fit_class, "decent");
5609 lua_set_string_by_index(L, semi_tight_fit_class, "semitight");
5610 lua_set_string_by_index(L, tight_fit_class, "tight");
5611 return 1;
5612}
5613
5614static int texlib_getprepoststatevalues(lua_State *L)
5615{
5616 lua_createtable(L, 2, 2);
5617 lua_set_string_by_index(L, has_pre_adjust, "preadjust");
5618 lua_set_string_by_index(L, has_post_adjust, "postadjust");
5619 lua_set_string_by_index(L, has_pre_migrated, "premigrated");
5620 lua_set_string_by_index(L, has_post_migrated, "postmigrated");
5621 return 1;
5622}
5623
5624static int texlib_getfillvalues(lua_State *L)
5625{
5626 return lmt_push_info_values(L, lmt_interface.node_fill_values);
5627}
5628
5629static int texlib_getdirectionvalues(lua_State *L)
5630{
5631 return lmt_push_info_values(L, lmt_interface.direction_values);
5632}
5633
5634static int texlib_getparametermodevalues(lua_State *L)
5635{
5636 lua_createtable(L, 1, 0);
5637 lua_set_string_by_index(L, parameter_escape_mode, "escape");
5638 return 1;
5639}
5640
5641
5642
5643static int texlib_getinsertdistance(lua_State *L)
5644{
5645 return texlib_aux_push_glue(L, tex_get_insert_distance(lmt_tointeger(L, 1)));
5646}
5647
5648static int texlib_getinsertmultiplier(lua_State *L)
5649{
5650 lua_pushinteger(L, tex_get_insert_multiplier(lmt_tointeger(L, 1)));
5651 return 1;
5652}
5653
5654static int texlib_getinsertlimit(lua_State *L)
5655{
5656 tex_set_insert_limit(lmt_tointeger(L, 1), lmt_opthalfword(L, 2, 0));
5657 return 0;
5658}
5659
5660static int texlib_setinsertdistance(lua_State *L)
5661{
5662 tex_set_insert_distance(lmt_tointeger(L, 1), texlib_aux_make_glue(L, lua_gettop(L), 2));
5663 return 0;
5664}
5665
5666static int texlib_setinsertmultiplier(lua_State *L)
5667{
5668 tex_set_insert_multiplier(lmt_tointeger(L, 1), lmt_tohalfword(L, 2));
5669 return 0;
5670}
5671
5672static int texlib_setinsertlimit(lua_State *L)
5673{
5674 lua_pushinteger(L, tex_get_insert_limit(lmt_tointeger(L, 1)));
5675 return 1;
5676}
5677
5678static int texlib_getinsertheight(lua_State *L)
5679{
5680 lua_pushinteger(L, tex_get_insert_height(lmt_tointeger(L, 1)));
5681 return 1;
5682}
5683
5684static int texlib_getinsertdepth(lua_State *L)
5685{
5686 lua_pushinteger(L, tex_get_insert_depth(lmt_tointeger(L, 1)));
5687 return 1;
5688}
5689
5690static int texlib_getinsertwidth(lua_State *L)
5691{
5692 lua_pushinteger(L, tex_get_insert_width(lmt_tointeger(L, 1)));
5693 return 1;
5694}
5695
5696static int texlib_getinsertcontent(lua_State *L)
5697{
5698 halfword index = lmt_tointeger(L, 1);
5699 lmt_node_list_to_lua(L, tex_get_insert_content(index));
5700 tex_set_insert_content(index, null);
5701 return 1;
5702}
5703
5704static int texlib_setinsertcontent(lua_State *L)
5705{
5706 halfword index = lmt_tointeger(L, 1);
5707 tex_flush_node(tex_get_insert_content(index));
5708 tex_set_insert_content(index, lmt_node_list_from_lua(L, 2));
5709 return 0;
5710}
5711
5712static int texlib_getlocalbox(lua_State *L)
5713{
5714 int location = lmt_tointeger(L, 1);
5715 if (is_valid_local_box_code(location)) {
5716 lmt_node_list_to_lua(L, tex_get_local_boxes(location));
5717 } else {
5718 lua_pushnil(L);
5719 }
5720 return 1;
5721}
5722
5723static int texlib_setlocalbox(lua_State *L)
5724{
5725 int location = lmt_tointeger(L, 1);
5726 if (is_valid_local_box_code(location)) {
5727 tex_set_local_boxes(lmt_node_list_from_lua(L, 1), location);
5728 }
5729 return 0;
5730}
5731
5732static int texlib_pushsavelevel(lua_State *L)
5733{
5734 (void) L;
5735 tex_new_save_level(lua_group);
5736 return 0;
5737}
5738
5739static int texlib_popsavelevel(lua_State *L)
5740{
5741 (void) L;
5742
5743 tex_unsave();
5744 return 0;
5745}
5746
5747
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5807
5808
5809
5810static const struct luaL_Reg texlib_function_list[] = {
5811 { "write", texlib_write },
5812 { "print", texlib_print },
5813 { "sprint", texlib_sprint },
5814 { "mprint", texlib_mprint },
5815 { "tprint", texlib_tprint },
5816 { "cprint", texlib_cprint },
5817 { "isprintable", texlib_isprintable },
5818 { "pushlocal", texlib_pushlocal },
5819 { "poplocal", texlib_poplocal },
5820 { "runlocal", texlib_runlocal },
5821 { "runstring", texlib_runstring },
5822 { "quitlocal", texlib_quitlocal },
5823 { "expandasvalue", texlib_expandasvalue },
5824 { "error", texlib_error },
5825 { "set", texlib_set },
5826 { "get", texlib_get },
5827 { "getregisterindex", texlib_get_register_index },
5828 { "isdimen", texlib_isdimen },
5829 { "setdimen", texlib_setdimen },
5830 { "getdimen", texlib_getdimen },
5831 { "isfloat", texlib_isfloat },
5832 { "setfloat", texlib_setfloat },
5833 { "getfloat", texlib_getfloat },
5834 { "isskip", texlib_isskip },
5835 { "setskip", texlib_setskip },
5836 { "getskip", texlib_getskip },
5837 { "isglue", texlib_isglue },
5838 { "setglue", texlib_setglue },
5839 { "getglue", texlib_getglue },
5840 { "ismuskip", texlib_ismuskip },
5841 { "setmuskip", texlib_setmuskip },
5842 { "getmuskip", texlib_getmuskip },
5843 { "ismuglue", texlib_ismuglue },
5844 { "setmuglue", texlib_setmuglue },
5845 { "getmuglue", texlib_getmuglue },
5846 { "isattribute", texlib_isattribute },
5847 { "setattribute", texlib_setattribute },
5848 { "getattribute", texlib_getattribute },
5849 { "iscount", texlib_iscount },
5850 { "setcount", texlib_setcount },
5851 { "getcount", texlib_getcount },
5852 { "istoks", texlib_istoks },
5853 { "settoks", texlib_settoks },
5854 { "scantoks", texlib_scantoks },
5855 { "gettoks", texlib_gettoks },
5856 { "getmark", texlib_getmark },
5857 { "isbox", texlib_isbox },
5858 { "setbox", texlib_setbox },
5859 { "getbox", texlib_getbox },
5860 { "splitbox", texlib_splitbox },
5861 { "setlist", texlib_setlist },
5862 { "getlist", texlib_getlist },
5863 { "setnest", texlib_setnest },
5864 { "getnest", texlib_getnest },
5865 { "getnestlevel", texlib_getnestlevel },
5866 { "setcatcode", texlib_setcatcode },
5867 { "getcatcode", texlib_getcatcode },
5868 { "setdelcode", texlib_setdelcode },
5869 { "getdelcode", texlib_getdelcode },
5870 { "getdelcodes", texlib_getdelcodes },
5871 { "sethccode", texlib_sethccode },
5872 { "gethccode", texlib_gethccode },
5873 { "sethmcode", texlib_sethmcode },
5874 { "gethmcode", texlib_gethmcode },
5875 { "setamcode", texlib_setamcode },
5876 { "getamcode", texlib_getamcode },
5877 { "setlccode", texlib_setlccode },
5878 { "getlccode", texlib_getlccode },
5879 { "setmathcode", texlib_setmathcode },
5880 { "getmathcode", texlib_getmathcode },
5881 { "getmathcodes", texlib_getmathcodes },
5882 { "setsfcode", texlib_setsfcode },
5883 { "getsfcode", texlib_getsfcode },
5884 { "setuccode", texlib_setuccode },
5885 { "getuccode", texlib_getuccode },
5886 { "round", texlib_round },
5887 { "scale", texlib_scale },
5888 { "sp", texlib_toscaled },
5889 { "toscaled", texlib_toscaled },
5890 { "tonumber", texlib_tonumber },
5891 { "fontname", texlib_getfontname },
5892 { "fontidentifier", texlib_getfontidentifier },
5893 { "getfontoffamily", texlib_getfontoffamily },
5894 { "number", texlib_getnumber },
5895
5896 { "romannumeral", texlib_getromannumeral },
5897 { "definefont", texlib_definefont },
5898 { "hashtokens", texlib_hashtokens },
5899 { "primitives", texlib_primitives },
5900 { "extraprimitives", texlib_extraprimitives },
5901 { "enableprimitives", texlib_enableprimitives },
5902 { "shipout", texlib_shipout },
5903 { "badness", texlib_badness },
5904 { "setmath", texlib_setmath },
5905 { "getmath", texlib_getmath },
5906 { "linebreak", texlib_linebreak },
5907 { "preparelinebreak", texlib_preparelinebreak },
5908 { "resetparagraph", texlib_resetparagraph },
5909 { "showcontext", texlib_showcontext },
5910 { "triggerbuildpage", texlib_triggerbuildpage },
5911 { "gethelptext", texlib_gethelptext },
5912 { "getpagestate", texlib_getpagestate },
5913 { "getlocallevel", texlib_getlocallevel },
5914 { "setinputstatemode", texlib_setinputstatemode },
5915 { "getinputstatemode", texlib_getinputstatemode },
5916 { "setinputstatefile", texlib_setinputstatefile },
5917 { "getinputstatefile", texlib_getinputstatefile },
5918 { "forceinputstatefile", texlib_forceinputstatefile },
5919 { "forceinputstateline", texlib_forceinputstateline },
5920 { "setinputstateline", texlib_setinputstateline },
5921 { "getinputstateline", texlib_getinputstateline },
5922 { "forcehmode", texlib_forcehmode },
5923 { "gettextdir", texlib_gettextdir },
5924 { "settextdir", texlib_settextdir },
5925 { "getlinedir", texlib_gettextdir },
5926 { "setlinedir", texlib_setlinedir },
5927 { "getmathdir", texlib_getmathdir },
5928 { "setmathdir", texlib_setmathdir },
5929 { "getpardir", texlib_getpardir },
5930 { "setpardir", texlib_setpardir },
5931 { "getboxdir", texlib_getboxdir },
5932 { "setboxdir", texlib_setboxdir },
5933 { "getinteraction", texlib_getinteraction },
5934 { "setinteraction", texlib_setinteraction },
5935 { "getglyphdata", texlib_getglyphdata },
5936 { "setglyphdata", texlib_setglyphdata },
5937 { "getglyphstate", texlib_getglyphstate },
5938 { "setglyphstate", texlib_setglyphstate },
5939 { "getglyphscript", texlib_getglyphscript },
5940 { "setglyphscript", texlib_setglyphscript },
5941 { "getglyphscales", texlib_getglyphscales },
5942 { "fatalerror", texlib_fatalerror },
5943 { "lastnodetype", texlib_lastnodetype },
5944 { "chardef", texlib_chardef },
5945 { "mathchardef", texlib_mathchardef },
5946 { "integerdef", texlib_setintegervalue },
5947 { "setintegervalue", texlib_setintegervalue },
5948 { "getintegervalue", texlib_getintegervalue },
5949 { "positdef", texlib_setfloatvalue },
5950 { "setpositvalue", texlib_setfloatvalue },
5951 { "getpositvalue", texlib_getfloatvalue },
5952 { "setcardinalvalue", texlib_setcardinalvalue },
5953 { "getcardinalvalue", texlib_getintegervalue },
5954 { "dimensiondef", texlib_setdimensionvalue },
5955 { "setdimensionvalue", texlib_setdimensionvalue },
5956 { "getdimensionvalue", texlib_getdimensionvalue },
5957 { "getmode", texlib_getmode },
5958 { "getmodevalues", texlib_getmodevalues },
5959 { "getrunstatevalues", texlib_getrunstatevalues },
5960 { "setrunstate", texlib_setrunstate },
5961 { "gethyphenationvalues", texlib_gethyphenationvalues },
5962 { "getglyphoptionvalues", texlib_getglyphoptionvalues },
5963 { "getglueoptionvalues", texlib_getglueoptionvalues },
5964 { "getmathoptionvalues", texlib_getmathoptionvalues },
5965 { "getpenaltyoptionvalues", texlib_getpenaltyoptionvalues },
5966 { "getnoadoptionvalues", texlib_getnoadoptionvalues },
5967 { "getdiscoptionvalues", texlib_getdiscoptionvalues },
5968 { "getmathsurroundvalues", texlib_getmathsurroundvalues },
5969 { "getlistanchorvalues", texlib_getlistanchorvalues },
5970 { "getlistsignvalues", texlib_getlistsignvalues },
5971 { "getlistgeometryvalues", texlib_getlistgeometryvalues },
5972 { "getmathgluevalues", texlib_getmathgluevalues },
5973 { "getdiscstatevalues", texlib_getdiscstatevalues },
5974 { "getmathparametervalues", texlib_getmathparametervalues },
5975 { "getmathstylenamevalues", texlib_getmathstylenamevalues },
5976 { "getmathstylevalues", texlib_getmathstylevalues },
5977 { "getmathvariantvalues", texlib_getmathvariantvalues },
5978
5979 { "getmathcontrolvalues", texlib_getmathcontrolvalues },
5980 { "gettextcontrolvalues", texlib_gettextcontrolvalues },
5981 { "getfitnessvalues", texlib_getfitnessvalues },
5982 { "getparpassclassvalues", texlib_getparpassclassvalues },
5983 { "getprepoststatevalues", texlib_getprepoststatevalues },
5984 { "getpacktypevalues", texlib_getpacktypevalues },
5985 { "getgroupvalues", texlib_getgroupvalues },
5986 { "getparcontextvalues", texlib_getparcontextvalues },
5987 { "getpagecontextvalues", texlib_getpagecontextvalues },
5988 { "getappendlinecontextvalues", texlib_getappendlinecontextvalues },
5989 { "getalignmentcontextvalues", texlib_getalignmentcontextvalues },
5990 { "getbreakcontextvalues", texlib_getbreakcontextvalues },
5991 { "getbuildcontextvalues", texlib_getbuildcontextvalues },
5992 { "getpartriggervalues", texlib_getpartriggervalues },
5993 { "getparmodevalues", texlib_getparmodevalues },
5994 { "getautomigrationvalues", texlib_getautomigrationvalues },
5995 { "getflagvalues", texlib_getflagvalues },
5996 { "getprotrusionboundaryvalues", texlib_getprotrusionboundaryvalues },
5997 { "getmathclassoptionvalues", texlib_getmathclassoptionvalues },
5998 { "getnormalizelinevalues", texlib_getnormalizelinevalues },
5999 { "getnormalizeparvalues", texlib_getnormalizeparvalues },
6000 { "getdirectionvalues", texlib_getdirectionvalues },
6001 { "getparametermodevalues", texlib_getparametermodevalues },
6002 { "getfillvalues", texlib_getfillvalues },
6003 { "getunitclassvalues", texlib_getunitclassvalues },
6004 { "geterrorvalues", texlib_geterrorvalues },
6005 { "getinteractionmodes", texlib_getinteractionmodes },
6006 { "getiftypes", texlib_getiftypes },
6007 { "getiovalues", texlib_getiovalues },
6008 { "getprimitiveorigins", texlib_getprimitiveorigins },
6009 { "getfrozenparvalues", texlib_getfrozenparvalues },
6010 { "getshapingpenaltiesvalues", texlib_getshapingpenaltiesvalues },
6011 { "getautoparagraphvalues", texlib_getautoparagraphvalues },
6012 { "getcharactertagvalues", texlib_getcharactertagvalues },
6013 { "getkerneloptionvalues", texlib_getkerneloptionvalues },
6014 { "getspecialmathclassvalues", texlib_getspecialmathclassvalues },
6015 { "getlargestusedmark", texlib_getlargestusedmark },
6016 { "getoutputactive", texlib_getoutputactive },
6017
6018 { "shiftparshape", texlib_shiftparshape },
6019 { "snapshotpar", texlib_snapshotpar },
6020 { "getparstate", texlib_getparstate },
6021
6022 { "getinsertdistance", texlib_getinsertdistance },
6023 { "getinsertmultiplier", texlib_getinsertmultiplier },
6024 { "getinsertlimit", texlib_getinsertlimit },
6025 { "getinsertheight", texlib_getinsertheight },
6026 { "getinsertdepth", texlib_getinsertdepth },
6027 { "getinsertwidth", texlib_getinsertwidth },
6028 { "getinsertcontent", texlib_getinsertcontent },
6029 { "setinsertdistance", texlib_setinsertdistance },
6030 { "setinsertmultiplier", texlib_setinsertmultiplier },
6031 { "setinsertlimit", texlib_setinsertlimit },
6032 { "setinsertcontent", texlib_setinsertcontent },
6033 { "getlocalbox", texlib_getlocalbox },
6034 { "setlocalbox", texlib_setlocalbox },
6035
6036 { "pushsavelevel", texlib_pushsavelevel },
6037 { "popsavelevel", texlib_popsavelevel },
6038
6039
6040
6041
6042 { NULL, NULL },
6043};
6044
6045# define defineindexers(name) \
6046 static int texlib_index_##name (lua_State *L) { lua_remove(L, 1); return texlib_get##name(L); } \
6047 static int texlib_newindex_##name(lua_State *L) { lua_remove(L, 1); return texlib_set##name(L); }
6048
6049defineindexers(attribute)
6050defineindexers(skip)
6051defineindexers(glue)
6052defineindexers(muskip)
6053defineindexers(muglue)
6054defineindexers(dimen)
6055defineindexers(count)
6056defineindexers(float)
6057defineindexers(toks)
6058defineindexers(box)
6059defineindexers(sfcode)
6060defineindexers(lccode)
6061defineindexers(uccode)
6062defineindexers(hccode)
6063defineindexers(hmcode)
6064defineindexers(amcode)
6065defineindexers(catcode)
6066defineindexers(mathcode)
6067defineindexers(delcode)
6068defineindexers(list)
6069defineindexers(nest)
6070
6071
6075
6076int luaopen_tex(lua_State *L)
6077{
6078
6079
6080 texlib_aux_initialize();
6081
6082 lua_newtable(L);
6083 luaL_setfuncs(L, texlib_function_list, 0);
6084 lmt_make_table(L, "attribute", TEX_METATABLE_ATTRIBUTE, texlib_index_attribute, texlib_newindex_attribute);
6085 lmt_make_table(L, "skip", TEX_METATABLE_SKIP, texlib_index_skip, texlib_newindex_skip);
6086 lmt_make_table(L, "glue", TEX_METATABLE_GLUE, texlib_index_glue, texlib_newindex_glue);
6087 lmt_make_table(L, "muskip", TEX_METATABLE_MUSKIP, texlib_index_muskip, texlib_newindex_muskip);
6088 lmt_make_table(L, "muglue", TEX_METATABLE_MUGLUE, texlib_index_muglue, texlib_newindex_muglue);
6089 lmt_make_table(L, "dimen", TEX_METATABLE_DIMEN, texlib_index_dimen, texlib_newindex_dimen);
6090 lmt_make_table(L, "count", TEX_METATABLE_COUNT, texlib_index_count, texlib_newindex_count);
6091 lmt_make_table(L, "posit", TEX_METATABLE_FLOAT, texlib_index_float, texlib_newindex_float);
6092 lmt_make_table(L, "toks", TEX_METATABLE_TOKS, texlib_index_toks, texlib_newindex_toks);
6093 lmt_make_table(L, "box", TEX_METATABLE_BOX, texlib_index_box, texlib_newindex_box);
6094 lmt_make_table(L, "sfcode", TEX_METATABLE_SFCODE, texlib_index_sfcode, texlib_newindex_sfcode);
6095 lmt_make_table(L, "lccode", TEX_METATABLE_LCCODE, texlib_index_lccode, texlib_newindex_lccode);
6096 lmt_make_table(L, "uccode", TEX_METATABLE_UCCODE, texlib_index_uccode, texlib_newindex_uccode);
6097 lmt_make_table(L, "hccode", TEX_METATABLE_HCCODE, texlib_index_hccode, texlib_newindex_hccode);
6098 lmt_make_table(L, "hmcode", TEX_METATABLE_HMCODE, texlib_index_hmcode, texlib_newindex_hmcode);
6099 lmt_make_table(L, "amcode", TEX_METATABLE_AMCODE, texlib_index_amcode, texlib_newindex_amcode);
6100 lmt_make_table(L, "catcode", TEX_METATABLE_CATCODE, texlib_index_catcode, texlib_newindex_catcode);
6101 lmt_make_table(L, "mathcode", TEX_METATABLE_MATHCODE, texlib_index_mathcode, texlib_newindex_mathcode);
6102 lmt_make_table(L, "delcode", TEX_METATABLE_DELCODE, texlib_index_delcode, texlib_newindex_delcode);
6103 lmt_make_table(L, "lists", TEX_METATABLE_LISTS, texlib_index_list, texlib_newindex_list);
6104 lmt_make_table(L, "nest", TEX_METATABLE_NEST, texlib_index_nest, texlib_newindex_nest);
6105 texlib_aux_init_nest_lib(L);
6106
6107 luaL_newmetatable(L, TEX_METATABLE_TEX);
6108 lua_pushstring(L, "__index");
6109 lua_pushcfunction(L, texlib_index);
6110 lua_settable(L, -3);
6111 lua_pushstring(L, "__newindex");
6112 lua_pushcfunction(L, texlib_newindex);
6113 lua_settable(L, -3);
6114 lua_setmetatable(L, -2);
6115 return 1;
6116}
6117 |