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