3
#include "elua_private.h"
5
static Eina_Prefix *_elua_pfx = NULL;
7
static int _elua_init_counter = 0;
13
const char *dom = "elua";
14
if (_elua_init_counter > 0) return ++_elua_init_counter;
19
_elua_log_dom = eina_log_domain_register(dom, EINA_COLOR_LIGHTBLUE);
20
if (_elua_log_dom < 0)
22
EINA_LOG_ERR("Could not register log domain: %s", dom);
26
eina_log_timing(_elua_log_dom, EINA_LOG_STATE_STOP, EINA_LOG_STATE_INIT);
29
_elua_pfx = eina_prefix_new(NULL, elua_init, "ELUA", "elua", "checkme",
30
PACKAGE_BIN_DIR, "", PACKAGE_DATA_DIR,
35
ERR("coul not find elua prefix");
39
return ++_elua_init_counter;
45
if (_elua_init_counter <= 0)
47
EINA_LOG_ERR("Init count not greater than 0 in shutdown.");
52
if (_elua_init_counter > 0)
53
return _elua_init_counter;
56
eina_log_timing(_elua_log_dom, EINA_LOG_STATE_START, EINA_LOG_STATE_SHUTDOWN);
58
eina_prefix_free(_elua_pfx);
61
eina_log_domain_unregister(_elua_log_dom);
64
ecore_file_shutdown();
66
return _elua_init_counter;
71
_ffi_loader(lua_State *L)
73
lua_pushvalue(L, lua_upvalueindex(1));
74
lua_pushliteral(L, "cffi");
75
lua_pushvalue(L, lua_upvalueindex(2));
80
#if LUA_VERSION_NUM < 502
81
/* adapted from lua 5.2 source */
83
_push_next_template(lua_State *L, const char *path)
85
while (*path == *LUA_PATHSEP) ++path;
88
const char *l = strchr(path, *LUA_PATHSEP);
90
l = path + strlen(path);
91
lua_pushlstring(L, path, l - path);
96
_elua_searchpath(lua_State *L)
98
const char *name = luaL_checkstring(L, 1);
99
const char *path = luaL_checkstring(L, 2);
100
const char *sep = luaL_optstring(L, 3, ".");
101
const char *dsep = luaL_optstring(L, 4, LUA_DIRSEP);
103
luaL_buffinit(L, &msg);
105
name = luaL_gsub(L, name, sep, dsep);
106
while ((path = _push_next_template(L, path)))
108
const char *fname = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name);
110
FILE *rf = fopen(fname, "r");
114
return 1; /* found */
116
lua_pushfstring(L, "\n\tno file " LUA_QS, fname);
120
luaL_pushresult(&msg);
123
return 2; /* nil plus error message */
129
elua_state_new(const char *progname)
131
Elua_State *ret = NULL;
132
lua_State *L = luaL_newstate();
135
ret = calloc(1, sizeof(Elua_State));
137
if (progname) ret->progname = eina_stringshare_add(progname);
140
/* search for cffi-lua early, and pass it through as ffi */
141
lua_getglobal(L, "package");
142
#if LUA_VERSION_NUM < 502
143
/* lua 5.1 does not have package.searchpath, we rely on having that */
144
lua_getfield(L, -1, "searchpath");
145
if (lua_isnil(L, -1))
147
lua_pushcfunction(L, _elua_searchpath);
148
lua_setfield(L, -3, "searchpath");
152
lua_getfield(L, -1, "preload");
153
lua_getfield(L, -2, "searchers");
154
if (lua_isnil(L, -1))
157
lua_getfield(L, -2, "loaders");
159
if (lua_isnil(L, -1))
161
ERR("could not find a module searcher");
164
lua_rawgeti(L, -1, 3);
165
lua_pushliteral(L, "cffi");
166
if (lua_pcall(L, 1, 2, 0))
168
ERR("could not find the cffi module");
171
if (!lua_isfunction(L, -2))
173
ERR("could not find the cffi module: %s", lua_tostring(L, -2));
176
lua_pushcclosure(L, _ffi_loader, 2);
177
lua_setfield(L, -3, "ffi");
180
/* on 64-bit, split the state pointer into two and reconstruct later */
181
size_t retn = (size_t)ret;
182
if (sizeof(void *) < sizeof(lua_Number))
184
lua_pushnumber(L, 0);
185
lua_pushnumber(L, (lua_Number)retn);
189
size_t hbits = (sizeof(void *) / 2) * CHAR_BIT;
190
lua_pushnumber(L, (lua_Number)(retn >> hbits));
191
lua_pushnumber(L, (lua_Number)(retn & (((size_t)1 << hbits) - 1)));
193
lua_setfield(L, LUA_REGISTRYINDEX, "elua_ptr1");
194
lua_setfield(L, LUA_REGISTRYINDEX, "elua_ptr2");
199
eina_stringshare_del(ret->progname);
206
elua_state_free(Elua_State *es)
212
EINA_LIST_FREE(es->cmods, data)
214
lua_rawgeti(es->luastate, LUA_REGISTRYINDEX, (size_t)data);
215
lua_call(es->luastate, 0, 0);
217
lua_close(es->luastate);
220
eina_list_free(es->cmods);
221
EINA_LIST_FREE(es->lmods, data)
222
eina_stringshare_del(data);
223
EINA_LIST_FREE(es->lincs, data)
224
eina_stringshare_del(data);
225
eina_stringshare_del(es->progname);
226
eina_stringshare_del(es->coredir);
227
eina_stringshare_del(es->moddir);
228
eina_stringshare_del(es->appsdir);
233
elua_state_dirs_set(Elua_State *es, const char *core, const char *mods,
237
EINA_SAFETY_ON_NULL_RETURN(es);
240
eina_stringshare_del(es->coredir);
241
spath = eina_file_path_sanitize(core);
242
es->coredir = eina_stringshare_add(spath);
247
eina_stringshare_del(es->moddir);
248
spath = eina_file_path_sanitize(mods);
249
es->moddir = eina_stringshare_add(spath);
254
eina_stringshare_del(es->appsdir);
255
spath = eina_file_path_sanitize(apps);
256
es->appsdir = eina_stringshare_add(spath);
262
elua_state_dirs_fill(Elua_State *es, Eina_Bool ignore_env)
264
const char *coredir = NULL, *moddir = NULL, *appsdir = NULL;
265
char coredirbuf[PATH_MAX], moddirbuf[PATH_MAX], appsdirbuf[PATH_MAX];
266
EINA_SAFETY_ON_NULL_RETURN(es);
267
if (!(coredir = es->coredir))
269
if (ignore_env || !(coredir = getenv("ELUA_CORE_DIR")) || !coredir[0])
271
coredir = coredirbuf;
272
snprintf(coredirbuf, sizeof(coredirbuf), "%s/core",
273
eina_prefix_data_get(_elua_pfx));
276
char *sdir = eina_file_path_sanitize(coredir);
277
es->coredir = eina_stringshare_add(sdir);
281
if (!(moddir = es->moddir))
283
if (ignore_env || !(moddir = getenv("ELUA_MODULES_DIR")) || !moddir[0])
286
snprintf(moddirbuf, sizeof(moddirbuf), "%s/modules",
287
eina_prefix_data_get(_elua_pfx));
290
char *sdir = eina_file_path_sanitize(moddir);
291
es->moddir = eina_stringshare_add(sdir);
295
if (!(appsdir = es->appsdir))
297
if (ignore_env || !(appsdir = getenv("ELUA_APPS_DIR")) || !appsdir[0])
299
appsdir = appsdirbuf;
300
snprintf(appsdirbuf, sizeof(appsdirbuf), "%s/apps",
301
eina_prefix_data_get(_elua_pfx));
304
char *sdir = eina_file_path_sanitize(appsdir);
305
es->appsdir = eina_stringshare_add(sdir);
311
EAPI Eina_Stringshare *
312
elua_state_core_dir_get(const Elua_State *es)
314
EINA_SAFETY_ON_NULL_RETURN_VAL(es, NULL);
318
EAPI Eina_Stringshare *
319
elua_state_mod_dir_get(const Elua_State *es)
321
EINA_SAFETY_ON_NULL_RETURN_VAL(es, NULL);
325
EAPI Eina_Stringshare *
326
elua_state_apps_dir_get(const Elua_State *es)
328
EINA_SAFETY_ON_NULL_RETURN_VAL(es, NULL);
332
EAPI Eina_Stringshare *
333
elua_state_prog_name_get(const Elua_State *es)
335
EINA_SAFETY_ON_NULL_RETURN_VAL(es, NULL);
340
elua_state_include_path_add(Elua_State *es, const char *path)
343
EINA_SAFETY_ON_NULL_RETURN(es);
344
EINA_SAFETY_ON_NULL_RETURN(path);
345
EINA_SAFETY_ON_FALSE_RETURN(path[0]);
346
spath = eina_file_path_sanitize(path);
347
es->lincs = eina_list_append(es->lincs, eina_stringshare_add(spath));
352
elua_state_require_ref_push(Elua_State *es)
354
EINA_SAFETY_ON_NULL_RETURN_VAL(es, EINA_FALSE);
355
EINA_SAFETY_ON_FALSE_RETURN_VAL(es->requireref != LUA_REFNIL, EINA_FALSE);
356
lua_rawgeti(es->luastate, LUA_REGISTRYINDEX, es->requireref);
361
elua_state_appload_ref_push(Elua_State *es)
363
EINA_SAFETY_ON_NULL_RETURN_VAL(es, EINA_FALSE);
364
EINA_SAFETY_ON_FALSE_RETURN_VAL(es->apploadref != LUA_REFNIL, EINA_FALSE);
365
lua_rawgeti(es->luastate, LUA_REGISTRYINDEX, es->apploadref);
370
elua_state_lua_state_get(const Elua_State *es)
372
EINA_SAFETY_ON_NULL_RETURN_VAL(es, NULL);
377
elua_state_from_lua_state_get(lua_State *L)
379
EINA_SAFETY_ON_NULL_RETURN_VAL(L, NULL);
380
lua_getfield(L, LUA_REGISTRYINDEX, "elua_ptr1");
381
lua_getfield(L, LUA_REGISTRYINDEX, "elua_ptr2");
382
if (!lua_isnil(L, -1) && !lua_isnil(L, -2))
384
size_t p1 = (size_t)lua_tonumber(L, -2),
385
p2 = (size_t)lua_tonumber(L, -1);
386
if (p2 && (sizeof(void *) >= sizeof(lua_Number)))
387
p1 |= p2 << ((sizeof(void *) / 2) * CHAR_BIT);
389
return (Elua_State *)p1;
396
_elua_gettext_bind_textdomain(lua_State *L)
399
const char *textdomain = luaL_checkstring(L, 1);
400
const char *dirname = luaL_checkstring(L, 2);
402
if (!textdomain[0] || !strcmp(textdomain, PACKAGE))
405
lua_pushliteral(L, "invalid textdomain");
408
if (!(ret = bindtextdomain(textdomain, dirname)))
411
lua_pushstring(L, strerror(errno));
414
bind_textdomain_codeset(textdomain, "UTF-8");
415
lua_pushstring(L, ret);
418
lua_pushliteral(L, "");
424
_elua_get_message_language(lua_State *L)
427
e = getenv("LANGUAGE");
428
if (e && e[0]) goto success;
429
e = getenv("LC_ALL");
430
if (e && e[0]) goto success;
431
e = getenv("LC_MESSAGES");
432
if (e && e[0]) goto success;
434
if (e && e[0]) goto success;
438
lua_pushstring(L, e);
443
_elua_get_localeconv(lua_State *L)
445
struct lconv *lc = localeconv();
446
lua_createtable(L, 0, 24);
448
#define ELUA_LCF_S(name) \
449
lua_pushstring(L, lc->name); \
450
lua_setfield(L, -2, #name);
452
#define ELUA_LCF_C(name) \
453
lua_pushinteger(L, (lc->name == CHAR_MAX) ? -1 : (int)lc->name); \
454
lua_setfield(L, -2, #name);
456
ELUA_LCF_S(decimal_point);
457
ELUA_LCF_S(thousands_sep);
458
ELUA_LCF_S(grouping);
459
ELUA_LCF_S(int_curr_symbol);
460
ELUA_LCF_S(currency_symbol);
461
ELUA_LCF_S(mon_decimal_point);
462
ELUA_LCF_S(mon_thousands_sep);
463
ELUA_LCF_S(mon_grouping);
464
ELUA_LCF_S(positive_sign);
465
ELUA_LCF_S(negative_sign);
467
ELUA_LCF_C(frac_digits);
468
ELUA_LCF_C(p_cs_precedes);
469
ELUA_LCF_C(n_cs_precedes);
470
ELUA_LCF_C(p_sep_by_space);
471
ELUA_LCF_C(n_sep_by_space);
472
ELUA_LCF_C(p_sign_posn);
473
ELUA_LCF_C(n_sign_posn);
474
ELUA_LCF_C(int_frac_digits);
484
_elua_dgettext(lua_State *L)
486
const char *domain = luaL_checkstring(L, 1);
487
const char *msgid = luaL_checkstring(L, 2);
488
char *ret = dgettext(domain, msgid);
492
lua_pushstring(L, ret);
497
_elua_dngettext(lua_State *L)
499
const char *domain = luaL_checkstring(L, 1);
500
const char *msgid = luaL_checkstring(L, 2);
501
const char *plmsgid = luaL_checkstring(L, 3);
502
char *ret = dngettext(domain, msgid, plmsgid, luaL_checklong(L, 4));
506
lua_pushstring(L, ret);
511
const luaL_Reg gettextlib[] =
513
{ "bind_textdomain", _elua_gettext_bind_textdomain },
514
{ "get_message_language", _elua_get_message_language },
515
{ "get_localeconv", _elua_get_localeconv },
517
{ "dgettext", _elua_dgettext },
518
{ "dngettext", _elua_dngettext },
524
_elua_state_i18n_setup(Elua_State *es)
527
EINA_SAFETY_ON_NULL_RETURN_VAL(es, EINA_FALSE);
528
EINA_SAFETY_ON_NULL_RETURN_VAL(es->coredir, EINA_FALSE);
529
EINA_SAFETY_ON_NULL_RETURN_VAL(es->progname, EINA_FALSE);
530
snprintf(buf, sizeof(buf), "%s/gettext.lua", es->coredir);
531
if (elua_util_error_report(es, elua_io_loadfile(es, buf)))
533
lua_createtable(es->luastate, 0, 0);
534
elua_register(es->luastate, gettextlib);
535
lua_call(es->luastate, 1, 0);
539
int _elua_module_init(lua_State *L);
540
int _elua_module_system_init(lua_State *L);
543
_elua_file_is_dir(lua_State *L)
545
lua_pushboolean(L, ecore_file_is_dir(luaL_checkstring(L, 1)));
550
_elua_file_exists(lua_State *L)
552
lua_pushboolean(L, ecore_file_exists(luaL_checkstring(L, 1)));
557
_elua_file_mkdir(lua_State *L)
559
lua_pushboolean(L, ecore_file_mkdir(luaL_checkstring(L, 1)));
564
_elua_file_mkpath(lua_State *L)
566
lua_pushboolean(L, ecore_file_mkpath(luaL_checkstring(L, 1)));
571
_elua_file_rmdir(lua_State *L)
573
lua_pushboolean(L, ecore_file_rmdir(luaL_checkstring(L, 1)));
578
_elua_file_unlink(lua_State *L)
580
lua_pushboolean(L, ecore_file_unlink(luaL_checkstring(L, 1)));
585
_elua_file_rmrf(lua_State *L)
587
lua_pushboolean(L, ecore_file_recursive_rm(luaL_checkstring(L, 1)));
591
const luaL_Reg _elua_cutillib[] =
593
{ "init_module", _elua_module_init },
594
{ "popenv" , _elua_io_popen },
595
{ "file_is_dir", _elua_file_is_dir },
596
{ "file_exists", _elua_file_exists },
597
{ "file_mkdir" , _elua_file_mkdir },
598
{ "file_mkpath", _elua_file_mkpath },
599
{ "file_rmdir" , _elua_file_rmdir },
600
{ "file_unlink", _elua_file_unlink },
601
{ "file_rmrf" , _elua_file_rmrf },
606
_elua_state_modules_setup(const Elua_State *es)
609
EINA_SAFETY_ON_NULL_RETURN_VAL(es, EINA_FALSE);
610
EINA_SAFETY_ON_NULL_RETURN_VAL(es->coredir, EINA_FALSE);
611
EINA_SAFETY_ON_NULL_RETURN_VAL(es->progname, EINA_FALSE);
612
snprintf(buf, sizeof(buf), "%s/module.lua", es->coredir);
613
if (elua_util_error_report(es, elua_io_loadfile(es, buf)))
615
lua_pushcfunction(es->luastate, _elua_module_system_init);
616
lua_createtable(es->luastate, 0, 0);
617
elua_register(es->luastate, _elua_cutillib);
618
lua_call(es->luastate, 2, 0);
623
_elua_module_init(lua_State *L)
625
Elua_State *es = elua_state_from_lua_state_get(L);
626
if (!lua_isnoneornil(L, 1))
631
if (!lua_isnoneornil(L, 2))
634
es->cmods = eina_list_append(es->cmods,
635
(void*)(size_t)luaL_ref(L, LUA_REGISTRYINDEX));
641
_elua_module_system_init(lua_State *L)
643
Elua_State *es = elua_state_from_lua_state_get(L);
644
const char *corepath = es->coredir;
645
const char *modpath = es->moddir;
646
const char *appspath = es->appsdir;
647
Eina_Stringshare *data = NULL;
648
if (!corepath || !modpath || !appspath)
651
es->requireref = luaL_ref(L, LUA_REGISTRYINDEX);
653
es->apploadref = luaL_ref(L, LUA_REGISTRYINDEX);
655
/* module path, local directories take priority */
657
lua_pushvalue(L, 3); ++n;
658
lua_pushfstring(L, ";%s/?.lua", corepath); ++n;
659
EINA_LIST_FREE(es->lincs, data)
661
lua_pushfstring(L, ";%s/?.lua", data);
662
eina_stringshare_del(data);
665
lua_pushfstring(L, ";%s/?.eo.lua", modpath); ++n;
666
lua_pushfstring(L, ";%s/?.lua", modpath); ++n;
667
lua_pushfstring(L, ";%s/?.lua", appspath); ++n;
670
/* apps path, local directory takes priority as well */
672
lua_pushfstring(L, ";%s/?.lua", appspath);
679
elua_state_setup(Elua_State *es)
681
Eina_Stringshare *data;
682
Eina_Bool failed = EINA_FALSE;
684
if (!_elua_state_modules_setup(es))
686
if (!_elua_state_i18n_setup(es))
688
if (!_elua_state_io_setup(es))
691
/* finally require the necessary modules */
692
EINA_LIST_FREE(es->lmods, data)
696
if (!elua_state_require_ref_push(es))
701
lua_pushstring(es->luastate, data);
702
if (elua_util_error_report(es, lua_pcall(es->luastate, 1, 0, 0)))
708
eina_stringshare_del(data);
714
/* Utility functions - these could be written using the other APIs */
717
_elua_traceback(lua_State *L)
719
lua_getglobal(L, "debug");
720
if (!lua_istable(L, -1))
725
lua_getfield(L, -1, "traceback");
726
if (!lua_isfunction(L, -1))
732
lua_pushinteger(L, 2);
738
_elua_docall(Elua_State *es, int narg, int nret)
741
EINA_SAFETY_ON_NULL_RETURN_VAL(es, -1);
742
int bs = lua_gettop(es->luastate) - narg;
743
lua_pushcfunction(es->luastate, _elua_traceback);
744
lua_insert(es->luastate, bs);
745
status = lua_pcall(es->luastate, narg, nret, bs);
746
lua_remove(es->luastate, bs);
748
lua_gc(es->luastate, LUA_GCCOLLECT, 0);
753
_elua_getargs(Elua_State *es, int argc, char **argv, int n)
756
int narg = argc - (n + 1);
757
EINA_SAFETY_ON_NULL_RETURN_VAL(es, -1);
758
luaL_checkstack(es->luastate, narg + 3, "too many arguments to script");
759
for (i = n + 1; i < argc; ++i)
761
lua_pushstring(es->luastate, argv[i]);
763
lua_createtable(es->luastate, narg, n + 1);
764
for (i = 0; i < argc; ++i)
766
lua_pushstring(es->luastate, argv[i]);
767
lua_rawseti(es->luastate, -2, i - n);
773
elua_util_require(Elua_State *es, const char *libname)
775
EINA_SAFETY_ON_NULL_RETURN_VAL(es, EINA_FALSE);
776
if (!elua_state_require_ref_push(es))
778
/* store stuff until things are correctly set up */
779
es->lmods = eina_list_append(es->lmods, eina_stringshare_add(libname));
782
lua_pushstring(es->luastate, libname);
783
return !elua_util_error_report(es, lua_pcall(es->luastate, 1, 0, 0));
787
elua_util_file_run(Elua_State *es, const char *fname)
789
EINA_SAFETY_ON_NULL_RETURN_VAL(es, EINA_FALSE);
790
return !elua_util_error_report(es, elua_io_loadfile(es, fname)
791
|| _elua_docall(es, 0, 1));
795
elua_util_string_run(Elua_State *es, const char *chunk, const char *chname)
797
EINA_SAFETY_ON_NULL_RETURN_VAL(es, EINA_FALSE);
798
return !elua_util_error_report(es, luaL_loadbuffer(es->luastate, chunk,
799
strlen(chunk), chname)
800
|| _elua_docall(es, 0, 0));
804
elua_util_app_load(Elua_State *es, const char *appname)
806
EINA_SAFETY_ON_NULL_RETURN_VAL(es, -1);
807
EINA_SAFETY_ON_FALSE_RETURN_VAL(elua_state_appload_ref_push(es), -1);
808
lua_pushstring(es->luastate, appname);
809
lua_call(es->luastate, 1, 2);
810
if (lua_isnil(es->luastate, -2))
812
lua_remove(es->luastate, -2);
815
lua_pop(es->luastate, 1);
820
elua_util_script_run(Elua_State *es, int argc, char **argv, int n, int *quit)
824
EINA_SAFETY_ON_FALSE_RETURN_VAL(n < argc, -1);
825
EINA_SAFETY_ON_NULL_RETURN_VAL(es, -1);
827
narg = _elua_getargs(es, argc, argv, n);
828
lua_setglobal(es->luastate, "arg");
829
if (fname[0] == '-' && !fname[1]) fname = NULL;
832
/* check if there is a file of that name */
833
FILE *f = fopen(fname, "rb");
837
status = elua_io_loadfile(es, fname);
840
status = elua_util_app_load(es, fname);
843
status = elua_io_loadfile(es, fname);
844
lua_insert(es->luastate, -(narg + 1));
846
status = _elua_docall(es, narg, 1);
848
lua_pop(es->luastate, narg);
851
*quit = lua_toboolean(es->luastate, -1);
852
lua_pop(es->luastate, 1);
854
return !elua_util_error_report(es, status);
858
_elua_errmsg(const char *pname, const char *msg)
860
ERR("%s%s%s", pname ? pname : "", pname ? ": " : "", msg);
864
elua_util_error_report(const Elua_State *es, int status)
866
EINA_SAFETY_ON_FALSE_RETURN_VAL(es, status);
867
if (status && !lua_isnil(es->luastate, -1))
869
const char *msg = lua_tostring(es->luastate, -1);
870
_elua_errmsg(es->progname, msg ? msg : "(non-string error)");
871
lua_pop(es->luastate, 1);