1 #include <limits.h>
2 #include <Ecore_File.h>
3 #include "elua_private.h"
4
5 static Eina_Prefix *_elua_pfx = NULL;
6
7 static int _elua_init_counter = 0;
8 int _elua_log_dom = -1;
9
10 EAPI int
elua_init(void)11 elua_init(void)
12 {
13 const char *dom = "elua";
14 if (_elua_init_counter > 0) return ++_elua_init_counter;
15
16 eina_init();
17 ecore_file_init();
18
19 _elua_log_dom = eina_log_domain_register(dom, EINA_COLOR_LIGHTBLUE);
20 if (_elua_log_dom < 0)
21 {
22 EINA_LOG_ERR("Could not register log domain: %s", dom);
23 return EINA_FALSE;
24 }
25
26 eina_log_timing(_elua_log_dom, EINA_LOG_STATE_STOP, EINA_LOG_STATE_INIT);
27 INF("elua init");
28
29 _elua_pfx = eina_prefix_new(NULL, elua_init, "ELUA", "elua", "checkme",
30 PACKAGE_BIN_DIR, "", PACKAGE_DATA_DIR,
31 LOCALE_DIR);
32
33 if (!_elua_pfx)
34 {
35 ERR("coul not find elua prefix");
36 return EINA_FALSE;
37 }
38
39 return ++_elua_init_counter;
40 }
41
42 EAPI int
elua_shutdown(void)43 elua_shutdown(void)
44 {
45 if (_elua_init_counter <= 0)
46 {
47 EINA_LOG_ERR("Init count not greater than 0 in shutdown.");
48 return EINA_FALSE;
49 }
50 --_elua_init_counter;
51
52 if (_elua_init_counter > 0)
53 return _elua_init_counter;
54
55 INF("shutdown");
56 eina_log_timing(_elua_log_dom, EINA_LOG_STATE_START, EINA_LOG_STATE_SHUTDOWN);
57
58 eina_prefix_free(_elua_pfx);
59 _elua_pfx = NULL;
60
61 eina_log_domain_unregister(_elua_log_dom);
62 _elua_log_dom = -1;
63
64 ecore_file_shutdown();
65 eina_shutdown();
66 return _elua_init_counter;
67 }
68
69 #ifdef ENABLE_LUA_OLD
70 static int
_ffi_loader(lua_State * L)71 _ffi_loader(lua_State *L)
72 {
73 lua_pushvalue(L, lua_upvalueindex(1));
74 lua_pushliteral(L, "cffi");
75 lua_pushvalue(L, lua_upvalueindex(2));
76 lua_call(L, 2, 1);
77 return 1;
78 }
79
80 #if LUA_VERSION_NUM < 502
81 /* adapted from lua 5.2 source */
82 static const char *
_push_next_template(lua_State * L,const char * path)83 _push_next_template(lua_State *L, const char *path)
84 {
85 while (*path == *LUA_PATHSEP) ++path;
86 if (!*path)
87 return NULL;
88 const char *l = strchr(path, *LUA_PATHSEP);
89 if (!l)
90 l = path + strlen(path);
91 lua_pushlstring(L, path, l - path);
92 return l;
93 }
94
95 static int
_elua_searchpath(lua_State * L)96 _elua_searchpath(lua_State *L)
97 {
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);
102 luaL_Buffer msg;
103 luaL_buffinit(L, &msg);
104 if (*sep)
105 name = luaL_gsub(L, name, sep, dsep);
106 while ((path = _push_next_template(L, path)))
107 {
108 const char *fname = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name);
109 lua_remove(L, -2);
110 FILE *rf = fopen(fname, "r");
111 if (rf)
112 {
113 fclose(rf);
114 return 1; /* found */
115 }
116 lua_pushfstring(L, "\n\tno file " LUA_QS, fname);
117 lua_remove(L, -2);
118 luaL_addvalue(&msg);
119 }
120 luaL_pushresult(&msg);
121 lua_pushnil(L);
122 lua_insert(L, -2);
123 return 2; /* nil plus error message */
124 }
125 #endif
126 #endif
127
128 EAPI Elua_State *
elua_state_new(const char * progname)129 elua_state_new(const char *progname)
130 {
131 Elua_State *ret = NULL;
132 lua_State *L = luaL_newstate();
133 if (!L)
134 return NULL;
135 ret = calloc(1, sizeof(Elua_State));
136 ret->luastate = L;
137 if (progname) ret->progname = eina_stringshare_add(progname);
138 luaL_openlibs(L);
139 #ifdef ENABLE_LUA_OLD
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))
146 {
147 lua_pushcfunction(L, _elua_searchpath);
148 lua_setfield(L, -3, "searchpath");
149 }
150 lua_pop(L, 1);
151 #endif
152 lua_getfield(L, -1, "preload");
153 lua_getfield(L, -2, "searchers");
154 if (lua_isnil(L, -1))
155 {
156 lua_pop(L, 1);
157 lua_getfield(L, -2, "loaders");
158 }
159 if (lua_isnil(L, -1))
160 {
161 ERR("could not find a module searcher");
162 goto err;
163 }
164 lua_rawgeti(L, -1, 3);
165 lua_pushliteral(L, "cffi");
166 if (lua_pcall(L, 1, 2, 0))
167 {
168 ERR("could not find the cffi module");
169 goto err;
170 }
171 if (!lua_isfunction(L, -2))
172 {
173 ERR("could not find the cffi module: %s", lua_tostring(L, -2));
174 goto err;
175 }
176 lua_pushcclosure(L, _ffi_loader, 2);
177 lua_setfield(L, -3, "ffi");
178 lua_pop(L, 3);
179 #endif
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))
183 {
184 lua_pushnumber(L, 0);
185 lua_pushnumber(L, (lua_Number)retn);
186 }
187 else
188 {
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)));
192 }
193 lua_setfield(L, LUA_REGISTRYINDEX, "elua_ptr1");
194 lua_setfield(L, LUA_REGISTRYINDEX, "elua_ptr2");
195 return ret;
196 err:
197 lua_close(L);
198 eina_stringshare_del(ret->progname);
199 free(ret);
200 return NULL;
201 }
202
203 EAPI void
elua_state_free(Elua_State * es)204 elua_state_free(Elua_State *es)
205 {
206 void *data;
207 if (!es) return;
208 if (es->luastate)
209 {
210 EINA_LIST_FREE(es->cmods, data)
211 {
212 lua_rawgeti(es->luastate, LUA_REGISTRYINDEX, (size_t)data);
213 lua_call(es->luastate, 0, 0);
214 }
215 lua_close(es->luastate);
216 }
217 else if (es->cmods)
218 eina_list_free(es->cmods);
219 EINA_LIST_FREE(es->lmods, data)
220 eina_stringshare_del(data);
221 EINA_LIST_FREE(es->lincs, data)
222 eina_stringshare_del(data);
223 eina_stringshare_del(es->progname);
224 eina_stringshare_del(es->coredir);
225 eina_stringshare_del(es->moddir);
226 eina_stringshare_del(es->appsdir);
227 free(es);
228 }
229
230 EAPI void
elua_state_dirs_set(Elua_State * es,const char * core,const char * mods,const char * apps)231 elua_state_dirs_set(Elua_State *es, const char *core, const char *mods,
232 const char *apps)
233 {
234 char *spath = NULL;
235 EINA_SAFETY_ON_NULL_RETURN(es);
236 if (core)
237 {
238 eina_stringshare_del(es->coredir);
239 spath = eina_file_path_sanitize(core);
240 es->coredir = eina_stringshare_add(spath);
241 free(spath);
242 }
243 if (mods)
244 {
245 eina_stringshare_del(es->moddir);
246 spath = eina_file_path_sanitize(mods);
247 es->moddir = eina_stringshare_add(spath);
248 free(spath);
249 }
250 if (apps)
251 {
252 eina_stringshare_del(es->appsdir);
253 spath = eina_file_path_sanitize(apps);
254 es->appsdir = eina_stringshare_add(spath);
255 free(spath);
256 }
257 }
258
259 EAPI void
elua_state_dirs_fill(Elua_State * es,Eina_Bool ignore_env)260 elua_state_dirs_fill(Elua_State *es, Eina_Bool ignore_env)
261 {
262 const char *coredir = NULL, *moddir = NULL, *appsdir = NULL;
263 char coredirbuf[PATH_MAX], moddirbuf[PATH_MAX], appsdirbuf[PATH_MAX];
264 EINA_SAFETY_ON_NULL_RETURN(es);
265 if (!(coredir = es->coredir))
266 {
267 if (ignore_env || !(coredir = getenv("ELUA_CORE_DIR")) || !coredir[0])
268 {
269 coredir = coredirbuf;
270 snprintf(coredirbuf, sizeof(coredirbuf), "%s/core",
271 eina_prefix_data_get(_elua_pfx));
272 }
273 if (coredir) {
274 char *sdir = eina_file_path_sanitize(coredir);
275 es->coredir = eina_stringshare_add(sdir);
276 free(sdir);
277 }
278 }
279 if (!(moddir = es->moddir))
280 {
281 if (ignore_env || !(moddir = getenv("ELUA_MODULES_DIR")) || !moddir[0])
282 {
283 moddir = moddirbuf;
284 snprintf(moddirbuf, sizeof(moddirbuf), "%s/modules",
285 eina_prefix_data_get(_elua_pfx));
286 }
287 if (moddir) {
288 char *sdir = eina_file_path_sanitize(moddir);
289 es->moddir = eina_stringshare_add(sdir);
290 free(sdir);
291 }
292 }
293 if (!(appsdir = es->appsdir))
294 {
295 if (ignore_env || !(appsdir = getenv("ELUA_APPS_DIR")) || !appsdir[0])
296 {
297 appsdir = appsdirbuf;
298 snprintf(appsdirbuf, sizeof(appsdirbuf), "%s/apps",
299 eina_prefix_data_get(_elua_pfx));
300 }
301 if (appsdir) {
302 char *sdir = eina_file_path_sanitize(appsdir);
303 es->appsdir = eina_stringshare_add(sdir);
304 free(sdir);
305 }
306 }
307 }
308
309 EAPI Eina_Stringshare *
elua_state_core_dir_get(const Elua_State * es)310 elua_state_core_dir_get(const Elua_State *es)
311 {
312 EINA_SAFETY_ON_NULL_RETURN_VAL(es, NULL);
313 return es->coredir;
314 }
315
316 EAPI Eina_Stringshare *
elua_state_mod_dir_get(const Elua_State * es)317 elua_state_mod_dir_get(const Elua_State *es)
318 {
319 EINA_SAFETY_ON_NULL_RETURN_VAL(es, NULL);
320 return es->moddir;
321 }
322
323 EAPI Eina_Stringshare *
elua_state_apps_dir_get(const Elua_State * es)324 elua_state_apps_dir_get(const Elua_State *es)
325 {
326 EINA_SAFETY_ON_NULL_RETURN_VAL(es, NULL);
327 return es->appsdir;
328 }
329
330 EAPI Eina_Stringshare *
elua_state_prog_name_get(const Elua_State * es)331 elua_state_prog_name_get(const Elua_State *es)
332 {
333 EINA_SAFETY_ON_NULL_RETURN_VAL(es, NULL);
334 return es->progname;
335 }
336
337 EAPI void
elua_state_include_path_add(Elua_State * es,const char * path)338 elua_state_include_path_add(Elua_State *es, const char *path)
339 {
340 char *spath = NULL;
341 EINA_SAFETY_ON_NULL_RETURN(es);
342 EINA_SAFETY_ON_NULL_RETURN(path);
343 EINA_SAFETY_ON_FALSE_RETURN(path[0]);
344 spath = eina_file_path_sanitize(path);
345 es->lincs = eina_list_append(es->lincs, eina_stringshare_add(spath));
346 free(spath);
347 }
348
349 EAPI Eina_Bool
elua_state_require_ref_push(Elua_State * es)350 elua_state_require_ref_push(Elua_State *es)
351 {
352 EINA_SAFETY_ON_NULL_RETURN_VAL(es, EINA_FALSE);
353 EINA_SAFETY_ON_FALSE_RETURN_VAL(es->requireref != LUA_REFNIL, EINA_FALSE);
354 lua_rawgeti(es->luastate, LUA_REGISTRYINDEX, es->requireref);
355 return EINA_TRUE;
356 }
357
358 EAPI Eina_Bool
elua_state_appload_ref_push(Elua_State * es)359 elua_state_appload_ref_push(Elua_State *es)
360 {
361 EINA_SAFETY_ON_NULL_RETURN_VAL(es, EINA_FALSE);
362 EINA_SAFETY_ON_FALSE_RETURN_VAL(es->apploadref != LUA_REFNIL, EINA_FALSE);
363 lua_rawgeti(es->luastate, LUA_REGISTRYINDEX, es->apploadref);
364 return EINA_TRUE;
365 }
366
367 EAPI lua_State *
elua_state_lua_state_get(const Elua_State * es)368 elua_state_lua_state_get(const Elua_State *es)
369 {
370 EINA_SAFETY_ON_NULL_RETURN_VAL(es, NULL);
371 return es->luastate;
372 }
373
374 EAPI Elua_State *
elua_state_from_lua_state_get(lua_State * L)375 elua_state_from_lua_state_get(lua_State *L)
376 {
377 EINA_SAFETY_ON_NULL_RETURN_VAL(L, NULL);
378 lua_getfield(L, LUA_REGISTRYINDEX, "elua_ptr1");
379 lua_getfield(L, LUA_REGISTRYINDEX, "elua_ptr2");
380 if (!lua_isnil(L, -1) && !lua_isnil(L, -2))
381 {
382 size_t p1 = (size_t)lua_tonumber(L, -2),
383 p2 = (size_t)lua_tonumber(L, -1);
384 if (p2 && (sizeof(void *) >= sizeof(lua_Number)))
385 p1 |= p2 << ((sizeof(void *) / 2) * CHAR_BIT);
386 lua_pop(L, 2);
387 return (Elua_State *)p1;
388 }
389 lua_pop(L, 2);
390 return NULL;
391 }
392
393 static int
_elua_gettext_bind_textdomain(lua_State * L)394 _elua_gettext_bind_textdomain(lua_State *L)
395 {
396 #ifdef ENABLE_NLS
397 const char *textdomain = luaL_checkstring(L, 1);
398 const char *dirname = luaL_checkstring(L, 2);
399 const char *ret;
400 if (!textdomain[0] || !strcmp(textdomain, PACKAGE))
401 {
402 lua_pushnil(L);
403 lua_pushliteral(L, "invalid textdomain");
404 return 2;
405 }
406 if (!(ret = bindtextdomain(textdomain, dirname)))
407 {
408 lua_pushnil(L);
409 lua_pushstring(L, strerror(errno));
410 return 2;
411 }
412 bind_textdomain_codeset(textdomain, "UTF-8");
413 lua_pushstring(L, ret);
414 return 1;
415 #else
416 lua_pushliteral(L, "");
417 return 1;
418 #endif
419 }
420
421 static int
_elua_get_message_language(lua_State * L)422 _elua_get_message_language(lua_State *L)
423 {
424 const char *e;
425 e = getenv("LANGUAGE");
426 if (e && e[0]) goto success;
427 e = getenv("LC_ALL");
428 if (e && e[0]) goto success;
429 e = getenv("LC_MESSAGES");
430 if (e && e[0]) goto success;
431 e = getenv("LANG");
432 if (e && e[0]) goto success;
433 lua_pushnil(L);
434 return 1;
435 success:
436 lua_pushstring(L, e);
437 return 1;
438 };
439
440 static int
_elua_get_localeconv(lua_State * L)441 _elua_get_localeconv(lua_State *L)
442 {
443 struct lconv *lc = localeconv();
444 lua_createtable(L, 0, 24);
445
446 #define ELUA_LCF_S(name) \
447 lua_pushstring(L, lc->name); \
448 lua_setfield(L, -2, #name);
449
450 #define ELUA_LCF_C(name) \
451 lua_pushinteger(L, (lc->name == CHAR_MAX) ? -1 : (int)lc->name); \
452 lua_setfield(L, -2, #name);
453
454 ELUA_LCF_S(decimal_point);
455 ELUA_LCF_S(thousands_sep);
456 ELUA_LCF_S(grouping);
457 ELUA_LCF_S(int_curr_symbol);
458 ELUA_LCF_S(currency_symbol);
459 ELUA_LCF_S(mon_decimal_point);
460 ELUA_LCF_S(mon_thousands_sep);
461 ELUA_LCF_S(mon_grouping);
462 ELUA_LCF_S(positive_sign);
463 ELUA_LCF_S(negative_sign);
464
465 ELUA_LCF_C(frac_digits);
466 ELUA_LCF_C(p_cs_precedes);
467 ELUA_LCF_C(n_cs_precedes);
468 ELUA_LCF_C(p_sep_by_space);
469 ELUA_LCF_C(n_sep_by_space);
470 ELUA_LCF_C(p_sign_posn);
471 ELUA_LCF_C(n_sign_posn);
472 ELUA_LCF_C(int_frac_digits);
473
474 #undef ELUA_LCF_S
475 #undef ELUA_LCF_C
476
477 return 1;
478 };
479
480 #ifdef ENABLE_NLS
481 static int
_elua_dgettext(lua_State * L)482 _elua_dgettext(lua_State *L)
483 {
484 const char *domain = luaL_checkstring(L, 1);
485 const char *msgid = luaL_checkstring(L, 2);
486 char *ret = dgettext(domain, msgid);
487 if (!ret)
488 lua_pushnil(L);
489 else
490 lua_pushstring(L, ret);
491 return 1;
492 }
493
494 static int
_elua_dngettext(lua_State * L)495 _elua_dngettext(lua_State *L)
496 {
497 const char *domain = luaL_checkstring(L, 1);
498 const char *msgid = luaL_checkstring(L, 2);
499 const char *plmsgid = luaL_checkstring(L, 3);
500 char *ret = dngettext(domain, msgid, plmsgid, luaL_checklong(L, 4));
501 if (!ret)
502 lua_pushnil(L);
503 else
504 lua_pushstring(L, ret);
505 return 1;
506 }
507 #endif
508
509 const luaL_Reg gettextlib[] =
510 {
511 { "bind_textdomain", _elua_gettext_bind_textdomain },
512 { "get_message_language", _elua_get_message_language },
513 { "get_localeconv", _elua_get_localeconv },
514 #ifdef ENABLE_NLS
515 { "dgettext", _elua_dgettext },
516 { "dngettext", _elua_dngettext },
517 #endif
518 { NULL, NULL }
519 };
520
521 static Eina_Bool
_elua_state_i18n_setup(Elua_State * es)522 _elua_state_i18n_setup(Elua_State *es)
523 {
524 char buf[PATH_MAX];
525 EINA_SAFETY_ON_NULL_RETURN_VAL(es, EINA_FALSE);
526 EINA_SAFETY_ON_NULL_RETURN_VAL(es->coredir, EINA_FALSE);
527 EINA_SAFETY_ON_NULL_RETURN_VAL(es->progname, EINA_FALSE);
528 snprintf(buf, sizeof(buf), "%s/gettext.lua", es->coredir);
529 if (elua_util_error_report(es, elua_io_loadfile(es, buf)))
530 return EINA_FALSE;
531 lua_createtable(es->luastate, 0, 0);
532 elua_register(es->luastate, gettextlib);
533 lua_call(es->luastate, 1, 0);
534 return EINA_TRUE;
535 }
536
537 int _elua_module_init(lua_State *L);
538 int _elua_module_system_init(lua_State *L);
539
540 static int
_elua_file_is_dir(lua_State * L)541 _elua_file_is_dir(lua_State *L)
542 {
543 lua_pushboolean(L, ecore_file_is_dir(luaL_checkstring(L, 1)));
544 return 1;
545 }
546
547 static int
_elua_file_exists(lua_State * L)548 _elua_file_exists(lua_State *L)
549 {
550 lua_pushboolean(L, ecore_file_exists(luaL_checkstring(L, 1)));
551 return 1;
552 }
553
554 static int
_elua_file_mkdir(lua_State * L)555 _elua_file_mkdir(lua_State *L)
556 {
557 lua_pushboolean(L, ecore_file_mkdir(luaL_checkstring(L, 1)));
558 return 1;
559 }
560
561 static int
_elua_file_mkpath(lua_State * L)562 _elua_file_mkpath(lua_State *L)
563 {
564 lua_pushboolean(L, ecore_file_mkpath(luaL_checkstring(L, 1)));
565 return 1;
566 }
567
568 static int
_elua_file_rmdir(lua_State * L)569 _elua_file_rmdir(lua_State *L)
570 {
571 lua_pushboolean(L, ecore_file_rmdir(luaL_checkstring(L, 1)));
572 return 1;
573 }
574
575 static int
_elua_file_unlink(lua_State * L)576 _elua_file_unlink(lua_State *L)
577 {
578 lua_pushboolean(L, ecore_file_unlink(luaL_checkstring(L, 1)));
579 return 1;
580 }
581
582 static int
_elua_file_rmrf(lua_State * L)583 _elua_file_rmrf(lua_State *L)
584 {
585 lua_pushboolean(L, ecore_file_recursive_rm(luaL_checkstring(L, 1)));
586 return 1;
587 }
588
589 const luaL_Reg _elua_cutillib[] =
590 {
591 { "init_module", _elua_module_init },
592 { "popenv" , _elua_io_popen },
593 { "file_is_dir", _elua_file_is_dir },
594 { "file_exists", _elua_file_exists },
595 { "file_mkdir" , _elua_file_mkdir },
596 { "file_mkpath", _elua_file_mkpath },
597 { "file_rmdir" , _elua_file_rmdir },
598 { "file_unlink", _elua_file_unlink },
599 { "file_rmrf" , _elua_file_rmrf },
600 { NULL , NULL }
601 };
602
603 static Eina_Bool
_elua_state_modules_setup(const Elua_State * es)604 _elua_state_modules_setup(const Elua_State *es)
605 {
606 char buf[PATH_MAX];
607 EINA_SAFETY_ON_NULL_RETURN_VAL(es, EINA_FALSE);
608 EINA_SAFETY_ON_NULL_RETURN_VAL(es->coredir, EINA_FALSE);
609 EINA_SAFETY_ON_NULL_RETURN_VAL(es->progname, EINA_FALSE);
610 snprintf(buf, sizeof(buf), "%s/module.lua", es->coredir);
611 if (elua_util_error_report(es, elua_io_loadfile(es, buf)))
612 return EINA_FALSE;
613 lua_pushcfunction(es->luastate, _elua_module_system_init);
614 lua_createtable(es->luastate, 0, 0);
615 elua_register(es->luastate, _elua_cutillib);
616 lua_call(es->luastate, 2, 0);
617 return EINA_TRUE;
618 }
619
620 int
_elua_module_init(lua_State * L)621 _elua_module_init(lua_State *L)
622 {
623 Elua_State *es = elua_state_from_lua_state_get(L);
624 if (!lua_isnoneornil(L, 1))
625 {
626 lua_pushvalue(L, 1);
627 lua_call(L, 0, 0);
628 }
629 if (!lua_isnoneornil(L, 2))
630 {
631 lua_pushvalue(L, 2);
632 es->cmods = eina_list_append(es->cmods,
633 (void*)(size_t)luaL_ref(L, LUA_REGISTRYINDEX));
634 }
635 return 0;
636 }
637
638 int
_elua_module_system_init(lua_State * L)639 _elua_module_system_init(lua_State *L)
640 {
641 Elua_State *es = elua_state_from_lua_state_get(L);
642 const char *corepath = es->coredir;
643 const char *modpath = es->moddir;
644 const char *appspath = es->appsdir;
645 Eina_Stringshare *data = NULL;
646 if (!corepath || !modpath || !appspath)
647 return 0;
648 lua_pushvalue(L, 1);
649 es->requireref = luaL_ref(L, LUA_REGISTRYINDEX);
650 lua_pushvalue(L, 2);
651 es->apploadref = luaL_ref(L, LUA_REGISTRYINDEX);
652
653 /* module path, local directories take priority */
654 int n = 0;
655 lua_pushvalue(L, 3); ++n;
656 lua_pushfstring(L, ";%s/?.lua", corepath); ++n;
657 EINA_LIST_FREE(es->lincs, data)
658 {
659 lua_pushfstring(L, ";%s/?.lua", data);
660 eina_stringshare_del(data);
661 ++n;
662 }
663 lua_pushfstring(L, ";%s/?.eo.lua", modpath); ++n;
664 lua_pushfstring(L, ";%s/?.lua", modpath); ++n;
665 lua_pushfstring(L, ";%s/?.lua", appspath); ++n;
666 lua_concat(L, n);
667
668 /* apps path, local directory takes priority as well */
669 lua_pushvalue(L, 4);
670 lua_pushfstring(L, ";%s/?.lua", appspath);
671 lua_concat(L, 2);
672
673 return 2;
674 }
675
676 EAPI Eina_Bool
elua_state_setup(Elua_State * es)677 elua_state_setup(Elua_State *es)
678 {
679 Eina_Stringshare *data;
680 Eina_Bool failed = EINA_FALSE;
681
682 if (!_elua_state_modules_setup(es))
683 return EINA_FALSE;
684 if (!_elua_state_i18n_setup(es))
685 return EINA_FALSE;
686 if (!_elua_state_io_setup(es))
687 return EINA_FALSE;
688
689 /* finally require the necessary modules */
690 EINA_LIST_FREE(es->lmods, data)
691 {
692 if (!failed)
693 {
694 if (!elua_state_require_ref_push(es))
695 {
696 failed = EINA_TRUE;
697 break;
698 }
699 lua_pushstring(es->luastate, data);
700 if (elua_util_error_report(es, lua_pcall(es->luastate, 1, 0, 0)))
701 {
702 failed = EINA_TRUE;
703 break;
704 }
705 }
706 eina_stringshare_del(data);
707 }
708
709 return EINA_TRUE;
710 }
711
712 /* Utility functions - these could be written using the other APIs */
713
714 static int
_elua_traceback(lua_State * L)715 _elua_traceback(lua_State *L)
716 {
717 lua_getglobal(L, "debug");
718 if (!lua_istable(L, -1))
719 {
720 lua_pop(L, 1);
721 return 1;
722 }
723 lua_getfield(L, -1, "traceback");
724 if (!lua_isfunction(L, -1))
725 {
726 lua_pop(L, 2);
727 return 1;
728 }
729 lua_pushvalue(L, 1);
730 lua_pushinteger(L, 2);
731 lua_call(L, 2, 1);
732 return 1;
733 }
734
735 static int
_elua_docall(Elua_State * es,int narg,int nret)736 _elua_docall(Elua_State *es, int narg, int nret)
737 {
738 int status;
739 EINA_SAFETY_ON_NULL_RETURN_VAL(es, -1);
740 int bs = lua_gettop(es->luastate) - narg;
741 lua_pushcfunction(es->luastate, _elua_traceback);
742 lua_insert(es->luastate, bs);
743 status = lua_pcall(es->luastate, narg, nret, bs);
744 lua_remove(es->luastate, bs);
745 if (status)
746 lua_gc(es->luastate, LUA_GCCOLLECT, 0);
747 return status;
748 }
749
750 static int
_elua_getargs(Elua_State * es,int argc,char ** argv,int n)751 _elua_getargs(Elua_State *es, int argc, char **argv, int n)
752 {
753 int i;
754 int narg = argc - (n + 1);
755 EINA_SAFETY_ON_NULL_RETURN_VAL(es, -1);
756 luaL_checkstack(es->luastate, narg + 3, "too many arguments to script");
757 for (i = n + 1; i < argc; ++i)
758 {
759 lua_pushstring(es->luastate, argv[i]);
760 }
761 lua_createtable(es->luastate, narg, n + 1);
762 for (i = 0; i < argc; ++i)
763 {
764 lua_pushstring(es->luastate, argv[i]);
765 lua_rawseti(es->luastate, -2, i - n);
766 }
767 return narg;
768 }
769
770 EAPI Eina_Bool
elua_util_require(Elua_State * es,const char * libname)771 elua_util_require(Elua_State *es, const char *libname)
772 {
773 EINA_SAFETY_ON_NULL_RETURN_VAL(es, EINA_FALSE);
774 if (!elua_state_require_ref_push(es))
775 {
776 /* store stuff until things are correctly set up */
777 es->lmods = eina_list_append(es->lmods, eina_stringshare_add(libname));
778 return 0;
779 }
780 lua_pushstring(es->luastate, libname);
781 return !elua_util_error_report(es, lua_pcall(es->luastate, 1, 0, 0));
782 }
783
784 EAPI Eina_Bool
elua_util_file_run(Elua_State * es,const char * fname)785 elua_util_file_run(Elua_State *es, const char *fname)
786 {
787 EINA_SAFETY_ON_NULL_RETURN_VAL(es, EINA_FALSE);
788 return !elua_util_error_report(es, elua_io_loadfile(es, fname)
789 || _elua_docall(es, 0, 1));
790 }
791
792 EAPI Eina_Bool
elua_util_string_run(Elua_State * es,const char * chunk,const char * chname)793 elua_util_string_run(Elua_State *es, const char *chunk, const char *chname)
794 {
795 EINA_SAFETY_ON_NULL_RETURN_VAL(es, EINA_FALSE);
796 return !elua_util_error_report(es, luaL_loadbuffer(es->luastate, chunk,
797 strlen(chunk), chname)
798 || _elua_docall(es, 0, 0));
799 }
800
801 EAPI int
elua_util_app_load(Elua_State * es,const char * appname)802 elua_util_app_load(Elua_State *es, const char *appname)
803 {
804 EINA_SAFETY_ON_NULL_RETURN_VAL(es, -1);
805 EINA_SAFETY_ON_FALSE_RETURN_VAL(elua_state_appload_ref_push(es), -1);
806 lua_pushstring(es->luastate, appname);
807 lua_call(es->luastate, 1, 2);
808 if (lua_isnil(es->luastate, -2))
809 {
810 lua_remove(es->luastate, -2);
811 return 1;
812 }
813 lua_pop(es->luastate, 1);
814 return 0;
815 }
816
817 EAPI Eina_Bool
elua_util_script_run(Elua_State * es,int argc,char ** argv,int n,int * quit)818 elua_util_script_run(Elua_State *es, int argc, char **argv, int n, int *quit)
819 {
820 int status, narg;
821 const char *fname;
822 EINA_SAFETY_ON_FALSE_RETURN_VAL(n < argc, -1);
823 EINA_SAFETY_ON_NULL_RETURN_VAL(es, -1);
824 fname = argv[n];
825 narg = _elua_getargs(es, argc, argv, n);
826 lua_setglobal(es->luastate, "arg");
827 if (fname[0] == '-' && !fname[1]) fname = NULL;
828 if (fname)
829 {
830 /* check if there is a file of that name */
831 FILE *f = fopen(fname, "rb");
832 if (f)
833 {
834 fclose(f);
835 status = elua_io_loadfile(es, fname);
836 }
837 else
838 status = elua_util_app_load(es, fname);
839 }
840 else
841 status = elua_io_loadfile(es, fname);
842 lua_insert(es->luastate, -(narg + 1));
843 if (!status)
844 status = _elua_docall(es, narg, 1);
845 else
846 lua_pop(es->luastate, narg);
847 if (!status)
848 {
849 *quit = lua_toboolean(es->luastate, -1);
850 lua_pop(es->luastate, 1);
851 }
852 return !elua_util_error_report(es, status);
853 }
854
855 static void
_elua_errmsg(const char * pname,const char * msg)856 _elua_errmsg(const char *pname, const char *msg)
857 {
858 ERR("%s%s%s", pname ? pname : "", pname ? ": " : "", msg);
859 }
860
861 EAPI int
elua_util_error_report(const Elua_State * es,int status)862 elua_util_error_report(const Elua_State *es, int status)
863 {
864 EINA_SAFETY_ON_FALSE_RETURN_VAL(es, status);
865 if (status && !lua_isnil(es->luastate, -1))
866 {
867 const char *msg = lua_tostring(es->luastate, -1);
868 _elua_errmsg(es->progname, msg ? msg : "(non-string error)");
869 lua_pop(es->luastate, 1);
870 }
871 return status;
872 }
873