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/>. */
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
)
34 return (unsigned char *) xstrdup("\\csname\\endcsname");
35 else if ((cs_text(cs
) < 0) || (cs_text(cs
) >= str_ptr
))
36 return (unsigned char *) xstrdup("");
38 return (unsigned char *) makecstring(cs_text(cs
));
42 static int test_expandable(lua_State
* L
)
45 if (is_valid_token(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);
55 lua_pushboolean(L
, 0);
64 static int test_protected(lua_State
* L
)
67 if (is_valid_token(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);
77 lua_pushboolean(L
, 0);
85 static int test_activechar(lua_State
* L
)
87 if (is_valid_token(L
, -1)) {
91 if (lua_isnumber(L
, -1)) {
92 cs
= (int) lua_tointeger(L
, -1);
95 if (cs
!= 0 && ((s
= get_cs_text(cs
)) != (unsigned char *) NULL
)) {
96 if (is_active_string(s
)) {
98 lua_pushboolean(L
, 1);
104 lua_pushboolean(L
, 0);
109 static int run_get_command_name(lua_State
* L
)
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
);
118 lua_pushstring(L
, "");
127 static int run_get_csname_name(lua_State
* L
)
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);
141 if (lua_isnumber(L
, -1)) {
142 cs
= (int) lua_tointeger(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));
150 lua_pushstring(L
, (char *) s
);
152 lua_pushstring(L
, "");
160 static int run_get_command_id(lua_State
* L
)
163 if (lua_isstring(L
, -1)) {
164 cs
= get_command_id(lua_tostring(L
, -1));
166 lua_pushnumber(L
, cs
);
171 static int run_get_csname_id(lua_State
* L
)
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
);
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
)
198 save_nncs
= no_new_control_sequence
;
199 no_new_control_sequence
= 0;
201 no_new_control_sequence
= save_nncs
;
202 make_token_table(L
, cur_cmd
, cur_chr
, cur_cs
);
206 static int run_expand(lua_State
* L
)
214 static int run_lookup(lua_State
* L
)
220 if (lua_isstring(L
, -1)) {
221 s
= lua_tolstring(L
, -1, &l
);
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
);
229 make_token_table(L
, cmd
, chr
, cs
);
230 no_new_control_sequence
= save_nncs
;
238 static int run_build(lua_State
* L
)
241 if (lua_isnumber(L
, 1)) {
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) {
247 "\n\nluatex error: not a good token.\nCatcode %i can not be returned, so I replaced it by 12 (other)",
253 cs
= active_to_cs(chr
, false);
257 make_token_table(L
, cmd
, chr
, cs
);
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
);