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