Prepare new Release
[tcc4lua.git] / tcc4lua.c
blobb0aeeedbd3e89bc28949095364bafefa7ce01526
1 /*
2 * Copyright (c) 2006-2007 Jérôme Vuarand
3 * Copyright (c) 2009 Miriam Ruiz
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 * THE SOFTWARE.
24 #include <lua.h>
25 #include <lauxlib.h>
26 #include <libtcc.h>
27 #include <stdlib.h>
28 #include <string.h>
30 #define LUATCC_DEBUG_LEVEL 2
32 #if LUATCC_DEBUG_LEVEL > 2
33 #define MSG_INFO printf
34 #else
35 #define MSG_INFO(...)
36 #endif
38 #if LUATCC_DEBUG_LEVEL > 1
39 #define MSG_WARNING printf
40 #else
41 #define MSG_WARNING(...)
42 #endif
44 #define MSG_ERROR printf
46 typedef struct S_LuaTCCState
48 TCCState* tcc;
49 void *mem;
50 #if LUATCC_DEBUG_LEVEL > 3
51 unsigned int id;
52 #endif
53 } LuaTCCState;
55 #if LUATCC_DEBUG_LEVEL > 3
56 static unsigned int last_id = 0;
57 #endif
59 static int busy_tcc = 0;
61 /* function context:compile(source [, chunkname]) return true end */
62 static int lua__tcc__compile(lua_State* L)
64 LuaTCCState* state;
65 TCCState* tcc;
66 const char* chunkname = NULL;
67 const char* code;
69 luaL_checktype(L, 1, LUA_TUSERDATA);
70 state = *(LuaTCCState**)lua_touserdata(L, 1);
71 tcc = state->tcc;
73 code = luaL_checkstring(L, 2);
75 if (lua_isstring(L, 3))
76 chunkname = lua_tostring(L, 3);
78 /* compile */
79 if (tcc_compile_named_string(tcc, code, chunkname))
81 return luaL_error(L, "unknown compilation error");
84 lua_pushboolean(L, 1);
85 return 1;
88 /* function context:add_library(libraryname) return true end */
89 static int lua__tcc__add_library(lua_State* L)
91 LuaTCCState* state;
92 TCCState* tcc;
93 const char* libname = NULL;
95 luaL_checktype(L, 1, LUA_TUSERDATA);
96 state = *(LuaTCCState**)lua_touserdata(L, 1);
97 tcc = state->tcc;
99 libname = luaL_checkstring(L, 2);
101 /* add libs */
102 if (tcc_add_library(tcc, libname))
103 return luaL_error(L, "can't load library %s", libname);
105 lua_pushboolean(L, 1);
106 return 1;
109 /* function context:relocate() return true end */
110 static int lua__tcc__relocate(lua_State* L)
112 LuaTCCState* state;
113 TCCState* tcc;
114 int size;
116 luaL_checktype(L, 1, LUA_TUSERDATA);
117 state = *(LuaTCCState**)lua_touserdata(L, 1);
118 tcc = state->tcc;
120 if (state->mem != NULL)
122 return luaL_error(L, "cannot relocate twice the same context");
125 /* get needed size of the code */
126 size = tcc_relocate(tcc, NULL);
127 if (size == -1)
129 return luaL_error(L, "unknown relocation (link) error");
132 state->mem = malloc(size);
133 tcc_relocate(tcc, state->mem);
135 busy_tcc = 0;
137 lua_pushboolean(L, 1);
138 return 1;
141 /* function context:get_symbol(symbolname) return symbol end */
142 static int lua__tcc__get_symbol(lua_State* L)
144 LuaTCCState* state;
145 TCCState* tcc;
146 const char* funcname = NULL;
147 int (*func)(int);
148 lua_CFunction f;
150 luaL_checktype(L, 1, LUA_TUSERDATA);
151 state = *(LuaTCCState**)lua_touserdata(L, 1);
152 tcc = state->tcc;
154 funcname = luaL_checkstring(L, 2);
156 func = tcc_get_symbol(tcc, funcname);
157 if (!func)
158 return luaL_error(L, "can't get symbol %s", funcname);
160 f = (lua_CFunction)func;
162 lua_pushcclosure(L, f, 0);
164 return 1;
167 /* function context:define_symbol(symbolname) return true end */
168 static int lua__tcc__define_symbol(lua_State* L)
170 LuaTCCState* state;
171 TCCState* tcc;
172 const char* defname = NULL;
173 const char* defvalue = NULL;
175 luaL_checktype(L, 1, LUA_TUSERDATA);
176 state = *(LuaTCCState**)lua_touserdata(L, 1);
177 tcc = state->tcc;
179 defname = luaL_checkstring(L, 2);
180 defvalue = luaL_checkstring(L, 3);
182 tcc_define_symbol(tcc, defname, defvalue);
184 lua_pushboolean(L, 1);
185 return 1;
188 /* function context:undefine_symbol(symbolname) return true end */
189 static int lua__tcc__undefine_symbol(lua_State* L)
191 LuaTCCState* state;
192 TCCState* tcc;
193 const char* defname = NULL;
195 luaL_checktype(L, 1, LUA_TUSERDATA);
196 state = *(LuaTCCState**)lua_touserdata(L, 1);
197 tcc = state->tcc;
199 defname = luaL_checkstring(L, 2);
201 tcc_undefine_symbol(tcc, defname);
203 lua_pushboolean(L, 1);
204 return 1;
207 /* function context:add_library_path(path) end */
208 static int lua__tcc__add_library_path(lua_State *L)
210 LuaTCCState* state;
211 TCCState* tcc;
212 const char* path;
214 luaL_checktype(L, 1, LUA_TUSERDATA);
215 state = *(LuaTCCState**)lua_touserdata(L, 1);
216 tcc = state->tcc;
218 path = luaL_checkstring (L, 2);
220 tcc_add_library_path(tcc, path);
222 return 0;
225 /* function context:add_include_path(path) end */
226 static int lua__tcc__add_include_path(lua_State *L)
228 LuaTCCState* state;
229 TCCState* tcc;
230 const char* path;
232 luaL_checktype(L, 1, LUA_TUSERDATA);
233 state = *(LuaTCCState**)lua_touserdata(L, 1);
234 tcc = state->tcc;
236 path = luaL_checkstring (L, 2);
238 tcc_add_include_path(tcc, path);
240 return 0;
243 static int lua__tcc___gc(lua_State* L)
245 LuaTCCState** pstate;
246 MSG_INFO("TCC: Garbage Collector\n");
248 luaL_checktype(L, 1, LUA_TUSERDATA);
249 pstate = (LuaTCCState**)lua_touserdata(L, 1);
251 if (pstate && *pstate)
253 #if LUATCC_DEBUG_LEVEL > 3
254 MSG_INFO("TCC: - Deleting state #%d\n", (*pstate)->id);
255 #endif
256 if ((*pstate)->tcc != NULL)
258 tcc_delete((*pstate)->tcc);
259 (*pstate)->tcc = NULL;
261 if ((*pstate)->mem != NULL)
263 free((*pstate)->mem);
264 (*pstate)->mem = NULL;
266 free(*pstate);
269 return 0;
272 static const struct luaL_reg tcc_methods[] = {
273 {"compile", lua__tcc__compile},
274 {"add_library", lua__tcc__add_library},
275 {"relocate", lua__tcc__relocate},
276 {"get_symbol", lua__tcc__get_symbol},
277 {"define_symbol", lua__tcc__define_symbol},
278 {"undefine_symbol", lua__tcc__undefine_symbol},
279 {"add_library_path", lua__tcc__add_library_path},
280 {"add_include_path", lua__tcc__add_include_path},
281 {NULL, NULL}
284 void luatcc__error_func(void* opaque, const char* msg)
286 luaL_error((lua_State*)opaque, "%s", msg);
289 static int lua__new(lua_State* L)
291 MSG_INFO("TCC: New TCC Context\n");
293 if (busy_tcc)
294 return luaL_error(L, "state compilation needs to be finished before creating new ones");
296 LuaTCCState* state = malloc(sizeof(LuaTCCState));
297 memset(state, 0, sizeof(LuaTCCState));
298 state->mem = NULL;
300 state->tcc = tcc_new();
301 if (!state->tcc)
302 return luaL_error(L, "can't create tcc state");
304 #if LUATCC_DEBUG_LEVEL > 3
305 state->id = ++last_id;
306 MSG_INFO("TCC: + Creating state #%d\n", state->id);
307 #endif
309 busy_tcc = 1;
311 tcc_set_output_type(state->tcc, TCC_OUTPUT_MEMORY);
312 tcc_set_error_func(state->tcc, (void*)L, luatcc__error_func);
314 LuaTCCState** pstate = (LuaTCCState**)lua_newuserdata(L, sizeof(LuaTCCState*));
315 *pstate = state;
316 lua_newtable(L); /* Metatable */
317 lua_newtable(L); /* __index */
318 luaL_register(L, 0, tcc_methods);
319 lua_setfield(L, -2, "__index");
320 lua_pushcfunction(L, lua__tcc___gc);
321 lua_setfield(L, -2, "__gc");
322 lua_setmetatable(L, -2);
324 return 1;
327 static const struct luaL_reg module_functions[] = {
328 {"new", lua__new},
329 {NULL, NULL}
332 MODULE_API int luaopen_module(lua_State *L)
334 lua_getglobal(L, "module");
335 lua_pushvalue(L, 1);
336 lua_call(L, 1, 0);
338 lua_pushvalue(L, LUA_ENVIRONINDEX);
339 luaL_register(L, 0, module_functions);
341 return 0;