synch with TL 37803
[luatex.git] / source / texk / web2c / luatexdir / lua / ltokenlib.c
blobfd3edb2921f767cfaf980c9bfae55f741385ec63
1 /* ltokenlib.c
3 Copyright 2006-2012 Taco Hoekwater <taco@luatex.org>
5 This file is part of LuaTeX.
7 LuaTeX is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2 of the License, or (at your
10 option) any later version.
12 LuaTeX is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 License for more details.
17 You should have received a copy of the GNU General Public License along
18 with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */
20 #include "ptexlib.h"
21 #include "lua/luatex-api.h"
24 #define is_valid_token(L,i) (lua_istable(L,i) && lua_rawlen(L,i)==3)
25 #define get_token_cmd(L,i) lua_rawgeti(L,i,1)
26 #define get_token_chr(L,i) lua_rawgeti(L,i,2)
27 #define get_token_cs(L,i) lua_rawgeti(L,i,3)
28 #define is_active_string(s) (strlen((char *)s)>3 && *s==0xEF && *(s+1)==0xBF && *(s+2)==0xBF)
31 static unsigned char *get_cs_text(int cs)
33 if (cs == null_cs)
34 return (unsigned char *) xstrdup("\\csname\\endcsname");
35 else if ((cs_text(cs) < 0) || (cs_text(cs) >= str_ptr))
36 return (unsigned char *) xstrdup("");
37 else
38 return (unsigned char *) makecstring(cs_text(cs));
42 static int test_expandable(lua_State * L)
44 int cmd = -1;
45 if (is_valid_token(L, -1)) {
46 get_token_cmd(L, -1);
47 if (lua_isnumber(L, -1)) {
48 cmd = (int) lua_tointeger(L, -1);
49 } else if (lua_isstring(L, -1)) {
50 cmd = get_command_id(lua_tostring(L, -1));
52 if (cmd > max_command_cmd) {
53 lua_pushboolean(L, 1);
54 } else {
55 lua_pushboolean(L, 0);
57 } else {
58 lua_pushnil(L);
60 return 1;
64 static int test_protected(lua_State * L)
66 int chr = -1;
67 if (is_valid_token(L, -1)) {
68 get_token_chr(L, -1);
69 if (lua_isnumber(L, -1)) {
70 chr = (int) lua_tointeger(L, -1);
71 } else if (lua_isstring(L, -1)) {
72 chr = get_command_id(lua_tostring(L, -1));
74 if (token_info(token_link(chr)) == protected_token) {
75 lua_pushboolean(L, 1);
76 } else {
77 lua_pushboolean(L, 0);
79 } else {
80 lua_pushnil(L);
82 return 1;
85 static int test_activechar(lua_State * L)
87 if (is_valid_token(L, -1)) {
88 unsigned char *s;
89 int cs = 0;
90 get_token_cs(L, -1);
91 if (lua_isnumber(L, -1)) {
92 cs = (int) lua_tointeger(L, -1);
94 lua_pop(L, 1);
95 if (cs != 0 && ((s = get_cs_text(cs)) != (unsigned char *) NULL)) {
96 if (is_active_string(s)) {
97 free(s);
98 lua_pushboolean(L, 1);
99 return 1;
101 free(s);
104 lua_pushboolean(L, 0);
105 return 1;
109 static int run_get_command_name(lua_State * L)
111 int cs;
112 if (is_valid_token(L, -1)) {
113 get_token_cmd(L, -1);
114 if (lua_isnumber(L, -1)) {
115 cs = (int) lua_tointeger(L, -1);
116 lua_pushstring(L, command_names[cs].cmd_name);
117 } else {
118 lua_pushstring(L, "");
120 } else {
121 lua_pushnil(L);
123 return 1;
127 static int run_get_csname_name(lua_State * L)
129 int cs /*, cmd*/;
130 unsigned char *s;
131 if (is_valid_token(L, -1)) {
132 get_token_cmd(L, -1);
134 if (lua_isnumber(L, -1)) {
135 cmd = (int) lua_tointeger(L, -1);
138 lua_pop(L, 1);
139 cs = 0;
140 get_token_cs(L, -1);
141 if (lua_isnumber(L, -1)) {
142 cs = (int) lua_tointeger(L, -1);
144 lua_pop(L, 1);
146 if (cs != 0 && ((s = get_cs_text(cs)) != (unsigned char *) NULL)) {
147 if (is_active_string(s))
148 lua_pushstring(L, (char *) (s + 3));
149 else
150 lua_pushstring(L, (char *) s);
151 } else {
152 lua_pushstring(L, "");
154 } else {
155 lua_pushnil(L);
157 return 1;
160 static int run_get_command_id(lua_State * L)
162 int cs = -1;
163 if (lua_isstring(L, -1)) {
164 cs = get_command_id(lua_tostring(L, -1));
166 lua_pushnumber(L, cs);
167 return 1;
171 static int run_get_csname_id(lua_State * L)
173 const char *s;
174 size_t k, cs = 0;
175 if (lua_isstring(L, -1)) {
176 s = lua_tolstring(L, -1, &k);
177 cs = (size_t) string_lookup(s, k);
179 lua_pushnumber(L, (lua_Number) cs);
180 return 1;
184 void make_token_table(lua_State * L, int cmd, int chr, int cs)
186 lua_createtable(L, 3, 0);
187 lua_pushnumber(L, cmd);
188 lua_rawseti(L, -2, 1);
189 lua_pushnumber(L, chr);
190 lua_rawseti(L, -2, 2);
191 lua_pushnumber(L, cs);
192 lua_rawseti(L, -2, 3);
195 static int run_get_next(lua_State * L)
197 int save_nncs;
198 save_nncs = no_new_control_sequence;
199 no_new_control_sequence = 0;
200 get_next();
201 no_new_control_sequence = save_nncs;
202 make_token_table(L, cur_cmd, cur_chr, cur_cs);
203 return 1;
206 static int run_expand(lua_State * L)
208 (void) L;
209 expand();
210 return 0;
214 static int run_lookup(lua_State * L)
216 const char *s;
217 size_t l;
218 int cs, cmd, chr;
219 int save_nncs;
220 if (lua_isstring(L, -1)) {
221 s = lua_tolstring(L, -1, &l);
222 if (l > 0) {
223 save_nncs = no_new_control_sequence;
224 no_new_control_sequence = true;
225 cs = id_lookup((last + 1), (int) l); /* cleans up the lookup buffer */
226 cs = string_lookup(s, l);
227 cmd = eq_type(cs);
228 chr = equiv(cs);
229 make_token_table(L, cmd, chr, cs);
230 no_new_control_sequence = save_nncs;
231 return 1;
234 lua_newtable(L);
235 return 1;
238 static int run_build(lua_State * L)
240 int cmd, chr, cs;
241 if (lua_isnumber(L, 1)) {
242 cs = 0;
243 chr = (int) lua_tointeger(L, 1);
244 cmd = (int) luaL_optinteger(L, 2, get_char_cat_code(chr));
245 if (cmd == 0 || cmd == 9 || cmd == 14 || cmd == 15) {
246 fprintf(stdout,
247 "\n\nluatex error: not a good token.\nCatcode %i can not be returned, so I replaced it by 12 (other)",
248 (int) cmd);
249 error();
250 cmd = 12;
252 if (cmd == 13) {
253 cs = active_to_cs(chr, false);
254 cmd = eq_type(cs);
255 chr = equiv(cs);
257 make_token_table(L, cmd, chr, cs);
258 return 1;
259 } else {
260 return run_lookup(L);
265 static const struct luaL_Reg tokenlib[] = {
266 {"get_next", run_get_next},
267 {"expand", run_expand},
268 {"lookup", run_lookup},
269 {"create", run_build},
270 {"is_expandable", test_expandable},
271 {"is_activechar", test_activechar},
272 {"is_protected", test_protected},
273 {"csname_id", run_get_csname_id},
274 {"csname_name", run_get_csname_name},
275 {"command_name", run_get_command_name},
276 {"command_id", run_get_command_id},
277 {NULL, NULL} /* sentinel */
280 int luaopen_token(lua_State * L)
282 luaL_register(L, "token", tokenlib);
283 return 1;