diff options
author | David Walter Seikel | 2014-05-23 13:22:36 +1000 |
---|---|---|
committer | David Walter Seikel | 2014-05-23 13:22:36 +1000 |
commit | f97c73bd1e43a0eb32ad8dc43fc28f6e40b28f38 (patch) | |
tree | df45770acc4a26d56e45bc7ae3420cddb6522d15 /src/libraries | |
parent | TODO-- (diff) | |
download | SledjHamr-f97c73bd1e43a0eb32ad8dc43fc28f6e40b28f38.zip SledjHamr-f97c73bd1e43a0eb32ad8dc43fc28f6e40b28f38.tar.gz SledjHamr-f97c73bd1e43a0eb32ad8dc43fc28f6e40b28f38.tar.bz2 SledjHamr-f97c73bd1e43a0eb32ad8dc43fc28f6e40b28f38.tar.xz |
Rewrite the LuaSL script running stuff (twice lol), plus much related tweakage and cleanups.
Diffstat (limited to 'src/libraries')
-rw-r--r-- | src/libraries/LumbrJack.c | 7 | ||||
-rw-r--r-- | src/libraries/Runnr.c | 593 | ||||
-rw-r--r-- | src/libraries/Runnr.h | 70 | ||||
-rw-r--r-- | src/libraries/SledjHamr.c | 2 |
4 files changed, 634 insertions, 38 deletions
diff --git a/src/libraries/LumbrJack.c b/src/libraries/LumbrJack.c index 56d4c50..27ca524 100644 --- a/src/libraries/LumbrJack.c +++ b/src/libraries/LumbrJack.c | |||
@@ -15,7 +15,7 @@ int HamrTime(char *argv0, void *main, int logDom) | |||
15 | { | 15 | { |
16 | Eina_Array *path; | 16 | Eina_Array *path; |
17 | char *env, name[PATH_MAX], cwd[PATH_MAX], temp[PATH_MAX * 2]; | 17 | char *env, name[PATH_MAX], cwd[PATH_MAX], temp[PATH_MAX * 2]; |
18 | int i, len = strlen(argv0); | 18 | int i, len; |
19 | 19 | ||
20 | if (!eina_init()) | 20 | if (!eina_init()) |
21 | { | 21 | { |
@@ -30,6 +30,7 @@ int HamrTime(char *argv0, void *main, int logDom) | |||
30 | logDom = loggingStartup(name, logDom); | 30 | logDom = loggingStartup(name, logDom); |
31 | eina_array_free(path); | 31 | eina_array_free(path); |
32 | 32 | ||
33 | len = strlen(name); | ||
33 | temp[len] = 0; | 34 | temp[len] = 0; |
34 | cwd[len] = 0; | 35 | cwd[len] = 0; |
35 | for (i = 0; i < len; i++) | 36 | for (i = 0; i < len; i++) |
@@ -39,9 +40,7 @@ int HamrTime(char *argv0, void *main, int logDom) | |||
39 | } | 40 | } |
40 | 41 | ||
41 | if (!(prefix = eina_prefix_new(argv0, main, temp, cwd, "checkme.txt", PACKAGE_BIN_DIR, PACKAGE_LIB_DIR, PACKAGE_DATA_DIR, PACKAGE_LOCALE_DIR))) | 42 | if (!(prefix = eina_prefix_new(argv0, main, temp, cwd, "checkme.txt", PACKAGE_BIN_DIR, PACKAGE_LIB_DIR, PACKAGE_DATA_DIR, PACKAGE_LOCALE_DIR))) |
42 | { | ||
43 | PC("Can't find application prefix!"); | 43 | PC("Can't find application prefix!"); |
44 | } | ||
45 | 44 | ||
46 | PD("%s is installed in %s", name, eina_prefix_get(prefix)); | 45 | PD("%s is installed in %s", name, eina_prefix_get(prefix)); |
47 | PD("The binaries are in %s", eina_prefix_bin_get(prefix)); | 46 | PD("The binaries are in %s", eina_prefix_bin_get(prefix)); |
@@ -67,7 +66,7 @@ const char *prefix_get() {return eina_prefix_get(prefix);} | |||
67 | const char *prefix_bin_get() {return eina_prefix_bin_get(prefix);} | 66 | const char *prefix_bin_get() {return eina_prefix_bin_get(prefix);} |
68 | const char *prefix_data_get() {return eina_prefix_data_get(prefix);} | 67 | const char *prefix_data_get() {return eina_prefix_data_get(prefix);} |
69 | const char *prefix_lib_get() {return eina_prefix_lib_get(prefix);} | 68 | const char *prefix_lib_get() {return eina_prefix_lib_get(prefix);} |
70 | const char *prefix_locale_get() {return eina_prefix_locale_get(prefix);} | 69 | const char *prefix_locale_get() {return eina_prefix_locale_get(prefix);} |
71 | 70 | ||
72 | void pantsOff(int logDom) | 71 | void pantsOff(int logDom) |
73 | { | 72 | { |
diff --git a/src/libraries/Runnr.c b/src/libraries/Runnr.c index 72bc523..c905ce9 100644 --- a/src/libraries/Runnr.c +++ b/src/libraries/Runnr.c | |||
@@ -1,62 +1,139 @@ | |||
1 | /* Runnr - a library that deals with running Lua scripts. | 1 | /* Runnr - a library that deals with running Lua scripts. |
2 | |||
3 | */ | 2 | */ |
4 | 3 | ||
5 | 4 | ||
5 | #include "LumbrJack.h" | ||
6 | #include "Runnr.h" | 6 | #include "Runnr.h" |
7 | 7 | ||
8 | 8 | ||
9 | static Ecore_Idle_Enterer *enterer; | ||
10 | static Eina_Clist scripts; | ||
11 | |||
12 | static int _send(lua_State *L); | ||
13 | static int _receive(lua_State *L); | ||
14 | static void _cancel(void *data, Ecore_Thread *thread); | ||
15 | |||
16 | |||
17 | static const struct luaL_reg runnrFunctions[] = | ||
18 | { | ||
19 | { "send", _send }, | ||
20 | { "receive", _receive }, | ||
21 | { NULL, NULL } | ||
22 | }; | ||
23 | |||
24 | |||
9 | void dumpStack(lua_State *L, int i) | 25 | void dumpStack(lua_State *L, int i) |
10 | { | 26 | { |
11 | int type = lua_type(L, i); | 27 | int type = lua_type(L, i); |
28 | const char *t = lua_typename(L, type); | ||
12 | 29 | ||
30 | printf("Stack %d is %s", i, t); | ||
13 | switch (type) | 31 | switch (type) |
14 | { | 32 | { |
15 | case LUA_TNONE : printf("Stack %d is empty\n", i); break; | 33 | case LUA_TNONE : break; |
16 | case LUA_TNIL : printf("Stack %d is a nil\n", i); break; | 34 | case LUA_TNIL : break; |
17 | case LUA_TBOOLEAN : printf("Stack %d is a boolean - %d\n", i, lua_toboolean(L, i)); break; | 35 | case LUA_TBOOLEAN : printf(" - %d", lua_toboolean(L, i)); break; |
18 | case LUA_TNUMBER : printf("Stack %d is a number\n - %f", i, lua_tonumber(L, i)); break; | 36 | case LUA_TNUMBER : printf(" - %f", lua_tonumber(L, i)); break; |
19 | case LUA_TSTRING : printf("Stack %d is a string - %s\n", i, lua_tostring(L, i)); break; | 37 | case LUA_TSTRING : printf(" - %s", lua_tostring(L, i)); break; |
20 | case LUA_TFUNCTION : printf("Stack %d is a function\n", i); break; | 38 | case LUA_TFUNCTION : break; |
21 | case LUA_TTHREAD : printf("Stack %d is a thread\n", i); break; | 39 | case LUA_TTHREAD : break; |
22 | case LUA_TTABLE : | 40 | case LUA_TTABLE : |
23 | { | 41 | { |
24 | int j; | 42 | int j; |
25 | 43 | ||
26 | printf("Stack %d is a table", i); | ||
27 | lua_getfield(L, i, "_NAME"); | 44 | lua_getfield(L, i, "_NAME"); |
28 | j = lua_gettop(L); | 45 | j = lua_gettop(L); |
29 | if (lua_isstring(L, j)) | 46 | if (lua_isstring(L, j)) |
30 | printf(" - %s", lua_tostring(L, j)); | 47 | printf(" - %s", lua_tostring(L, j)); |
31 | lua_pop(L, 1); | 48 | lua_pop(L, 1); |
32 | printf("\n"); | ||
33 | break; | 49 | break; |
34 | } | 50 | } |
35 | case LUA_TUSERDATA : printf("Stack %d is a userdata\n", i); break; | 51 | case LUA_TUSERDATA : break; |
36 | case LUA_TLIGHTUSERDATA : printf("Stack %d is a light userdata\n", i); break; | 52 | case LUA_TLIGHTUSERDATA : break; |
37 | default : printf("Stack %d is unknown\n", i); break; | 53 | default : printf("- unknown!"); break; |
38 | } | 54 | } |
55 | printf("\n"); | ||
39 | } | 56 | } |
40 | 57 | ||
41 | static int traceBack(lua_State *L) | 58 | static int traceBack(lua_State *L) |
42 | { | 59 | { |
43 | const char *msg = ""; | 60 | lua_Debug ar; |
44 | int top = lua_gettop(L); | 61 | int i, top = lua_gettop(L), b = 1; |
45 | // int i; | ||
46 | 62 | ||
47 | // printf("Stack is %d deep\n", top); | 63 | // printf("Stack is %d deep\n", top); |
48 | // for (i = 1; i <= top; i++) | 64 | // for (i = 1; i <= top; i++) |
49 | // dumpStack(L, i); | 65 | // dumpStack(L, i); |
50 | 66 | ||
51 | if (top) | 67 | if (top) |
52 | msg = lua_tostring(L, 1); | 68 | printf("Lua error - %s\n", lua_tostring(L, 1)); |
53 | lua_getglobal(L, "debug"); | 69 | |
54 | push_lua(L, "@ ( )", lua_gettop(L), "traceback", 1); | 70 | i = 0; |
55 | lua_pushstring(L, "\n"); | 71 | while (lua_getstack(L, i++, &ar)) |
56 | lua_pushstring(L, msg); | 72 | { |
57 | lua_concat(L, 3); | 73 | if (lua_getinfo(L, "nSlu", &ar)) |
58 | 74 | { | |
59 | return 1; | 75 | if (NULL == ar.name) |
76 | ar.name = "DUNNO"; | ||
77 | printf(" Lua backtrace %d - %s %s %s @ %s : %d\n", i, ar.what, ar.namewhat, ar.name, ar.short_src, ar.currentline); | ||
78 | b = 0; | ||
79 | } | ||
80 | else | ||
81 | printf(" Failed to get trace line!\n"); | ||
82 | } | ||
83 | |||
84 | if (b) | ||
85 | printf(" NO BACKTRACE!\n"); | ||
86 | |||
87 | return 0; | ||
88 | } | ||
89 | |||
90 | static void printLuaError(int err, char *string, lua_State *L) | ||
91 | { | ||
92 | const char *err_type; | ||
93 | |||
94 | switch (err) | ||
95 | { | ||
96 | case LUA_ERRRUN: err_type = "runtime"; break; | ||
97 | case LUA_ERRSYNTAX: err_type = "syntax"; break; | ||
98 | case LUA_ERRMEM: err_type = "memory allocation"; break; | ||
99 | case LUA_ERRERR: err_type = "error handler"; break; | ||
100 | default: err_type = "unknown"; break; | ||
101 | } | ||
102 | printf("Error running - %s, \n %s - %s\n", string, err_type, lua_tostring(L, -1)); | ||
103 | } | ||
104 | |||
105 | static int panics = 0; | ||
106 | static int _panic(lua_State *L) // Stack usage [-0, +0, m] | ||
107 | { | ||
108 | // If we somehow manage to have multiple panics, it's likely due to being out | ||
109 | // of memory in the following lua_tostring() call. | ||
110 | panics++; | ||
111 | if (panics) | ||
112 | printf("Lua PANICS!!!!!"); | ||
113 | else | ||
114 | printf("Lua PANIC!!!!!: %s", lua_tostring(L, -1)); // Stack usage [-0, +0, m] | ||
115 | // The docs say that this will cause an exit(EXIT_FAILURE) if we return, | ||
116 | // and that we we should long jump some where to avoid that. This is only | ||
117 | // called for things not called from a protected environment. We always | ||
118 | // use pcalls though, except for the library load calls. If we can't load | ||
119 | // the standard libraries, then perhaps a crash is the right thing. | ||
120 | // | ||
121 | // The above is not true when we deal with the threaded stuff, that uses lua_resume(). | ||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | void printScriptsStatus() | ||
126 | { | ||
127 | int active, pending_total, pending_feedback, pending_short, available; | ||
128 | |||
129 | active = ecore_thread_active_get(); | ||
130 | pending_total = ecore_thread_pending_total_get(); | ||
131 | pending_feedback = ecore_thread_pending_feedback_get(); | ||
132 | pending_short = ecore_thread_pending_get(); | ||
133 | available = ecore_thread_available_get(); | ||
134 | |||
135 | printf("Scripts - active %d available %d pending short jobs %d pending feedback jobs %d pending total %d\n", | ||
136 | active, available, pending_short, pending_feedback, pending_total); | ||
60 | } | 137 | } |
61 | 138 | ||
62 | void doLuaString(lua_State *L, char *string, char *module) | 139 | void doLuaString(lua_State *L, char *string, char *module) |
@@ -87,23 +164,452 @@ void doLuaString(lua_State *L, char *string, char *module) | |||
87 | } | 164 | } |
88 | } | 165 | } |
89 | 166 | ||
167 | //printf("doLuaString(%s)\n", string); | ||
90 | if ((err = lua_pcall(L, 0, LUA_MULTRET, _T))) | 168 | if ((err = lua_pcall(L, 0, LUA_MULTRET, _T))) |
169 | printLuaError(err, string, L); | ||
170 | } | ||
171 | } | ||
172 | |||
173 | static void _stopScript(script *s) | ||
174 | { | ||
175 | scriptMessage *sm0, *sm1; | ||
176 | |||
177 | //printf("^^^^^^^^^^^^^^^^^^^_stop(, %s)\n", s->name); | ||
178 | if (s->L) lua_close(s->L); s->L = NULL; | ||
179 | if (s->timer) ecore_timer_del(s->timer); s->timer = NULL; | ||
180 | EINA_CLIST_FOR_EACH_ENTRY_SAFE(sm0, sm1, &(s->messages), scriptMessage, node) | ||
181 | { | ||
182 | eina_clist_remove(&(sm0->node)); | ||
183 | free(sm0); | ||
184 | } | ||
185 | s->status = RUNNR_NOT_STARTED; | ||
186 | } | ||
187 | |||
188 | static void _workerFunction(void *data, Ecore_Thread *thread) | ||
189 | { | ||
190 | script *s = data; | ||
191 | scriptMessage *msg = NULL; | ||
192 | const char *message = NULL; | ||
193 | |||
194 | takeScript(s); | ||
195 | // if (RUNNR_FINISHED == s->status) | ||
196 | // { | ||
197 | // releaseScript(s); | ||
198 | // return; | ||
199 | // } | ||
200 | |||
201 | // The documentation is not clear on which thread is which inside and out, | ||
202 | // but states that at least for some they are different. | ||
203 | // So store the internal one as well. | ||
204 | #if THREADIT | ||
205 | s->me = thread; | ||
206 | #endif | ||
207 | |||
208 | if (RUNNR_RESET == s->status) | ||
209 | _stopScript(s); | ||
210 | |||
211 | if (RUNNR_READY == s->status) | ||
212 | { | ||
213 | //printf("_workerFunction() READY %s\n", s->name); | ||
214 | if ((msg = (scriptMessage *) eina_clist_head(&(s->messages)))) | ||
91 | { | 215 | { |
92 | const char *err_type; | 216 | eina_clist_remove(&(msg->node)); |
217 | message = msg->message; | ||
218 | if (s->L) | ||
219 | s->status = RUNNR_RUNNING; | ||
220 | else | ||
221 | s->status = RUNNR_NOT_STARTED; | ||
222 | } | ||
223 | } | ||
224 | |||
225 | if (RUNNR_NOT_STARTED == s->status) | ||
226 | { | ||
227 | int err; | ||
93 | 228 | ||
94 | switch (err) | 229 | //printf("_workerFunction() STARTING %s\n", s->name); |
230 | s->status = RUNNR_RUNNING; | ||
231 | s->L = luaL_newstate(); // Sets a standard allocator and panic function. | ||
232 | |||
233 | lua_atpanic(s->L, _panic); | ||
234 | // TODO - Set our allocator here. | ||
235 | luaL_openlibs(s->L); | ||
236 | luaL_register(s->L, "Runnr", runnrFunctions); | ||
237 | |||
238 | // Store the script struct in its own Lua state, | ||
239 | lua_pushlightuserdata(s->L, s); | ||
240 | lua_setfield(s->L, LUA_REGISTRYINDEX, "_SELF"); | ||
241 | |||
242 | err = luaL_loadfile(s->L, s->binName); | ||
243 | if (err != 0) | ||
244 | s->status = RUNNR_FINISHED; | ||
245 | gettimeofday(&s->startTime, NULL); | ||
246 | } | ||
247 | |||
248 | releaseScript(s); | ||
249 | |||
250 | if (RUNNR_RUNNING == s->status) | ||
251 | { | ||
252 | int stat; | ||
253 | |||
254 | //printf("_workerFunction() RUNNING %s %s\n", s->name, message); | ||
255 | // Resume running the script. | ||
256 | // lua_resume() needs a Lua thread, and the initial Lua state is a thread. | ||
257 | // Other Lua threads have their own state, but share the environment with the initial state. | ||
258 | // In theory lua_resume() is a pcall. | ||
259 | if (message) | ||
260 | lua_pushstring(s->L, message); | ||
261 | stat = lua_resume(s->L, (message) ? 1 : 0); | ||
262 | free(msg); | ||
263 | |||
264 | takeScript(s); | ||
265 | // If the script finished. | ||
266 | if (stat == 0) | ||
267 | s->status = RUNNR_FINISHED; | ||
268 | else if (stat != LUA_YIELD) | ||
269 | { | ||
270 | printf("lua_resume error at %s\n", s->name); | ||
271 | printLuaError(stat, s->name, s->L); | ||
272 | s->status = RUNNR_FINISHED; | ||
273 | } | ||
274 | else | ||
275 | { | ||
276 | if (eina_clist_count(&s->messages) == 0) | ||
277 | s->status = RUNNR_WAIT; | ||
278 | else | ||
279 | s->status = RUNNR_READY; | ||
280 | } | ||
281 | releaseScript(s); | ||
282 | } | ||
283 | |||
284 | takeScript(s); | ||
285 | // Start again from the top when Ecore_Thread has a spare thread ready, unless the script finished. | ||
286 | if (RUNNR_FINISHED == s->status) | ||
287 | { | ||
288 | //printf("_workerFunction() FINISHED %s\n", s->name); | ||
289 | #if THREADIT | ||
290 | ecore_thread_cancel(thread); | ||
291 | #else | ||
292 | _cancel(s, NULL); | ||
293 | #endif | ||
294 | } | ||
295 | else if (RUNNR_WAIT == s->status) | ||
296 | { | ||
297 | ;//printf("_workerFunction() WAIT %s\n", s->name); | ||
298 | } | ||
299 | #if THREADIT | ||
300 | else if (RUNNR_READY == s->status) | ||
301 | ecore_thread_reschedule(thread); | ||
302 | #endif | ||
303 | releaseScript(s); | ||
304 | } | ||
305 | |||
306 | static void _notify(void *data, Ecore_Thread *thread, void *message) | ||
307 | { | ||
308 | script *s = data; | ||
309 | |||
310 | if (s->send2server) s->send2server(s, message); | ||
311 | free(message); | ||
312 | } | ||
313 | |||
314 | static void _cancel(void *data, Ecore_Thread *thread) | ||
315 | { | ||
316 | script *s = data; | ||
317 | |||
318 | takeScript(s); | ||
319 | _stopScript(s); | ||
320 | s->status = RUNNR_FINISHED; | ||
321 | eina_clist_remove(&(s->node)); | ||
322 | if (s->SID[0]) ecore_thread_global_data_del(s->SID); s->SID[0] = 0; | ||
323 | //printf("^^^^^^^^^^^^^^^^^^^_del(, %s)\n", s->name); | ||
324 | // TODO - Perhaps have our own deletion callback to pass back? | ||
325 | releaseScript(s); | ||
326 | #if THREADIT | ||
327 | eina_lock_free(&s->mutex); | ||
328 | #endif | ||
329 | free(s); | ||
330 | } | ||
331 | |||
332 | #if THREADIT | ||
333 | static void _end(void *data, Ecore_Thread *thread) | ||
334 | { | ||
335 | } | ||
336 | #endif | ||
337 | |||
338 | static Eina_Bool _enterer(void *data) | ||
339 | { | ||
340 | script *s, *s1; | ||
341 | |||
342 | EINA_CLIST_FOR_EACH_ENTRY_SAFE(s, s1, &(scripts), script, node) | ||
343 | { | ||
344 | takeScript(s); | ||
345 | if ((RUNNR_WAIT == s->status) && (eina_clist_count(&s->messages))) | ||
346 | { | ||
347 | s->status = RUNNR_READY; | ||
348 | #if THREADIT | ||
349 | ecore_thread_feedback_run(_workerFunction, _notify, _end, _cancel, s, EINA_FALSE); | ||
350 | #else | ||
351 | _workerFunction(s, NULL); | ||
352 | #endif | ||
353 | } | ||
354 | if ((RUNNR_RESET == s->status) || (RUNNR_READY == s->status) || (RUNNR_RUNNING == s->status) || (RUNNR_NOT_STARTED == s->status)) | ||
355 | { | ||
356 | #if THREADIT | ||
357 | ecore_thread_feedback_run(_workerFunction, _notify, _end, _cancel, s, EINA_FALSE); | ||
358 | #else | ||
359 | _workerFunction(s, NULL); | ||
360 | #endif | ||
361 | } | ||
362 | releaseScript(s); | ||
363 | } | ||
364 | |||
365 | return ECORE_CALLBACK_RENEW; | ||
366 | } | ||
367 | |||
368 | script *scriptAdd(char *file, char *SID, RunnrServerCb send2server, void *data) | ||
369 | { | ||
370 | script *result; | ||
371 | |||
372 | if (!enterer) | ||
373 | { | ||
374 | eina_clist_init(&(scripts)); | ||
375 | enterer = ecore_idler_add(_enterer, NULL); | ||
376 | } | ||
377 | |||
378 | result = calloc(1, sizeof(script)); | ||
379 | gettimeofday(&result->startTime, NULL); | ||
380 | strcpy(result->SID, SID); | ||
381 | result->status = RUNNR_NOT_STARTED; | ||
382 | result->data = data; | ||
383 | result->send2server = send2server; | ||
384 | |||
385 | strncpy(result->fileName, file, sizeof(result->fileName)); | ||
386 | result->name = &result->fileName[strlen(prefix_data_get())]; | ||
387 | sprintf(result->binName, "%s.lua.out", result->fileName); | ||
388 | |||
389 | #if THREADIT | ||
390 | eina_lock_new(&result->mutex); | ||
391 | #endif | ||
392 | eina_clist_init(&(result->messages)); | ||
393 | ecore_thread_global_data_add(result->SID, result, NULL, EINA_FALSE); | ||
394 | |||
395 | eina_clist_add_tail(&(scripts), &(result->node)); | ||
396 | |||
397 | return result; | ||
398 | } | ||
399 | |||
400 | static int luaWriter(lua_State *L, const void* p, size_t sz, void* ud) | ||
401 | { | ||
402 | FILE *out = ud; | ||
403 | int result = 0; | ||
404 | |||
405 | if (sz != fwrite(p, 1, sz, out)) | ||
406 | result = -1; | ||
407 | return result; | ||
408 | } | ||
409 | |||
410 | // TODO - This didn't help the compile time much, perhaps move the rest of the compiling stage into this thread as a callback? | ||
411 | static void _compileNotify(void *data, Ecore_Thread *thread, void *message) | ||
412 | { | ||
413 | LuaCompiler *compiler = data; | ||
414 | |||
415 | if (compiler->cb) compiler->cb(compiler); | ||
416 | } | ||
417 | |||
418 | static void _compileThread(void *data, Ecore_Thread *thread) | ||
419 | { | ||
420 | LuaCompiler *compiler = data; | ||
421 | char name[PATH_MAX]; | ||
422 | lua_State *L; | ||
423 | FILE *out; | ||
424 | int err; | ||
425 | |||
426 | strcpy(name, compiler->luaName); | ||
427 | if ((L = luaL_newstate())) | ||
428 | { | ||
429 | luaL_openlibs(L); | ||
430 | // This ends up pushing a function onto the stack. The function is the compiled code. | ||
431 | err = luaL_loadfile(L, name); | ||
432 | if (err) | ||
433 | { | ||
434 | compiler->bugCount++; | ||
435 | if (LUA_ERRSYNTAX == err) | ||
436 | printf("Lua syntax error in %s: %s\n", name, lua_tostring(L, -1)); | ||
437 | else if (LUA_ERRFILE == err) | ||
438 | printf("Lua compile file error in %s: %s\n", name, lua_tostring(L, -1)); | ||
439 | else if (LUA_ERRMEM == err) | ||
440 | printf("Lua compile memory allocation error in %s: %s\n", name, lua_tostring(L, -1)); | ||
441 | } | ||
442 | else | ||
443 | { | ||
444 | // Write the compiled code to a file. | ||
445 | strcat(name, ".out"); | ||
446 | out = fopen(name, "w"); | ||
447 | if (out) | ||
448 | { | ||
449 | err = lua_dump(L, luaWriter, out); | ||
450 | if (err) | ||
451 | { | ||
452 | compiler->bugCount++; | ||
453 | printf("Lua compile file error writing to %s\n", name); | ||
454 | } | ||
455 | fclose(out); | ||
456 | } | ||
457 | else | ||
458 | { | ||
459 | compiler->bugCount++; | ||
460 | printf("CRITICAL! Unable to open file %s for writing!\n", name); | ||
461 | } | ||
462 | } | ||
463 | } | ||
464 | else | ||
465 | { | ||
466 | compiler->bugCount++; | ||
467 | printf("Can't create a new Lua state!\n"); | ||
468 | } | ||
469 | |||
470 | ecore_thread_feedback(thread, compiler); | ||
471 | } | ||
472 | |||
473 | void compileScript(LuaCompiler *compiler) | ||
474 | { | ||
475 | ecore_thread_feedback_run(_compileThread, _compileNotify, NULL, NULL, compiler, EINA_FALSE); | ||
476 | } | ||
477 | |||
478 | // Assumes the scripts mutex is taken already. | ||
479 | void runScript(script *s) | ||
480 | { | ||
481 | #if THREADIT | ||
482 | if ((RUNNR_NOT_STARTED == s->status) || (RUNNR_FINISHED == s->status)) | ||
483 | #endif | ||
484 | { | ||
485 | #if THREADIT | ||
486 | ecore_thread_feedback_run(_workerFunction, _notify, _end, _cancel, s, EINA_FALSE); | ||
487 | #elsif | ||
488 | _workerFunction(s, NULL); | ||
489 | #endif | ||
490 | } | ||
491 | } | ||
492 | |||
493 | void resetScript(script *s) | ||
494 | { | ||
495 | takeScript(s); | ||
496 | s->status = RUNNR_RESET; | ||
497 | releaseScript(s); | ||
498 | } | ||
499 | |||
500 | script *getScript(char *SID) | ||
501 | { | ||
502 | script *result = ecore_thread_global_data_find(SID); | ||
503 | |||
504 | if (result) | ||
505 | { | ||
506 | takeScript(result); | ||
507 | if (RUNNR_FINISHED == result->status) | ||
508 | { | ||
509 | releaseScript(result); | ||
510 | result = NULL; | ||
511 | } | ||
512 | } | ||
513 | return result; | ||
514 | } | ||
515 | |||
516 | void takeScript(script *s) | ||
517 | { | ||
518 | #if THREADIT | ||
519 | Eina_Lock_Result result = eina_lock_take(&s->mutex); | ||
520 | if (EINA_LOCK_DEADLOCK == result) printf("Script %s IS DEADLOCKED!\n", s->name); | ||
521 | if (EINA_LOCK_FAIL == result) printf("Script %s LOCK FAILED!\n", s->name); | ||
522 | #endif | ||
523 | } | ||
524 | |||
525 | void releaseScript(script *s) | ||
526 | { | ||
527 | #if THREADIT | ||
528 | eina_lock_release(&s->mutex); | ||
529 | #endif | ||
530 | } | ||
531 | |||
532 | void send2script(const char *SID, const char *message) | ||
533 | { | ||
534 | if (SID) | ||
535 | { | ||
536 | script *s = ecore_thread_global_data_find(SID); | ||
537 | |||
538 | if (s) | ||
539 | { | ||
540 | takeScript(s); | ||
541 | if (RUNNR_FINISHED != s->status) | ||
95 | { | 542 | { |
96 | case LUA_ERRRUN: err_type = "runtime"; break; | 543 | scriptMessage *sm = NULL; |
97 | case LUA_ERRSYNTAX: err_type = "syntax"; break; | 544 | |
98 | case LUA_ERRMEM: err_type = "memory allocation"; break; | 545 | if ((sm = malloc(sizeof(scriptMessage)))) |
99 | case LUA_ERRERR: err_type = "error handler"; break; | 546 | { |
100 | default: err_type = "unknown"; break; | 547 | runnrStatus stat; |
548 | |||
549 | sm->s = s; | ||
550 | strcpy((char *) sm->message, message); | ||
551 | eina_clist_add_tail(&(s->messages), &(sm->node)); | ||
552 | |||
553 | stat = s->status; | ||
554 | s->status = RUNNR_READY; | ||
555 | if (RUNNR_WAIT == stat) | ||
556 | #if THREADIT | ||
557 | ecore_thread_feedback_run(_workerFunction, _notify, _end, _cancel, s, EINA_FALSE); | ||
558 | #else | ||
559 | _workerFunction(s, NULL); | ||
560 | #endif | ||
561 | } | ||
101 | } | 562 | } |
102 | printf("Error running - %s, \n%s - %s", string, err_type, lua_tostring(L, -1)); | 563 | releaseScript(s); |
103 | } | 564 | } |
104 | } | 565 | } |
105 | } | 566 | } |
106 | 567 | ||
568 | static script *_getSelf(lua_State *L) | ||
569 | { | ||
570 | script *s; | ||
571 | |||
572 | lua_getfield(L, LUA_REGISTRYINDEX, "_SELF"); | ||
573 | s = (script *) lua_touserdata(L, -1); | ||
574 | lua_pop(L, 1); | ||
575 | |||
576 | return s; | ||
577 | } | ||
578 | |||
579 | static int _send(lua_State *L) | ||
580 | { | ||
581 | script *self = _getSelf(L); | ||
582 | const char *SID = NULL, *message = luaL_checkstring(L, 2); | ||
583 | |||
584 | if (lua_isstring(L, 1)) | ||
585 | SID = lua_tostring(L, 1); | ||
586 | |||
587 | if (SID) | ||
588 | send2script(SID, message); | ||
589 | else | ||
590 | { | ||
591 | takeScript(self); | ||
592 | #if THREADIT | ||
593 | ecore_thread_feedback(self->me, strdup(message)); | ||
594 | #else | ||
595 | _notify(self, NULL, strdup(message)); | ||
596 | #endif | ||
597 | releaseScript(self); | ||
598 | } | ||
599 | |||
600 | return 0; | ||
601 | } | ||
602 | |||
603 | static int _receive(lua_State *L) | ||
604 | { | ||
605 | script *self = _getSelf(L); | ||
606 | |||
607 | takeScript(self); | ||
608 | self->status = RUNNR_WAIT; | ||
609 | releaseScript(self); | ||
610 | return lua_yield(L, 0); | ||
611 | } | ||
612 | |||
107 | 613 | ||
108 | // These are what the various symbols are for each type - | 614 | // These are what the various symbols are for each type - |
109 | // int % | 615 | // int % |
@@ -282,10 +788,24 @@ int push_lua(lua_State *L, char *params, ...) // Stack usage [-0, +n, em] | |||
282 | va_list vl; | 788 | va_list vl; |
283 | char *f = strdup(params); | 789 | char *f = strdup(params); |
284 | char *p = f; | 790 | char *p = f; |
285 | int n = 0, table = 0, i = -1; | 791 | int n = 0, table = 0, i = -1, needTrace = 0, _T; |
286 | 792 | ||
287 | if (!f) return -1; | 793 | if (!f) return -1; |
288 | 794 | ||
795 | // Scan ahead looking for ), so we know to put the traceBack function on the stack first. | ||
796 | while (*p) | ||
797 | { | ||
798 | p++; | ||
799 | if ('0' == *p) | ||
800 | { | ||
801 | lua_pushcfunction(L, traceBack); | ||
802 | _T = lua_gettop(L); | ||
803 | needTrace = 1; | ||
804 | break; | ||
805 | } | ||
806 | } | ||
807 | p = f; | ||
808 | |||
289 | va_start(vl, params); | 809 | va_start(vl, params); |
290 | 810 | ||
291 | while (*p) | 811 | while (*p) |
@@ -364,7 +884,10 @@ int push_lua(lua_State *L, char *params, ...) // Stack usage [-0, +n, em] | |||
364 | } | 884 | } |
365 | case ')': | 885 | case ')': |
366 | { | 886 | { |
367 | lua_call(L, n - 1, va_arg(vl, int)); | 887 | int err; |
888 | |||
889 | if ((err = lua_pcall(L, n - 1, va_arg(vl, int), _T))) | ||
890 | printLuaError(err, params, L); | ||
368 | n = 0; | 891 | n = 0; |
369 | set = EINA_FALSE; | 892 | set = EINA_FALSE; |
370 | break; | 893 | break; |
@@ -401,6 +924,8 @@ int push_lua(lua_State *L, char *params, ...) // Stack usage [-0, +n, em] | |||
401 | } | 924 | } |
402 | 925 | ||
403 | va_end(vl); | 926 | va_end(vl); |
927 | if (needTrace) | ||
928 | lua_remove(L, _T); | ||
404 | free(f); | 929 | free(f); |
405 | return n; | 930 | return n; |
406 | } | 931 | } |
diff --git a/src/libraries/Runnr.h b/src/libraries/Runnr.h index 0e0fc73..ba5c17e 100644 --- a/src/libraries/Runnr.h +++ b/src/libraries/Runnr.h | |||
@@ -4,12 +4,82 @@ | |||
4 | #include <ctype.h> | 4 | #include <ctype.h> |
5 | 5 | ||
6 | #include <Eina.h> | 6 | #include <Eina.h> |
7 | #include <Ecore.h> | ||
8 | #include <Ecore_Con.h> | ||
7 | 9 | ||
8 | #include <lua.h> | 10 | #include <lua.h> |
9 | #include <luajit.h> | 11 | #include <luajit.h> |
10 | #include <lualib.h> | 12 | #include <lualib.h> |
11 | #include <lauxlib.h> | 13 | #include <lauxlib.h> |
12 | 14 | ||
15 | // Stick with Plan C for now. | ||
16 | #define THREADIT 0 | ||
17 | |||
18 | typedef enum | ||
19 | { | ||
20 | RUNNR_COMPILING, | ||
21 | RUNNR_NOT_STARTED, | ||
22 | RUNNR_RUNNING, | ||
23 | RUNNR_WAIT, | ||
24 | RUNNR_READY, | ||
25 | RUNNR_RESET, | ||
26 | RUNNR_FINISHED | ||
27 | } runnrStatus; | ||
28 | |||
29 | typedef struct _LuaCompile LuaCompile; | ||
30 | typedef void (* compileCb)(LuaCompile *compiler); | ||
31 | |||
32 | typedef struct _LuaCompile | ||
33 | { | ||
34 | char *file, *SID, *luaName; | ||
35 | int bugCount; | ||
36 | void *data; | ||
37 | Ecore_Con_Client *client; | ||
38 | compileCb cb; | ||
39 | } LuaCompiler; | ||
40 | |||
41 | typedef struct _script script; | ||
42 | typedef void (* RunnrServerCb)(script *me, const char *message); | ||
43 | |||
44 | typedef struct _script | ||
45 | { | ||
46 | Eina_Clist node; | ||
47 | #if THREADIT | ||
48 | Eina_Lock mutex; | ||
49 | Ecore_Thread *me; | ||
50 | #endif | ||
51 | void *data; | ||
52 | char SID[PATH_MAX]; | ||
53 | char *name; | ||
54 | char fileName[PATH_MAX]; | ||
55 | char binName[PATH_MAX]; | ||
56 | lua_State *L; | ||
57 | struct timeval startTime; | ||
58 | float timerTime; | ||
59 | runnrStatus status; | ||
60 | RunnrServerCb send2server; | ||
61 | Eina_Clist messages; | ||
62 | Ecore_Con_Client *client; | ||
63 | Ecore_Timer *timer; | ||
64 | } script; | ||
65 | |||
66 | typedef struct | ||
67 | { | ||
68 | Eina_Clist node; | ||
69 | script *s; | ||
70 | const char message[PATH_MAX]; | ||
71 | } scriptMessage; | ||
72 | |||
73 | |||
74 | script *scriptAdd(char *file, char *SID, RunnrServerCb send2server, void *data); | ||
75 | void compileScript(LuaCompiler *compiler); | ||
76 | void runScript(script *me); | ||
77 | void resetScript(script *me); | ||
78 | script *getScript(char *SID); | ||
79 | void takeScript(script *me); | ||
80 | void releaseScript(script *me); | ||
81 | void send2script(const char *SID, const char *message); | ||
82 | void printScriptsStatus(); | ||
13 | 83 | ||
14 | void dumpStack(lua_State *L, int i); | 84 | void dumpStack(lua_State *L, int i); |
15 | void doLuaString(lua_State *L, char *string, char *module); | 85 | void doLuaString(lua_State *L, char *string, char *module); |
diff --git a/src/libraries/SledjHamr.c b/src/libraries/SledjHamr.c index 5f26fde..5e1d387 100644 --- a/src/libraries/SledjHamr.c +++ b/src/libraries/SledjHamr.c | |||
@@ -1,3 +1,5 @@ | |||
1 | // This might become nails, since at the moment it's only got comms stuff in it. | ||
2 | |||
1 | #include <unistd.h> | 3 | #include <unistd.h> |
2 | #include "SledjHamr.h" | 4 | #include "SledjHamr.h" |
3 | 5 | ||