3 Copyright 2006-2012 Taco Hoekwater <taco@luatex.org>
5 This file is part of LuaTeX.
7 LuaTeX is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2 of the License, or (at your
10 option) any later version.
12 LuaTeX is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 License for more details.
17 You should have received a copy of the GNU General Public License along
18 with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */
20 /* hh-ls: Because the lists start with a temp node, we have to set the prev link
21 to nil because otherwise at the lua end we expose temp which can create havoc. In the
22 setter no prev link is created so we can presume that it's not used later on. */
25 #include "lua/luatex-api.h"
27 /* tex random generators */
28 extern int unif_rand(int );
29 extern int norm_rand(void );
30 extern void init_randoms(int );
44 char complete
; /* currently still writing ? */
47 #define PARTIAL_LINE 1
50 #define write_spindle spindles[spindle_index]
51 #define read_spindle spindles[(spindle_index-1)]
53 static int spindle_size
= 0;
54 static spindle
*spindles
= NULL
;
55 static int spindle_index
= 0;
57 static void luac_store(lua_State
* L
, int i
, int partial
, int cattable
)
63 sttemp
= lua_tolstring(L
, i
, &tsize
);
64 st
= xmalloc((unsigned) (tsize
+ 1));
65 memcpy(st
, sttemp
, (tsize
+ 1));
68 rn
= (rope
*) xmalloc(sizeof(rope
));
70 rn
->tsize
= (unsigned) tsize
;
71 rn
->partial
= partial
;
72 rn
->cattable
= cattable
;
75 if (write_spindle
.head
== NULL
) {
76 assert(write_spindle
.tail
== NULL
);
77 write_spindle
.head
= rn
;
79 write_spindle
.tail
->next
= rn
;
81 write_spindle
.tail
= rn
;
82 write_spindle
.complete
= 0;
86 static int do_luacprint(lua_State
* L
, int partial
, int deftable
)
88 int cattable
= deftable
;
90 int n
= lua_gettop(L
);
91 if (cattable
!= NO_CAT_TABLE
) {
92 if (lua_type(L
, 1) == LUA_TNUMBER
&& n
> 1) {
93 cattable
= lua_tointeger(L
, 1);
95 if (cattable
!= -1 && cattable
!= -2 && !valid_catcode_table(cattable
)) {
96 cattable
= DEFAULT_CAT_TABLE
;
100 if (lua_type(L
, startstrings
) == LUA_TTABLE
) {
103 lua_rawgeti(L
, startstrings
, i
);
104 if (lua_isstring(L
,-1)) { /* or number */
105 luac_store(L
, -1, partial
, cattable
);
113 for (i
= startstrings
; i
<= n
; i
++) {
114 if (!lua_isstring(L
,i
)) { /* or number */
115 luaL_error(L
, "no string to print");
117 luac_store(L
, i
, partial
, cattable
);
119 /* hh: We could use this but it makes not much different, apart from allocating more ropes so less
120 memory. To be looked into: lua 5.2 buffer mechanism as now we still hash the concatination. This
121 test was part of the why-eis-luajit-so-slow on crited experiments. */
123 if (startstrings == n) {
124 luac_store(L, n, partial, cattable);
126 lua_concat(L,n-startstrings+1);
127 luac_store(L, startstrings, partial, cattable);
136 // some first experiments .. somewhat tricky at the other end
138 int luatwrite(lua_State * L)
140 int top = lua_gettop(L);
142 rope *rn = xmalloc(sizeof(rope)); // overkill
144 luacstrings++; // should be luactokens
148 rn->cattable = DEFAULT_CAT_TABLE;
151 if (write_spindle.head == NULL) {
152 write_spindle.head = rn;
154 write_spindle.tail->next = rn;
156 write_spindle.tail = rn;
157 write_spindle.complete = 0;
159 rn->tok = lua_tointeger(L,i);
161 rope *r = xmalloc(sizeof(rope)); // overkill
165 r->cattable = DEFAULT_CAT_TABLE;
170 write_spindle.tail = rn;
182 static int luacwrite(lua_State
* L
)
184 return do_luacprint(L
, FULL_LINE
, NO_CAT_TABLE
);
187 static int luacprint(lua_State
* L
)
189 return do_luacprint(L
, FULL_LINE
, DEFAULT_CAT_TABLE
);
192 static int luacsprint(lua_State
* L
)
194 return do_luacprint(L
, PARTIAL_LINE
, DEFAULT_CAT_TABLE
);
197 static int luaccprint(lua_State
* L
)
199 /* so a negative value is a specific catcode with offset 1 */
200 int cattable
= lua_tointeger(L
,1);
201 if (cattable
< 0 || cattable
> 15) {
202 cattable
= - 12 - 0xFF ;
204 cattable
= - cattable
- 0xFF;
206 if (lua_type(L
, 2) == LUA_TTABLE
) {
209 lua_rawgeti(L
, 2, i
);
210 if (lua_isstring(L
,-1)) { /* or number */
211 luac_store(L
, -1, PARTIAL_LINE
, cattable
);
219 int n
= lua_gettop(L
);
220 for (i
= 2; i
<= n
; i
++) {
221 if (!lua_isstring(L
,i
)) { /* or number */
222 luaL_error(L
, "no string to print");
224 luac_store(L
, i
, PARTIAL_LINE
, cattable
);
230 static int luactprint(lua_State
* L
)
233 int cattable
, startstrings
;
234 int n
= lua_gettop(L
);
235 for (i
= 1; i
<= n
; i
++) {
236 cattable
= DEFAULT_CAT_TABLE
;
238 if (lua_type(L
, i
) != LUA_TTABLE
) {
239 luaL_error(L
, "no string to print");
241 lua_pushvalue(L
, i
); /* push the table */
242 lua_pushinteger(L
, 1);
244 if (lua_type(L
, -1) == LUA_TNUMBER
) {
245 cattable
= lua_tointeger(L
, -1);
247 if (cattable
!= -1 && cattable
!= -2 && !valid_catcode_table(cattable
)) {
248 cattable
= DEFAULT_CAT_TABLE
;
252 for (j
= startstrings
;; j
++) {
253 lua_pushinteger(L
, j
);
255 if (lua_isstring(L
, -1)) { /* or number */
256 luac_store(L
, -1, PARTIAL_LINE
, cattable
);
263 lua_pop(L
, 1); /* pop the table */
268 int luacstring_cattable(void)
270 return (int) read_spindle
.tail
->cattable
;
273 int luacstring_partial(void)
275 return read_spindle
.tail
->partial
;
278 int luacstring_final_line(void)
280 return (read_spindle
.tail
->next
== NULL
);
283 int luacstring_input(void)
285 rope
*t
= read_spindle
.head
;
287 if (!read_spindle
.complete
) {
288 read_spindle
.complete
= 1;
289 read_spindle
.tail
= NULL
;
292 if (read_spindle
.tail
!= NULL
)
293 free(read_spindle
.tail
);
294 read_spindle
.tail
= NULL
;
297 if (t
->text
!= NULL
) {
298 /* put that thing in the buffer */
302 check_buffer_overflow(last
+ (int) t
->tsize
);
303 while (t
->tsize
-- > 0)
304 buffer
[last
++] = (packed_ASCII_code
) * st
++;
306 while (last
- 1 > ret
&& buffer
[last
- 1] == ' ')
312 } else if (t->tok > 0) {
316 if (read_spindle
.tail
!= NULL
) { /* not a one-liner */
317 free(read_spindle
.tail
);
319 read_spindle
.tail
= t
;
320 read_spindle
.head
= t
->next
;
324 /* open for reading, and make a new one for writing */
325 void luacstring_start(int n
)
327 (void) n
; /* for -W */
329 if (spindle_size
== spindle_index
) { /* add a new one */
330 spindles
= xrealloc(spindles
, (unsigned) (sizeof(spindle
) * (unsigned) (spindle_size
+ 1)));
331 spindles
[spindle_index
].head
= NULL
;
332 spindles
[spindle_index
].tail
= NULL
;
333 spindles
[spindle_index
].complete
= 0;
338 /* close for reading */
340 void luacstring_close(int n
)
343 (void) n
; /* for -W */
344 next
= read_spindle
.head
;
345 while (next
!= NULL
) {
346 if (next
->text
!= NULL
)
350 if (t
==read_spindle
.tail
) {
351 read_spindle
.tail
= NULL
;
355 read_spindle
.head
= NULL
;
356 if (read_spindle
.tail
!= NULL
)
357 free(read_spindle
.tail
);
358 read_spindle
.tail
= NULL
;
359 read_spindle
.complete
= 0;
363 /* local (static) versions */
365 #define check_index_range(j,s) \
366 if (j<0 || j > 65535) { \
367 luaL_error(L, "incorrect index specification for tex.%s()", s); }
369 #define check_register(base) do { \
370 int k = get_item_index(L, lua_gettop(L), base); \
371 if ((k>=0) && (k <= 65535)) { \
372 lua_pushinteger(L,k); \
374 lua_pushboolean(L,false); \
379 static const char *scan_integer_part(lua_State
* L
, const char *ss
, int *ret
, int *radix_ret
)
381 boolean negative
= false; /* should the answer be negated? */
382 int m
= 214748364; /* |$2^{31}$ / radix|, the threshold of danger */
383 int d
; /* the digit just scanned */
384 boolean vacuous
= true; /* have no digits appeared? */
385 boolean OK_so_far
= true; /* has an error message been issued? */
386 int radix1
= 10; /* the radix of the integer */
387 int c
= 0; /* the current character */
388 const char *s
; /* where we stopped in the string |ss| */
389 integer val
= 0; /* return value */
394 } while (c
&& c
== ' ');
396 negative
= !negative
;
404 } else if (c
== '"') {
409 /* Accumulate the constant until |cur_tok| is not a suitable digit */
411 if ((c
< '0' + radix1
) && (c
>= '0') && (c
<= '0' + 9)) {
413 } else if (radix1
== 16) {
414 if ((c
<= 'A' + 5) && (c
>= 'A')) {
416 } else if ((c
<= 'a' + 5) && (c
>= 'a')) {
425 if ((val
>= m
) && ((val
> m
) || (d
> 7) || (radix1
!= 10))) {
427 luaL_error(L
, "Number too big");
432 val
= val
* radix1
+ d
;
437 /* Express astonishment that no number was here */
438 luaL_error(L
, "Missing number, treated as zero");
444 if (c
!= ' ' && s
> ss
)
449 #define set_conversion(A,B) do { num=(A); denom=(B); } while(0)
452 static const char *scan_dimen_part(lua_State
* L
, const char *ss
, int *ret
)
453 /* sets |cur_val| to a dimension */
455 boolean negative
= false; /* should the answer be negated? */
456 int f
= 0; /* numerator of a fraction whose denominator is $2^{16}$ */
457 int num
, denom
; /* conversion ratio for the scanned units */
458 int k
; /* number of digits in a decimal fraction */
459 scaled v
; /* an internal dimension */
460 int save_cur_val
; /* temporary storage of |cur_val| */
461 int c
; /* the current character */
462 const char *s
= ss
; /* where we are in the string */
463 int radix1
= 0; /* the current radix */
464 int rdig
[18]; /* to save the |dig[]| array */
465 int saved_tex_remainder
; /* to save |tex_remainder| */
466 int saved_arith_error
; /* to save |arith_error| */
467 int saved_cur_val
; /* to save the global |cur_val| */
468 saved_tex_remainder
= tex_remainder
;
469 saved_arith_error
= arith_error
;
470 saved_cur_val
= cur_val
;
471 /* Get the next non-blank non-sign... */
473 /* Get the next non-blank non-call token */
476 } while (c
&& c
== ' ');
478 negative
= !negative
;
486 s
= scan_integer_part(L
, (s
> ss
? (s
- 1) : ss
), &cur_val
, &radix1
);
495 if ((radix1
== 10) && (c
== '.')) {
496 /* Scan decimal fraction */
497 for (k
= 0; k
< 18; k
++)
500 s
++; /* get rid of the '.' */
503 if ((c
> '0' + 9) || (c
< '0'))
505 if (k
< 17) { /* digits for |k>=17| cannot affect the result */
509 f
= round_decimals(k
);
512 for (k
= 0; k
< 18; k
++)
515 if (cur_val
< 0) { /* in this case |f=0| */
516 negative
= !negative
;
519 /* Scan for (u)units that are internal dimensions;
520 |goto attach_sign| with |cur_val| set if found */
521 save_cur_val
= cur_val
;
522 /* Get the next non-blank non-call... */
525 } while (c
&& c
== ' ');
528 if (strncmp(s
, "em", 2) == 0) {
530 v
= (quad(get_cur_font()));
531 } else if (strncmp(s
, "ex", 2) == 0) {
533 v
= (x_height(get_cur_font()));
534 } else if (strncmp(s
, "px", 2) == 0) {
544 cur_val
= nx_plus_y(save_cur_val
, v
, xn_over_d(v
, f
, 0200000));
547 /* Scan for (m)\.{mu} units and |goto attach_fraction| */
548 if (strncmp(s
, "mu", 2) == 0) {
550 goto ATTACH_FRACTION
;
552 if (strncmp(s
, "true", 4) == 0) {
553 /* Adjust (f)for the magnification ratio */
555 if (output_mode_used
<= OMODE_DVI
) {
557 if (mag_par
!= 1000) {
558 cur_val
= xn_over_d(cur_val
, 1000, mag_par
);
559 f
= (1000 * f
+ 0200000 * tex_remainder
) / mag_par
;
560 cur_val
= cur_val
+ (f
/ 0200000);
566 } while (c
&& c
== ' ');
569 if (strncmp(s
, "pt", 2) == 0) {
571 goto ATTACH_FRACTION
; /* the easy case */
573 /* Scan for (a)all other units and adjust |cur_val| and |f| accordingly;
574 |goto done| in the case of scaled points */
575 if (strncmp(s
, "mm", 2) == 0) {
577 set_conversion(7227, 2540);
578 } else if (strncmp(s
, "cm", 2) == 0) {
580 set_conversion(7227, 254);
581 } else if (strncmp(s
, "sp", 2) == 0) {
584 } else if (strncmp(s
, "bp", 2) == 0) {
586 set_conversion(7227, 7200);
587 } else if (strncmp(s
, "in", 2) == 0) {
589 set_conversion(7227, 100);
590 } else if (strncmp(s
, "dd", 2) == 0) {
592 set_conversion(1238, 1157);
593 } else if (strncmp(s
, "cc", 2) == 0) {
595 set_conversion(14856, 1157);
596 } else if (strncmp(s
, "pc", 2) == 0) {
598 set_conversion(12, 1);
599 } else if (strncmp(s
, "nd", 2) == 0) {
601 set_conversion(685, 642);
602 } else if (strncmp(s
, "nc", 2) == 0) {
604 set_conversion(1370, 107);
606 /* Complain about unknown unit and |goto done2| */
607 luaL_error(L
, "Illegal unit of measure (pt inserted)");
610 cur_val
= xn_over_d(cur_val
, num
, denom
);
611 f
= (num
* f
+ 0200000 * tex_remainder
) / denom
;
612 cur_val
= cur_val
+ (f
/ 0200000);
616 if (cur_val
>= 040000)
619 cur_val
= cur_val
* 65536 + f
;
621 /* Scan an optional space */
626 if (arith_error
|| (abs(cur_val
) >= 010000000000)) {
627 /* Report that this dimension is out of range */
628 luaL_error(L
, "Dimension too large");
634 tex_remainder
= saved_tex_remainder
;
635 arith_error
= saved_arith_error
;
636 cur_val
= saved_cur_val
;
640 int dimen_to_number(lua_State
* L
, const char *s
)
643 const char *d
= scan_dimen_part(L
, s
, &j
);
645 luaL_error(L
, "conversion failed (trailing junk?)");
651 static int tex_scaledimen(lua_State
* L
)
654 int t
= lua_type(L
, 1);
655 if (t
== LUA_TNUMBER
) {
656 sp
= lua_roundnumber(L
, 1);
657 } else if (t
== LUA_TSTRING
) {
658 sp
= dimen_to_number(L
, lua_tostring(L
, 1));
660 luaL_error(L
, "argument must be a string or a number");
663 lua_pushinteger(L
, sp
);
667 static int texerror (lua_State
* L
)
669 const char **errhlp
= NULL
;
670 const char *error
= luaL_checkstring(L
,1);
671 int n
= lua_gettop(L
);
672 if (n
==2 && lua_type(L
, n
) == LUA_TTABLE
) {
674 int l
= 1; /* |errhlp| is terminated by a NULL entry */
676 lua_rawgeti(L
, n
, i
);
677 if (lua_type(L
,-1) == LUA_TSTRING
) {
686 errhlp
= xmalloc(l
* sizeof(char *));
687 memset(errhlp
,0,l
* sizeof(char *));
689 lua_rawgeti(L
, n
, i
);
690 if (lua_type(L
,-1) == LUA_TSTRING
) {
691 errhlp
[(i
-1)] = lua_tostring(L
,-1);
699 deletions_allowed
= false;
700 tex_error(error
, errhlp
);
703 deletions_allowed
= true;
707 static int get_item_index(lua_State
* L
, int i
, int base
)
713 switch (lua_type(L
, i
)) {
715 s
= lua_tolstring(L
, i
, &kk
);
716 cur_cs1
= string_lookup(s
, kk
);
717 if (cur_cs1
== undefined_control_sequence
|| cur_cs1
== undefined_cs_cmd
)
718 k
= -1; /* guarandeed invalid */
720 k
= (equiv(cur_cs1
) - base
);
723 k
= luaL_checkinteger(L
, i
);
726 luaL_error(L
, "argument must be a string or a number");
727 k
= -1; /* not a valid index */
732 #define check_item_global(L,top,isglobal) \
733 if (top == 3 && (lua_type(L,1) == LUA_TSTRING)) { \
734 const char *s = lua_tostring(L, 1); \
735 if (lua_key_eq(s,global)) { \
740 #define set_item_index_plus(L, where, base, what, value, is_global, is_assign, set_register, glue) { \
744 int save_global_defs = global_defs_par; \
746 global_defs_par = 1; \
748 switch (lua_type(L, where)) { \
750 str = lua_tolstring(L, where, &len); \
751 cs = string_lookup(str, len); \
752 if (cs == undefined_control_sequence || cs == undefined_cs_cmd) { \
753 luaL_error(L, "incorrect %s name", what); \
755 key = equiv(cs) - base; \
756 if (key >= 0 && key <= 65535) { \
757 err = set_register(key, value); \
759 luaL_error(L, "incorrect %s value", what); \
761 } else if (is_assign(eq_type(cs))) { \
764 define(equiv(cs), assign_glue_cmd, value); \
766 assign_internal_value((is_global ? 4 : 0), equiv(cs), value); \
769 luaL_error(L, "incorrect %s name", what); \
774 key = luaL_checkinteger(L, where); \
775 if (key>=0 && key <= 65535) { \
776 err = set_register(key, value); \
778 luaL_error(L, "incorrect %s value", what); \
781 luaL_error(L, "incorrect %s index", what); \
785 luaL_error(L, "argument of 'set%s' must be a string or a number", what); \
787 global_defs_par = save_global_defs; \
790 static int gettex(lua_State
* L
);
792 #define get_item_index_plus(L, where, base, what, value, is_assign, get_register, glue) { \
796 switch (lua_type(L, where)) { \
798 str = lua_tolstring(L, where, &len); \
799 cs = string_lookup(str, len); \
800 if (cs == undefined_control_sequence || cs == undefined_cs_cmd) { \
801 luaL_error(L, "incorrect %s name", what); \
803 key = equiv(cs) - base; \
804 if (key >= 0 && key <= 65535) { \
805 value = get_register(key); \
806 } else if (is_assign(eq_type(cs))) { \
807 gettex(L); /* lazy */ \
809 luaL_error(L, "incorrect %s name", what); \
814 key = luaL_checkinteger(L, where); \
815 if (key>=0 && key <= 65535) { \
816 value = get_register(key); \
818 luaL_error(L, "incorrect %s index", what); \
822 luaL_error(L, "argument of 'get%s' must be a string or a number", what); \
826 static int isdimen(lua_State
* L
)
828 check_register(scaled_base
);
831 static int setdimen(lua_State
* L
)
835 int top
= lua_gettop(L
);
836 int t
= lua_type(L
, top
);
837 check_item_global(L
,top
,isglobal
);
838 if (t
== LUA_TNUMBER
) {
839 value
= lua_roundnumber(L
, top
);
840 } else if (t
== LUA_TSTRING
) {
841 value
= dimen_to_number(L
, lua_tostring(L
, top
));
843 luaL_error(L
, "unsupported %s value type","dimen");
845 set_item_index_plus(L
, top
-1, scaled_base
, "dimen", value
, isglobal
, is_dim_assign
, set_tex_dimen_register
, false);
849 static int getdimen(lua_State
* L
)
852 get_item_index_plus(L
, lua_gettop(L
), scaled_base
, "dimen", value
, is_dim_assign
, get_tex_dimen_register
, false);
853 lua_pushinteger(L
, value
);
857 static int isskip(lua_State
* L
)
859 check_register(skip_base
);
862 static int setskip(lua_State
* L
)
865 halfword
*value
= NULL
;
866 int top
= lua_gettop(L
);
867 check_item_global(L
,top
,isglobal
);
868 value
= check_isnode(L
, top
);
869 if (type(*value
) == glue_spec_node
) {
870 set_item_index_plus(L
, top
-1, skip_base
, "skip", *value
, isglobal
, is_glue_assign
, set_tex_skip_register
, true);
872 luaL_error(L
, "glue_spec expected");
877 static int getskip(lua_State
* L
)
880 get_item_index_plus(L
, lua_gettop(L
), skip_base
, "skip", value
, is_glue_assign
, get_tex_skip_register
, true);
882 lua_nodelib_push_fast(L
, copy_node(zero_glue
));
884 lua_nodelib_push_fast(L
, copy_node(value
));
889 static int setglue(lua_State
* L
)
893 halfword value
= copy_node(zero_glue
);
894 int top
= lua_gettop(L
);
895 check_item_global(L
,top
,isglobal
);
900 /* [global] slot [width] [stretch] [shrink] [stretch_order] [shrink_order] */
901 if (top
> 1) { width(value
) = lua_roundnumber(L
,index
+1); }
902 if (top
> 2) { stretch(value
) = lua_roundnumber(L
,index
+2); }
903 if (top
> 3) { shrink(value
) = lua_roundnumber(L
,index
+3); }
904 if (top
> 4) { stretch_order(value
) = lua_tointeger(L
,index
+4); }
905 if (top
> 5) { shrink_order(value
) = lua_tointeger(L
,index
+5); }
906 set_item_index_plus(L
, index
, skip_base
, "skip", value
, isglobal
, is_glue_assign
, set_tex_skip_register
, true);
910 static int getglue(lua_State
* L
)
913 int top
= lua_gettop(L
);
914 get_item_index_plus(L
, top
, skip_base
, "skip", value
, is_glue_assign
, get_tex_skip_register
, true);
916 lua_pushinteger(L
,0);
917 lua_pushinteger(L
,0);
918 lua_pushinteger(L
,0);
919 lua_pushinteger(L
,0);
920 lua_pushinteger(L
,0);
922 lua_pushinteger(L
,width(value
));
923 lua_pushinteger(L
,stretch(value
));
924 lua_pushinteger(L
,shrink(value
));
925 lua_pushinteger(L
,stretch_order(value
));
926 lua_pushinteger(L
,shrink_order(value
));
931 static int ismuskip(lua_State
* L
)
933 check_register(mu_skip_base
);
936 static int setmuskip(lua_State
* L
)
939 halfword
*value
= NULL
;
940 int top
= lua_gettop(L
);
941 check_item_global(L
,top
,isglobal
);
942 value
= check_isnode(L
, top
);
943 set_item_index_plus(L
, top
-1, mu_skip_base
, "muskip", *value
, isglobal
, is_mu_glue_assign
, set_tex_mu_skip_register
, true);
947 static int getmuskip(lua_State
* L
)
950 get_item_index_plus(L
, lua_gettop(L
), mu_skip_base
, "muskip", value
, is_mu_glue_assign
, get_tex_mu_skip_register
, true);
951 lua_nodelib_push_fast(L
, copy_node(value
));
955 static int setmuglue(lua_State
* L
)
959 halfword value
= copy_node(zero_glue
);
960 int top
= lua_gettop(L
);
961 check_item_global(L
,top
,isglobal
);
966 /* [global] slot [width] [stretch] [shrink] [stretch_order] [shrink_order] */
967 if (top
> 1) { width(value
) = lua_roundnumber(L
,index
+1); }
968 if (top
> 2) { stretch(value
) = lua_roundnumber(L
,index
+2); }
969 if (top
> 3) { shrink(value
) = lua_roundnumber(L
,index
+3); }
970 if (top
> 4) { stretch_order(value
) = lua_tointeger(L
,index
+4); }
971 if (top
> 5) { shrink_order(value
) = lua_tointeger(L
,index
+5); }
972 set_item_index_plus(L
, index
, mu_skip_base
, "muskip", value
, isglobal
, is_mu_glue_assign
, set_tex_mu_skip_register
, true);
976 static int getmuglue(lua_State
* L
)
979 get_item_index_plus(L
, lua_gettop(L
), mu_skip_base
, "muskip", value
, is_mu_glue_assign
, get_tex_mu_skip_register
, true);
984 lua_pushinteger(L
,width(value
));
985 lua_pushinteger(L
,stretch(value
));
986 lua_pushinteger(L
,shrink(value
));
987 lua_pushinteger(L
,stretch_order(value
));
988 lua_pushinteger(L
,shrink_order(value
));
993 static int iscount(lua_State
* L
)
995 check_register(count_base
);
998 static int setcount(lua_State
* L
)
1003 int top
= lua_gettop(L
);
1004 check_item_global(L
,top
,isglobal
);
1005 t
= lua_type(L
,top
);
1006 if (t
== LUA_TNUMBER
) {
1007 value
= lua_tointeger(L
, top
);
1009 luaL_error(L
, "unsupported %s value type","count");
1011 set_item_index_plus(L
, top
-1, count_base
, "count", value
, isglobal
, is_int_assign
, set_tex_count_register
, false);
1015 static int getcount(lua_State
* L
)
1018 get_item_index_plus(L
, lua_gettop(L
), count_base
, "count", value
, is_int_assign
, get_tex_count_register
, false);
1019 lua_pushinteger(L
, value
);
1023 static int isattribute(lua_State
* L
)
1025 check_register(attribute_base
);
1028 /* there are no system set attributes so this is a bit overkill */
1030 static int setattribute(lua_State
* L
)
1035 int top
= lua_gettop(L
);
1036 check_item_global(L
,top
,isglobal
);
1037 t
= lua_type(L
,top
);
1038 if (t
== LUA_TNUMBER
) {
1039 value
= lua_tointeger(L
, top
);
1041 luaL_error(L
, "unsupported %s value type","attribute");
1043 set_item_index_plus(L
, top
-1, attribute_base
, "attribute", value
, isglobal
, is_attr_assign
, set_tex_attribute_register
, false);
1047 static int getattribute(lua_State
* L
)
1050 get_item_index_plus(L
, lua_gettop(L
), attribute_base
, "attribute", value
, is_attr_assign
, get_tex_attribute_register
, false);
1051 lua_pushinteger(L
, value
);
1055 /* todo: we can avoid memcpy as there is no need to go through the pool */
1057 /* use string_to_toks */
1059 static int istoks(lua_State
* L
)
1061 check_register(toks_base
);
1064 static int settoks(lua_State
* L
)
1071 int save_global_defs
= global_defs_par
;
1072 int n
= lua_gettop(L
);
1073 if (n
== 3 && (lua_type(L
,1) == LUA_TSTRING
)) {
1074 const char *s
= lua_tostring(L
, 1);
1075 if (lua_key_eq(s
,global
))
1079 global_defs_par
= 1;
1081 if (lua_type(L
,i
) != LUA_TSTRING
) {
1082 luaL_error(L
, "unsupported value type");
1084 ss
= lua_tolstring(L
, i
, &str
.l
);
1085 s
= xmalloc (str
.l
+1);
1086 memcpy (s
, ss
, str
.l
+1);
1087 str
.s
= (unsigned char *)s
;
1088 k
= get_item_index(L
, (i
- 1), toks_base
);
1089 check_index_range(k
, "settoks");
1090 err
= set_tex_toks_register(k
, str
);
1092 global_defs_par
= save_global_defs
;
1094 luaL_error(L
, "incorrect value");
1099 static int scantoks(lua_State
* L
)
1106 int save_global_defs
= global_defs_par
;
1107 int n
= lua_gettop(L
);
1108 if (n
== 4 && (lua_type(L
,1) == LUA_TSTRING
)) {
1109 const char *s
= lua_tostring(L
, 1);
1110 if (lua_key_eq(s
,global
))
1113 /* action : vsettokscct(L, is_global); */
1115 global_defs_par
= 1;
1117 if (lua_type(L
,i
) != LUA_TSTRING
) {
1118 luaL_error(L
, "unsupported value type");
1120 ss
= lua_tolstring(L
, i
, &str
.l
);
1121 s
= xmalloc (str
.l
+1);
1122 memcpy (s
, ss
, str
.l
+1);
1123 str
.s
= (unsigned char *)s
;
1124 k
= get_item_index(L
, (i
- 2), toks_base
);
1125 c
= luaL_checkinteger(L
, i
- 1);
1126 check_index_range(k
, "settoks");
1127 err
= scan_tex_toks_register(k
, c
, str
);
1129 global_defs_par
= save_global_defs
;
1131 luaL_error(L
, "incorrect value");
1136 static int gettoks(lua_State
* L
)
1140 int k
= get_item_index(L
, lua_gettop(L
), toks_base
);
1141 check_index_range(k
, "gettoks");
1142 t
= get_tex_toks_register(k
);
1143 ss
= makecstring(t
);
1144 lua_pushstring(L
, ss
);
1150 static int get_box_id(lua_State
* L
, int i
, boolean report
)
1153 int cur_cs1
, cur_cmd1
;
1156 switch (lua_type(L
, i
)) {
1158 s
= lua_tolstring(L
, i
, &k
);
1159 cur_cs1
= string_lookup(s
, k
);
1160 cur_cmd1
= eq_type(cur_cs1
);
1161 if (cur_cmd1
== char_given_cmd
||
1162 cur_cmd1
== math_given_cmd
) {
1167 j
= lua_tointeger(L
, (i
));
1171 luaL_error(L
, "argument must be a string or a number");
1173 j
= -1; /* not a valid box id */
1178 static int getbox(lua_State
* L
)
1181 int k
= get_box_id(L
, -1, true);
1182 check_index_range(k
, "getbox");
1183 t
= get_tex_box_register(k
);
1184 nodelist_to_lua(L
, t
);
1188 static int splitbox(lua_State
* L
)
1191 int k
= get_box_id(L
, 1, true);
1192 check_index_range(k
, "splitbox");
1193 if (lua_isnumber(L
, 2)) {
1195 if (lua_type(L
, 3) == LUA_TSTRING
) {
1196 s
= lua_tostring(L
, 3);
1197 if (lua_key_eq(s
, exactly
)) {
1199 } else if (lua_key_eq(s
, additional
)) {
1202 } else if (lua_type(L
, 3) == LUA_TNUMBER
) {
1203 m
= (int) lua_tointeger(L
, 3);
1205 if ((m
<0) || (m
>1)) {
1206 luaL_error(L
, "wrong mode in splitbox");
1208 nodelist_to_lua(L
, vsplit(k
,lua_roundnumber(L
,2),m
));
1210 /* maybe a warning */
1216 static int isbox(lua_State
* L
)
1218 int k
= get_box_id(L
, -1, false);
1219 lua_pushboolean(L
,(k
>=0 && k
<=65535));
1223 static int vsetbox(lua_State
* L
, int is_global
)
1226 int save_global_defs
;
1227 k
= get_box_id(L
, -2, true);
1228 check_index_range(k
, "setbox");
1229 t
= lua_type(L
, -1);
1230 if (t
== LUA_TBOOLEAN
) {
1231 j
= lua_toboolean(L
, -1);
1237 } else if (t
== LUA_TNIL
) {
1240 j
= nodelist_from_lua(L
);
1241 if (j
!= null
&& type(j
) != hlist_node
&& type(j
) != vlist_node
) {
1242 luaL_error(L
, "setbox: incompatible node type (%s)\n", get_node_name(type(j
), subtype(j
)));
1246 save_global_defs
= global_defs_par
;
1248 global_defs_par
= 1;
1250 err
= set_tex_box_register(k
, j
);
1251 global_defs_par
= save_global_defs
;
1253 luaL_error(L
, "incorrect value");
1258 static int setbox(lua_State
* L
)
1261 int n
= lua_gettop(L
);
1262 if (n
== 3 && (lua_type(L
,1) == LUA_TSTRING
)) {
1263 const char *s
= lua_tostring(L
, 1);
1264 if (lua_key_eq(s
,global
))
1267 return vsetbox(L
, isglobal
);
1270 #define check_char_range(j,s,lim) \
1271 if (j<0 || j >= lim) { \
1272 luaL_error(L, "incorrect character value %d for tex.%s()", (int) j, s); \
1275 static int setcode (lua_State
*L
, void (*setone
)(int,halfword
,quarterword
),
1276 void (*settwo
)(int,halfword
,quarterword
), const char *name
, int lim
)
1279 halfword val
, ucval
;
1280 int level
= cur_level
;
1281 int n
= lua_gettop(L
);
1283 if (n
>1 && lua_type(L
,1) == LUA_TTABLE
)
1285 if (n
>2 && (lua_type(L
,f
) == LUA_TSTRING
)) {
1286 const char *s
= lua_tostring(L
, f
);
1287 if (lua_key_eq(s
,global
)) {
1292 ch
= luaL_checkinteger(L
, f
);
1293 check_char_range(ch
, name
, 65536*17);
1294 val
= (halfword
) luaL_checkinteger(L
, f
+1);
1295 check_char_range(val
, name
, lim
);
1296 (setone
)(ch
, val
, level
);
1297 if (settwo
!= NULL
&& n
-f
== 2) {
1298 ucval
= (halfword
) luaL_checkinteger(L
, f
+2);
1299 check_char_range(ucval
, name
, lim
);
1300 (settwo
)(ch
, ucval
, level
);
1305 static int setlccode(lua_State
* L
)
1307 return setcode(L
, &set_lc_code
, &set_uc_code
, "setlccode", 65536*17);
1310 static int getlccode(lua_State
* L
)
1312 int ch
= luaL_checkinteger(L
, -1);
1313 check_char_range(ch
, "getlccode", 65536*17);
1314 lua_pushinteger(L
, get_lc_code(ch
));
1318 static int setuccode(lua_State
* L
)
1320 return setcode(L
, &set_uc_code
, &set_lc_code
, "setuccode", 65536*17);
1323 static int getuccode(lua_State
* L
)
1325 int ch
= luaL_checkinteger(L
, -1);
1326 check_char_range(ch
, "getuccode", 65536*17);
1327 lua_pushinteger(L
, get_uc_code(ch
));
1331 static int setsfcode(lua_State
* L
)
1333 return setcode(L
, &set_sf_code
, NULL
, "setsfcode", 32768);
1336 static int getsfcode(lua_State
* L
)
1338 int ch
= luaL_checkinteger(L
, -1);
1339 check_char_range(ch
, "getsfcode", 65536*17);
1340 lua_pushinteger(L
, get_sf_code(ch
));
1344 static int setcatcode(lua_State
* L
)
1348 int level
= cur_level
;
1349 int cattable
= cat_code_table_par
;
1350 int n
= lua_gettop(L
);
1352 if (n
>1 && lua_type(L
,1) == LUA_TTABLE
)
1354 if (n
>2 && (lua_type(L
,f
) == LUA_TSTRING
)) {
1355 const char *s
= lua_tostring(L
, f
);
1356 if (lua_key_eq(s
,global
)) {
1362 cattable
= luaL_checkinteger(L
, -3);
1364 ch
= luaL_checkinteger(L
, -2);
1365 check_char_range(ch
, "setcatcode", 65536*17);
1366 val
= (halfword
) luaL_checkinteger(L
, -1);
1367 check_char_range(val
, "setcatcode", 16);
1368 set_cat_code(cattable
, ch
, val
, level
);
1372 static int getcatcode(lua_State
* L
)
1374 int cattable
= cat_code_table_par
;
1375 int ch
= luaL_checkinteger(L
, -1);
1376 if (lua_gettop(L
)>=2 && lua_type(L
,-2)==LUA_TNUMBER
) {
1377 cattable
= luaL_checkinteger(L
, -2);
1379 check_char_range(ch
, "getcatcode", 65536*17);
1380 lua_pushinteger(L
, get_cat_code(cattable
, ch
));
1386 static int setmathcode(lua_State * L)
1389 halfword cval, fval, chval;
1390 int level = cur_level;
1391 int n = lua_gettop(L);
1393 if (n>1 && lua_type(L,1) == LUA_TTABLE)
1395 if (n>2 && (lua_type(L,f) == LUA_TSTRING)) {
1396 const char *s = lua_tostring(L, f);
1397 if (lua_key_eq(s,global)) {
1402 if (n-f!=1 || lua_type(L,f+1) != LUA_TTABLE) {
1403 luaL_error(L, "Bad arguments for tex.setmathcode()");
1405 ch = luaL_checkinteger(L, -2);
1406 check_char_range(ch, "setmathcode", 65536*17);
1408 lua_rawgeti(L, -1, 1);
1409 cval = (halfword) luaL_checkinteger(L, -1);
1410 lua_rawgeti(L, -2, 2);
1411 fval = (halfword) luaL_checkinteger(L, -1);
1412 lua_rawgeti(L, -3, 3);
1413 chval = (halfword) luaL_checkinteger(L, -1);
1416 check_char_range(cval, "setmathcode", 8);
1417 check_char_range(fval, "setmathcode", 256);
1418 check_char_range(chval, "setmathcode", 65536*17);
1419 set_math_code(ch, cval,fval, chval, (quarterword) (level));
1426 [global] code { c f ch }
1427 [global] code c f ch (a bit easier on memory, counterpart of getter)
1430 static int setmathcode(lua_State
* L
)
1433 halfword cval
, fval
, chval
;
1434 int level
= cur_level
;
1436 if (lua_type(L
,1) == LUA_TSTRING
) {
1437 const char *s
= lua_tostring(L
,1);
1438 if (lua_key_eq(s
,global
)) {
1443 ch
= luaL_checkinteger(L
, f
);
1444 check_char_range(ch
, "setmathcode", 65536*17);
1446 if (lua_type(L
,f
) == LUA_TNUMBER
) {
1447 cval
= luaL_checkinteger(L
, f
);
1448 fval
= luaL_checkinteger(L
, f
+1);
1449 chval
= luaL_checkinteger(L
, f
+2);
1450 } else if (lua_type(L
,f
) == LUA_TTABLE
) {
1451 lua_rawgeti(L
, f
, 1);
1452 cval
= (halfword
) luaL_checkinteger(L
, -1);
1453 lua_rawgeti(L
, f
, 2);
1454 fval
= (halfword
) luaL_checkinteger(L
, -1);
1455 lua_rawgeti(L
, f
, 3);
1456 chval
= (halfword
) luaL_checkinteger(L
, -1);
1459 luaL_error(L
, "Bad arguments for tex.setmathcode()");
1462 check_char_range(cval
, "setmathcode", 8);
1463 check_char_range(fval
, "setmathcode", 256);
1464 check_char_range(chval
, "setmathcode", 65536*17);
1465 set_math_code(ch
, cval
,fval
, chval
, (quarterword
) (level
));
1469 static int getmathcode(lua_State
* L
)
1471 mathcodeval mval
= { 0, 0, 0 };
1472 int ch
= luaL_checkinteger(L
, -1);
1473 check_char_range(ch
, "getmathcode", 65536*17);
1474 mval
= get_math_code(ch
);
1476 lua_pushinteger(L
,mval
.class_value
);
1477 lua_rawseti(L
, -2, 1);
1478 lua_pushinteger(L
,mval
.family_value
);
1479 lua_rawseti(L
, -2, 2);
1480 lua_pushinteger(L
,mval
.character_value
);
1481 lua_rawseti(L
, -2, 3);
1485 static int getmathcodes(lua_State
* L
)
1487 mathcodeval mval
= { 0, 0, 0 };
1488 int ch
= luaL_checkinteger(L
, -1);
1489 check_char_range(ch
, "getmathcodes", 65536*17);
1490 mval
= get_math_code(ch
);
1491 lua_pushinteger(L
,mval
.class_value
);
1492 lua_pushinteger(L
,mval
.family_value
);
1493 lua_pushinteger(L
,mval
.character_value
);
1499 static int setdelcode(lua_State * L)
1502 halfword sfval, scval, lfval, lcval;
1503 int level = cur_level;
1504 int n = lua_gettop(L);
1506 if (n>1 && lua_type(L,1) == LUA_TTABLE)
1508 if (n>2 && (lua_type(L,f) == LUA_TSTRING)) {
1509 const char *s = lua_tostring(L, f);
1510 if (lua_key_eq(s,global)) {
1515 if (n-f!=1 || lua_type(L,f+1) != LUA_TTABLE) {
1516 luaL_error(L, "Bad arguments for tex.setdelcode()");
1518 ch = luaL_checkinteger(L, -2);
1519 check_char_range(ch, "setdelcode", 65536*17);
1520 lua_rawgeti(L, -1, 1);
1521 sfval = (halfword) luaL_checkinteger(L, -1);
1522 lua_rawgeti(L, -2, 2);
1523 scval = (halfword) luaL_checkinteger(L, -1);
1524 lua_rawgeti(L, -3, 3);
1525 lfval = (halfword) luaL_checkinteger(L, -1);
1526 lua_rawgeti(L, -4, 4);
1527 lcval = (halfword) luaL_checkinteger(L, -1);
1530 check_char_range(sfval, "setdelcode", 256);
1531 check_char_range(scval, "setdelcode", 65536*17);
1532 check_char_range(lfval, "setdelcode", 256);
1533 check_char_range(lcval, "setdelcode", 65536*17);
1534 set_del_code(ch, sfval, scval, lfval, lcval, (quarterword) (level));
1542 [global] code { c f ch }
1543 [global] code c f ch (a bit easier on memory, counterpart of getter)
1546 static int setdelcode(lua_State
* L
)
1549 halfword sfval
, scval
, lfval
, lcval
;
1550 int level
= cur_level
;
1552 if (lua_type(L
,1) == LUA_TSTRING
) {
1553 const char *s
= lua_tostring(L
,1);
1554 if (lua_key_eq(s
,global
)) {
1559 ch
= luaL_checkinteger(L
, f
);
1560 check_char_range(ch
, "setdelcode", 65536*17);
1562 if (lua_type(L
,f
) == LUA_TNUMBER
) {
1563 sfval
= luaL_checkinteger(L
, f
);
1564 scval
= luaL_checkinteger(L
, f
+1);
1565 lfval
= luaL_checkinteger(L
, f
+2);
1566 lcval
= luaL_checkinteger(L
, f
+3);
1567 } else if (lua_type(L
,f
) == LUA_TTABLE
) {
1568 lua_rawgeti(L
, f
, 1);
1569 sfval
= (halfword
) luaL_checkinteger(L
, -1);
1570 lua_rawgeti(L
, f
, 2);
1571 scval
= (halfword
) luaL_checkinteger(L
, -1);
1572 lua_rawgeti(L
, f
, 3);
1573 lfval
= (halfword
) luaL_checkinteger(L
, -1);
1574 lua_rawgeti(L
, f
, 4);
1575 lcval
= (halfword
) luaL_checkinteger(L
, -1);
1578 luaL_error(L
, "Bad arguments for tex.setdelcode()");
1581 check_char_range(sfval
, "setdelcode", 256);
1582 check_char_range(scval
, "setdelcode", 65536*17);
1583 check_char_range(lfval
, "setdelcode", 256);
1584 check_char_range(lcval
, "setdelcode", 65536*17);
1585 set_del_code(ch
, sfval
, scval
, lfval
, lcval
, (quarterword
) (level
));
1589 static int getdelcode(lua_State
* L
)
1591 delcodeval mval
= { 0, 0, 0, 0, 0 };
1592 int ch
= luaL_checkinteger(L
, -1);
1593 check_char_range(ch
, "getdelcode", 65536*17);
1594 mval
= get_del_code(ch
);
1596 lua_pushinteger(L
,mval
.small_family_value
);
1597 lua_rawseti(L
, -2, 1);
1598 lua_pushinteger(L
,mval
.small_character_value
);
1599 lua_rawseti(L
, -2, 2);
1600 lua_pushinteger(L
,mval
.large_family_value
);
1601 lua_rawseti(L
, -2, 3);
1602 lua_pushinteger(L
,mval
.large_character_value
);
1603 lua_rawseti(L
, -2, 4);
1607 static int getdelcodes(lua_State
* L
)
1609 delcodeval mval
= { 0, 0, 0, 0, 0 };
1610 int ch
= luaL_checkinteger(L
, -1);
1611 check_char_range(ch
, "getdelcodes", 65536*17);
1612 mval
= get_del_code(ch
);
1613 lua_pushinteger(L
,mval
.small_family_value
);
1614 lua_pushinteger(L
,mval
.small_character_value
);
1615 lua_pushinteger(L
,mval
.large_family_value
);
1616 lua_pushinteger(L
,mval
.large_character_value
);
1620 static int settex(lua_State
* L
)
1625 int cur_cs1
, cur_cmd1
;
1628 int i
= lua_gettop(L
);
1629 if (lua_type(L
,i
-1) == LUA_TSTRING
) {
1630 st
= lua_tolstring(L
, (i
- 1), &k
);
1631 if (lua_key_eq(st
,prevdepth
)) {
1632 if (lua_type(L
, i
) == LUA_TNUMBER
) {
1633 cur_list
.prev_depth_field
= lua_roundnumber(L
, i
);
1634 } else if (lua_type(L
, i
) == LUA_TSTRING
) {
1635 cur_list
.prev_depth_field
= dimen_to_number(L
, lua_tostring(L
, i
));
1637 luaL_error(L
, "unsupported value type");
1640 } else if (lua_key_eq(st
,prevgraf
)) {
1641 if (lua_type(L
, i
) == LUA_TNUMBER
) {
1642 cur_list
.pg_field
= lua_tointeger(L
, i
);
1644 luaL_error(L
, "unsupported value type");
1647 } else if (lua_key_eq(st
,spacefactor
)) {
1648 if (lua_type(L
, i
) == LUA_TNUMBER
) {
1649 cur_list
.space_factor_field
= lua_roundnumber(L
, i
);
1651 luaL_error(L
, "unsupported value type");
1655 texstr
= maketexlstring(st
, k
);
1656 if (is_primitive(texstr
)) {
1657 if (i
== 3 && (lua_type(L
,1) == LUA_TSTRING
)) {
1658 const char *s
= lua_tostring(L
, 1);
1659 if (lua_key_eq(s
,global
))
1662 cur_cs1
= string_lookup(st
, k
);
1664 cur_cmd1
= eq_type(cur_cs1
);
1665 if (is_int_assign(cur_cmd1
)) {
1666 if (lua_type(L
, i
) == LUA_TNUMBER
) {
1667 int luai
= lua_tointeger(L
, i
);
1668 assign_internal_value((isglobal
? 4 : 0), equiv(cur_cs1
), luai
);
1670 luaL_error(L
, "unsupported value type");
1672 } else if (is_dim_assign(cur_cmd1
)) {
1673 if (lua_type(L
, i
) == LUA_TNUMBER
) {
1674 j
= lua_roundnumber(L
, i
);
1675 } else if (lua_type(L
, i
) == LUA_TSTRING
) {
1676 j
= dimen_to_number(L
, lua_tostring(L
, i
));
1678 luaL_error(L
, "unsupported value type");
1680 assign_internal_value((isglobal
? 4 : 0), equiv(cur_cs1
), j
);
1681 } else if (is_glue_assign(cur_cmd1
)) {
1683 if (lua_type(L
, i
) == LUA_TNUMBER
) {
1684 halfword value
= copy_node(zero_glue
);
1685 width(value
) = lua_roundnumber(L
,i
);
1686 if (i
> 1) { stretch(value
) = lua_roundnumber(L
,i
+1); }
1687 if (i
> 3) { shrink(value
) = lua_roundnumber(L
,i
+2); }
1688 if (i
> 4) { stretch_order(value
) = lua_tointeger(L
,i
+3); }
1689 if (i
> 5) { shrink_order(value
) = lua_tointeger(L
,i
+4); }
1690 define(equiv(cur_cs1
), assign_glue_cmd
, value
);
1692 halfword
*j1
= check_isnode(L
, i
); /* the value */
1693 define(equiv(cur_cs1
), assign_glue_cmd
, *j1
);
1695 } else if (is_toks_assign(cur_cmd1
)) {
1696 if (lua_type(L
,i
) == LUA_TSTRING
) {
1697 j
= tokenlist_from_lua(L
); /* uses stack -1 */
1698 assign_internal_value((isglobal
? 4 : 0), equiv(cur_cs1
), j
);
1701 luaL_error(L
, "unsupported value type");
1704 } else if (lua_istable(L
, (i
- 2))) {
1706 people may want to add keys that are also primitives |tex.wd| for example)
1707 so creating an error is not right here
1709 lua_rawset(L
, (i
- 2));
1711 } else if (lua_istable(L
, (i
- 2))) {
1712 lua_rawset(L
, (i
- 2));
1714 } else if (lua_istable(L
, (i
- 2))) {
1715 lua_rawset(L
, (i
- 2));
1720 /* todo: some will to the pdf namespace .. ignore > 31 */
1722 static int do_convert(lua_State
* L
, int cur_code
)
1730 case insert_ht_code
: /* arg <register int> */
1731 case lua_code
: /* arg complex */
1732 case lua_escape_string_code
: /* arg token list */
1733 case left_margin_kern_code
: /* arg box */
1734 case right_margin_kern_code
: /* arg box */
1735 case string_code
: /* arg token */
1736 case cs_string_code
: /* arg token */
1737 case meaning_code
: /* arg token */
1740 /* the next fall through, and come from 'official' indices! */
1742 case font_name_code
: /* arg fontid */
1743 case font_identifier_code
: /* arg fontid */
1744 case uniform_deviate_code
: /* arg int */
1745 case number_code
: /* arg int */
1746 case roman_numeral_code
: /* arg int */
1748 if (lua_gettop(L
) < 1) {
1751 i
= lua_tointeger(L
, 1);
1753 /* these fall through! */
1756 /* no backend here */
1757 if (cur_code
< 32) {
1758 texstr
= the_convert_string(cur_code
, i
);
1760 str
= makecstring(texstr
);
1767 lua_pushstring(L
, str
);
1775 static int do_scan_internal(lua_State
* L
, int cur_cmd1
, int cur_code
, int values
)
1779 int save_cur_val
, save_cur_val_level
;
1780 save_cur_val
= cur_val
;
1781 save_cur_val_level
= cur_val_level
;
1782 scan_something_simple(cur_cmd1
, cur_code
);
1783 switch (cur_val_level
) {
1785 case dimen_val_level
:
1786 case attr_val_level
:
1787 lua_pushinteger(L
, cur_val
);
1789 case glue_val_level
:
1792 lua_pushinteger(L
,width(cur_val
));
1793 } else if (values
== 1) {
1794 lua_pushinteger(L
,width(cur_val
));
1795 lua_pushinteger(L
,stretch(cur_val
));
1796 lua_pushinteger(L
,shrink(cur_val
));
1797 lua_pushinteger(L
,stretch_order(cur_val
));
1798 lua_pushinteger(L
,shrink_order(cur_val
));
1801 lua_nodelib_push_fast(L
, cur_val
);
1805 texstr
= the_scanned_result();
1806 str
= makecstring(texstr
);
1808 lua_pushstring(L
, str
);
1816 cur_val
= save_cur_val
;
1817 cur_val_level
= save_cur_val_level
;
1821 static int do_lastitem(lua_State
* L
, int cur_code
)
1825 /* the next two do not actually exist */
1830 /* the expressions do something complicated with arguments, yuck */
1837 /* these read a glue or muglue, todo */
1838 case mu_to_glue_code
:
1839 case glue_to_mu_code
:
1840 case glue_stretch_order_code
:
1841 case glue_shrink_order_code
:
1842 case glue_stretch_code
:
1843 case glue_shrink_code
:
1846 /* these read a fontid and a char, todo */
1847 case font_char_wd_code
:
1848 case font_char_ht_code
:
1849 case font_char_dp_code
:
1850 case font_char_ic_code
:
1853 /* these read an integer, todo */
1854 case par_shape_length_code
:
1855 case par_shape_indent_code
:
1856 case par_shape_dimen_code
:
1859 case lastpenalty_code
:
1862 case last_node_type_code
:
1863 case input_line_no_code
:
1865 case last_saved_box_resource_index_code
:
1866 case last_saved_image_resource_index_code
:
1867 case last_saved_image_resource_pages_code
:
1868 case last_x_pos_code
:
1869 case last_y_pos_code
:
1870 case random_seed_code
:
1871 case luatex_version_code
:
1872 case eTeX_minor_version_code
:
1873 case eTeX_version_code
:
1874 case current_group_level_code
:
1875 case current_group_type_code
:
1876 case current_if_level_code
:
1877 case current_if_type_code
:
1878 case current_if_branch_code
:
1879 retval
= do_scan_internal(L
, last_item_cmd
, cur_code
, -1);
1888 static int tex_setmathparm(lua_State
* L
)
1894 int n
= lua_gettop(L
);
1895 if ((n
== 3) || (n
== 4)) {
1896 if (n
== 4 && (lua_type(L
,1) == LUA_TSTRING
)) {
1897 const char *s
= lua_tostring(L
, 1);
1898 if (lua_key_eq(s
,global
))
1901 i
= luaL_checkoption(L
, (n
- 2), NULL
, math_param_names
);
1902 j
= luaL_checkoption(L
, (n
- 1), NULL
, math_style_names
);
1903 if (i
<0 && i
>=math_param_last
) {
1904 /* invalid spec, just ignore it */
1905 } else if (i
>=math_param_first_mu_glue
) {
1906 p
= lua_touserdata(L
, n
);
1907 k
= *((halfword
*)p
);
1908 def_math_param(i
, j
, (scaled
) k
, l
);
1909 } else if (lua_type(L
, n
) == LUA_TNUMBER
) {
1910 k
= lua_roundnumber(L
, n
);
1911 def_math_param(i
, j
, (scaled
) k
, l
);
1913 luaL_error(L
, "argument must be a number");
1919 static int tex_getmathparm(lua_State
* L
)
1921 if ((lua_gettop(L
) == 2)) {
1922 int i
= luaL_checkoption(L
, 1, NULL
, math_param_names
);
1923 int j
= luaL_checkoption(L
, 2, NULL
, math_style_names
);
1924 scaled k
= get_math_param(i
, j
);
1925 if (i
<0 && i
>=math_param_last
) {
1927 } else if (i
>=math_param_first_mu_glue
) {
1928 if (k
<= thick_mu_skip_code
) {
1931 lua_nodelib_push_fast(L
, k
);
1933 lua_pushinteger(L
, k
);
1939 static int getfontname(lua_State
* L
)
1941 return do_convert(L
, font_name_code
);
1944 static int getfontidentifier(lua_State
* L
)
1946 return do_convert(L
, font_identifier_code
);
1949 static int getuniformdeviate(lua_State
* L
)
1951 return do_convert(L
, uniform_deviate_code
);
1954 static int getnumber(lua_State
* L
)
1956 return do_convert(L
, number_code
);
1959 static int getromannumeral(lua_State
* L
)
1961 return do_convert(L
, roman_numeral_code
);
1964 static int get_parshape(lua_State
* L
)
1966 halfword par_shape_ptr
= par_shape_par_ptr
;
1967 if (par_shape_ptr
!= 0) {
1969 int n
= vinfo(par_shape_ptr
+ 1);
1970 lua_createtable(L
, n
, 0);
1972 lua_createtable(L
, 2, 0);
1973 lua_pushinteger(L
, vlink((par_shape_ptr
) + (2 * (m
- 1)) + 2));
1974 lua_rawseti(L
, -2, 1);
1975 lua_pushinteger(L
, vlink((par_shape_ptr
) + (2 * (m
- 1)) + 3));
1976 lua_rawseti(L
, -2, 2);
1977 lua_rawseti(L
, -2, m
);
1986 static int gettex(lua_State
* L
)
1989 int retval
= 1; /* default is to return nil */
1990 int t
= lua_gettop(L
);
1992 if (t
> 1 && lua_type(L
,t
) == LUA_TBOOLEAN
) {
1994 0 == flush width only
1995 1 == flush all glue parameters
1997 b
= lua_toboolean(L
,t
);
2000 if (lua_type(L
,t
) == LUA_TSTRING
) {
2009 const char *st
= lua_tolstring(L
, t
, &k
);
2010 if (lua_key_eq(st
,prevdepth
)) {
2011 lua_pushinteger(L
, cur_list
.prev_depth_field
);
2013 } else if (lua_key_eq(st
,prevgraf
)) {
2014 lua_pushinteger(L
, cur_list
.pg_field
);
2016 } else if (lua_key_eq(st
,spacefactor
)) {
2017 lua_pushinteger(L
, cur_list
.space_factor_field
);
2020 texstr
= maketexlstring(st
, k
);
2021 cur_cs1
= prim_lookup(texstr
); /* not found == relax == 0 */
2025 int cur_cmd1
= get_prim_eq_type(cur_cs1
);
2026 int cur_code
= get_prim_equiv(cur_cs1
);
2029 retval
= do_lastitem(L
, cur_code
);
2032 retval
= do_convert(L
, cur_code
);
2034 case assign_toks_cmd
:
2035 case assign_int_cmd
:
2036 case assign_attr_cmd
:
2037 case assign_dir_cmd
:
2038 case assign_dimen_cmd
:
2040 case set_prev_graf_cmd
:
2041 case set_page_int_cmd
:
2042 case set_page_dimen_cmd
:
2043 case char_given_cmd
:
2044 case math_given_cmd
:
2045 retval
= do_scan_internal(L
, cur_cmd1
, cur_code
, -1);
2047 case assign_glue_cmd
:
2048 case assign_mu_glue_cmd
:
2049 retval
= do_scan_internal(L
, cur_cmd1
, cur_code
, b
);
2051 case set_tex_shape_cmd
:
2052 retval
= get_parshape(L
);
2058 } else if ((t
== 2) && (lua_type(L
,2) == LUA_TSTRING
)) {
2064 static int getlist(lua_State
* L
)
2067 if (lua_type(L
,2) == LUA_TSTRING
) {
2068 str
= lua_tostring(L
, 2);
2069 if (lua_key_eq(str
,page_ins_head
)) {
2070 if (vlink(page_ins_head
) == page_ins_head
)
2071 lua_pushinteger(L
, null
);
2073 lua_pushinteger(L
, vlink(page_ins_head
));
2074 lua_nodelib_push(L
);
2075 } else if (lua_key_eq(str
,contrib_head
)) {
2076 alink(vlink(contrib_head
)) = null
;
2077 lua_pushinteger(L
, vlink(contrib_head
));
2078 lua_nodelib_push(L
);
2079 } else if (lua_key_eq(str
,page_discards_head
)) {
2080 alink(vlink(page_disc
)) = null
;
2081 lua_pushinteger(L
, page_disc
);
2082 lua_nodelib_push(L
);
2083 } else if (lua_key_eq(str
,split_discards_head
)) {
2084 alink(vlink(split_disc
)) = null
;
2085 lua_pushinteger(L
, split_disc
);
2086 lua_nodelib_push(L
);
2087 } else if (lua_key_eq(str
,page_head
)) {
2088 alink(vlink(page_head
)) = null
;/*hh-ls */
2089 lua_pushinteger(L
, vlink(page_head
));
2090 lua_nodelib_push(L
);
2091 } else if (lua_key_eq(str
,temp_head
)) {
2092 alink(vlink(temp_head
)) = null
;/*hh-ls */
2093 lua_pushinteger(L
, vlink(temp_head
));
2094 lua_nodelib_push(L
);
2095 } else if (lua_key_eq(str
,hold_head
)) {
2096 alink(vlink(hold_head
)) = null
;/*hh-ls */
2097 lua_pushinteger(L
, vlink(hold_head
));
2098 lua_nodelib_push(L
);
2099 } else if (lua_key_eq(str
,adjust_head
)) {
2100 alink(vlink(adjust_head
)) = null
;/*hh-ls */
2101 lua_pushinteger(L
, vlink(adjust_head
));
2102 lua_nodelib_push(L
);
2103 } else if (lua_key_eq(str
,best_page_break
)) {
2104 lua_pushinteger(L
, best_page_break
);
2105 lua_nodelib_push(L
);
2106 } else if (lua_key_eq(str
,least_page_cost
)) {
2107 lua_pushinteger(L
, least_page_cost
);
2108 } else if (lua_key_eq(str
,best_size
)) {
2109 lua_pushinteger(L
, best_size
);
2110 } else if (lua_key_eq(str
,pre_adjust_head
)) {
2111 alink(vlink(pre_adjust_head
)) = null
;/*hh-ls */
2112 lua_pushinteger(L
, vlink(pre_adjust_head
));
2113 lua_nodelib_push(L
);
2114 } else if (lua_key_eq(str
,align_head
)) {
2115 alink(vlink(align_head
)) = null
;/*hh-ls */
2116 lua_pushinteger(L
, vlink(align_head
));
2117 lua_nodelib_push(L
);
2127 static int setlist(lua_State
* L
)
2129 if (lua_type(L
,2) == LUA_TSTRING
) {
2130 const char *str
= lua_tostring(L
, 2);
2131 if (lua_key_eq(str
,best_size
)) {
2132 best_size
= (int) lua_tointeger(L
, 3);
2133 } else if (lua_key_eq(str
,least_page_cost
)) {
2134 least_page_cost
= (int) lua_tointeger(L
, 3);
2138 if (!lua_isnil(L
, 3)) {
2139 n_ptr
= check_isnode(L
, 3);
2142 if (lua_key_eq(str
,page_ins_head
)) {
2144 vlink(page_ins_head
) = page_ins_head
;
2147 vlink(page_ins_head
) = n
;
2148 m
= tail_of_list(n
);
2149 vlink(m
) = page_ins_head
;
2151 } else if (lua_key_eq(str
,contrib_head
)) {
2152 vlink(contrib_head
) = n
;
2154 contrib_tail
= contrib_head
;
2156 } else if (lua_key_eq(str
,best_page_break
)) {
2157 best_page_break
= n
;
2158 } else if (lua_key_eq(str
,page_head
)) {
2159 vlink(page_head
) = n
;
2160 page_tail
= (n
== 0 ? page_head
: tail_of_list(n
));
2161 } else if (lua_key_eq(str
,temp_head
)) {
2162 vlink(temp_head
) = n
;
2163 } else if (lua_key_eq(str
,page_discards_head
)) {
2165 } else if (lua_key_eq(str
,split_discards_head
)) {
2167 } else if (lua_key_eq(str
,hold_head
)) {
2168 vlink(hold_head
) = n
;
2169 } else if (lua_key_eq(str
,adjust_head
)) {
2170 vlink(adjust_head
) = n
;
2171 adjust_tail
= (n
== 0 ? adjust_head
: tail_of_list(n
));
2172 } else if (lua_key_eq(str
,pre_adjust_head
)) {
2173 vlink(pre_adjust_head
) = n
;
2174 pre_adjust_tail
= (n
== 0 ? pre_adjust_head
: tail_of_list(n
));
2175 } else if (lua_key_eq(str
,align_head
)) {
2176 vlink(align_head
) = n
;
2183 #define NEST_METATABLE "luatex.nest"
2185 static int lua_nest_getfield(lua_State
* L
)
2187 list_state_record
*r
, **rv
= lua_touserdata(L
, -2);
2188 const char *field
= lua_tostring(L
, -1);
2190 if (lua_key_eq(field
,mode
)) {
2191 lua_pushinteger(L
, r
->mode_field
);
2192 } else if (lua_key_eq(field
,head
)) {
2193 lua_nodelib_push_fast(L
, r
->head_field
);
2194 } else if (lua_key_eq(field
,tail
)) {
2195 lua_nodelib_push_fast(L
, r
->tail_field
);
2196 } else if (lua_key_eq(field
,delimptr
)) {
2197 lua_pushinteger(L
, r
->eTeX_aux_field
);
2198 lua_nodelib_push(L
);
2199 } else if (lua_key_eq(field
,prevgraf
)) {
2200 lua_pushinteger(L
, r
->pg_field
);
2201 } else if (lua_key_eq(field
,modeline
)) {
2202 lua_pushinteger(L
, r
->ml_field
);
2203 } else if (lua_key_eq(field
,prevdepth
)) {
2204 lua_pushinteger(L
, r
->prev_depth_field
);
2205 } else if (lua_key_eq(field
,spacefactor
)) {
2206 lua_pushinteger(L
, r
->space_factor_field
);
2207 } else if (lua_key_eq(field
,noad
)) {
2208 lua_pushinteger(L
, r
->incompleat_noad_field
);
2209 lua_nodelib_push(L
);
2210 } else if (lua_key_eq(field
,dirs
)) {
2211 lua_pushinteger(L
, r
->dirs_field
);
2212 lua_nodelib_push(L
);
2213 } else if (lua_key_eq(field
,mathdir
)) {
2214 lua_pushboolean(L
, r
->math_field
);
2215 } else if (lua_key_eq(field
,mathstyle
)) {
2216 lua_pushinteger(L
, r
->math_style_field
);
2223 static int lua_nest_setfield(lua_State
* L
)
2227 list_state_record
*r
, **rv
= lua_touserdata(L
, -3);
2228 const char *field
= lua_tostring(L
, -2);
2230 if (lua_key_eq(field
,mode
)) {
2231 i
= lua_tointeger(L
, -1);
2233 } else if (lua_key_eq(field
,head
)) {
2234 n
= check_isnode(L
, -1);
2236 } else if (lua_key_eq(field
,tail
)) {
2237 n
= check_isnode(L
, -1);
2239 } else if (lua_key_eq(field
,delimptr
)) {
2240 n
= check_isnode(L
, -1);
2241 r
->eTeX_aux_field
= *n
;
2242 } else if (lua_key_eq(field
,prevgraf
)) {
2243 i
= lua_tointeger(L
, -1);
2245 } else if (lua_key_eq(field
,modeline
)) {
2246 i
= lua_tointeger(L
, -1);
2248 } else if (lua_key_eq(field
,prevdepth
)) {
2249 i
= lua_roundnumber(L
, -1);
2250 r
->prev_depth_field
= i
;
2251 } else if (lua_key_eq(field
,spacefactor
)) {
2252 i
= lua_roundnumber(L
, -1);
2253 r
->space_factor_field
= i
;
2254 } else if (lua_key_eq(field
,noad
)) {
2255 n
= check_isnode(L
, -1);
2256 r
->incompleat_noad_field
= *n
;
2257 } else if (lua_key_eq(field
,dirs
)) {
2258 n
= check_isnode(L
, -1);
2260 } else if (lua_key_eq(field
,mathdir
)) {
2261 r
->math_field
= lua_toboolean(L
, -1);
2262 } else if (lua_key_eq(field
,mathstyle
)) {
2263 i
= lua_tointeger(L
, -1);
2264 r
->math_style_field
= i
;
2269 static const struct luaL_Reg nest_m
[] = {
2270 {"__index", lua_nest_getfield
},
2271 {"__newindex", lua_nest_setfield
},
2272 {NULL
, NULL
} /* sentinel */
2275 static void init_nest_lib(lua_State
* L
)
2277 luaL_newmetatable(L
, NEST_METATABLE
);
2278 luaL_register(L
, NULL
, nest_m
);
2282 static int getnest(lua_State
* L
)
2284 list_state_record
**nestitem
;
2285 int t
= lua_type(L
, 2);
2286 if (t
== LUA_TNUMBER
) {
2287 int ptr
= lua_tointeger(L
, 2);
2288 if (ptr
>= 0 && ptr
<= nest_ptr
) {
2289 nestitem
= lua_newuserdata(L
, sizeof(list_state_record
*));
2290 *nestitem
= &nest
[ptr
];
2291 luaL_getmetatable(L
, NEST_METATABLE
);
2292 lua_setmetatable(L
, -2);
2296 } else if (t
== LUA_TSTRING
) {
2297 const char *s
= lua_tostring(L
, 2);
2298 if (lua_key_eq(s
,ptr
)) {
2299 lua_pushinteger(L
, nest_ptr
);
2309 static int setnest(lua_State
* L
)
2311 luaL_error(L
, "You can't modify the semantic nest array directly");
2315 static int do_integer_error(double m
)
2317 const char *help
[] = {
2318 "I can only go up to 2147483647='17777777777=" "7FFFFFFF,",
2319 "so I'm using that number instead of yours.",
2322 tex_error("Number too big", help
);
2323 return (m
> 0.0 ? infinity
: -infinity
);
2326 static int tex_roundnumber(lua_State
* L
)
2328 double m
= (double) lua_tonumber(L
, 1) + 0.5; /* integer or float */
2329 if (abs(m
) > (double) infinity
)
2330 lua_pushinteger(L
, do_integer_error(m
));
2332 lua_pushinteger(L
, floor(m
));
2336 static int tex_scaletable(lua_State
* L
)
2338 double delta
= luaL_checknumber(L
, 2);
2339 if (lua_istable(L
, 1)) {
2340 lua_newtable(L
); /* the new table is at index 3 */
2342 while (lua_next(L
, 1) != 0) { /* numeric value */
2343 lua_pushvalue(L
, -2);
2345 if (lua_type(L
,-2) == LUA_TNUMBER
) {
2346 double m
= (double) lua_tonumber(L
, -1) * delta
+ 0.5; /* integer or float */
2348 if (abs(m
) > (double) infinity
)
2349 lua_pushinteger(L
, do_integer_error(m
));
2351 lua_pushinteger(L
, floor(m
));
2355 } else if (lua_type(L
,1) == LUA_TNUMBER
) {
2356 double m
= (double) lua_tonumber(L
, 1) * delta
+ 0.5; /* integer or float */
2357 if (abs(m
) > (double) infinity
)
2358 lua_pushinteger(L
, do_integer_error(m
));
2360 lua_pushinteger(L
, floor(m
));
2367 #define hash_text(A) hash[(A)].rh
2369 static int tex_definefont(lua_State
* L
)
2377 if (!no_new_control_sequence
) {
2378 const char *help
[] = { "You can't create a new font inside a \\csname\\endcsname pair", NULL
};
2379 tex_error("Definition active", help
);
2381 if ((lua_gettop(L
) == 3) && lua_isboolean(L
, 1)) {
2382 a
= lua_toboolean(L
, 1);
2385 csname
= luaL_checklstring(L
, i
, &l
);
2386 f
= luaL_checkinteger(L
, (i
+ 1));
2387 t
= maketexlstring(csname
, l
);
2388 no_new_control_sequence
= 0;
2389 u
= string_lookup(csname
, l
);
2390 no_new_control_sequence
= 1;
2392 geq_define(u
, set_font_cmd
, f
);
2394 eq_define(u
, set_font_cmd
, f
);
2395 eqtb
[font_id_base
+ f
] = eqtb
[u
];
2396 hash_text(font_id_base
+ f
) = t
;
2401 static int tex_hashpairs(lua_State * L)
2407 while (cs < hash_size) {
2410 char *ss = makecstring(s);
2411 lua_pushstring(L, ss);
2415 make_token_table(L, cmd, chr, cs);
2423 static int tex_primitives(lua_State * L)
2429 while (cs < prim_size) {
2430 s = get_prim_text(cs);
2432 char *ss = makecstring(s);
2433 lua_pushstring(L, ss);
2435 cmd = get_prim_eq_type(cs);
2436 chr = get_prim_equiv(cs);
2437 make_token_table(L, cmd, chr, 0);
2445 static int tex_extraprimitives(lua_State * L)
2452 mask = etex_command + luatex_command;
2454 for (i = 1; i <= n; i++) {
2455 if (lua_type(L,i) == LUA_TSTRING) {
2456 const char *s = lua_tostring(L, i);
2457 if (lua_key_eq(s,etex)) {
2458 mask |= etex_command;
2459 } else if (lua_key_eq(s,tex)) {
2460 mask |= tex_command;
2461 } else if (lua_key_eq(s,core)) {
2462 mask |= core_command;
2463 } else if (lua_key_eq(s,luatex)) {
2464 mask |= luatex_command;
2471 while (cs < prim_size) {
2473 s = get_prim_text(cs);
2475 if (get_prim_origin(cs) & mask) {
2476 char *ss = makecstring(s);
2477 lua_pushstring(L, ss);
2479 lua_rawseti(L, -2, i++);
2489 static int tex_hashpairs(lua_State
* L
)
2495 while (cs
< hash_size
) {
2498 char *ss
= makecstring(s
);
2499 lua_pushstring(L
, ss
);
2501 lua_rawseti(L
, -2, ++nt
);
2508 static int tex_primitives(lua_State
* L
)
2514 while (cs
< prim_size
) {
2515 s
= get_prim_text(cs
);
2517 char *ss
= makecstring(s
);
2518 lua_pushstring(L
, ss
);
2520 lua_rawseti(L
, -2, ++nt
);
2527 static int tex_extraprimitives(lua_State
* L
)
2535 mask
= etex_command
+ luatex_command
;
2537 for (i
= 1; i
<= n
; i
++) {
2538 if (lua_type(L
,i
) == LUA_TSTRING
) {
2539 const char *s
= lua_tostring(L
, i
);
2540 if (lua_key_eq(s
,etex
)) {
2541 mask
|= etex_command
;
2542 } else if (lua_key_eq(s
,tex
)) {
2543 mask
|= tex_command
;
2544 } else if (lua_key_eq(s
,core
)) {
2545 mask
|= core_command
;
2546 } else if (lua_key_eq(s
,luatex
)) {
2547 mask
|= luatex_command
;
2553 while (cs
< prim_size
) {
2555 s
= get_prim_text(cs
);
2557 if (get_prim_origin(cs
) & mask
) {
2558 char *ss
= makecstring(s
);
2559 lua_pushstring(L
, ss
);
2561 lua_rawseti(L
, -2, ++nt
);
2569 static int tex_enableprimitives(lua_State
* L
)
2571 int n
= lua_gettop(L
);
2573 luaL_error(L
, "wrong number of arguments");
2577 const char *pre
= luaL_checklstring(L
, 1, &l
);
2578 if (lua_istable(L
, 2)) {
2579 int nncs
= no_new_control_sequence
;
2580 no_new_control_sequence
= true;
2583 lua_rawgeti(L
, 2, i
);
2584 if (lua_type(L
,3) == LUA_TSTRING
) {
2585 const char *prim
= lua_tostring(L
, 3);
2586 str_number s
= maketexstring(prim
);
2587 halfword prim_val
= prim_lookup(s
);
2588 if (prim_val
!= undefined_primitive
) {
2592 halfword cur_cmd1
= get_prim_eq_type(prim_val
);
2593 halfword cur_chr1
= get_prim_equiv(prim_val
);
2594 if (strncmp(pre
, prim
, l
) != 0) { /* not a prefix */
2595 newl
= strlen(prim
) + l
;
2596 newprim
= (char *) xmalloc((unsigned) (newl
+ 1));
2597 strcpy(newprim
, pre
);
2598 strcat(newprim
+ l
, prim
);
2600 newl
= strlen(prim
);
2601 newprim
= (char *) xmalloc((unsigned) (newl
+ 1));
2602 strcpy(newprim
, prim
);
2604 val
= string_lookup(newprim
, newl
);
2605 if (val
== undefined_control_sequence
||
2606 eq_type(val
) == undefined_cs_cmd
) {
2607 primitive_def(newprim
, newl
, (quarterword
) cur_cmd1
, cur_chr1
);
2619 lua_pop(L
, 1); /* the table */
2620 no_new_control_sequence
= nncs
;
2622 luaL_error(L
, "Expected an array of names as second argument");
2628 #define get_int_par(A,B) do { \
2629 lua_key_rawgeti(A); \
2630 if (lua_type(L, -1) == LUA_TNUMBER) { \
2631 A = (int) lua_tointeger(L, -1); \
2638 #define get_intx_par(A,B,C,D) do { \
2639 lua_key_rawgeti(A); \
2640 if (lua_type(L, -1) == LUA_TNUMBER) { \
2641 A = (int) lua_tointeger(L, -1); \
2643 } else if (lua_type(L, -1) == LUA_TTABLE){ \
2645 C = nodelib_topenalties(L, lua_gettop(L)); \
2653 #define get_dimen_par(A,B) do { \
2654 lua_key_rawgeti(A); \
2655 if (lua_type(L, -1) == LUA_TNUMBER) { \
2656 A = (int) lua_tointeger(L, -1); \
2663 #define get_glue_par(A,B) do { \
2664 lua_key_rawgeti(A); \
2665 if (lua_type(L, -1) != LUA_TNIL) { \
2666 A = *check_isnode(L, -1); \
2673 static halfword
nodelib_toparshape(lua_State
* L
, int i
)
2677 int width
, indent
, j
;
2680 while (lua_next(L
, i
) != 0) {
2686 p
= new_node(shape_node
, 2 * (n
+ 1) + 1);
2691 while (lua_next(L
, i
) != 0) {
2692 /* don't give an error for non-tables, we may add special syntaxes at some point */
2694 if (lua_type(L
, i
) == LUA_TTABLE
) {
2695 lua_rawgeti(L
, -1, 1); /* indent */
2696 if (lua_type(L
, -1) == LUA_TNUMBER
) {
2697 indent
= lua_roundnumber(L
, -1);
2699 lua_rawgeti(L
, -1, 2); /* width */
2700 if (lua_type(L
, -1) == LUA_TNUMBER
) {
2701 width
= lua_roundnumber(L
, -1);
2703 varmem
[p
+ 2 * j
].cint
= indent
;
2704 varmem
[p
+ 2 * j
+ 1].cint
= width
;
2715 static halfword
nodelib_topenalties(lua_State
* L
, int i
)
2722 while (lua_next(L
, i
) != 0) {
2728 p
= new_node(shape_node
, 2 * ((n
/ 2) + 1) + 1 + 1);
2729 vinfo(p
+ 1) = (n
/ 2) + 1;
2730 varmem
[p
+ 2].cint
= n
;
2733 while (lua_next(L
, i
) != 0) {
2735 if (lua_type(L
, -1) == LUA_TNUMBER
) {
2736 int pen
= lua_tointeger(L
, -1);
2737 varmem
[p
+j
].cint
= pen
;
2742 varmem
[p
+j
+1].cint
= 0;
2746 static int tex_run_linebreak(lua_State
* L
)
2751 halfword final_par_glue
;
2752 int paragraph_dir
= 0;
2753 /* locally initialized parameters for line breaking */
2754 int pretolerance
, tracingparagraphs
, tolerance
, looseness
,
2755 adjustspacing
, adjdemerits
, protrudechars
,
2756 linepenalty
, lastlinefit
, doublehyphendemerits
, finalhyphendemerits
,
2757 hangafter
, interlinepenalty
, widowpenalty
, clubpenalty
, brokenpenalty
;
2758 halfword emergencystretch
, hangindent
, hsize
, leftskip
, rightskip
,parshape
;
2759 int fewest_demerits
= 0, actual_looseness
= 0;
2760 halfword clubpenalties
, interlinepenalties
, widowpenalties
;
2761 int save_vlink_tmp_head
;
2762 /* push a new nest level */
2764 save_vlink_tmp_head
= vlink(temp_head
);
2766 j
= check_isnode(L
, 1); /* the value */
2767 vlink(temp_head
) = *j
;
2769 if ((!is_char_node(vlink(*j
))) && ((type(vlink(*j
)) == local_par_node
))) {
2770 paragraph_dir
= local_par_dir(vlink(*j
));
2773 while (vlink(p
) != null
)
2777 /* initialize local parameters */
2779 if (lua_gettop(L
) != 2 || lua_type(L
, 2) != LUA_TTABLE
) {
2780 lua_checkstack(L
, 3);
2783 lua_key_rawgeti(pardir
);
2784 if (lua_type(L
, -1) == LUA_TSTRING
) {
2785 paragraph_dir
= nodelib_getdir(L
, -1, 1);
2789 lua_key_rawgeti(parshape
);
2790 if (lua_type(L
, -1) == LUA_TTABLE
) {
2791 parshape
= nodelib_toparshape(L
, lua_gettop(L
));
2793 parshape
= equiv(par_shape_loc
);
2797 get_int_par (pretolerance
, pretolerance_par
);
2798 get_int_par (tracingparagraphs
, tracing_paragraphs_par
);
2799 get_int_par (tolerance
, tolerance_par
);
2800 get_int_par (looseness
, looseness_par
);
2801 get_int_par (adjustspacing
, adjust_spacing_par
);
2802 get_int_par (adjdemerits
, adj_demerits_par
);
2803 get_int_par (protrudechars
, protrude_chars_par
);
2804 get_int_par (linepenalty
, line_penalty_par
);
2805 get_int_par (lastlinefit
, last_line_fit_par
);
2806 get_int_par (doublehyphendemerits
, double_hyphen_demerits_par
);
2807 get_int_par (finalhyphendemerits
, final_hyphen_demerits_par
);
2808 get_int_par (hangafter
, hang_after_par
);
2809 get_intx_par (interlinepenalty
,inter_line_penalty_par
, interlinepenalties
, equiv(inter_line_penalties_loc
));
2810 get_intx_par (clubpenalty
, club_penalty_par
, clubpenalties
, equiv(club_penalties_loc
));
2811 get_intx_par (widowpenalty
, widow_penalty_par
, widowpenalties
, equiv(widow_penalties_loc
));
2812 get_int_par (brokenpenalty
, broken_penalty_par
);
2813 get_dimen_par(emergencystretch
, emergency_stretch_par
);
2814 get_dimen_par(hangindent
, hang_indent_par
);
2815 get_dimen_par(hsize
, hsize_par
);
2816 get_glue_par (leftskip
, left_skip_par
);
2817 get_glue_par (rightskip
, right_skip_par
);
2818 ext_do_line_break(paragraph_dir
,
2830 doublehyphendemerits
,
2831 finalhyphendemerits
,
2846 /* return the generated list, and its prevdepth */
2847 get_linebreak_info (&fewest_demerits
, &actual_looseness
) ;
2848 lua_nodelib_push_fast(L
, vlink(cur_list
.head_field
));
2850 lua_push_key(demerits
);
2851 lua_pushinteger(L
, fewest_demerits
);
2852 lua_settable(L
, -3);
2853 lua_push_key(looseness
);
2854 lua_pushinteger(L
, actual_looseness
);
2855 lua_settable(L
, -3);
2856 lua_push_key(prevdepth
);
2857 lua_pushinteger(L
, cur_list
.prev_depth_field
);
2858 lua_settable(L
, -3);
2859 lua_push_key(prevgraf
);
2860 lua_pushinteger(L
, cur_list
.pg_field
);
2861 lua_settable(L
, -3);
2863 /* restore nest stack */
2864 vlink(temp_head
) = save_vlink_tmp_head
;
2866 if (parshape
!= equiv(par_shape_loc
))
2867 flush_node(parshape
);
2871 static int tex_reset_paragraph(lua_State
* L
)
2878 static int tex_shipout(lua_State
* L
)
2880 int boxnum
= get_box_id(L
, 1, true);
2881 ship_out(static_pdf
, box(boxnum
), SHIPPING_PAGE
);
2886 static int tex_badness(lua_State
* L
)
2888 scaled t
= lua_tointeger(L
,1);
2889 scaled s
= lua_tointeger(L
,2);
2890 lua_pushinteger(L
, badness(t
,s
));
2894 static int tex_run_boot(lua_State
* L
)
2896 int n
= lua_gettop(L
);
2897 const char *format
= NULL
;
2900 format
= luaL_checkstring(L
, 1);
2904 if (main_initialize()) { /* > 0 = failure */
2905 lua_pushboolean(L
, 0); /* false */
2909 if (!zopen_w_input(&fmt_file
, format
, DUMP_FORMAT
, FOPEN_RBIN_MODE
)) {
2910 lua_pushboolean(L
, 0); /* false */
2913 if (!load_fmt_file(format
)) {
2915 lua_pushboolean(L
, 0); /* false */
2920 pdf_init_map_file("pdftex.map");
2922 if (end_line_char_inactive
)
2925 buffer
[ilimit
] = (packed_ASCII_code
) end_line_char_par
;
2926 fix_date_and_time();
2927 random_seed
= (microseconds
* 1000) + (epochseconds
% 1000000);
2928 init_randoms(random_seed
);
2930 fixup_selector(log_opened_global
);
2931 check_texconfig_init();
2932 text_dir_ptr
= new_dir(0);
2933 history
= spotless
; /* ready to go! */
2934 /* Initialize synctex primitive */
2935 synctexinitcommand();
2936 /* tex is ready to go, now */
2937 unhide_lua_table(Luas
, "tex", tex_table_id
);
2938 unhide_lua_table(Luas
, "pdf", pdf_table_id
);
2939 unhide_lua_table(Luas
, "token", token_table_id
);
2940 unhide_lua_table(Luas
, "node", node_table_id
);
2942 lua_pushboolean(L
, 1); /* true */
2946 /* tex random generators */
2948 static int tex_init_rand(lua_State
* L
)
2951 if (lua_type(L
, 1) != LUA_TNUMBER
) {
2952 luaL_error(L
, "argument must be a number");
2955 sp
= lua_roundnumber(L
, 1);
2960 static int tex_unif_rand(lua_State
* L
)
2963 if (lua_type(L
, 1) != LUA_TNUMBER
) {
2964 luaL_error(L
, "argument must be a number");
2967 sp
= lua_roundnumber(L
, 1);
2968 lua_pushinteger(L
, unif_rand(sp
));
2972 static int tex_norm_rand(lua_State
* L
)
2974 lua_pushinteger(L
, norm_rand());
2978 /* Same as lua but with tex rng */
2980 static int lua_math_random (lua_State
*L
)
2982 lua_Number rand_max
= 0x7fffffff ;
2983 lua_Number r
= unif_rand(rand_max
) ;
2984 r
= (r
>=0 ? 0+r
: 0-r
) ;
2986 switch (lua_gettop(L
)) { /* check number of arguments */
2987 case 0: { /* no arguments */
2988 lua_pushnumber(L
, r
); /* float: [0, 1] */
2991 case 1: { /* only upper limit */
2992 lua_Number u
= luaL_checknumber(L
, 1);
2993 luaL_argcheck(L
, (lua_Number
)1.0 <= u
, 1, "interval is empty");
2994 lua_pushnumber(L
, floor(r
*u
) + (lua_Number
)(1.0)); /* float: [1, u] */
2997 case 2: { /* lower and upper limits */
2998 lua_Number l
= luaL_checknumber(L
, 1);
2999 lua_Number u
= luaL_checknumber(L
, 2);
3000 luaL_argcheck(L
, l
<= u
, 2, "interval is empty");
3001 lua_pushnumber(L
, floor(r
*(u
-l
+1)) + l
); /* float: [l, u] */
3005 return luaL_error(L
, "wrong number of arguments");
3010 static int tex_run_main(lua_State
* L
)
3017 static int tex_run_end(lua_State
* L
)
3020 final_cleanup(); /* prepare for death */
3021 close_files_and_terminate();
3026 static int tex_show_context(lua_State
* L
)
3033 static int tex_save_box_resource(lua_State
* L
)
3037 int attributes
= null
;
3038 int resources
= null
;
3040 boolean immediate
= false;
3041 /* box attributes resources */
3042 halfword boxnumber
= lua_tointeger(L
,1);
3043 if (lua_type(L
,2) == LUA_TSTRING
) {
3044 lua_pushvalue(L
, 2);
3045 attributes
= luaL_ref(L
, LUA_REGISTRYINDEX
);
3047 if (lua_type(L
,3) == LUA_TSTRING
) {
3048 lua_pushvalue(L
, 3);
3049 resources
= luaL_ref(L
, LUA_REGISTRYINDEX
);
3051 if (lua_type(L
,4) == LUA_TBOOLEAN
) {
3052 immediate
= lua_toboolean(L
, 4);
3054 if (lua_type(L
,5) == LUA_TNUMBER
) {
3055 type
= lua_tointeger(L
, 5);
3057 /* more or less same as scanner variant */
3058 boxdata
= box(boxnumber
);
3059 if (boxdata
== null
)
3060 normal_error("pdf backend", "xforms cannot be used with a void box");
3061 static_pdf
->xform_count
++;
3062 index
= pdf_create_obj(static_pdf
, obj_type_xform
, static_pdf
->xform_count
);
3063 set_obj_data_ptr(static_pdf
, index
, pdf_get_mem(static_pdf
, pdfmem_xform_size
));
3064 set_obj_xform_attr(static_pdf
, index
, null
);
3065 set_obj_xform_attr_str(static_pdf
, index
, attributes
);
3066 set_obj_xform_resources(static_pdf
, index
, null
);
3067 set_obj_xform_resources_str(static_pdf
, index
, resources
);
3068 set_obj_xform_box(static_pdf
, index
, (int) boxdata
);
3069 set_obj_xform_width(static_pdf
, index
, width(boxdata
));
3070 set_obj_xform_height(static_pdf
, index
, height(boxdata
));
3071 set_obj_xform_depth(static_pdf
, index
, depth(boxdata
));
3072 set_obj_xform_type(static_pdf
, index
, type
);
3073 box(boxnumber
) = null
;
3074 last_saved_box_index
= index
;
3075 lua_pushinteger(L
, index
);
3077 pdf_cur_form
= last_saved_box_index
;
3078 ship_out(static_pdf
, obj_xform_box(static_pdf
, last_saved_box_index
), SHIPPING_FORM
);
3083 static int tex_use_box_resource(lua_State
* L
)
3087 scaled_whd alt
, nat
, dim
;
3088 if (lua_type(L
,1) != LUA_TNUMBER
) {
3094 index
= lua_tointeger(L
,1);
3098 if (lua_type(L
,2) == LUA_TNUMBER
) {
3099 alt
.wd
= (scaled
) lua_roundnumber(L
,2);
3101 if (lua_type(L
,3) == LUA_TNUMBER
) {
3102 alt
.ht
= (scaled
) lua_roundnumber(L
,3);
3104 if (lua_type(L
,4) == LUA_TNUMBER
) {
3105 alt
.dp
= (scaled
) lua_roundnumber(L
,4);
3107 /* sort of the same as backend */
3108 check_obj_type(static_pdf
, obj_type_xform
, index
);
3109 nat
.wd
= obj_xform_width(static_pdf
, index
);
3110 nat
.ht
= obj_xform_height(static_pdf
, index
);
3111 nat
.dp
= obj_xform_depth(static_pdf
, index
);
3112 if (alt
.wd
!= null_flag
|| alt
.ht
!= null_flag
|| alt
.dp
!= null_flag
) {
3113 dim
= tex_scale(nat
, alt
);
3117 rule
= new_rule(box_rule
);
3118 rule_index(rule
) = index
;
3119 width(rule
) = dim
.wd
;
3120 height(rule
) = dim
.ht
;
3121 depth(rule
) = dim
.dp
;
3122 nodelist_to_lua(L
, rule
);
3123 lua_pushinteger(L
, (int) dim
.wd
);
3124 lua_pushinteger(L
, (int) dim
.ht
);
3125 lua_pushinteger(L
, (int) dim
.dp
);
3130 static int tex_get_box_resource_dimensions(lua_State
* L
)
3133 if (lua_type(L
,1) != LUA_TNUMBER
) {
3138 index
= lua_tointeger(L
,1);
3139 check_obj_type(static_pdf
, obj_type_xform
, index
);
3140 lua_pushinteger(L
, (int) obj_xform_width(static_pdf
, index
));
3141 lua_pushinteger(L
, (int) obj_xform_height(static_pdf
, index
));
3142 lua_pushinteger(L
, (int) obj_xform_depth(static_pdf
, index
));
3147 static int tex_build_page(lua_State
* L
)
3153 void init_tex_table(lua_State
* L
)
3155 lua_createtable(L
, 0, 3);
3156 lua_pushcfunction(L
, tex_run_boot
);
3157 lua_setfield(L
, -2, "initialize");
3158 lua_pushcfunction(L
, tex_run_main
);
3159 lua_setfield(L
, -2, "run");
3160 lua_pushcfunction(L
, tex_run_end
);
3161 lua_setfield(L
, -2, "finish");
3162 lua_setglobal(L
, "tex");
3165 static const struct luaL_Reg texlib
[] = {
3166 { "run", tex_run_main
}, /* may be needed */
3167 { "finish", tex_run_end
}, /* may be needed */
3168 { "write", luacwrite
},
3169 { "print", luacprint
},
3170 { "tprint", luactprint
},
3171 { "cprint", luaccprint
},
3172 { "error", texerror
},
3173 { "sprint", luacsprint
},
3176 { "isdimen", isdimen
},
3177 { "setdimen", setdimen
},
3178 { "getdimen", getdimen
},
3179 { "isskip", isskip
},
3180 { "setskip", setskip
},
3181 { "getskip", getskip
},
3182 { "setglue", setglue
},
3183 { "getglue", getglue
},
3184 { "ismuskip", ismuskip
},
3185 { "setmuskip", setmuskip
},
3186 { "getmuskip", getmuskip
},
3187 { "setmuglue", setmuglue
},
3188 { "getmuglue", getmuglue
},
3189 { "isattribute", isattribute
},
3190 { "setattribute", setattribute
},
3191 { "getattribute", getattribute
},
3192 { "iscount", iscount
},
3193 { "setcount", setcount
},
3194 { "getcount", getcount
},
3195 { "istoks", istoks
},
3196 { "settoks", settoks
},
3197 { "scantoks", scantoks
},
3198 { "gettoks", gettoks
},
3200 { "setbox", setbox
},
3201 { "getbox", getbox
},
3202 { "splitbox", splitbox
},
3203 { "setlist", setlist
},
3204 { "getlist", getlist
},
3205 { "setnest", setnest
},
3206 { "getnest", getnest
},
3207 { "setcatcode", setcatcode
},
3208 { "getcatcode", getcatcode
},
3209 { "setdelcode", setdelcode
},
3210 { "getdelcode", getdelcode
},
3211 { "getdelcodes", getdelcodes
},
3212 { "setlccode", setlccode
},
3213 { "getlccode", getlccode
},
3214 { "setmathcode", setmathcode
},
3215 { "getmathcode", getmathcode
},
3216 { "getmathcodes", getmathcodes
},
3217 { "setsfcode", setsfcode
},
3218 { "getsfcode", getsfcode
},
3219 { "setuccode", setuccode
},
3220 { "getuccode", getuccode
},
3221 { "round", tex_roundnumber
},
3222 { "scale", tex_scaletable
},
3223 { "sp", tex_scaledimen
},
3224 { "fontname", getfontname
},
3225 { "fontidentifier", getfontidentifier
},
3226 { "uniformdeviate", getuniformdeviate
},
3227 { "number", getnumber
},
3228 { "romannumeral", getromannumeral
},
3229 { "definefont", tex_definefont
},
3230 { "hashtokens", tex_hashpairs
},
3231 { "primitives", tex_primitives
},
3232 { "extraprimitives", tex_extraprimitives
},
3233 { "enableprimitives", tex_enableprimitives
},
3234 { "shipout", tex_shipout
},
3235 { "badness", tex_badness
},
3236 { "setmath", tex_setmathparm
},
3237 { "getmath", tex_getmathparm
},
3238 { "linebreak", tex_run_linebreak
},
3239 { "resetparagraph", tex_reset_paragraph
},
3240 /* tex random generators */
3241 { "init_rand", tex_init_rand
},
3242 { "uniform_rand",tex_unif_rand
},
3243 { "normal_rand", tex_norm_rand
},
3244 { "lua_math_randomseed", tex_init_rand
}, /* syntactic sugar */
3245 { "lua_math_random", lua_math_random
},
3246 { "show_context", tex_show_context
},
3247 { "saveboxresource", tex_save_box_resource
},
3248 { "useboxresource", tex_use_box_resource
},
3249 { "getboxresourcedimensions", tex_get_box_resource_dimensions
},
3250 /* just for testing: it will probably stay but maybe with options */
3251 { "triggerbuildpage", tex_build_page
},
3256 int luaopen_tex(lua_State
* L
)
3258 luaL_register(L
, "tex", texlib
);
3260 make_table(L
, "attribute", "tex.attribute", "getattribute", "setattribute");
3261 make_table(L
, "skip", "tex.skip", "getskip", "setskip");
3262 make_table(L
, "glue", "tex.glue", "getglue", "setglue");
3263 make_table(L
, "muskip", "tex.muskip", "getmuskip", "setmuskip");
3264 make_table(L
, "muglue", "tex.muglue", "getmuglue", "setmuglue");
3265 make_table(L
, "dimen", "tex.dimen", "getdimen", "setdimen");
3266 make_table(L
, "count", "tex.count", "getcount", "setcount");
3267 make_table(L
, "toks", "tex.toks", "gettoks", "settoks");
3268 make_table(L
, "box", "tex.box", "getbox", "setbox");
3269 make_table(L
, "sfcode", "tex.sfcode", "getsfcode", "setsfcode");
3270 make_table(L
, "lccode", "tex.lccode", "getlccode", "setlccode");
3271 make_table(L
, "uccode", "tex.uccode", "getuccode", "setuccode");
3272 make_table(L
, "catcode", "tex.catcode", "getcatcode", "setcatcode");
3273 make_table(L
, "mathcode", "tex.mathcode", "getmathcode", "setmathcode");
3274 make_table(L
, "delcode", "tex.delcode", "getdelcode", "setdelcode");
3275 make_table(L
, "lists", "tex.lists", "getlist", "setlist");
3276 make_table(L
, "nest", "tex.nest", "getnest", "setnest");
3279 /* make the meta entries */
3281 luaL_newmetatable(L
, "tex.meta");
3282 lua_pushstring(L
, "__index");
3283 lua_pushcfunction(L
, gettex
);
3284 lua_settable(L
, -3);
3285 lua_pushstring(L
, "__newindex");
3286 lua_pushcfunction(L
, settex
);
3287 lua_settable(L
, -3);
3288 lua_setmetatable(L
, -2); /* meta to itself */
3289 /* initialize the I/O stack: */
3290 spindles
= xmalloc(sizeof(spindle
));
3292 spindles
[0].head
= NULL
;
3293 spindles
[0].tail
= NULL
;
3295 /* a somewhat odd place for this assert, maybe */
3296 assert(command_names
[data_cmd
].command_offset
== data_cmd
);