diff options
Diffstat (limited to '')
-rw-r--r-- | ClientHamr/GuiLua/GuiLua.c | 320 | ||||
-rw-r--r-- | ClientHamr/GuiLua/GuiLua.h | 3 | ||||
-rw-r--r-- | ClientHamr/GuiLua/test_c.c | 1 |
3 files changed, 286 insertions, 38 deletions
diff --git a/ClientHamr/GuiLua/GuiLua.c b/ClientHamr/GuiLua/GuiLua.c index 985d0c6..e26ce36 100644 --- a/ClientHamr/GuiLua/GuiLua.c +++ b/ClientHamr/GuiLua/GuiLua.c | |||
@@ -230,6 +230,278 @@ char *getDateTime(struct tm **nowOut, char *dateOut, time_t *timeOut) | |||
230 | } | 230 | } |
231 | 231 | ||
232 | 232 | ||
233 | // These are what the various symbols are for each type - | ||
234 | // int % | ||
235 | // num # | ||
236 | // str $ | ||
237 | // bool ! | ||
238 | // C func & | ||
239 | // table.field @ Expects an integer and a string. | ||
240 | // nil ~ | ||
241 | // table {} Starts and stops filling up a new table. | ||
242 | // ( Just syntax sugar for call. | ||
243 | // call ) Expects an integer, the number of results left after the call. | ||
244 | // FIXME: Still to do, if we ever use them - | ||
245 | // userdata + | ||
246 | // lightuserdata * | ||
247 | // thread ^ | ||
248 | |||
249 | static char *_push_name(lua_State *L, char *q, int *idx) // Stack usage [-0, +1, e or m] | ||
250 | { | ||
251 | char *p = q; | ||
252 | char temp = '\0'; | ||
253 | |||
254 | // A simplistic scan through an identifier, it's wrong, but it's quick, | ||
255 | // and we don't mind that it's wrong, coz this is only internal. | ||
256 | while (isalnum((int)*q)) | ||
257 | q++; | ||
258 | temp = *q; | ||
259 | *q = '\0'; | ||
260 | if (*idx > 0) | ||
261 | lua_getfield(L, *idx, p); // Stack usage [-0, +1, e] | ||
262 | else | ||
263 | { | ||
264 | if (p != q) | ||
265 | lua_pushstring(L, p); // Stack usage [-0, +1, m] | ||
266 | else | ||
267 | { | ||
268 | lua_pushnumber(L, (lua_Number) (0 - (*idx))); | ||
269 | (*idx)--; | ||
270 | } | ||
271 | } | ||
272 | *q = temp; | ||
273 | |||
274 | return q; | ||
275 | } | ||
276 | |||
277 | int pull_lua(lua_State *L, int i, char *params, ...) // Stack usage - | ||
278 | // if i is a table | ||
279 | // [-n, +n, e] | ||
280 | // else | ||
281 | // [-0, +0, -] | ||
282 | { | ||
283 | va_list vl; | ||
284 | char *f = strdup(params); | ||
285 | char *p = f; | ||
286 | int n = 0, j = i, count = 0; | ||
287 | Eina_Bool table = EINA_FALSE; | ||
288 | |||
289 | if (!f) return -1; | ||
290 | va_start(vl, params); | ||
291 | |||
292 | if (lua_istable(L, i)) // Stack usage [-0, +0, -] | ||
293 | { | ||
294 | j = -1; | ||
295 | table = EINA_TRUE; | ||
296 | } | ||
297 | |||
298 | while (*p) | ||
299 | { | ||
300 | char *q; | ||
301 | Eina_Bool get = EINA_TRUE; | ||
302 | |||
303 | while (isspace((int)*p)) | ||
304 | p++; | ||
305 | q = p + 1; | ||
306 | switch (*p) | ||
307 | { | ||
308 | case '%': | ||
309 | { | ||
310 | if (table) q = _push_name(L, q, &i); // Stack usage [-0, +1, e] | ||
311 | if (lua_isnumber(L, j)) // Stack usage [-0, +0, -] | ||
312 | { | ||
313 | int *v = va_arg(vl, int *); | ||
314 | *v = lua_tointeger(L, j); // Stack usage [-0, +0, -] | ||
315 | n++; | ||
316 | } | ||
317 | break; | ||
318 | } | ||
319 | case '#': | ||
320 | { | ||
321 | if (table) q = _push_name(L, q, &i); // Stack usage [-0, +1, e] | ||
322 | if (lua_isnumber(L, j)) // Stack usage [-0, +0, -] | ||
323 | { | ||
324 | double *v = va_arg(vl, double *); | ||
325 | *v = lua_tonumber(L, j); // Stack usage [-0, +0, -] | ||
326 | n++; | ||
327 | } | ||
328 | break; | ||
329 | } | ||
330 | case '$': | ||
331 | { | ||
332 | if (table) q = _push_name(L, q, &i); // Stack usage [-0, +1, e] | ||
333 | if (lua_isstring(L, j)) // Stack usage [-0, +0, -] | ||
334 | { | ||
335 | char **v = va_arg(vl, char **); | ||
336 | size_t len; | ||
337 | char *temp = (char *) lua_tolstring(L, j, &len); // Stack usage [-0, +0, m] | ||
338 | |||
339 | len++; // Cater for the null at the end. | ||
340 | *v = malloc(len); | ||
341 | if (*v) | ||
342 | { | ||
343 | memcpy(*v, temp, len); | ||
344 | n++; | ||
345 | } | ||
346 | } | ||
347 | break; | ||
348 | } | ||
349 | case '!': | ||
350 | { | ||
351 | if (table) q = _push_name(L, q, &i); // Stack usage [-0, +1, e] | ||
352 | if (lua_isboolean(L, j)) // Stack usage [-0, +0, -] | ||
353 | { | ||
354 | int *v = va_arg(vl, int *); | ||
355 | *v = lua_toboolean(L, j); // Stack usage [-0, +0, -] | ||
356 | n++; | ||
357 | } | ||
358 | break; | ||
359 | } | ||
360 | default: | ||
361 | { | ||
362 | get = EINA_FALSE; | ||
363 | break; | ||
364 | } | ||
365 | } | ||
366 | |||
367 | if (get) | ||
368 | { | ||
369 | if (table) | ||
370 | { | ||
371 | // If this is a table, then we pushed a value on the stack, pop it off. | ||
372 | lua_pop(L, 1); // Stack usage [-n, +0, -] | ||
373 | } | ||
374 | else | ||
375 | j++; | ||
376 | count++; | ||
377 | } | ||
378 | p = q; | ||
379 | } | ||
380 | |||
381 | va_end(vl); | ||
382 | free(f); | ||
383 | if (count > n) | ||
384 | n = 0; | ||
385 | else if (table) | ||
386 | n = 1; | ||
387 | return n; | ||
388 | } | ||
389 | |||
390 | int push_lua(lua_State *L, char *params, ...) // Stack usage [-0, +n, em] | ||
391 | { | ||
392 | va_list vl; | ||
393 | char *f = strdup(params); | ||
394 | char *p = f; | ||
395 | int n = 0, table = 0, i = -1; | ||
396 | |||
397 | if (!f) return -1; | ||
398 | |||
399 | va_start(vl, params); | ||
400 | |||
401 | while (*p) | ||
402 | { | ||
403 | char *q; | ||
404 | Eina_Bool set = EINA_TRUE; | ||
405 | |||
406 | while (isspace((int)*p)) | ||
407 | p++; | ||
408 | q = p + 1; | ||
409 | switch (*p) | ||
410 | { | ||
411 | case '%': | ||
412 | { | ||
413 | if (table) q = _push_name(L, q, &i); // Stack usage [-0, +1, m] | ||
414 | lua_pushinteger(L, va_arg(vl, int)); // Stack usage [-0, +1, -] | ||
415 | break; | ||
416 | } | ||
417 | case '#': | ||
418 | { | ||
419 | if (table) q = _push_name(L, q, &i); // Stack usage [-0, +1, m] | ||
420 | lua_pushnumber(L, va_arg(vl, double)); // Stack usage [-0, +1, -] | ||
421 | break; | ||
422 | } | ||
423 | case '$': | ||
424 | { | ||
425 | if (table) q = _push_name(L, q, &i); // Stack usage [-0, +1, m] | ||
426 | lua_pushstring(L, va_arg(vl, char *)); // Stack usage [-0, +1, m] | ||
427 | break; | ||
428 | } | ||
429 | case '!': | ||
430 | { | ||
431 | if (table) q = _push_name(L, q, &i); // Stack usage [-0, +1, m] | ||
432 | lua_pushboolean(L, va_arg(vl, int)); // Stack usage [-0, +1, -] | ||
433 | break; | ||
434 | } | ||
435 | case '@': | ||
436 | { | ||
437 | int tabl = va_arg(vl, int); | ||
438 | char *field = va_arg(vl, char *); | ||
439 | |||
440 | if (table) q = _push_name(L, q, &i); // Stack usage [-0, +1, m] | ||
441 | lua_getfield(L, tabl, field); // Stack usage [-0, +1, e] | ||
442 | break; | ||
443 | } | ||
444 | case '&': | ||
445 | { | ||
446 | if (table) q = _push_name(L, q, &i); // Stack usage [-0, +1, m] | ||
447 | lua_pushcfunction(L, va_arg(vl, void *)); // Stack usage [-0, +1, m] | ||
448 | break; | ||
449 | } | ||
450 | case '~': | ||
451 | { | ||
452 | if (table) q = _push_name(L, q, &i); // Stack usage [-0, +1, m] | ||
453 | lua_pushnil(L); // Stack usage [-0, +1, -] | ||
454 | break; | ||
455 | } | ||
456 | case '(': // Just syntax sugar. | ||
457 | { | ||
458 | set = EINA_FALSE; | ||
459 | break; | ||
460 | } | ||
461 | case ')': | ||
462 | { | ||
463 | lua_call(L, n - 1, va_arg(vl, int)); | ||
464 | n = 0; | ||
465 | set = EINA_FALSE; | ||
466 | break; | ||
467 | } | ||
468 | case '{': | ||
469 | { | ||
470 | lua_newtable(L); | ||
471 | table++; | ||
472 | n++; | ||
473 | set = EINA_FALSE; | ||
474 | break; | ||
475 | } | ||
476 | case '}': | ||
477 | { | ||
478 | table--; | ||
479 | set = EINA_FALSE; | ||
480 | break; | ||
481 | } | ||
482 | default: | ||
483 | { | ||
484 | set = EINA_FALSE; | ||
485 | break; | ||
486 | } | ||
487 | } | ||
488 | |||
489 | if (set) | ||
490 | { | ||
491 | if (table > 0) | ||
492 | lua_settable(L, -3); // Stack usage [-2, +0, e] | ||
493 | else | ||
494 | n++; | ||
495 | } | ||
496 | p = q; | ||
497 | } | ||
498 | |||
499 | va_end(vl); | ||
500 | free(f); | ||
501 | return n; | ||
502 | } | ||
503 | |||
504 | |||
233 | static void _on_done(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) | 505 | static void _on_done(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) |
234 | { | 506 | { |
235 | // globals *ourGlobals = data; | 507 | // globals *ourGlobals = data; |
@@ -332,48 +604,23 @@ int luaopen_widget(lua_State *L) | |||
332 | lua_getfield(L, LUA_REGISTRYINDEX, "skang"); | 604 | lua_getfield(L, LUA_REGISTRYINDEX, "skang"); |
333 | 605 | ||
334 | // local _M = skang.moduleBegin('widget', nil, 'Copyright 2014 David Seikel', '0.1', '2014-04-08 00:42:00', nil, false) | 606 | // local _M = skang.moduleBegin('widget', nil, 'Copyright 2014 David Seikel', '0.1', '2014-04-08 00:42:00', nil, false) |
335 | lua_getfield(L, skang, "moduleBegin"); | 607 | push_lua(L, "@ ( $ ~ $ $ $ ~ ! )", skang, "moduleBegin", ourName, "Copyright 2014 David Seikel", "0.1", "2014-04-08 00:42:00", 0, 1); |
336 | lua_pushstring(L, ourName); | ||
337 | lua_pushnil(L); // Author comes from copyright. | ||
338 | lua_pushstring(L, "Copyright 2014 David Seikel"); | ||
339 | lua_pushstring(L, "0.1"); | ||
340 | lua_pushstring(L, "2014-04-08 00:42:00"); | ||
341 | lua_pushnil(L); // No skin. | ||
342 | lua_pushboolean(L, 0); // We are not a Lua module. | ||
343 | lua_call(L, 7, 1); // call 'skang.moduleBegin' with 7 arguments and 1 result. | ||
344 | |||
345 | _M = lua_gettop(L); | 608 | _M = lua_gettop(L); |
346 | // Save this module in the C registry. | 609 | // Save this module in the C registry. |
347 | lua_setfield(L, LUA_REGISTRYINDEX, ourName); | 610 | lua_setfield(L, LUA_REGISTRYINDEX, ourName); |
348 | 611 | ||
349 | // Define our functions. | 612 | // Define our functions. |
350 | lua_getfield(L, skang, "thingasm"); | 613 | push_lua(L, "@ ( @ $ $ & )", skang, "thingasm", LUA_REGISTRYINDEX, ourName, "openWindow", "Opens our window.", openWindow, 0); |
351 | lua_getfield(L, LUA_REGISTRYINDEX, ourName); // Coz getfenv() can't find C environment. | 614 | push_lua(L, "@ ( @ $ $ & )", skang, "thingasm", LUA_REGISTRYINDEX, ourName, "loopWindow", "Run our windows main loop.", loopWindow, 0); |
352 | lua_pushstring(L, "openWindow"); | 615 | push_lua(L, "@ ( @ $ $ & )", skang, "thingasm", LUA_REGISTRYINDEX, ourName, "closeWindow", "Closes our window.", closeWindow, 0); |
353 | lua_pushstring(L, "Opens our window."); | 616 | |
354 | lua_pushcfunction(L, openWindow); | 617 | // skang.thingasm{_M, 'cfooble,c', 'cfooble help text', 1, widget=\"'edit', 'The cfooble:', 1, 1, 10, 50\", required=true} |
355 | lua_call(L, 4, 0); | 618 | push_lua(L, "@ ( { @ $ $ % $widget !required } )", skang, "thingasm", LUA_REGISTRYINDEX, ourName, "wibble", "It's wibbly!", 1, "'edit', 'The wibblinator:', 1, 1, 10, 50", 1, 0); |
356 | |||
357 | lua_getfield(L, skang, "thingasm"); | ||
358 | lua_getfield(L, LUA_REGISTRYINDEX, ourName); // Coz getfenv() can't find C environment. | ||
359 | lua_pushstring(L, "loopWindow"); | ||
360 | lua_pushstring(L, "Run our windows main loop."); | ||
361 | lua_pushcfunction(L, loopWindow); | ||
362 | lua_call(L, 4, 0); | ||
363 | |||
364 | lua_getfield(L, skang, "thingasm"); | ||
365 | lua_getfield(L, LUA_REGISTRYINDEX, ourName); // Coz getfenv() can't find C environment. | ||
366 | lua_pushstring(L, "closeWindow"); | ||
367 | lua_pushstring(L, "Closes our window."); | ||
368 | lua_pushcfunction(L, closeWindow); | ||
369 | lua_call(L, 4, 0); | ||
370 | 619 | ||
371 | lua_pop(L, openWindow(L)); | 620 | lua_pop(L, openWindow(L)); |
372 | 621 | ||
373 | // skang.moduleEnd(_M) | 622 | // skang.moduleEnd(_M) |
374 | lua_getfield(L, skang, "moduleEnd"); | 623 | push_lua(L, "@ ( @ )", skang, "moduleEnd", LUA_REGISTRYINDEX, ourName, 0); |
375 | lua_getfield(L, LUA_REGISTRYINDEX, ourName); | ||
376 | lua_call(L, 1, 0); | ||
377 | 624 | ||
378 | return 1; | 625 | return 1; |
379 | } | 626 | } |
@@ -399,8 +646,7 @@ void GuiLuaDo(int argc, char **argv) | |||
399 | 646 | ||
400 | // Pass all our command line arguments to skang. | 647 | // Pass all our command line arguments to skang. |
401 | i = 1; | 648 | i = 1; |
402 | lua_getfield(ourGlobals.L, LUA_REGISTRYINDEX, "skang"); | 649 | push_lua(ourGlobals.L, "@ ( @", LUA_REGISTRYINDEX, "skang", 1, "scanArguments"); |
403 | lua_getfield(ourGlobals.L, 1, "scanArguments"); | ||
404 | lua_newtable(ourGlobals.L); | 650 | lua_newtable(ourGlobals.L); |
405 | while (--argc > 0 && *++argv != '\0') | 651 | while (--argc > 0 && *++argv != '\0') |
406 | { | 652 | { |
@@ -409,9 +655,7 @@ void GuiLuaDo(int argc, char **argv) | |||
409 | lua_settable(ourGlobals.L, -3); | 655 | lua_settable(ourGlobals.L, -3); |
410 | } | 656 | } |
411 | lua_call(ourGlobals.L, 1, 0); | 657 | lua_call(ourGlobals.L, 1, 0); |
412 | lua_getfield(ourGlobals.L, 1, "pullArguments"); | 658 | push_lua(ourGlobals.L, "@ ( @ )", 1, "pullArguments", LUA_REGISTRYINDEX, "skang", 0); |
413 | lua_getfield(ourGlobals.L, LUA_REGISTRYINDEX, "skang"); | ||
414 | lua_call(ourGlobals.L, 1, 0); | ||
415 | 659 | ||
416 | // Run the main loop via a Lua call. | 660 | // Run the main loop via a Lua call. |
417 | lua_pop(ourGlobals.L, loopWindow(ourGlobals.L)); | 661 | lua_pop(ourGlobals.L, loopWindow(ourGlobals.L)); |
diff --git a/ClientHamr/GuiLua/GuiLua.h b/ClientHamr/GuiLua/GuiLua.h index 6debac5..dfc554a 100644 --- a/ClientHamr/GuiLua/GuiLua.h +++ b/ClientHamr/GuiLua/GuiLua.h | |||
@@ -56,5 +56,8 @@ void dumpStack(lua_State *L, int i); | |||
56 | void loggingStartup(globals *ourGlobals); | 56 | void loggingStartup(globals *ourGlobals); |
57 | char *getDateTime(struct tm **nowOut, char *dateOut, time_t *tiemOut); | 57 | char *getDateTime(struct tm **nowOut, char *dateOut, time_t *tiemOut); |
58 | 58 | ||
59 | int pull_lua(lua_State *L, int i, char *params, ...); | ||
60 | int push_lua(lua_State *L, char *params, ...); | ||
61 | |||
59 | int luaopen_widget(lua_State *L); | 62 | int luaopen_widget(lua_State *L); |
60 | void GuiLuaDo(int argc, char **argv); | 63 | void GuiLuaDo(int argc, char **argv); |
diff --git a/ClientHamr/GuiLua/test_c.c b/ClientHamr/GuiLua/test_c.c index 6faf928..ae21139 100644 --- a/ClientHamr/GuiLua/test_c.c +++ b/ClientHamr/GuiLua/test_c.c | |||
@@ -158,6 +158,7 @@ int luaopen_test_c(lua_State *L) | |||
158 | lua_call(L, 2, 0); | 158 | lua_call(L, 2, 0); |
159 | 159 | ||
160 | // skang.thingasm(_M, 'cfunc', 'cfunc does nothing really', cfunc, 'number,string') | 160 | // skang.thingasm(_M, 'cfunc', 'cfunc does nothing really', cfunc, 'number,string') |
161 | // push_lua(L, "@ @ $ $ & $", skang, "thingasm", LUA_REGISTRYINDEX, ourName, "cfunc", "cfunc does nothing really", cfunc, "number,string"); | ||
161 | lua_getfield(L, skang, "thingasm"); | 162 | lua_getfield(L, skang, "thingasm"); |
162 | lua_getfield(L, LUA_REGISTRYINDEX, ourName); // Coz getfenv() can't find C environment. | 163 | lua_getfield(L, LUA_REGISTRYINDEX, ourName); // Coz getfenv() can't find C environment. |
163 | lua_pushstring(L, "cfunc"); | 164 | lua_pushstring(L, "cfunc"); |