1% luatoken.w
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@ @c
21
22
23#include "ptexlib.h"
24#include "lua/luatex-api.h"
25
26@ @c
27command_item command_names[] = {
28    {"relax", relax_cmd, NULL},
29    {"left_brace", left_brace_cmd, NULL},
30    {"right_brace", right_brace_cmd, NULL},
31    {"math_shift", math_shift_cmd, NULL},
32    {"tab_mark", tab_mark_cmd, NULL},
33    {"car_ret", car_ret_cmd, NULL},
34    {"mac_param", mac_param_cmd, NULL},
35    {"sup_mark", sup_mark_cmd, NULL},
36    {"sub_mark", sub_mark_cmd, NULL},
37    {"endv", endv_cmd, NULL},
38    {"spacer", spacer_cmd, NULL},
39    {"letter", letter_cmd, NULL},
40    {"other_char", other_char_cmd, NULL},
41    {"par_end", par_end_cmd, NULL},
42    {"stop", stop_cmd, NULL},
43    {"delim_num", delim_num_cmd, NULL},
44    {"char_num", char_num_cmd, NULL},
45    {"math_char_num", math_char_num_cmd, NULL},
46    {"mark", mark_cmd, NULL},
47    {"xray", xray_cmd, NULL},
48    {"make_box", make_box_cmd, NULL},
49    {"hmove", hmove_cmd, NULL},
50    {"vmove", vmove_cmd, NULL},
51    {"un_hbox", un_hbox_cmd, NULL},
52    {"un_vbox", un_vbox_cmd, NULL},
53    {"remove_item", remove_item_cmd, NULL},
54    {"hskip", hskip_cmd, NULL},
55    {"vskip", vskip_cmd, NULL},
56    {"mskip", mskip_cmd, NULL},
57    {"kern", kern_cmd, NULL},
58    {"mkern", mkern_cmd, NULL},
59    {"leader_ship", leader_ship_cmd, NULL},
60    {"halign", halign_cmd, NULL},
61    {"valign", valign_cmd, NULL},
62    {"no_align", no_align_cmd, NULL},
63    {"vrule", vrule_cmd, NULL},
64    {"hrule", hrule_cmd, NULL},
65    {"insert", insert_cmd, NULL},
66    {"vadjust", vadjust_cmd, NULL},
67    {"ignore_spaces", ignore_spaces_cmd, NULL},
68    {"after_assignment", after_assignment_cmd, NULL},
69    {"after_group", after_group_cmd, NULL},
70    {"break_penalty", break_penalty_cmd, NULL},
71    {"start_par", start_par_cmd, NULL},
72    {"ital_corr", ital_corr_cmd, NULL},
73    {"accent", accent_cmd, NULL},
74    {"math_accent", math_accent_cmd, NULL},
75    {"discretionary", discretionary_cmd, NULL},
76    {"eq_no", eq_no_cmd, NULL},
77    {"left_right", left_right_cmd, NULL},
78    {"math_comp", math_comp_cmd, NULL},
79    {"limit_switch", limit_switch_cmd, NULL},
80    {"above", above_cmd, NULL},
81    {"math_style", math_style_cmd, NULL},
82    {"math_choice", math_choice_cmd, NULL},
83    {"non_script", non_script_cmd, NULL},
84    {"vcenter", vcenter_cmd, NULL},
85    {"case_shift", case_shift_cmd, NULL},
86    {"message", message_cmd, NULL},
87    {"extension", extension_cmd, NULL},
88    {"in_stream", in_stream_cmd, NULL},
89    {"begin_group", begin_group_cmd, NULL},
90    {"end_group", end_group_cmd, NULL},
91    {"omit", omit_cmd, NULL},
92    {"ex_space", ex_space_cmd, NULL},
93    {"no_boundary", no_boundary_cmd, NULL},
94    {"radical", radical_cmd, NULL},
95    {"super_sub_script", super_sub_script_cmd, NULL},
96    {"math_shift_cs", math_shift_cs_cmd, NULL},
97    {"end_cs_name", end_cs_name_cmd, NULL},
98    {"char_ghost", char_ghost_cmd, NULL},
99    {"assign_local_box", assign_local_box_cmd, NULL},
100    {"char_given", char_given_cmd, NULL},
101    {"math_given", math_given_cmd, NULL},
102    {"xmath_given", xmath_given_cmd, NULL},
103    {"last_item", last_item_cmd, NULL},
104    {"toks_register", toks_register_cmd, NULL},
105    {"assign_toks", assign_toks_cmd, NULL},
106    {"assign_int", assign_int_cmd, NULL},
107    {"assign_attr", assign_attr_cmd, NULL},
108    {"assign_dimen", assign_dimen_cmd, NULL},
109    {"assign_glue", assign_glue_cmd, NULL},
110    {"assign_mu_glue", assign_mu_glue_cmd, NULL},
111    {"assign_font_dimen", assign_font_dimen_cmd, NULL},
112    {"assign_font_int", assign_font_int_cmd, NULL},
113    {"set_aux", set_aux_cmd, NULL},
114    {"set_prev_graf", set_prev_graf_cmd, NULL},
115    {"set_page_dimen", set_page_dimen_cmd, NULL},
116    {"set_page_int", set_page_int_cmd, NULL},
117    {"set_box_dimen", set_box_dimen_cmd, NULL},
118    {"set_tex_shape", set_tex_shape_cmd, NULL},
119    {"set_etex_shape", set_etex_shape_cmd, NULL},
120    {"def_char_code", def_char_code_cmd, NULL},
121    {"def_del_code", def_del_code_cmd, NULL},
122    {"extdef_math_code", extdef_math_code_cmd, NULL},
123    {"extdef_del_code", extdef_del_code_cmd, NULL},
124    {"def_family", def_family_cmd, NULL},
125    {"set_math_param", set_math_param_cmd, NULL},
126    {"set_font", set_font_cmd, NULL},
127    {"def_font", def_font_cmd, NULL},
128    {"register", register_cmd, NULL},
129    {"assign_box_dir", assign_box_dir_cmd, NULL},
130    {"assign_dir", assign_dir_cmd, NULL},
131    {"advance", advance_cmd, NULL},
132    {"multiply", multiply_cmd, NULL},
133    {"divide", divide_cmd, NULL},
134    {"prefix", prefix_cmd, NULL},
135    {"let", let_cmd, NULL},
136    {"shorthand_def", shorthand_def_cmd, NULL},
137    {"read_to_cs", read_to_cs_cmd, NULL},
138    {"def", def_cmd, NULL},
139    {"set_box", set_box_cmd, NULL},
140    {"hyph_data", hyph_data_cmd, NULL},
141    {"set_interaction", set_interaction_cmd, NULL},
142    {"letterspace_font", letterspace_font_cmd, NULL},
143    {"pdf_copy_font", pdf_copy_font_cmd, NULL},
144    {"undefined_cs", undefined_cs_cmd, NULL},
145    {"expand_after", expand_after_cmd, NULL},
146    {"no_expand", no_expand_cmd, NULL},
147    {"input", input_cmd, NULL},
148    {"if_test", if_test_cmd, NULL},
149    {"fi_or_else", fi_or_else_cmd, NULL},
150    {"cs_name", cs_name_cmd, NULL},
151    {"convert", convert_cmd, NULL},
152    {"the", the_cmd, NULL},
153    {"top_bot_mark", top_bot_mark_cmd, NULL},
154    {"call", call_cmd, NULL},
155    {"long_call", long_call_cmd, NULL},
156    {"outer_call", outer_call_cmd, NULL},
157    {"long_outer_call", long_outer_call_cmd, NULL},
158    {"end_template", end_template_cmd, NULL},
159    {"dont_expand", dont_expand_cmd, NULL},
160    {"glue_ref", glue_ref_cmd, NULL},
161    {"shape_ref", shape_ref_cmd, NULL},
162    {"box_ref", box_ref_cmd, NULL},
163    {"data", data_cmd, NULL},
164    {NULL, 0, NULL}
165};
166
167
168@ @c
169int get_command_id(const char *s)
170{
171    int i;
172    int cmd = -1;
173    for (i = 0; command_names[i].cmd_name != NULL; i++) {
174        if (strcmp(s, command_names[i].cmd_name) == 0)
175            break;
176    }
177    if (command_names[i].cmd_name != NULL) {
178        cmd = i;
179    }
180    return cmd;
181}
182
183@ @c
184static int get_cur_cmd(lua_State * L)
185{
186    int r = 0;
187    size_t len = lua_rawlen(L, -1);
188    cur_cs = 0;
189    if (len == 3 || len == 2) {
190        r = 1;
191        lua_rawgeti(L, -1, 1);
192        cur_cmd = (int) lua_tointeger(L, -1);
193        lua_rawgeti(L, -2, 2);
194        cur_chr = (halfword) lua_tointeger(L, -1);
195        if (len == 3) {
196            lua_rawgeti(L, -3, 3);
197            cur_cs = (halfword) lua_tointeger(L, -1);
198        }
199        lua_pop(L, (int) len);
200        if (cur_cs == 0)
201            cur_tok = token_val(cur_cmd, cur_chr);
202        else
203            cur_tok = cs_token_flag + cur_cs;
204    }
205    return r;
206}
207
208
209@ @c
210static int token_from_lua(lua_State * L)
211{
212    int cmd, chr;
213    int cs = 0;
214    size_t len = lua_rawlen(L, -1);
215    if (len == 3 || len == 2) {
216        lua_rawgeti(L, -1, 1);
217        cmd = (int) lua_tointeger(L, -1);
218        lua_rawgeti(L, -2, 2);
219        chr = (int) lua_tointeger(L, -1);
220        if (len == 3) {
221            lua_rawgeti(L, -3, 3);
222            cs = (int) lua_tointeger(L, -1);
223        }
224        lua_pop(L, (int) len);
225        if (cs == 0) {
226            return token_val(cmd, chr);
227        } else {
228            return cs_token_flag + cs;
229        }
230    }
231    return -1;
232}
233
234@ @c
235static int get_cur_cs(lua_State * L)
236{
237    const char *s;
238    unsigned j;
239    size_t l;
240    int cs;
241    int save_nncs;
242    int ret;
243    ret = 0;
244    cur_cs = 0;
245    lua_getfield(L, -1, "name");
246    if (lua_isstring(L, -1)) {
247        s = lua_tolstring(L, -1, &l);
248        if (l > 0) {
249            if ((last + (int) l) > buf_size)
250                check_buffer_overflow((last + (int) l));
251            for (j = 0; j < l; j++) {
252                buffer[(unsigned) last + 1 + j] = (packed_ASCII_code) * s++;
253            }
254            save_nncs = no_new_control_sequence;
255            no_new_control_sequence = false;
256            cs = id_lookup((last + 1), (int) l);
257            cur_tok = cs_token_flag + cs;
258            cur_cmd = eq_type(cs);
259            cur_chr = equiv(cs);
260            no_new_control_sequence = save_nncs;
261            ret = 1;
262        }
263    }
264    lua_pop(L, 1);
265    return ret;
266}
267
268@ @c
269void tokenlist_to_lua(lua_State * L, int p)
270{
271    int cmd, chr, cs;
272    int v;
273    int i = 1;
274    v = p;
275    while (v != null && v < (int) fix_mem_end) {
276        i++;
277        v = token_link(v);
278    }
279    i = 1;
280    lua_createtable(L, i, 0);
281    while (p != null && p < (int) fix_mem_end) {
282        if (token_info(p) >= cs_token_flag) {
283            cs = token_info(p) - cs_token_flag;
284            cmd = eq_type(cs);
285            chr = equiv(cs);
286            make_token_table(L, cmd, chr, cs);
287        } else {
288            cmd = token_cmd(token_info(p));
289            chr = token_chr(token_info(p));
290            make_token_table(L, cmd, chr, 0);
291        }
292        lua_rawseti(L, -2, i++);
293        p = token_link(p);
294    }
295}
296
297@ @c
298void tokenlist_to_luastring(lua_State * L, int p)
299{
300    int l;
301    char *s;
302    s = tokenlist_to_cstring(p, 1, &l);
303    lua_pushlstring(L, s, (size_t) l);
304}
305
306
307@ @c
308int tokenlist_from_lua(lua_State * L)
309{
310    const char *s;
311    int tok;
312    size_t i, j;
313    halfword p, q, r;
314    r = get_avail();
315    token_info(r) = 0;          /* ref count */
316    token_link(r) = null;
317    p = r;
318    if (lua_istable(L, -1)) {
319        j = lua_rawlen(L, -1);
320        if (j > 0) {
321            for (i = 1; i <= j; i++) {
322                lua_rawgeti(L, -1, (int) i);
323                tok = token_from_lua(L);
324                if (tok >= 0) {
325                    store_new_token(tok);
326                }
327                lua_pop(L, 1);
328            };
329        }
330        return r;
331    } else if (lua_isstring(L, -1)) {
332        s = lua_tolstring(L, -1, &j);
333        for (i = 0; i < j; i++) {
334            if (s[i] == 32) {
335                tok = token_val(10, s[i]);
336            } else {
337                int j1 = (int) str2uni((const unsigned char *) (s + i));
338                i = i + (size_t) (utf8_size(j1) - 1);
339                tok = token_val(12, j1);
340            }
341            store_new_token(tok);
342        }
343        return r;
344    } else {
345        free_avail(r);
346        return null;
347    }
348}
349
350@ @c
351void do_get_token_lua(int callback_id)
352{
353    lua_State *L = Luas;
354    while (1) {
355        if (!get_callback(L, callback_id)) {
356            get_next();
357            lua_pop(L, 2);      /* the not-a-function callback and the container */
358            break;
359        }
360        if (lua_pcall(L, 0, 1, 0) != 0) {       /* no arg, 1 result */
361            tex_error(lua_tostring(L, -1), NULL);
362            lua_pop(L, 2);      /* container and result */
363            break;
364        }
365        if (lua_istable(L, -1)) {
366            lua_rawgeti(L, -1, 1);
367            if (lua_istable(L, -1)) {   /* container, result, result[1] */
368                int p, q, r;
369                size_t i, j;
370                lua_pop(L, 1);  /* container, result */
371                /* build a token list */
372                r = get_avail();
373                p = r;
374                j = lua_rawlen(L, -1);
375                if (j > 0) {
376                    for (i = 1; i <= j; i++) {
377                        lua_rawgeti(L, -1, (int) i);
378                        if (get_cur_cmd(L) || get_cur_cs(L)) {
379                            store_new_token(cur_tok);
380                        }
381                        lua_pop(L, 1);
382                    }
383                }
384                if (p != r) {
385                    p = token_link(r);
386                    free_avail(r);
387                    begin_token_list(p, inserted);
388                    cur_input.nofilter_field = true;
389                    get_next();
390                } else {
391                    tex_error("error: illegal or empty token list returned",
392                              NULL);
393                }
394                lua_pop(L, 2);
395                break;
396            } else {            /* container, result, whatever */
397                lua_pop(L, 1);  /* container, result */
398                if (get_cur_cmd(L) || get_cur_cs(L)) {
399                    lua_pop(L, 2);
400                    break;
401                } else {
402                    lua_pop(L, 2);
403                    continue;
404                }
405            }
406        } else {
407            lua_pop(L, 2);      /* container, result */
408        }
409    }
410    return;
411}
412