1 /* ltexlib.c
2
3 Copyright 2006-2012 Taco Hoekwater <taco@luatex.org>
4
5 This file is part of LuaTeX.
6
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.
11
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.
16
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/>. */
19
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. */
23
24 #include "ptexlib.h"
25 #include "lua/luatex-api.h"
26
27
28 #define attribute(A) eqtb[attribute_base+(A)].hh.rh
29 #define dimen(A) eqtb[scaled_base+(A)].hh.rh
30 #undef skip
31 #define skip(A) eqtb[skip_base+(A)].hh.rh
32 #define mu_skip(A) eqtb[mu_skip_base+(A)].hh.rh
33 #define count(A) eqtb[count_base+(A)].hh.rh
34 #define box(A) equiv(box_base+(A))
35
36 /* tex random generators */
37 extern int unif_rand(int );
38 extern int norm_rand(void );
39 extern void init_randoms(int );
40
41
42 typedef struct {
43 char *text;
44 unsigned int tsize;
45 void *next;
46 boolean partial;
47 int cattable;
48 } rope;
49
50 typedef struct {
51 rope *head;
52 rope *tail;
53 char complete; /* currently still writing ? */
54 } spindle;
55
56 #define PARTIAL_LINE 1
57 #define FULL_LINE 0
58
59 #define write_spindle spindles[spindle_index]
60 #define read_spindle spindles[(spindle_index-1)]
61
62 static int spindle_size = 0;
63 static spindle *spindles = NULL;
64 static int spindle_index = 0;
65
66
67
luac_store(lua_State * L,int i,int partial,int cattable)68 static void luac_store(lua_State * L, int i, int partial, int cattable)
69 {
70 char *st;
71 const char *sttemp;
72 size_t tsize;
73 rope *rn = NULL;
74 sttemp = lua_tolstring(L, i, &tsize);
75 st = xmalloc((unsigned) (tsize + 1));
76 memcpy(st, sttemp, (tsize + 1));
77 if (st) {
78 luacstrings++;
79 rn = (rope *) xmalloc(sizeof(rope));
80 rn->text = st;
81 rn->tsize = (unsigned) tsize;
82 rn->partial = partial;
83 rn->cattable = cattable;
84 rn->next = NULL;
85 if (write_spindle.head == NULL) {
86 assert(write_spindle.tail == NULL);
87 write_spindle.head = rn;
88 } else {
89 write_spindle.tail->next = rn;
90 }
91 write_spindle.tail = rn;
92 write_spindle.complete = 0;
93 }
94 }
95
96
do_luacprint(lua_State * L,int partial,int deftable)97 static int do_luacprint(lua_State * L, int partial, int deftable)
98 {
99 int i, n;
100 int cattable = deftable;
101 int startstrings = 1;
102 n = lua_gettop(L);
103 if (cattable != NO_CAT_TABLE) {
104 if (lua_type(L, 1) == LUA_TNUMBER && n > 1) {
105 cattable=(int)lua_tonumber(L, 1);
106 startstrings = 2;
107 if (cattable != -1 && cattable != -2 && !valid_catcode_table(cattable)) {
108 cattable = DEFAULT_CAT_TABLE;
109 }
110 }
111 }
112 if (lua_type(L, startstrings) == LUA_TTABLE) {
113 for (i = 1;; i++) {
114 lua_rawgeti(L, startstrings, i);
115 if (lua_isstring(L, -1)) {
116 luac_store(L, -1, partial, cattable);
117 lua_pop(L, 1);
118 } else {
119 break;
120 }
121 }
122 } else {
123 for (i = startstrings; i <= n; i++) {
124 if (!lua_isstring(L, i)) {
125 luaL_error(L, "no string to print");
126 }
127 luac_store(L, i, partial, cattable);
128 }
129 /* hh: We could use this but it makes not much different, apart from allocating more ropes so less
130 memory. To be looked into: lua 5.2 buffer mechanism as now we still hash the concatination. This
131 test was part of the why-eis-luajit-so-slow on crited experiments. */
132 /*
133 if (startstrings == n) {
134 luac_store(L, n, partial, cattable);
135 } else {
136 lua_concat(L,n-startstrings+1);
137 luac_store(L, startstrings, partial, cattable);
138 }
139 */
140 }
141 return 0;
142 }
143
144
145
146
luacwrite(lua_State * L)147 static int luacwrite(lua_State * L)
148 {
149 return do_luacprint(L, FULL_LINE, NO_CAT_TABLE);
150 }
151
luacprint(lua_State * L)152 static int luacprint(lua_State * L)
153 {
154 return do_luacprint(L, FULL_LINE, DEFAULT_CAT_TABLE);
155 }
156
luacsprint(lua_State * L)157 static int luacsprint(lua_State * L)
158 {
159 return do_luacprint(L, PARTIAL_LINE, DEFAULT_CAT_TABLE);
160 }
161
luactprint(lua_State * L)162 static int luactprint(lua_State * L)
163 {
164 int i, j, n;
165 int cattable, startstrings;
166 n = lua_gettop(L);
167 for (i = 1; i <= n; i++) {
168 cattable = DEFAULT_CAT_TABLE;
169 startstrings = 1;
170 if (lua_type(L, i) != LUA_TTABLE) {
171 luaL_error(L, "no string to print");
172 }
173 lua_pushvalue(L, i); /* push the table */
174 lua_pushnumber(L, 1);
175 lua_gettable(L, -2);
176 if (lua_type(L, -1) == LUA_TNUMBER) {
177 cattable=(int)lua_tonumber(L, -1);
178 startstrings = 2;
179 if (cattable != -1 && cattable != -2 && !valid_catcode_table(cattable)) {
180 cattable = DEFAULT_CAT_TABLE;
181 }
182 }
183 lua_pop(L, 1);
184
185 for (j = startstrings;; j++) {
186 lua_pushnumber(L, j);
187 lua_gettable(L, -2);
188 if (lua_type(L, -1) == LUA_TSTRING) {
189 luac_store(L, -1, PARTIAL_LINE, cattable);
190 lua_pop(L, 1);
191 } else {
192 lua_pop(L, 1);
193 break;
194 }
195 }
196 lua_pop(L, 1); /* pop the table */
197 }
198 return 0;
199 }
200
201
luacstring_cattable(void)202 int luacstring_cattable(void)
203 {
204 return (int) read_spindle.tail->cattable;
205 }
206
luacstring_partial(void)207 int luacstring_partial(void)
208 {
209 return read_spindle.tail->partial;
210 }
211
luacstring_final_line(void)212 int luacstring_final_line(void)
213 {
214 return (read_spindle.tail->next == NULL);
215 }
216
luacstring_input(void)217 int luacstring_input(void)
218 {
219 char *st;
220 int ret;
221 rope *t = read_spindle.head;
222 if (!read_spindle.complete) {
223 read_spindle.complete = 1;
224 read_spindle.tail = NULL;
225 }
226 if (t == NULL) {
227 if (read_spindle.tail != NULL)
228 free(read_spindle.tail);
229 read_spindle.tail = NULL;
230 return 0;
231 }
232 if (t->text != NULL) {
233 st = t->text;
234 /* put that thing in the buffer */
235 last = first;
236 ret = last;
237 check_buffer_overflow(last + (int) t->tsize);
238
239 while (t->tsize-- > 0)
240 buffer[last++] = (packed_ASCII_code) * st++;
241 if (!t->partial) {
242 while (last - 1 > ret && buffer[last - 1] == ' ')
243 last--;
244 }
245 free(t->text);
246 t->text = NULL;
247 }
248 if (read_spindle.tail != NULL) { /* not a one-liner */
249 free(read_spindle.tail);
250 }
251 read_spindle.tail = t;
252 read_spindle.head = t->next;
253 return 1;
254 }
255
256 /* open for reading, and make a new one for writing */
luacstring_start(int n)257 void luacstring_start(int n)
258 {
259 (void) n; /* for -W */
260 spindle_index++;
261 if (spindle_size == spindle_index) { /* add a new one */
262 spindles =
263 xrealloc(spindles,
264 (unsigned) (sizeof(spindle) *
265 (unsigned) (spindle_size + 1)));
266 spindles[spindle_index].head = NULL;
267 spindles[spindle_index].tail = NULL;
268 spindles[spindle_index].complete = 0;
269 spindle_size++;
270 }
271 }
272
273 /* close for reading */
274
luacstring_close(int n)275 void luacstring_close(int n)
276 {
277 rope *next, *t;
278 (void) n; /* for -W */
279 next = read_spindle.head;
280 while (next != NULL) {
281 if (next->text != NULL)
282 free(next->text);
283 t = next;
284 next = next->next;
285 if (t==read_spindle.tail) {
286 read_spindle.tail = NULL; // prevent double-free
287 }
288 free(t);
289 }
290 read_spindle.head = NULL;
291 if (read_spindle.tail != NULL)
292 free(read_spindle.tail);
293 read_spindle.tail = NULL;
294 read_spindle.complete = 0;
295 spindle_index--;
296 }
297
298 /* local (static) versions */
299
300 #define check_index_range(j,s) \
301 if (j<0 || j > 65535) { \
302 luaL_error(L, "incorrect index value %d for tex.%s()", (int)j, s); }
303
304
scan_integer_part(lua_State * L,const char * ss,int * ret,int * radix_ret)305 static const char *scan_integer_part(lua_State * L, const char *ss, int *ret,
306 int *radix_ret)
307 {
308 boolean negative = false; /* should the answer be negated? */
309 int m; /* |$2^{31}$ / radix|, the threshold of danger */
310 int d; /* the digit just scanned */
311 boolean vacuous; /* have no digits appeared? */
312 boolean OK_so_far; /* has an error message been issued? */
313 int radix1 = 0; /* the radix of the integer */
314 int c = 0; /* the current character */
315 const char *s; /* where we stopped in the string |ss| */
316 integer val = 0; /* return value */
317 s = ss;
318 do {
319 do {
320 c = *s++;
321 } while (c && c == ' ');
322 if (c == '-') {
323 negative = !negative;
324 c = '+';
325 }
326 } while (c == '+');
327
328
329 radix1 = 10;
330 m = 214748364;
331 if (c == '\'') {
332 radix1 = 8;
333 m = 02000000000;
334 c = *s++;
335 } else if (c == '"') {
336 radix1 = 16;
337 m = 01000000000;
338 c = *s++;
339 }
340 vacuous = true;
341 val = 0;
342 OK_so_far = true;
343
344 /* Accumulate the constant until |cur_tok| is not a suitable digit */
345 while (1) {
346 if ((c < '0' + radix1) && (c >= '0') && (c <= '0' + 9)) {
347 d = c - '0';
348 } else if (radix1 == 16) {
349 if ((c <= 'A' + 5) && (c >= 'A')) {
350 d = c - 'A' + 10;
351 } else if ((c <= 'a' + 5) && (c >= 'a')) {
352 d = c - 'a' + 10;
353 } else {
354 break;
355 }
356 } else {
357 break;
358 }
359 vacuous = false;
360 if ((val >= m) && ((val > m) || (d > 7) || (radix1 != 10))) {
361 if (OK_so_far) {
362 luaL_error(L, "Number too big");
363 val = infinity;
364 OK_so_far = false;
365 }
366 } else {
367 val = val * radix1 + d;
368 }
369 c = *s++;
370 }
371 if (vacuous) {
372 /* Express astonishment that no number was here */
373 luaL_error(L, "Missing number, treated as zero");
374 }
375 if (negative)
376 val = -val;
377 *ret = val;
378 *radix_ret = radix1;
379 if (c != ' ' && s > ss)
380 s--;
381 return s;
382 }
383
384 #define set_conversion(A,B) do { num=(A); denom=(B); } while(0)
385
386
scan_dimen_part(lua_State * L,const char * ss,int * ret)387 static const char *scan_dimen_part(lua_State * L, const char *ss, int *ret)
388 /* sets |cur_val| to a dimension */
389 {
390 boolean negative = false; /* should the answer be negated? */
391 int f = 0; /* numerator of a fraction whose denominator is $2^{16}$ */
392 int num, denom; /* conversion ratio for the scanned units */
393 int k; /* number of digits in a decimal fraction */
394 scaled v; /* an internal dimension */
395 int save_cur_val; /* temporary storage of |cur_val| */
396 int c; /* the current character */
397 const char *s = ss; /* where we are in the string */
398 int radix1 = 0; /* the current radix */
399 int rdig[18]; /* to save the |dig[]| array */
400 int saved_tex_remainder; /* to save |tex_remainder| */
401 int saved_arith_error; /* to save |arith_error| */
402 int saved_cur_val; /* to save the global |cur_val| */
403 saved_tex_remainder = tex_remainder;
404 saved_arith_error = arith_error;
405 saved_cur_val = cur_val;
406 /* Get the next non-blank non-sign... */
407 do {
408 /* Get the next non-blank non-call token */
409 do {
410 c = *s++;
411 } while (c && c == ' ');
412 if (c == '-') {
413 negative = !negative;
414 c = '+';
415 }
416 } while (c == '+');
417
418 if (c == ',') {
419 c = '.';
420 }
421 if (c != '.') {
422 s = scan_integer_part(L, (s > ss ? (s - 1) : ss), &cur_val, &radix1);
423 c = *s;
424 } else {
425 radix1 = 10;
426 cur_val = 0;
427 c = *(--s);
428 }
429 if (c == ',')
430 c = '.';
431 if ((radix1 == 10) && (c == '.')) {
432 /* Scan decimal fraction */
433 for (k = 0; k < 18; k++)
434 rdig[k] = dig[k];
435 k = 0;
436 s++; /* get rid of the '.' */
437 while (1) {
438 c = *s++;
439 if ((c > '0' + 9) || (c < '0'))
440 break;
441 if (k < 17) { /* digits for |k>=17| cannot affect the result */
442 dig[k++] = c - '0';
443 }
444 }
445 f = round_decimals(k);
446 if (c != ' ')
447 c = *(--s);
448 for (k = 0; k < 18; k++)
449 dig[k] = rdig[k];
450 }
451 if (cur_val < 0) { /* in this case |f=0| */
452 negative = !negative;
453 cur_val = -cur_val;
454 }
455
456 /* Scan for (u)units that are internal dimensions;
457 |goto attach_sign| with |cur_val| set if found */
458 save_cur_val = cur_val;
459 /* Get the next non-blank non-call... */
460 do {
461 c = *s++;
462 } while (c && c == ' ');
463 if (c != ' ')
464 c = *(--s);
465 if (strncmp(s, "em", 2) == 0) {
466 s += 2;
467 v = (quad(get_cur_font()));
468 } else if (strncmp(s, "ex", 2) == 0) {
469 s += 2;
470 v = (x_height(get_cur_font()));
471 } else if (strncmp(s, "px", 2) == 0) {
472 s += 2;
473 v = dimen_par(pdf_px_dimen_code);
474 } else {
475 goto NOT_FOUND;
476 }
477 c = *s++;
478 if (c != ' ') {
479 c = *(--s);
480 }
481 cur_val = nx_plus_y(save_cur_val, v, xn_over_d(v, f, 0200000));
482 goto ATTACH_SIGN;
483 NOT_FOUND:
484
485 /* Scan for (m)\.{mu} units and |goto attach_fraction| */
486 if (strncmp(s, "mu", 2) == 0) {
487 s += 2;
488 goto ATTACH_FRACTION;
489 }
490 if (strncmp(s, "true", 4) == 0) {
491 /* Adjust (f)for the magnification ratio */
492 s += 4;
493 prepare_mag();
494 if (int_par(mag_code) != 1000) {
495 cur_val = xn_over_d(cur_val, 1000, int_par(mag_code));
496 f = (1000 * f + 0200000 * tex_remainder) / int_par(mag_code);
497 cur_val = cur_val + (f / 0200000);
498 f = f % 0200000;
499 }
500 do {
501 c = *s++;
502 } while (c && c == ' ');
503 c = *(--s);
504 }
505 if (strncmp(s, "pt", 2) == 0) {
506 s += 2;
507 goto ATTACH_FRACTION; /* the easy case */
508 }
509 /* Scan for (a)all other units and adjust |cur_val| and |f| accordingly;
510 |goto done| in the case of scaled points */
511
512 if (strncmp(s, "in", 2) == 0) {
513 s += 2;
514 set_conversion(7227, 100);
515 } else if (strncmp(s, "pc", 2) == 0) {
516 s += 2;
517 set_conversion(12, 1);
518 } else if (strncmp(s, "cm", 2) == 0) {
519 s += 2;
520 set_conversion(7227, 254);
521 } else if (strncmp(s, "mm", 2) == 0) {
522 s += 2;
523 set_conversion(7227, 2540);
524 } else if (strncmp(s, "bp", 2) == 0) {
525 s += 2;
526 set_conversion(7227, 7200);
527 } else if (strncmp(s, "dd", 2) == 0) {
528 s += 2;
529 set_conversion(1238, 1157);
530 } else if (strncmp(s, "cc", 2) == 0) {
531 s += 2;
532 set_conversion(14856, 1157);
533 } else if (strncmp(s, "nd", 2) == 0) {
534 s += 2;
535 set_conversion(685, 642);
536 } else if (strncmp(s, "nc", 2) == 0) {
537 s += 2;
538 set_conversion(1370, 107);
539 } else if (strncmp(s, "sp", 2) == 0) {
540 s += 2;
541 goto DONE;
542 } else {
543 /* Complain about unknown unit and |goto done2| */
544 luaL_error(L, "Illegal unit of measure (pt inserted)");
545 goto DONE2;
546 }
547 cur_val = xn_over_d(cur_val, num, denom);
548 f = (num * f + 0200000 * tex_remainder) / denom;
549 cur_val = cur_val + (f / 0200000);
550 f = f % 0200000;
551 DONE2:
552 ATTACH_FRACTION:
553 if (cur_val >= 040000)
554 arith_error = true;
555 else
556 cur_val = cur_val * 65536 + f;
557 DONE:
558 /* Scan an optional space */
559 c = *s++;
560 if (c != ' ')
561 s--;
562 ATTACH_SIGN:
563 if (arith_error || (abs(cur_val) >= 010000000000)) {
564 /* Report that this dimension is out of range */
565 luaL_error(L, "Dimension too large");
566 cur_val = max_dimen;
567 }
568 if (negative)
569 cur_val = -cur_val;
570 *ret = cur_val;
571 tex_remainder = saved_tex_remainder;
572 arith_error = saved_arith_error;
573 cur_val = saved_cur_val;
574 return s;
575 }
576
dimen_to_number(lua_State * L,const char * s)577 int dimen_to_number(lua_State * L, const char *s)
578 {
579 int j = 0;
580 const char *d = scan_dimen_part(L, s, &j);
581 if (*d) {
582 luaL_error(L, "conversion failed (trailing junk?)");
583 j = 0;
584 }
585 return j;
586 }
587
588
tex_scaledimen(lua_State * L)589 static int tex_scaledimen(lua_State * L)
590 { /* following vsetdimen() */
591 int sp;
592 if (!lua_isnumber(L, 1)) {
593 if (lua_isstring(L, 1)) {
594 sp = dimen_to_number(L, lua_tostring(L, 1));
595 } else {
596 luaL_error(L, "argument must be a string or a number");
597 return 0;
598 }
599 } else {
600 sp=(int)lua_tonumber(L, 1);
601 }
602 lua_pushnumber(L, sp);
603 return 1;
604 }
605
texerror(lua_State * L)606 static int texerror (lua_State * L)
607 {
608 int i, n, l;
609 const char **errhlp = NULL;
610 const char *error = luaL_checkstring(L,1);
611 n = lua_gettop(L);
612 if (n==2 && lua_type(L, n) == LUA_TTABLE) {
613 l = 1; /* |errhlp| is terminated by a NULL entry */
614 for (i = 1;; i++) {
615 lua_rawgeti(L, n, i);
616 if (lua_isstring(L, -1)) {
617 l++;
618 lua_pop(L, 1);
619 } else {
620 lua_pop(L, 1);
621 break;
622 }
623 }
624 if (l>1) {
625 errhlp = xmalloc(l * sizeof(char *));
626 memset(errhlp,0,l * sizeof(char *));
627 for (i = 1;; i++) {
628 lua_rawgeti(L, n, i);
629 if (lua_isstring(L, -1)) {
630 errhlp[(i-1)] = lua_tostring(L,-1);
631 lua_pop(L, 1);
632 } else {
633 break;
634 }
635 }
636 }
637 }
638 deletions_allowed = false;
639 tex_error(error, errhlp);
640 if (errhlp)
641 xfree(errhlp);
642 deletions_allowed = true;
643 return 0;
644 }
645
get_item_index(lua_State * L,int i,int base)646 static int get_item_index(lua_State * L, int i, int base)
647 {
648 size_t kk;
649 int k;
650 int cur_cs1;
651 const char *s;
652 switch (lua_type(L, i)) {
653 case LUA_TSTRING:
654 s = lua_tolstring(L, i, &kk);
655 cur_cs1 = string_lookup(s, kk);
656 if (cur_cs1 == undefined_control_sequence || cur_cs1 == undefined_cs_cmd)
657 k = -1; /* guarandeed invalid */
658 else
659 k = (equiv(cur_cs1) - base);
660 break;
661 case LUA_TNUMBER:
662 k = (int) luaL_checkinteger(L, i);
663 break;
664 default:
665 luaL_error(L, "argument must be a string or a number");
666 k = -1; /* not a valid index */
667 }
668 return k;
669 }
670
vsetdimen(lua_State * L,int is_global)671 static int vsetdimen(lua_State * L, int is_global)
672 {
673 int i, j, err;
674 int k;
675 int save_global_defs = int_par(global_defs_code);
676 if (is_global)
677 int_par(global_defs_code) = 1;
678 i = lua_gettop(L);
679 j = 0;
680 /* find the value */
681 if (!lua_isnumber(L, i)) {
682 if (lua_isstring(L, i)) {
683 j = dimen_to_number(L, lua_tostring(L, i));
684 } else {
685 luaL_error(L, "unsupported value type");
686 }
687 } else {
688 j=(int)lua_tonumber(L, i);
689 }
690 k = get_item_index(L, (i - 1), scaled_base);
691 check_index_range(k, "setdimen");
692 err = set_tex_dimen_register(k, j);
693 int_par(global_defs_code) = save_global_defs;
694 if (err) {
695 luaL_error(L, "incorrect value");
696 }
697 return 0;
698 }
699
setdimen(lua_State * L)700 static int setdimen(lua_State * L)
701 {
702 int isglobal = 0;
703 int n = lua_gettop(L);
704 if (n == 3 && lua_isstring(L, 1)) {
705 const char *s = lua_tostring(L, 1);
706 if (lua_key_eq(s,global))
707 isglobal = 1;
708 }
709 return vsetdimen(L, isglobal);
710 }
711
getdimen(lua_State * L)712 static int getdimen(lua_State * L)
713 {
714 int j;
715 int k;
716 k = get_item_index(L, lua_gettop(L), scaled_base);
717 check_index_range(k, "getdimen");
718 j = get_tex_dimen_register(k);
719 lua_pushnumber(L, j);
720 return 1;
721 }
722
vsetskip(lua_State * L,int is_global)723 static int vsetskip(lua_State * L, int is_global)
724 {
725 int i, err;
726 halfword *j;
727 int k;
728 int save_global_defs = int_par(global_defs_code);
729 if (is_global)
730 int_par(global_defs_code) = 1;
731 i = lua_gettop(L);
732 j = check_isnode(L, i); /* the value */
733 k = get_item_index(L, (i - 1), skip_base);
734 check_index_range(k, "setskip"); /* the index */
735 err = set_tex_skip_register(k, *j);
736 int_par(global_defs_code) = save_global_defs;
737 if (err) {
738 luaL_error(L, "incorrect value");
739 }
740 return 0;
741 }
742
setskip(lua_State * L)743 static int setskip(lua_State * L)
744 {
745 int isglobal = 0;
746 int n = lua_gettop(L);
747 if (n == 3 && lua_isstring(L, 1)) {
748 const char *s = lua_tostring(L, 1);
749 if (lua_key_eq(s,global))
750 isglobal = 1;
751 }
752 return vsetskip(L, isglobal);
753 }
754
getskip(lua_State * L)755 static int getskip(lua_State * L)
756 {
757 halfword j;
758 int k;
759 k = get_item_index(L, lua_gettop(L), skip_base);
760 check_index_range(k, "getskip");
761 j = get_tex_skip_register(k);
762 lua_nodelib_push_fast(L, j);
763 return 1;
764 }
765
766
767
vsetcount(lua_State * L,int is_global)768 static int vsetcount(lua_State * L, int is_global)
769 {
770 int i, j, err;
771 int k;
772 int save_global_defs = int_par(global_defs_code);
773 if (is_global)
774 int_par(global_defs_code) = 1;
775 i = lua_gettop(L);
776 j = (int) luaL_checkinteger(L, i);
777 k = get_item_index(L, (i - 1), count_base);
778 check_index_range(k, "setcount");
779 err = set_tex_count_register(k, j);
780 int_par(global_defs_code) = save_global_defs;
781 if (err) {
782 luaL_error(L, "incorrect value");
783 }
784 return 0;
785 }
786
setcount(lua_State * L)787 static int setcount(lua_State * L)
788 {
789 int isglobal = 0;
790 int n = lua_gettop(L);
791 if (n == 3 && lua_isstring(L, 1)) {
792 const char *s = lua_tostring(L, 1);
793 if (lua_key_eq(s,global))
794 isglobal = 1;
795 }
796 return vsetcount(L, isglobal);
797 }
798
getcount(lua_State * L)799 static int getcount(lua_State * L)
800 {
801 int j;
802 int k;
803 k = get_item_index(L, lua_gettop(L), count_base);
804 check_index_range(k, "getcount");
805 j = get_tex_count_register(k);
806 lua_pushnumber(L, j);
807 return 1;
808 }
809
810
vsetattribute(lua_State * L,int is_global)811 static int vsetattribute(lua_State * L, int is_global)
812 {
813 int i, j, err;
814 int k;
815 int save_global_defs = int_par(global_defs_code);
816 if (is_global)
817 int_par(global_defs_code) = 1;
818 i = lua_gettop(L);
819 j = (int) luaL_checkinteger(L, i);
820 k = get_item_index(L, (i - 1), attribute_base);
821 check_index_range(k, "setattribute");
822 err = set_tex_attribute_register(k, j);
823 int_par(global_defs_code) = save_global_defs;
824 if (err) {
825 luaL_error(L, "incorrect value");
826 }
827 return 0;
828 }
829
setattribute(lua_State * L)830 static int setattribute(lua_State * L)
831 {
832 int isglobal = 0;
833 int n = lua_gettop(L);
834 if (n == 3 && lua_isstring(L, 1)) {
835 const char *s = lua_tostring(L, 1);
836 if (lua_key_eq(s,global))
837 isglobal = 1;
838 }
839 return vsetattribute(L, isglobal);
840 }
841
getattribute(lua_State * L)842 static int getattribute(lua_State * L)
843 {
844 int j;
845 int k;
846 k = get_item_index(L, lua_gettop(L), attribute_base);
847 check_index_range(k, "getattribute");
848 j = get_tex_attribute_register(k);
849 lua_pushnumber(L, j);
850 return 1;
851 }
852
vsettoks(lua_State * L,int is_global)853 static int vsettoks(lua_State * L, int is_global)
854 {
855 int i, err;
856 int k;
857 lstring str;
858 char *s;
859 const char *ss;
860 int save_global_defs = int_par(global_defs_code);
861 if (is_global)
862 int_par(global_defs_code) = 1;
863 i = lua_gettop(L);
864 if (!lua_isstring(L, i)) {
865 luaL_error(L, "unsupported value type");
866 }
867 ss = lua_tolstring(L, i, &str.l);
868 s = xmalloc (str.l+1);
869 memcpy (s, ss, str.l+1);
870 str.s = (unsigned char *)s;
871 k = get_item_index(L, (i - 1), toks_base);
872 check_index_range(k, "settoks");
873 err = set_tex_toks_register(k, str);
874 xfree(str.s);
875 int_par(global_defs_code) = save_global_defs;
876 if (err) {
877 luaL_error(L, "incorrect value");
878 }
879 return 0;
880 }
881
settoks(lua_State * L)882 static int settoks(lua_State * L)
883 {
884 int isglobal = 0;
885 int n = lua_gettop(L);
886 if (n == 3 && lua_isstring(L, 1)) {
887 const char *s = lua_tostring(L, 1);
888 if (lua_key_eq(s,global))
889 isglobal = 1;
890 }
891 return vsettoks(L, isglobal);
892 }
893
gettoks(lua_State * L)894 static int gettoks(lua_State * L)
895 {
896 int k;
897 str_number t;
898 char *ss;
899 k = get_item_index(L, lua_gettop(L), toks_base);
900 check_index_range(k, "gettoks");
901 t = get_tex_toks_register(k);
902 ss = makecstring(t);
903 lua_pushstring(L, ss);
904 free(ss);
905 flush_str(t);
906 return 1;
907 }
908
get_box_id(lua_State * L,int i)909 static int get_box_id(lua_State * L, int i)
910 {
911 const char *s;
912 int cur_cs1, cur_cmd1;
913 size_t k = 0;
914 int j = -1;
915 switch (lua_type(L, i)) {
916 case LUA_TSTRING:
917 s = lua_tolstring(L, i, &k);
918 cur_cs1 = string_lookup(s, k);
919 cur_cmd1 = eq_type(cur_cs1);
920 if (cur_cmd1 == char_given_cmd ||
921 cur_cmd1 == math_given_cmd) {
922 j = equiv(cur_cs1);
923 }
924 break;
925 case LUA_TNUMBER:
926 j=(int)lua_tonumber(L, (i));
927 break;
928 default:
929 luaL_error(L, "argument must be a string or a number");
930 j = -1; /* not a valid box id */
931 }
932 return j;
933 }
934
getbox(lua_State * L)935 static int getbox(lua_State * L)
936 {
937 int k, t;
938 k = get_box_id(L, -1);
939 check_index_range(k, "getbox");
940 t = get_tex_box_register(k);
941 nodelist_to_lua(L, t);
942 return 1;
943 }
944
vsetbox(lua_State * L,int is_global)945 static int vsetbox(lua_State * L, int is_global)
946 {
947 int j, k, err;
948 int save_global_defs = int_par(global_defs_code);
949 if (is_global)
950 int_par(global_defs_code) = 1;
951 k = get_box_id(L, -2);
952 check_index_range(k, "setbox");
953 if (lua_isboolean(L, -1)) {
954 j = lua_toboolean(L, -1);
955 if (j == 0)
956 j = null;
957 else
958 return 0;
959 } else {
960 j = nodelist_from_lua(L);
961 if (j != null && type(j) != hlist_node && type(j) != vlist_node) {
962 luaL_error(L, "setbox: incompatible node type (%s)\n",
963 get_node_name(type(j), subtype(j)));
964 return 0;
965 }
966
967 }
968 err = set_tex_box_register(k, j);
969 int_par(global_defs_code) = save_global_defs;
970 if (err) {
971 luaL_error(L, "incorrect value");
972 }
973 return 0;
974 }
975
setbox(lua_State * L)976 static int setbox(lua_State * L)
977 {
978 int isglobal = 0;
979 int n = lua_gettop(L);
980 if (n == 3 && lua_isstring(L, 1)) {
981 const char *s = lua_tostring(L, 1);
982 if (lua_key_eq(s,global))
983 isglobal = 1;
984 }
985 return vsetbox(L, isglobal);
986 }
987
988 #define check_char_range(j,s,lim) \
989 if (j<0 || j >= lim) { \
990 luaL_error(L, "incorrect character value %d for tex.%s()", (int)j, s); }
991
992
setcode(lua_State * L,void (* setone)(int,halfword,quarterword),void (* settwo)(int,halfword,quarterword),const char * name,int lim)993 static int setcode (lua_State *L, void (*setone)(int,halfword,quarterword),
994 void (*settwo)(int,halfword,quarterword), const char *name, int lim)
995 {
996 int ch;
997 halfword val, ucval;
998 int level = cur_level;
999 int n = lua_gettop(L);
1000 int f = 1;
1001 if (n>1 && lua_type(L,1) == LUA_TTABLE)
1002 f++;
1003 if (n>2 && lua_isstring(L, f)) {
1004 const char *s = lua_tostring(L, f);
1005 if (lua_key_eq(s,global)) {
1006 level = level_one;
1007 f++;
1008 }
1009 }
1010 ch = (int) luaL_checkinteger(L, f);
1011 check_char_range(ch, name, 65536*17);
1012 val = (halfword) luaL_checkinteger(L, f+1);
1013 check_char_range(val, name, lim);
1014 (setone)(ch, val, level);
1015 if (settwo != NULL && n-f == 2) {
1016 ucval = (halfword) luaL_checkinteger(L, f+2);
1017 check_char_range(ucval, name, lim);
1018 (settwo)(ch, ucval, level);
1019 }
1020 return 0;
1021 }
1022
setlccode(lua_State * L)1023 static int setlccode(lua_State * L)
1024 {
1025 return setcode(L, &set_lc_code, &set_uc_code, "setlccode", 65536*17);
1026 }
1027
getlccode(lua_State * L)1028 static int getlccode(lua_State * L)
1029 {
1030 int ch = (int) luaL_checkinteger(L, -1);
1031 check_char_range(ch, "getlccode", 65536*17);
1032 lua_pushnumber(L, get_lc_code(ch));
1033 return 1;
1034 }
1035
setuccode(lua_State * L)1036 static int setuccode(lua_State * L)
1037 {
1038 return setcode(L, &set_uc_code, &set_lc_code, "setuccode", 65536*17);
1039 }
1040
getuccode(lua_State * L)1041 static int getuccode(lua_State * L)
1042 {
1043 int ch = (int) luaL_checkinteger(L, -1);
1044 check_char_range(ch, "getuccode", 65536*17);
1045 lua_pushnumber(L, get_uc_code(ch));
1046 return 1;
1047 }
1048
setsfcode(lua_State * L)1049 static int setsfcode(lua_State * L)
1050 {
1051 return setcode(L, &set_sf_code, NULL, "setsfcode", 32768);
1052 }
1053
getsfcode(lua_State * L)1054 static int getsfcode(lua_State * L)
1055 {
1056 int ch = (int) luaL_checkinteger(L, -1);
1057 check_char_range(ch, "getsfcode", 65536*17);
1058 lua_pushnumber(L, get_sf_code(ch));
1059 return 1;
1060 }
1061
setcatcode(lua_State * L)1062 static int setcatcode(lua_State * L)
1063 {
1064 int ch;
1065 halfword val;
1066 int level = cur_level;
1067 int cattable = int_par(cat_code_table_code);
1068 int n = lua_gettop(L);
1069 int f = 1;
1070 if (n>1 && lua_type(L,1) == LUA_TTABLE)
1071 f++;
1072 if (n>2 && lua_isstring(L, f)) {
1073 const char *s = lua_tostring(L, f);
1074 if (lua_key_eq(s,global)) {
1075 level = level_one;
1076 f++;
1077 }
1078 }
1079 if (n-f == 2) {
1080 cattable = (int) luaL_checkinteger(L, -3);
1081 }
1082 ch = (int) luaL_checkinteger(L, -2);
1083 check_char_range(ch, "setcatcode", 65536*17);
1084 val = (halfword) luaL_checkinteger(L, -1);
1085 check_char_range(val, "setcatcode", 16);
1086 set_cat_code(cattable, ch, val, level);
1087 return 0;
1088 }
1089
getcatcode(lua_State * L)1090 static int getcatcode(lua_State * L)
1091 {
1092 int cattable = int_par(cat_code_table_code);
1093 int ch = (int) luaL_checkinteger(L, -1);
1094 if (lua_gettop(L)>=2 && lua_type(L,-2)==LUA_TNUMBER) {
1095 cattable = luaL_checkinteger(L, -2);
1096 }
1097 check_char_range(ch, "getcatcode", 65536*17);
1098 lua_pushnumber(L, get_cat_code(cattable, ch));
1099 return 1;
1100 }
1101
1102
setmathcode(lua_State * L)1103 static int setmathcode(lua_State * L)
1104 {
1105 int ch;
1106 halfword cval, fval, chval;
1107 int level = cur_level;
1108 int n = lua_gettop(L);
1109 int f = 1;
1110 if (n>1 && lua_type(L,1) == LUA_TTABLE)
1111 f++;
1112 if (n>2 && lua_isstring(L, f)) {
1113 const char *s = lua_tostring(L, f);
1114 if (lua_key_eq(s,global)) {
1115 level = level_one;
1116 f++;
1117 }
1118 }
1119 if (n-f!=1 || lua_type(L,f+1) != LUA_TTABLE) {
1120 luaL_error(L, "Bad arguments for tex.setmathcode()");
1121 }
1122 ch = (int) luaL_checkinteger(L, -2);
1123 check_char_range(ch, "setmathcode", 65536*17);
1124
1125 lua_rawgeti(L, -1, 1);
1126 cval = (halfword) luaL_checkinteger(L, -1);
1127 lua_rawgeti(L, -2, 2);
1128 fval = (halfword) luaL_checkinteger(L, -1);
1129 lua_rawgeti(L, -3, 3);
1130 chval = (halfword) luaL_checkinteger(L, -1);
1131 lua_pop(L,3);
1132
1133 check_char_range(cval, "setmathcode", 8);
1134 check_char_range(fval, "setmathcode", 256);
1135 check_char_range(chval, "setmathcode", 65536*17);
1136 set_math_code(ch, xetex_mathcode, cval,fval, chval, (quarterword) (level));
1137 return 0;
1138 }
1139
getmathcode(lua_State * L)1140 static int getmathcode(lua_State * L)
1141 {
1142 mathcodeval mval = { 0, 0, 0, 0 };
1143 int ch = (int) luaL_checkinteger(L, -1);
1144 check_char_range(ch, "getmathcode", 65536*17);
1145 mval = get_math_code(ch);
1146 lua_newtable(L);
1147 lua_pushnumber(L,mval.class_value);
1148 lua_rawseti(L, -2, 1);
1149 lua_pushnumber(L,mval.family_value);
1150 lua_rawseti(L, -2, 2);
1151 lua_pushnumber(L,mval.character_value);
1152 lua_rawseti(L, -2, 3);
1153 return 1;
1154 }
1155
1156
1157
setdelcode(lua_State * L)1158 static int setdelcode(lua_State * L)
1159 {
1160 int ch;
1161 halfword sfval, scval, lfval, lcval;
1162 int level = cur_level;
1163 int n = lua_gettop(L);
1164 int f = 1;
1165 if (n>1 && lua_type(L,1) == LUA_TTABLE)
1166 f++;
1167 if (n>2 && lua_isstring(L, f)) {
1168 const char *s = lua_tostring(L, f);
1169 if (lua_key_eq(s,global)) {
1170 level = level_one;
1171 f++;
1172 }
1173 }
1174 if (n-f!=1 || lua_type(L,f+1) != LUA_TTABLE) {
1175 luaL_error(L, "Bad arguments for tex.setdelcode()");
1176 }
1177 ch = (int) luaL_checkinteger(L, -2);
1178 check_char_range(ch, "setdelcode", 65536*17);
1179 lua_rawgeti(L, -1, 1);
1180 sfval = (halfword) luaL_checkinteger(L, -1);
1181 lua_rawgeti(L, -2, 2);
1182 scval = (halfword) luaL_checkinteger(L, -1);
1183 lua_rawgeti(L, -3, 3);
1184 lfval = (halfword) luaL_checkinteger(L, -1);
1185 lua_rawgeti(L, -4, 4);
1186 lcval = (halfword) luaL_checkinteger(L, -1);
1187 lua_pop(L,4);
1188
1189 check_char_range(sfval, "setdelcode", 256);
1190 check_char_range(scval, "setdelcode", 65536*17);
1191 check_char_range(lfval, "setdelcode", 256);
1192 check_char_range(lcval, "setdelcode", 65536*17);
1193 set_del_code(ch, xetex_mathcode, sfval, scval, lfval, lcval, (quarterword) (level));
1194
1195 return 0;
1196 }
1197
getdelcode(lua_State * L)1198 static int getdelcode(lua_State * L)
1199 {
1200 delcodeval mval = { 0, 0, 0, 0, 0, 0 };
1201 int ch = (int) luaL_checkinteger(L, -1);
1202 check_char_range(ch, "getdelcode", 65536*17);
1203 mval = get_del_code(ch);
1204 /* lua_pushnumber(L, mval.class_value); */
1205 /* lua_pushnumber(L, mval.origin_value); */
1206 lua_newtable(L);
1207 lua_pushnumber(L,mval.small_family_value);
1208 lua_rawseti(L, -2, 1);
1209 lua_pushnumber(L,mval.small_character_value);
1210 lua_rawseti(L, -2, 2);
1211 lua_pushnumber(L,mval.large_family_value);
1212 lua_rawseti(L, -2, 3);
1213 lua_pushnumber(L,mval.large_character_value);
1214 lua_rawseti(L, -2, 4);
1215 return 1;
1216 }
1217
1218
1219
settex(lua_State * L)1220 static int settex(lua_State * L)
1221 {
1222 const char *st;
1223 int i, j, texstr;
1224 size_t k;
1225 int cur_cs1, cur_cmd1;
1226 int isglobal = 0;
1227 j = 0;
1228 i = lua_gettop(L);
1229 if (lua_isstring(L, (i - 1))) {
1230 st = lua_tolstring(L, (i - 1), &k);
1231 texstr = maketexlstring(st, k);
1232 if (is_primitive(texstr)) {
1233 if (i == 3 && lua_isstring(L, 1)) {
1234 const char *s = lua_tostring(L, 1);
1235 if (lua_key_eq(s,global))
1236 isglobal = 1;
1237 }
1238 cur_cs1 = string_lookup(st, k);
1239 flush_str(texstr);
1240 cur_cmd1 = eq_type(cur_cs1);
1241 if (is_int_assign(cur_cmd1)) {
1242 if (lua_isnumber(L, i)) {
1243 int luai;
1244 luai=(int)lua_tonumber(L, i);
1245 assign_internal_value((isglobal ? 4 : 0),
1246 equiv(cur_cs1), luai);
1247 } else {
1248 luaL_error(L, "unsupported value type");
1249 }
1250 } else if (is_dim_assign(cur_cmd1)) {
1251 if (!lua_isnumber(L, i)) {
1252 if (lua_isstring(L, i)) {
1253 j = dimen_to_number(L, lua_tostring(L, i));
1254 } else {
1255 luaL_error(L, "unsupported value type");
1256 }
1257 } else {
1258 j=(int)lua_tonumber(L, i);
1259 }
1260 assign_internal_value((isglobal ? 4 : 0), equiv(cur_cs1), j);
1261 } else if (is_glue_assign(cur_cmd1)) {
1262 halfword *j1 = check_isnode(L, i); /* the value */
1263 { int a = isglobal;
1264 define(equiv(cur_cs1), assign_glue_cmd, *j1);
1265 }
1266 } else if (is_toks_assign(cur_cmd1)) {
1267 if (lua_isstring(L, i)) {
1268 j = tokenlist_from_lua(L); /* uses stack -1 */
1269 assign_internal_value((isglobal ? 4 : 0), equiv(cur_cs1), j);
1270
1271 } else {
1272 luaL_error(L, "unsupported value type");
1273 }
1274
1275 } else {
1276 /* people may want to add keys that are also primitives
1277 (|tex.wd| for example) so creating an error is not
1278 right here */
1279 if (lua_istable(L, (i - 2)))
1280 lua_rawset(L, (i - 2));
1281 /* luaL_error(L, "unsupported tex internal assignment"); */
1282 }
1283 } else {
1284 if (lua_istable(L, (i - 2)))
1285 lua_rawset(L, (i - 2));
1286 }
1287 } else {
1288 if (lua_istable(L, (i - 2)))
1289 lua_rawset(L, (i - 2));
1290 }
1291 return 0;
1292 }
1293
do_convert(lua_State * L,int cur_code)1294 static int do_convert(lua_State * L, int cur_code)
1295 {
1296 int texstr;
1297 int i = -1;
1298 char *str = NULL;
1299 switch (cur_code) {
1300 case pdf_creation_date_code: /* ? */
1301 case pdf_insert_ht_code: /* arg <register int> */
1302 case pdf_ximage_bbox_code: /* arg 2 ints */
1303 case lua_code: /* arg complex */
1304 case lua_escape_string_code: /* arg token list */
1305 case pdf_colorstack_init_code: /* arg complex */
1306 case left_margin_kern_code: /* arg box */
1307 case right_margin_kern_code: /* arg box */
1308 break;
1309 case string_code: /* arg token */
1310 case meaning_code: /* arg token */
1311 break;
1312
1313 /* the next fall through, and come from 'official' indices! */
1314 case font_name_code: /* arg fontid */
1315 case font_identifier_code: /* arg fontid */
1316 case pdf_font_name_code: /* arg fontid */
1317 case pdf_font_objnum_code: /* arg fontid */
1318 case pdf_font_size_code: /* arg fontid */
1319 case uniform_deviate_code: /* arg int */
1320 case number_code: /* arg int */
1321 case roman_numeral_code: /* arg int */
1322 case pdf_page_ref_code: /* arg int */
1323 case pdf_xform_name_code: /* arg int */
1324 if (lua_gettop(L) < 1) {
1325 /* error */
1326 }
1327 i=(int)lua_tonumber(L, 1); /* these fall through! */
1328 default:
1329 texstr = the_convert_string(cur_code, i);
1330 if (texstr) {
1331 str = makecstring(texstr);
1332 flush_str(texstr);
1333 }
1334 }
1335 if (str) {
1336 lua_pushstring(L, str);
1337 free(str);
1338 } else {
1339 lua_pushnil(L);
1340 }
1341 return 1;
1342 }
1343
1344
do_scan_internal(lua_State * L,int cur_cmd1,int cur_code)1345 static int do_scan_internal(lua_State * L, int cur_cmd1, int cur_code)
1346 {
1347 int texstr;
1348 char *str = NULL;
1349 int save_cur_val, save_cur_val_level;
1350 save_cur_val = cur_val;
1351 save_cur_val_level = cur_val_level;
1352 scan_something_simple(cur_cmd1, cur_code);
1353
1354 if (cur_val_level == int_val_level ||
1355 cur_val_level == dimen_val_level || cur_val_level == attr_val_level) {
1356 lua_pushnumber(L, cur_val);
1357 } else if (cur_val_level == glue_val_level) {
1358 lua_nodelib_push_fast(L, cur_val);
1359 } else { /* dir_val_level, mu_val_level, tok_val_level */
1360 texstr = the_scanned_result();
1361 str = makecstring(texstr);
1362 if (str) {
1363 lua_pushstring(L, str);
1364 free(str);
1365 } else {
1366 lua_pushnil(L);
1367 }
1368 flush_str(texstr);
1369 }
1370 cur_val = save_cur_val;
1371 cur_val_level = save_cur_val_level;
1372 return 1;
1373 }
1374
do_lastitem(lua_State * L,int cur_code)1375 static int do_lastitem(lua_State * L, int cur_code)
1376 {
1377 int retval = 1;
1378 switch (cur_code) {
1379 /* the next two do not actually exist */
1380 case lastattr_code:
1381 case attrexpr_code:
1382 lua_pushnil(L);
1383 break;
1384 /* the expressions do something complicated with arguments, yuck */
1385 case numexpr_code:
1386 case dimexpr_code:
1387 case glueexpr_code:
1388 case muexpr_code:
1389 lua_pushnil(L);
1390 break;
1391 /* these read a glue or muglue, todo */
1392 case mu_to_glue_code:
1393 case glue_to_mu_code:
1394 case glue_stretch_order_code:
1395 case glue_shrink_order_code:
1396 case glue_stretch_code:
1397 case glue_shrink_code:
1398 lua_pushnil(L);
1399 break;
1400 /* these read a fontid and a char, todo */
1401 case font_char_wd_code:
1402 case font_char_ht_code:
1403 case font_char_dp_code:
1404 case font_char_ic_code:
1405 lua_pushnil(L);
1406 break;
1407 /* these read an integer, todo */
1408 case par_shape_length_code:
1409 case par_shape_indent_code:
1410 case par_shape_dimen_code:
1411 lua_pushnil(L);
1412 break;
1413 case lastpenalty_code:
1414 case lastkern_code:
1415 case lastskip_code:
1416 case last_node_type_code:
1417 case input_line_no_code:
1418 case badness_code:
1419 case pdftex_version_code:
1420 case pdf_last_obj_code:
1421 case pdf_last_xform_code:
1422 case pdf_last_ximage_code:
1423 case pdf_last_ximage_pages_code:
1424 case pdf_last_annot_code:
1425 case pdf_last_x_pos_code:
1426 case pdf_last_y_pos_code:
1427 case pdf_retval_code:
1428 case pdf_last_ximage_colordepth_code:
1429 case random_seed_code:
1430 case pdf_last_link_code:
1431 case luatex_version_code:
1432 case eTeX_minor_version_code:
1433 case eTeX_version_code:
1434 case current_group_level_code:
1435 case current_group_type_code:
1436 case current_if_level_code:
1437 case current_if_type_code:
1438 case current_if_branch_code:
1439 retval = do_scan_internal(L, last_item_cmd, cur_code);
1440 break;
1441 default:
1442 lua_pushnil(L);
1443 break;
1444 }
1445 return retval;
1446 }
1447
tex_setmathparm(lua_State * L)1448 static int tex_setmathparm(lua_State * L)
1449 {
1450 int i, j;
1451 int k;
1452 int n;
1453 int l = cur_level;
1454 n = lua_gettop(L);
1455
1456 if ((n == 3) || (n == 4)) {
1457 if (n == 4 && lua_isstring(L, 1)) {
1458 const char *s = lua_tostring(L, 1);
1459 if (lua_key_eq(s,global))
1460 l = 1;
1461 }
1462 i = luaL_checkoption(L, (n - 2), NULL, math_param_names);
1463 j = luaL_checkoption(L, (n - 1), NULL, math_style_names);
1464 if (!lua_isnumber(L, n))
1465 luaL_error(L, "argument must be a number");
1466 k=(int)lua_tonumber(L, n);
1467 def_math_param(i, j, (scaled) k, l);
1468 }
1469 return 0;
1470 }
1471
tex_getmathparm(lua_State * L)1472 static int tex_getmathparm(lua_State * L)
1473 {
1474 int i, j;
1475 scaled k;
1476 if ((lua_gettop(L) == 2)) {
1477 i = luaL_checkoption(L, 1, NULL, math_param_names);
1478 j = luaL_checkoption(L, 2, NULL, math_style_names);
1479 k = get_math_param(i, j);
1480 lua_pushnumber(L, k);
1481 }
1482 return 1;
1483 }
1484
getfontname(lua_State * L)1485 static int getfontname(lua_State * L)
1486 {
1487 return do_convert(L, font_name_code);
1488 }
1489
getfontidentifier(lua_State * L)1490 static int getfontidentifier(lua_State * L)
1491 {
1492 return do_convert(L, font_identifier_code);
1493 }
1494
getpdffontname(lua_State * L)1495 static int getpdffontname(lua_State * L)
1496 {
1497 return do_convert(L, pdf_font_name_code);
1498 }
1499
getpdffontobjnum(lua_State * L)1500 static int getpdffontobjnum(lua_State * L)
1501 {
1502 return do_convert(L, pdf_font_objnum_code);
1503 }
1504
getpdffontsize(lua_State * L)1505 static int getpdffontsize(lua_State * L)
1506 {
1507 return do_convert(L, pdf_font_size_code);
1508 }
1509
getuniformdeviate(lua_State * L)1510 static int getuniformdeviate(lua_State * L)
1511 {
1512 return do_convert(L, uniform_deviate_code);
1513 }
1514
getnumber(lua_State * L)1515 static int getnumber(lua_State * L)
1516 {
1517 return do_convert(L, number_code);
1518 }
1519
getromannumeral(lua_State * L)1520 static int getromannumeral(lua_State * L)
1521 {
1522 return do_convert(L, roman_numeral_code);
1523 }
1524
getpdfpageref(lua_State * L)1525 static int getpdfpageref(lua_State * L)
1526 {
1527 return do_convert(L, pdf_page_ref_code);
1528 }
1529
getpdfxformname(lua_State * L)1530 static int getpdfxformname(lua_State * L)
1531 {
1532 return do_convert(L, pdf_xform_name_code);
1533 }
1534
1535
get_parshape(lua_State * L)1536 static int get_parshape(lua_State * L)
1537 {
1538 int n;
1539 halfword par_shape_ptr = equiv(par_shape_loc);
1540 if (par_shape_ptr != 0) {
1541 int m = 1;
1542 n = vinfo(par_shape_ptr + 1);
1543 lua_createtable(L, n, 0);
1544 while (m <= n) {
1545 lua_createtable(L, 2, 0);
1546 lua_pushnumber(L, vlink((par_shape_ptr) + (2 * (m - 1)) + 2));
1547 lua_rawseti(L, -2, 1);
1548 lua_pushnumber(L, vlink((par_shape_ptr) + (2 * (m - 1)) + 3));
1549 lua_rawseti(L, -2, 2);
1550 lua_rawseti(L, -2, m);
1551 m++;
1552 }
1553 } else {
1554 lua_pushnil(L);
1555 }
1556 return 1;
1557 }
1558
1559
gettex(lua_State * L)1560 static int gettex(lua_State * L)
1561 {
1562 int cur_cs1 = -1;
1563 int retval = 1; /* default is to return nil */
1564 int t = lua_gettop(L);
1565 if (lua_isstring(L, t)) { /* 1 == 'tex', 2 == 'boxmaxdepth', or 1 == 'boxmaxdepth' */
1566 int texstr;
1567 size_t k;
1568 const char *st = lua_tolstring(L, t, &k);
1569 texstr = maketexlstring(st, k);
1570 cur_cs1 = prim_lookup(texstr); /* not found == relax == 0 */
1571 flush_str(texstr);
1572 }
1573 if (cur_cs1 > 0) {
1574 int cur_cmd1, cur_code;
1575 cur_cmd1 = get_prim_eq_type(cur_cs1);
1576 cur_code = get_prim_equiv(cur_cs1);
1577 switch (cur_cmd1) {
1578 case last_item_cmd:
1579 retval = do_lastitem(L, cur_code);
1580 break;
1581 case convert_cmd:
1582 retval = do_convert(L, cur_code);
1583 break;
1584 case assign_toks_cmd:
1585 case assign_int_cmd:
1586 case assign_attr_cmd:
1587 case assign_dir_cmd:
1588 case assign_dimen_cmd:
1589 case assign_glue_cmd:
1590 case assign_mu_glue_cmd:
1591 case set_aux_cmd:
1592 case set_prev_graf_cmd:
1593 case set_page_int_cmd:
1594 case set_page_dimen_cmd:
1595 case char_given_cmd:
1596 case math_given_cmd:
1597 retval = do_scan_internal(L, cur_cmd1, cur_code);
1598 break;
1599 case set_tex_shape_cmd:
1600 retval = get_parshape(L);
1601 break;
1602 default:
1603 lua_pushnil(L);
1604 break;
1605 }
1606 } else {
1607 if (t == 2) {
1608 lua_rawget(L, 1);
1609 }
1610 }
1611 return retval;
1612 }
1613
1614
getlist(lua_State * L)1615 static int getlist(lua_State * L)
1616 {
1617 const char *str;
1618 if (lua_isstring(L, 2)) {
1619 str = lua_tostring(L, 2);
1620 if (lua_key_eq(str,page_ins_head)) {
1621 if (vlink(page_ins_head) == page_ins_head)
1622 lua_pushnumber(L, null);
1623 else
1624 lua_pushnumber(L, vlink(page_ins_head));
1625 lua_nodelib_push(L);
1626 } else if (lua_key_eq(str,contrib_head)) {
1627 alink(vlink(contrib_head)) = null ;
1628 lua_pushnumber(L, vlink(contrib_head));
1629 lua_nodelib_push(L);
1630 } else if (lua_key_eq(str,page_head)) {
1631 alink(vlink(page_head)) = null ;/*hh-ls */
1632 lua_pushnumber(L, vlink(page_head));
1633 lua_nodelib_push(L);
1634 } else if (lua_key_eq(str,temp_head)) {
1635 alink(vlink(temp_head)) = null ;/*hh-ls */
1636 lua_pushnumber(L, vlink(temp_head));
1637 lua_nodelib_push(L);
1638 } else if (lua_key_eq(str,hold_head)) {
1639 alink(vlink(hold_head)) = null ;/*hh-ls */
1640 lua_pushnumber(L, vlink(hold_head));
1641 lua_nodelib_push(L);
1642 } else if (lua_key_eq(str,adjust_head)) {
1643 alink(vlink(adjust_head)) = null ;/*hh-ls */
1644 lua_pushnumber(L, vlink(adjust_head));
1645 lua_nodelib_push(L);
1646 } else if (lua_key_eq(str,best_page_break)) {
1647 lua_pushnumber(L, best_page_break);
1648 lua_nodelib_push(L);
1649 } else if (lua_key_eq(str,least_page_cost)) {
1650 lua_pushnumber(L, least_page_cost);
1651 } else if (lua_key_eq(str,best_size)) {
1652 lua_pushnumber(L, best_size);
1653 } else if (lua_key_eq(str,pre_adjust_head)) {
1654 alink(vlink(pre_adjust_head)) = null ;/*hh-ls */
1655 lua_pushnumber(L, vlink(pre_adjust_head));
1656 lua_nodelib_push(L);
1657 } else if (lua_key_eq(str,align_head)) {
1658 alink(vlink(align_head)) = null ;/*hh-ls */
1659 lua_pushnumber(L, vlink(align_head));
1660 lua_nodelib_push(L);
1661 } else {
1662 lua_pushnil(L);
1663 }
1664 } else {
1665 lua_pushnil(L);
1666 }
1667 return 1;
1668 }
1669
setlist(lua_State * L)1670 static int setlist(lua_State * L)
1671 {
1672 halfword *n_ptr;
1673 const char *str;
1674 halfword n = 0;
1675 if (lua_isstring(L, 2)) {
1676 str = lua_tostring(L, 2);
1677 if (lua_key_eq(str,best_size)) {
1678 best_size = (int) lua_tointeger(L, 3);
1679 } else if (lua_key_eq(str,least_page_cost)) {
1680 least_page_cost = (int) lua_tointeger(L, 3);
1681 } else {
1682 if (!lua_isnil(L, 3)) {
1683 n_ptr = check_isnode(L, 3);
1684 n = *n_ptr;
1685 }
1686 if (lua_key_eq(str,page_ins_head)) {
1687 if (n == 0) {
1688 vlink(page_ins_head) = page_ins_head;
1689 } else {
1690 halfword m;
1691 vlink(page_ins_head) = n;
1692 m = tail_of_list(n);
1693 vlink(m) = page_ins_head;
1694 }
1695 } else if (lua_key_eq(str,contrib_head)) {
1696 vlink(contrib_head) = n;
1697 if (n == 0) {
1698 contrib_tail = contrib_head;
1699 }
1700 } else if (lua_key_eq(str,best_page_break)) {
1701 best_page_break = n;
1702 } else if (lua_key_eq(str,page_head)) {
1703 vlink(page_head) = n;
1704 page_tail = (n == 0 ? page_head : tail_of_list(n));
1705 } else if (lua_key_eq(str,temp_head)) {
1706 vlink(temp_head) = n;
1707 } else if (lua_key_eq(str,hold_head)) {
1708 vlink(hold_head) = n;
1709 } else if (lua_key_eq(str,adjust_head)) {
1710 vlink(adjust_head) = n;
1711 adjust_tail = (n == 0 ? adjust_head : tail_of_list(n));
1712 } else if (lua_key_eq(str,pre_adjust_head)) {
1713 vlink(pre_adjust_head) = n;
1714 pre_adjust_tail = (n == 0 ? pre_adjust_head : tail_of_list(n));
1715 } else if (lua_key_eq(str,align_head)) {
1716 vlink(align_head) = n;
1717 }
1718 }
1719 }
1720 return 0;
1721 }
1722
1723 #define NEST_METATABLE "luatex.nest"
1724
lua_nest_getfield(lua_State * L)1725 static int lua_nest_getfield(lua_State * L)
1726 {
1727 list_state_record *r, **rv = lua_touserdata(L, -2);
1728 const char *field = lua_tostring(L, -1);
1729 r = *rv;
1730 if (lua_key_eq(field,mode)) {
1731 lua_pushnumber(L, r->mode_field);
1732 } else if (lua_key_eq(field,head)) {
1733 lua_nodelib_push_fast(L, r->head_field);
1734 } else if (lua_key_eq(field,tail)) {
1735 lua_nodelib_push_fast(L, r->tail_field);
1736 } else if (lua_key_eq(field,delimptr)) {
1737 lua_pushnumber(L, r->eTeX_aux_field);
1738 lua_nodelib_push(L);
1739 } else if (lua_key_eq(field,prevgraf)) {
1740 lua_pushnumber(L, r->pg_field);
1741 } else if (lua_key_eq(field,modeline)) {
1742 lua_pushnumber(L, r->ml_field);
1743 } else if (lua_key_eq(field,prevdepth)) {
1744 lua_pushnumber(L, r->prev_depth_field);
1745 } else if (lua_key_eq(field,spacefactor)) {
1746 lua_pushnumber(L, r->space_factor_field);
1747 } else if (lua_key_eq(field,noad)) {
1748 lua_pushnumber(L, r->incompleat_noad_field);
1749 lua_nodelib_push(L);
1750 } else if (lua_key_eq(field,dirs)) {
1751 lua_pushnumber(L, r->dirs_field);
1752 lua_nodelib_push(L);
1753 } else if (lua_key_eq(field,mathdir)) {
1754 lua_pushboolean(L, r->math_field);
1755 } else if (lua_key_eq(field,mathstyle)) {
1756 lua_pushnumber(L, r->math_style_field);
1757 } else {
1758 lua_pushnil(L);
1759 }
1760 return 1;
1761 }
1762
lua_nest_setfield(lua_State * L)1763 static int lua_nest_setfield(lua_State * L)
1764 {
1765 halfword *n;
1766 int i;
1767 list_state_record *r, **rv = lua_touserdata(L, -3);
1768 const char *field = lua_tostring(L, -2);
1769 r = *rv;
1770 if (lua_key_eq(field,mode)) {
1771 i=(int)lua_tonumber(L, -1);
1772 r->mode_field = i;
1773 } else if (lua_key_eq(field,head)) {
1774 n = check_isnode(L, -1);
1775 r->head_field = *n;
1776 } else if (lua_key_eq(field,tail)) {
1777 n = check_isnode(L, -1);
1778 r->tail_field = *n;
1779 } else if (lua_key_eq(field,delimptr)) {
1780 n = check_isnode(L, -1);
1781 r->eTeX_aux_field = *n;
1782 } else if (lua_key_eq(field,prevgraf)) {
1783 i=(int)lua_tonumber(L, -1);
1784 r->pg_field = i;
1785 } else if (lua_key_eq(field,modeline)) {
1786 i=(int)lua_tonumber(L, -1);
1787 r->ml_field = i;
1788 } else if (lua_key_eq(field,prevdepth)) {
1789 i=(int)lua_tonumber(L, -1);
1790 r->prev_depth_field = i;
1791 } else if (lua_key_eq(field,spacefactor)) {
1792 i=(int)lua_tonumber(L, -1);
1793 r->space_factor_field = i;
1794 } else if (lua_key_eq(field,noad)) {
1795 n = check_isnode(L, -1);
1796 r->incompleat_noad_field = *n;
1797 } else if (lua_key_eq(field,dirs)) {
1798 n = check_isnode(L, -1);
1799 r->dirs_field = *n;
1800 } else if (lua_key_eq(field,mathdir)) {
1801 r->math_field = lua_toboolean(L, -1);
1802 } else if (lua_key_eq(field,mathstyle)) {
1803 i=(int)lua_tonumber(L, -1);
1804 r->math_style_field = i;
1805 }
1806 return 0;
1807 }
1808
1809 static const struct luaL_Reg nest_m[] = {
1810 {"__index", lua_nest_getfield},
1811 {"__newindex", lua_nest_setfield},
1812 {NULL, NULL} /* sentinel */
1813 };
1814
init_nest_lib(lua_State * L)1815 static void init_nest_lib(lua_State * L)
1816 {
1817 luaL_newmetatable(L, NEST_METATABLE);
1818 luaL_register(L, NULL, nest_m);
1819 lua_pop(L, 1);
1820 }
1821
getnest(lua_State * L)1822 static int getnest(lua_State * L)
1823 {
1824 int ptr;
1825 list_state_record **nestitem;
1826 if (lua_isnumber(L, 2)) {
1827 ptr=(int)lua_tonumber(L, 2);
1828 if (ptr >= 0 && ptr <= nest_ptr) {
1829 nestitem = lua_newuserdata(L, sizeof(list_state_record *));
1830 *nestitem = &nest[ptr];
1831 luaL_getmetatable(L, NEST_METATABLE);
1832 lua_setmetatable(L, -2);
1833 } else {
1834 lua_pushnil(L);
1835 }
1836 } else if (lua_isstring(L, 2)) {
1837 const char *s = lua_tostring(L, 2);
1838 if (lua_key_eq(s,ptr)) {
1839 lua_pushnumber(L, nest_ptr);
1840 } else {
1841 lua_pushnil(L);
1842 }
1843 } else {
1844 lua_pushnil(L);
1845 }
1846 return 1;
1847 }
1848
setnest(lua_State * L)1849 static int setnest(lua_State * L)
1850 {
1851 luaL_error(L, "You can't modify the semantic nest array directly");
1852 return 2;
1853 }
1854
do_integer_error(double m)1855 static int do_integer_error(double m)
1856 {
1857 const char *help[] =
1858 { "I can only go up to 2147483647='17777777777=" "7FFFFFFF,",
1859 "so I'm using that number instead of yours.",
1860 NULL
1861 };
1862 tex_error("Number too big", help);
1863 return (m > 0.0 ? infinity : -infinity);
1864 }
1865
1866
tex_roundnumber(lua_State * L)1867 static int tex_roundnumber(lua_State * L)
1868 {
1869 double m = (double) lua_tonumber(L, 1) + 0.5;
1870 if (abs(m) > (double) infinity)
1871 lua_pushnumber(L, do_integer_error(m));
1872 else
1873 lua_pushnumber(L, floor(m));
1874 return 1;
1875 }
1876
tex_scaletable(lua_State * L)1877 static int tex_scaletable(lua_State * L)
1878 {
1879 double delta = luaL_checknumber(L, 2);
1880 if (lua_istable(L, 1)) {
1881 lua_newtable(L); /* the new table is at index 3 */
1882 lua_pushnil(L);
1883 while (lua_next(L, 1) != 0) { /* numeric value */
1884 lua_pushvalue(L, -2);
1885 lua_insert(L, -2);
1886 if (lua_isnumber(L, -1)) {
1887 double m = (double) lua_tonumber(L, -1) * delta + 0.5;
1888 lua_pop(L, 1);
1889 if (abs(m) > (double) infinity)
1890 lua_pushnumber(L, do_integer_error(m));
1891 else
1892 lua_pushnumber(L, floor(m));
1893 }
1894 lua_rawset(L, 3);
1895 }
1896 } else if (lua_isnumber(L, 1)) {
1897 double m = (double) lua_tonumber(L, 1) * delta + 0.5;
1898 if (abs(m) > (double) infinity)
1899 lua_pushnumber(L, do_integer_error(m));
1900 else
1901 lua_pushnumber(L, floor(m));
1902 } else {
1903 lua_pushnil(L);
1904 }
1905 return 1;
1906 }
1907
1908 #define hash_text(A) hash[(A)].rh
1909
tex_definefont(lua_State * L)1910 static int tex_definefont(lua_State * L)
1911 {
1912 const char *csname;
1913 int f, u;
1914 str_number t;
1915 size_t l;
1916 int i = 1;
1917 int a = 0;
1918 if (!no_new_control_sequence) {
1919 const char *help[] =
1920 { "You can't create a new font inside a \\csname\\endcsname pair",
1921 NULL
1922 };
1923 tex_error("Definition active", help);
1924 }
1925 if ((lua_gettop(L) == 3) && lua_isboolean(L, 1)) {
1926 a = lua_toboolean(L, 1);
1927 i = 2;
1928 }
1929 csname = luaL_checklstring(L, i, &l);
1930 f = (int) luaL_checkinteger(L, (i + 1));
1931 t = maketexlstring(csname, l);
1932 no_new_control_sequence = 0;
1933 u = string_lookup(csname, l);
1934 no_new_control_sequence = 1;
1935 if (a)
1936 geq_define(u, set_font_cmd, f);
1937 else
1938 eq_define(u, set_font_cmd, f);
1939 eqtb[font_id_base + f] = eqtb[u];
1940 hash_text(font_id_base + f) = t;
1941 return 0;
1942 }
1943
tex_hashpairs(lua_State * L)1944 static int tex_hashpairs(lua_State * L)
1945 {
1946 int cmd, chr;
1947 str_number s = 0;
1948 int cs = 1;
1949 lua_newtable(L);
1950 while (cs < hash_size) {
1951 s = hash_text(cs);
1952 if (s > 0) {
1953 char *ss = makecstring(s);
1954 lua_pushstring(L, ss);
1955 free(ss);
1956 cmd = eq_type(cs);
1957 chr = equiv(cs);
1958 make_token_table(L, cmd, chr, cs);
1959 lua_rawset(L, -3);
1960 }
1961 cs++;
1962 }
1963 return 1;
1964 }
1965
tex_primitives(lua_State * L)1966 static int tex_primitives(lua_State * L)
1967 {
1968 int cmd, chr;
1969 str_number s = 0;
1970 int cs = 0;
1971 lua_newtable(L);
1972 while (cs < prim_size) {
1973 s = get_prim_text(cs);
1974 if (s > 0) {
1975 char *ss = makecstring(s);
1976 lua_pushstring(L, ss);
1977 free(ss);
1978 cmd = get_prim_eq_type(cs);
1979 chr = get_prim_equiv(cs);
1980 make_token_table(L, cmd, chr, 0);
1981 lua_rawset(L, -3);
1982 }
1983 cs++;
1984 }
1985 return 1;
1986 }
1987
tex_extraprimitives(lua_State * L)1988 static int tex_extraprimitives(lua_State * L)
1989 {
1990 int n, i;
1991 int mask = 0;
1992 int cs = 0;
1993 n = lua_gettop(L);
1994 if (n == 0) {
1995 mask = etex_command + aleph_command + omega_command +
1996 pdftex_command + luatex_command + umath_command;
1997 } else {
1998 for (i = 1; i <= n; i++) {
1999 if (lua_isstring(L, i)) {
2000 const char *s = lua_tostring(L, i);
2001 if (lua_key_eq(s,etex)) {
2002 mask |= etex_command;
2003 } else if (lua_key_eq(s,tex)) {
2004 mask |= tex_command;
2005 } else if (lua_key_eq(s,core)) {
2006 mask |= core_command;
2007 } else if (lua_key_eq(s,pdftex)) {
2008 mask |= pdftex_command;
2009 } else if (lua_key_eq(s,aleph)) {
2010 mask |= aleph_command;
2011 } else if (lua_key_eq(s,omega)) {
2012 mask |= omega_command;
2013 } else if (lua_key_eq(s,luatex)) {
2014 mask |= luatex_command | umath_command;
2015 } else if (lua_key_eq(s,umath)) {
2016 mask |= umath_command;
2017 }
2018 }
2019 }
2020 }
2021 lua_newtable(L);
2022 i = 1;
2023 while (cs < prim_size) {
2024 str_number s = 0;
2025 s = get_prim_text(cs);
2026 if (s > 0) {
2027 if (get_prim_origin(cs) & mask) {
2028 char *ss = makecstring(s);
2029 lua_pushstring(L, ss);
2030 free(ss);
2031 lua_rawseti(L, -2, i++);
2032 }
2033 }
2034 cs++;
2035 }
2036 return 1;
2037 }
2038
tex_enableprimitives(lua_State * L)2039 static int tex_enableprimitives(lua_State * L)
2040 {
2041 int n = lua_gettop(L);
2042 if (n != 2) {
2043 luaL_error(L, "wrong number of arguments");
2044 } else {
2045 size_t l;
2046 int i;
2047 const char *pre = luaL_checklstring(L, 1, &l);
2048 if (lua_istable(L, 2)) {
2049 int nncs = no_new_control_sequence;
2050 no_new_control_sequence = true;
2051 i = 1;
2052 while (1) {
2053 lua_rawgeti(L, 2, i);
2054 if (lua_isstring(L, 3)) {
2055 const char *prim = lua_tostring(L, 3);
2056 str_number s = maketexstring(prim);
2057 halfword prim_val = prim_lookup(s);
2058 if (prim_val != undefined_primitive) {
2059 char *newprim;
2060 int val;
2061 size_t newl;
2062 halfword cur_cmd1 = get_prim_eq_type(prim_val);
2063 halfword cur_chr1 = get_prim_equiv(prim_val);
2064 if (strncmp(pre, prim, l) != 0) { /* not a prefix */
2065 newl = strlen(prim) + l;
2066 newprim = (char *) xmalloc((unsigned) (newl + 1));
2067 strcpy(newprim, pre);
2068 strcat(newprim + l, prim);
2069 } else {
2070 newl = strlen(prim);
2071 newprim = (char *) xmalloc((unsigned) (newl + 1));
2072 strcpy(newprim, prim);
2073 }
2074 val = string_lookup(newprim, newl);
2075 if (val == undefined_control_sequence ||
2076 eq_type(val) == undefined_cs_cmd) {
2077 primitive_def(newprim, newl, (quarterword) cur_cmd1,
2078 cur_chr1);
2079 }
2080 free(newprim);
2081 }
2082 flush_str(s);
2083 } else {
2084 lua_pop(L, 1);
2085 break;
2086 }
2087 lua_pop(L, 1);
2088 i++;
2089 }
2090 lua_pop(L, 1); /* the table */
2091 no_new_control_sequence = nncs;
2092 } else {
2093 luaL_error(L, "Expected an array of names as second argument");
2094 }
2095 }
2096 return 0;
2097 }
2098
2099 #define get_int_par(A,B,C) do { \
2100 lua_pushstring(L,(A)); \
2101 lua_gettable(L,-2); \
2102 if (lua_type(L, -1) == LUA_TNUMBER) { \
2103 B=(int)lua_tonumber(L, -1); \
2104 } else { \
2105 B = (C); \
2106 } \
2107 lua_pop(L,1); \
2108 } while (0)
2109
2110
2111 #define get_intx_par(A,B,C,D,E) do { \
2112 lua_pushstring(L,(A)); \
2113 lua_gettable(L,-2); \
2114 if (lua_type(L, -1) == LUA_TNUMBER) { \
2115 B=(int)lua_tonumber(L, -1); \
2116 D = null; \
2117 } else if (lua_type(L, -1) == LUA_TTABLE){ \
2118 B = 0; \
2119 D = nodelib_topenalties(L, lua_gettop(L)); \
2120 } else { \
2121 B = (C); \
2122 D = (E); \
2123 } \
2124 lua_pop(L,1); \
2125 } while (0)
2126
2127 #define get_dimen_par(A,B,C) do { \
2128 lua_pushstring(L,(A)); \
2129 lua_gettable(L,-2); \
2130 if (lua_type(L, -1) == LUA_TNUMBER) { \
2131 B=(int)lua_tonumber(L, -1); \
2132 } else { \
2133 B = (C); \
2134 } \
2135 lua_pop(L,1); \
2136 } while (0)
2137
2138
2139 #define get_glue_par(A,B,C) do { \
2140 lua_pushstring(L,(A)); \
2141 lua_gettable(L,-2); \
2142 if (lua_type(L, -1) != LUA_TNIL) { \
2143 B = *check_isnode(L, -1); \
2144 } else { \
2145 B = (C); \
2146 } \
2147 lua_pop(L,1); \
2148 } while (0)
2149
2150
nodelib_toparshape(lua_State * L,int i)2151 static halfword nodelib_toparshape(lua_State * L, int i)
2152 {
2153 halfword p;
2154 int n = 0;
2155 int width, indent, j;
2156 /* find |n| */
2157 lua_pushnil(L);
2158 while (lua_next(L, i) != 0) {
2159 n++;
2160 lua_pop(L, 1);
2161 }
2162 if (n == 0)
2163 return null;
2164 p = new_node(shape_node, 2 * (n + 1) + 1);
2165 vinfo(p + 1) = n;
2166 /* fill |p| */
2167 lua_pushnil(L);
2168 j = 0;
2169 while (lua_next(L, i) != 0) {
2170 /* don't give an error for non-tables, we may add special syntaxes at some point */
2171 j++;
2172 if (lua_type(L, i) == LUA_TTABLE) {
2173 lua_rawgeti(L, -1, 1); /* indent */
2174 if (lua_type(L, -1) == LUA_TNUMBER) {
2175 indent=(int)lua_tonumber(L, -1);
2176 lua_pop(L, 1);
2177 lua_rawgeti(L, -1, 2); /* width */
2178 if (lua_type(L, -1) == LUA_TNUMBER) {
2179 width=(int)lua_tonumber(L, -1);
2180 lua_pop(L, 1);
2181 varmem[p + 2 * j].cint = indent;
2182 varmem[p + 2 * j + 1].cint = width;
2183 }
2184 }
2185 }
2186 lua_pop(L, 1);
2187 }
2188 return p;
2189 }
2190
2191 /* penalties */
2192
nodelib_topenalties(lua_State * L,int i)2193 static halfword nodelib_topenalties(lua_State * L, int i)
2194 {
2195 halfword p;
2196 int n = 0;
2197 int j;
2198 /* find |n| */
2199 lua_pushnil(L);
2200 while (lua_next(L, i) != 0) {
2201 n++;
2202 lua_pop(L, 1);
2203 }
2204 if (n == 0)
2205 return null;
2206 p = new_node(shape_node, 2 * ((n / 2) + 1) + 1 + 1);
2207 vinfo(p + 1) = (n / 2) + 1;
2208 varmem[p + 2].cint = n;
2209 lua_pushnil(L);
2210 j = 2;
2211 while (lua_next(L, i) != 0) {
2212 j++;
2213 if (lua_isnumber(L, -1)) {
2214 int pen = 0;
2215 pen=(int)lua_tonumber(L, -1);
2216 varmem[p+j].cint = pen;
2217 }
2218 lua_pop(L, 1);
2219 }
2220 if (!odd(n))
2221 varmem[p+j+1].cint = 0;
2222 return p;
2223 }
2224
2225
2226
2227
tex_run_linebreak(lua_State * L)2228 static int tex_run_linebreak(lua_State * L)
2229 {
2230
2231 halfword *j;
2232 halfword p;
2233 halfword final_par_glue;
2234 int paragraph_dir = 0;
2235 /* locally initialized parameters for line breaking */
2236 int pretolerance, tracingparagraphs, tolerance, looseness, hyphenpenalty,
2237 exhyphenpenalty, pdfadjustspacing, adjdemerits, pdfprotrudechars,
2238 linepenalty, lastlinefit, doublehyphendemerits, finalhyphendemerits,
2239 hangafter, interlinepenalty, widowpenalty, clubpenalty, brokenpenalty;
2240 halfword emergencystretch, hangindent, hsize, leftskip, rightskip,
2241 pdfeachlineheight, pdfeachlinedepth, pdffirstlineheight,
2242 pdflastlinedepth, pdfignoreddimen, parshape;
2243 int fewest_demerits = 0, actual_looseness = 0;
2244 halfword clubpenalties, interlinepenalties, widowpenalties;
2245 int save_vlink_tmp_head;
2246 /* push a new nest level */
2247 push_nest();
2248 save_vlink_tmp_head = vlink(temp_head);
2249
2250 j = check_isnode(L, 1); /* the value */
2251 vlink(temp_head) = *j;
2252 p = *j;
2253 if ((!is_char_node(vlink(*j)))
2254 && ((type(vlink(*j)) == whatsit_node)
2255 && (subtype(vlink(*j)) == local_par_node))) {
2256 paragraph_dir = local_par_dir(vlink(*j));
2257 }
2258
2259 while (vlink(p) != null)
2260 p = vlink(p);
2261 final_par_glue = p;
2262
2263 /* initialize local parameters */
2264
2265 if (lua_gettop(L) != 2 || lua_type(L, 2) != LUA_TTABLE) {
2266 lua_checkstack(L, 3);
2267 lua_newtable(L);
2268 }
2269 lua_pushstring(L, "pardir");
2270 lua_gettable(L, -2);
2271 if (lua_type(L, -1) == LUA_TSTRING) {
2272 paragraph_dir = nodelib_getdir(L, -1, 1);
2273 }
2274 lua_pop(L, 1);
2275
2276 lua_pushstring(L, "parshape");
2277 lua_gettable(L, -2);
2278 if (lua_type(L, -1) == LUA_TTABLE) {
2279 parshape = nodelib_toparshape(L, lua_gettop(L));
2280 } else {
2281 parshape = equiv(par_shape_loc);
2282 }
2283 lua_pop(L, 1);
2284
2285 get_int_par("pretolerance", pretolerance, int_par(pretolerance_code));
2286 get_int_par("tracingparagraphs", tracingparagraphs,
2287 int_par(tracing_paragraphs_code));
2288 get_int_par("tolerance", tolerance, int_par(tolerance_code));
2289 get_int_par("looseness", looseness, int_par(looseness_code));
2290 get_int_par("hyphenpenalty", hyphenpenalty, int_par(hyphen_penalty_code));
2291 get_int_par("exhyphenpenalty", exhyphenpenalty,
2292 int_par(ex_hyphen_penalty_code));
2293 get_int_par("pdfadjustspacing", pdfadjustspacing,
2294 int_par(pdf_adjust_spacing_code));
2295 get_int_par("adjdemerits", adjdemerits, int_par(adj_demerits_code));
2296 get_int_par("pdfprotrudechars", pdfprotrudechars,
2297 int_par(pdf_protrude_chars_code));
2298 get_int_par("linepenalty", linepenalty, int_par(line_penalty_code));
2299 get_int_par("lastlinefit", lastlinefit, int_par(last_line_fit_code));
2300 get_int_par("doublehyphendemerits", doublehyphendemerits,
2301 int_par(double_hyphen_demerits_code));
2302 get_int_par("finalhyphendemerits", finalhyphendemerits,
2303 int_par(final_hyphen_demerits_code));
2304 get_int_par("hangafter", hangafter, int_par(hang_after_code));
2305 get_intx_par("interlinepenalty", interlinepenalty,int_par(inter_line_penalty_code),
2306 interlinepenalties, equiv(inter_line_penalties_loc));
2307 get_intx_par("clubpenalty", clubpenalty, int_par(club_penalty_code),
2308 clubpenalties, equiv(club_penalties_loc));
2309 get_intx_par("widowpenalty", widowpenalty, int_par(widow_penalty_code),
2310 widowpenalties, equiv(widow_penalties_loc));
2311 get_int_par("brokenpenalty", brokenpenalty, int_par(broken_penalty_code));
2312 get_dimen_par("emergencystretch", emergencystretch,
2313 dimen_par(emergency_stretch_code));
2314 get_dimen_par("hangindent", hangindent, dimen_par(hang_indent_code));
2315 get_dimen_par("hsize", hsize, dimen_par(hsize_code));
2316 get_glue_par("leftskip", leftskip, glue_par(left_skip_code));
2317 get_glue_par("rightskip", rightskip, glue_par(right_skip_code));
2318 get_dimen_par("pdfeachlineheight", pdfeachlineheight,
2319 dimen_par(pdf_each_line_height_code));
2320 get_dimen_par("pdfeachlinedepth", pdfeachlinedepth,
2321 dimen_par(pdf_each_line_depth_code));
2322 get_dimen_par("pdffirstlineheight", pdffirstlineheight,
2323 dimen_par(pdf_first_line_height_code));
2324 get_dimen_par("pdflastlinedepth", pdflastlinedepth,
2325 dimen_par(pdf_last_line_depth_code));
2326 get_dimen_par("pdfignoreddimen", pdfignoreddimen,
2327 dimen_par(pdf_ignored_dimen_code));
2328
2329 ext_do_line_break(paragraph_dir,
2330 pretolerance, tracingparagraphs, tolerance,
2331 emergencystretch,
2332 looseness, hyphenpenalty, exhyphenpenalty,
2333 pdfadjustspacing,
2334 parshape,
2335 adjdemerits, pdfprotrudechars,
2336 linepenalty, lastlinefit,
2337 doublehyphendemerits, finalhyphendemerits,
2338 hangindent, hsize, hangafter, leftskip, rightskip,
2339 pdfeachlineheight, pdfeachlinedepth,
2340 pdffirstlineheight, pdflastlinedepth,
2341 interlinepenalties,
2342 interlinepenalty, clubpenalty,
2343 clubpenalties,
2344 widowpenalties,
2345 widowpenalty, brokenpenalty,
2346 final_par_glue, pdfignoreddimen);
2347
2348 /* return the generated list, and its prevdepth */
2349 get_linebreak_info (&fewest_demerits, &actual_looseness) ;
2350 lua_nodelib_push_fast(L, vlink(cur_list.head_field));
2351 lua_newtable(L);
2352 lua_pushstring(L, "demerits");
2353 lua_pushnumber(L, fewest_demerits);
2354 lua_settable(L, -3);
2355 lua_pushstring(L, "looseness");
2356 lua_pushnumber(L, actual_looseness);
2357 lua_settable(L, -3);
2358 lua_pushstring(L, "prevdepth");
2359 lua_pushnumber(L, cur_list.prev_depth_field);
2360 lua_settable(L, -3);
2361 lua_pushstring(L, "prevgraf");
2362 lua_pushnumber(L, cur_list.pg_field);
2363 lua_settable(L, -3);
2364
2365 /* restore nest stack */
2366 vlink(temp_head) = save_vlink_tmp_head;
2367 pop_nest();
2368 if (parshape != equiv(par_shape_loc))
2369 flush_node(parshape);
2370 return 2;
2371 }
2372
tex_shipout(lua_State * L)2373 static int tex_shipout(lua_State * L)
2374 {
2375 int boxnum = get_box_id(L, 1);
2376 ship_out(static_pdf, box(boxnum), SHIPPING_PAGE);
2377 box(boxnum) = null;
2378 return 0;
2379 }
2380
tex_badness(lua_State * L)2381 static int tex_badness(lua_State * L)
2382 {
2383 scaled t,s;
2384 t=(int)lua_tonumber(L,1);
2385 s=(int)lua_tonumber(L,2);
2386 lua_pushnumber(L, badness(t,s));
2387 return 1;
2388 }
2389
2390
tex_run_boot(lua_State * L)2391 static int tex_run_boot(lua_State * L)
2392 {
2393 int n = lua_gettop(L);
2394 const char *format = NULL;
2395 if (n >= 1) {
2396 ini_version = 0;
2397 format = luaL_checkstring(L, 1);
2398 } else {
2399 ini_version = 1;
2400 }
2401 if (main_initialize()) { /* > 0 = failure */
2402 lua_pushboolean(L, 0); /* false */
2403 return 1;
2404 }
2405 if (format) {
2406 if (!zopen_w_input(&fmt_file, format, DUMP_FORMAT, FOPEN_RBIN_MODE)) {
2407 lua_pushboolean(L, 0); /* false */
2408 return 1;
2409 }
2410 if (!load_fmt_file(format)) {
2411 zwclose(fmt_file);
2412 lua_pushboolean(L, 0); /* false */
2413 return 1;
2414 }
2415 zwclose(fmt_file);
2416 }
2417 fix_date_and_time();
2418 /* if (format == NULL) */
2419 /* make_pdftex_banner(); */
2420 random_seed = (microseconds * 1000) + (epochseconds % 1000000);
2421 init_randoms(random_seed);
2422 initialize_math();
2423 fixup_selector(log_opened_global);
2424 check_texconfig_init();
2425 text_dir_ptr = new_dir(0);
2426 history = spotless; /* ready to go! */
2427 /* Initialize synctex primitive */
2428 synctexinitcommand();
2429 /* tex is ready to go, now */
2430 unhide_lua_table(Luas, "tex", tex_table_id);
2431 unhide_lua_table(Luas, "pdf", pdf_table_id);
2432 unhide_lua_table(Luas, "newtoken", newtoken_table_id);
2433 unhide_lua_table(Luas, "token", token_table_id);
2434 unhide_lua_table(Luas, "node", node_table_id);
2435
2436 lua_pushboolean(L, 1); /* true */
2437 return 1;
2438
2439 }
2440
2441 /* tex random generators */
tex_init_rand(lua_State * L)2442 static int tex_init_rand(lua_State * L)
2443 {
2444 int sp;
2445 if (!lua_isnumber(L, 1)) {
2446 luaL_error(L, "argument must be a number");
2447 return 0;
2448 }
2449 sp=(int)lua_tonumber(L, 1);
2450 init_randoms(sp);
2451 return 0;
2452 }
2453
tex_unif_rand(lua_State * L)2454 static int tex_unif_rand(lua_State * L)
2455 {
2456 int sp;
2457 if (!lua_isnumber(L, 1)) {
2458 luaL_error(L, "argument must be a number");
2459 return 0;
2460 }
2461 sp=(int)lua_tonumber(L, 1);
2462 lua_pushnumber(L, unif_rand(sp));
2463 return 1;
2464 }
2465
tex_norm_rand(lua_State * L)2466 static int tex_norm_rand(lua_State * L)
2467 {
2468 lua_pushnumber(L, norm_rand());
2469 return 1;
2470 }
2471
2472 /* Same as lua but with tex rng */
lua_math_random(lua_State * L)2473 static int lua_math_random (lua_State *L)
2474 {
2475 lua_Number rand_max = 0x7fffffff ;
2476 lua_Number r = unif_rand(rand_max) ;
2477 r = (r>=0 ? 0+r : 0-r) ;
2478 r = r / rand_max;
2479 switch (lua_gettop(L)) { /* check number of arguments */
2480 case 0: { /* no arguments */
2481 lua_pushnumber(L, r); /* Number between 0 and 1 */
2482 break;
2483 }
2484 case 1: { /* only upper limit */
2485 lua_Number u = luaL_checknumber(L, 1);
2486 luaL_argcheck(L, (lua_Number)1.0 <= u, 1, "interval is empty");
2487 lua_pushnumber(L, floor(r*u) + (lua_Number)(1.0)); /* [1, u] */
2488 break;
2489 }
2490 case 2: { /* lower and upper limits */
2491 lua_Number l = luaL_checknumber(L, 1);
2492 lua_Number u = luaL_checknumber(L, 2);
2493 luaL_argcheck(L, l <= u, 2, "interval is empty");
2494 lua_pushnumber(L, floor(r*(u-l+1)) + l); /* [l, u] */
2495 break;
2496 }
2497 default: return luaL_error(L, "wrong number of arguments");
2498 }
2499 return 1;
2500 }
2501
2502
2503
2504 /* Experimental code can either become permanent or disappear. It is
2505 undocumented and mostly present in the experimental branch but for
2506 practical reasons we also have the setup code in the regular binary.
2507 The experimental_code array is indexed by i with 1<= i <= max_experimental_code,
2508 position 0 is not used */
2509 int experimental_code[MAX_EXPERIMENTAL_CODE_SIZE] = { 0 };
2510
2511
set_experimental_code(lua_State * L)2512 static int set_experimental_code(lua_State *L)
2513 {
2514 int e, b, i ;
2515
2516 if (lua_isboolean(L,1)) {
2517 e = 0 ;
2518 b = lua_toboolean(L,1) ;
2519 } else if (lua_isnumber(L,1) && lua_isboolean(L,2)) {
2520 e = (int) lua_tonumber(L, 1);
2521 b = lua_toboolean(L,2) ;
2522 } else {
2523 return luaL_error(L, "boolean or number and boolean expected");
2524 }
2525 if (e==0) {
2526 for (i=1;i<=max_experimental_code;i++) {
2527 experimental_code[i] = b;
2528 }
2529 } else if (0<e && e<=max_experimental_code ) {
2530 experimental_code[e] = b;
2531 } else {
2532 return luaL_error(L, "first number out of range");
2533 }
2534 return 0;
2535 }
2536
tex_run_main(lua_State * L)2537 static int tex_run_main(lua_State * L)
2538 {
2539 (void) L;
2540 main_control();
2541 return 0;
2542 }
2543
tex_run_end(lua_State * L)2544 static int tex_run_end(lua_State * L)
2545 {
2546 (void) L;
2547 final_cleanup(); /* prepare for death */
2548 close_files_and_terminate();
2549 do_final_end();
2550 return 0;
2551 }
2552
tex_show_context(lua_State * L)2553 static int tex_show_context(lua_State * L)
2554 {
2555 (void) L;
2556 show_context();
2557 return 0;
2558 }
2559
init_tex_table(lua_State * L)2560 void init_tex_table(lua_State * L)
2561 {
2562 lua_createtable(L, 0, 3);
2563 lua_pushcfunction(L, tex_run_boot);
2564 lua_setfield(L, -2, "initialize");
2565 lua_pushcfunction(L, tex_run_main);
2566 lua_setfield(L, -2, "run");
2567 lua_pushcfunction(L, tex_run_end);
2568 lua_setfield(L, -2, "finish");
2569 lua_setglobal(L, "tex");
2570 }
2571
2572
2573
2574
2575 static const struct luaL_Reg texlib[] = {
2576 {"run", tex_run_main}, /* may be needed */
2577 {"finish", tex_run_end}, /* may be needed */
2578 {"write", luacwrite},
2579 {"print", luacprint},
2580 {"tprint", luactprint},
2581 {"error", texerror},
2582 {"sprint", luacsprint},
2583 {"set", settex},
2584 {"get", gettex},
2585 {"setdimen", setdimen},
2586 {"getdimen", getdimen},
2587 {"setskip", setskip},
2588 {"getskip", getskip},
2589 {"setattribute", setattribute},
2590 {"getattribute", getattribute},
2591 {"setcount", setcount},
2592 {"getcount", getcount},
2593 {"settoks", settoks},
2594 {"gettoks", gettoks},
2595 {"setbox", setbox},
2596 {"getbox", getbox},
2597 {"setlist", setlist},
2598 {"getlist", getlist},
2599 {"setnest", setnest},
2600 {"getnest", getnest},
2601 {"setcatcode", setcatcode},
2602 {"getcatcode", getcatcode},
2603 {"setdelcode", setdelcode},
2604 {"getdelcode", getdelcode},
2605 {"setlccode", setlccode},
2606 {"getlccode", getlccode},
2607 {"setmathcode", setmathcode},
2608 {"getmathcode", getmathcode},
2609 {"setsfcode", setsfcode},
2610 {"getsfcode", getsfcode},
2611 {"setuccode", setuccode},
2612 {"getuccode", getuccode},
2613 {"round", tex_roundnumber},
2614 {"scale", tex_scaletable},
2615 {"sp", tex_scaledimen},
2616 {"fontname", getfontname},
2617 {"fontidentifier", getfontidentifier},
2618 {"pdffontname", getpdffontname},
2619 {"pdffontobjnum", getpdffontobjnum},
2620 {"pdffontsize", getpdffontsize},
2621 {"uniformdeviate", getuniformdeviate},
2622 {"number", getnumber},
2623 {"romannumeral", getromannumeral},
2624 {"pdfpageref", getpdfpageref},
2625 {"pdfxformname", getpdfxformname},
2626 {"definefont", tex_definefont},
2627 {"hashtokens", tex_hashpairs},
2628 {"primitives", tex_primitives},
2629 {"extraprimitives", tex_extraprimitives},
2630 {"enableprimitives", tex_enableprimitives},
2631 {"shipout", tex_shipout},
2632 {"badness", tex_badness},
2633 {"setmath", tex_setmathparm},
2634 {"getmath", tex_getmathparm},
2635 {"linebreak", tex_run_linebreak},
2636 /* tex random generators */
2637 {"init_rand", tex_init_rand},
2638 {"uniform_rand",tex_unif_rand},
2639 {"normal_rand", tex_norm_rand},
2640 {"lua_math_randomseed", tex_init_rand}, /* syntactic sugar */
2641 {"lua_math_random", lua_math_random},
2642 {"set_experimental_code",set_experimental_code},
2643 {"show_context", tex_show_context},
2644 {NULL, NULL} /* sentinel */
2645 };
2646
luaopen_tex(lua_State * L)2647 int luaopen_tex(lua_State * L)
2648 {
2649 luaL_register(L, "tex", texlib);
2650 /* *INDENT-OFF* */
2651 make_table(L, "attribute", "tex.attribute" ,"getattribute", "setattribute");
2652 make_table(L, "skip", "tex.skip" ,"getskip", "setskip");
2653 make_table(L, "dimen", "tex.dimen" ,"getdimen", "setdimen");
2654 make_table(L, "count", "tex.count" ,"getcount", "setcount");
2655 make_table(L, "toks", "tex.toks" ,"gettoks", "settoks");
2656 make_table(L, "box", "tex.box" ,"getbox", "setbox");
2657 make_table(L, "sfcode", "tex.sfcode" ,"getsfcode", "setsfcode");
2658 make_table(L, "lccode", "tex.lccode" ,"getlccode", "setlccode");
2659 make_table(L, "uccode", "tex.uccode" ,"getuccode", "setuccode");
2660 make_table(L, "catcode", "tex.catcode" ,"getcatcode", "setcatcode");
2661 make_table(L, "mathcode", "tex.mathcode" ,"getmathcode", "setmathcode");
2662 make_table(L, "delcode", "tex.delcode" ,"getdelcode", "setdelcode");
2663 make_table(L, "lists", "tex.lists" ,"getlist", "setlist");
2664 make_table(L, "nest", "tex.nest" ,"getnest", "setnest");
2665 /* *INDENT-ON* */
2666 init_nest_lib(L);
2667 /* make the meta entries */
2668 /* fetch it back */
2669 luaL_newmetatable(L, "tex.meta");
2670 lua_pushstring(L, "__index");
2671 lua_pushcfunction(L, gettex);
2672 lua_settable(L, -3);
2673 lua_pushstring(L, "__newindex");
2674 lua_pushcfunction(L, settex);
2675 lua_settable(L, -3);
2676 lua_setmetatable(L, -2); /* meta to itself */
2677 /* initialize the I/O stack: */
2678 spindles = xmalloc(sizeof(spindle));
2679 spindle_index = 0;
2680 spindles[0].head = NULL;
2681 spindles[0].tail = NULL;
2682 spindle_size = 1;
2683 /* a somewhat odd place for this assert, maybe */
2684 assert(command_names[data_cmd].command_offset == data_cmd);
2685 return 1;
2686 }
2687