4 * Copyright (c) Tuomo Valkonen 1999-2005.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
25 #include <libtu/obj.h>
26 #include <libtu/objp.h>
27 #include <libtu/dlist.h>
29 #include "readconfig.h"
33 #define MAGIC 0xf00ba7
35 /* Maximum number of parameters and return values for calls from Lua
36 * and (if va_copy is not available) return value from Lua functions.
40 static lua_State *l_st=NULL;
42 static bool extl_stack_get(lua_State *st, int pos, char type,
43 bool copystring, bool *wasdeadobject,
46 static int extl_protected(lua_State *st);
48 #ifdef EXTL_LOG_ERRORS
49 static void flushtrace();
55 /*{{{ Safer rawget/set/getn */
58 #define CHECK_TABLE(ST, INDEX) luaL_checktype(ST, INDEX, LUA_TTABLE)
60 static int luaL_getn_check(lua_State *st, int index)
62 CHECK_TABLE(st, index);
63 return luaL_getn(st, index);
67 static void lua_rawset_check(lua_State *st, int index)
69 CHECK_TABLE(st, index);
70 lua_rawset(st, index);
74 static void lua_rawseti_check(lua_State *st, int index, int n)
76 CHECK_TABLE(st, index);
77 lua_rawseti(st, index, n);
81 static void lua_rawget_check(lua_State *st, int index)
83 CHECK_TABLE(st, index);
84 lua_rawget(st, index);
88 static void lua_rawgeti_check(lua_State *st, int index, int n)
90 CHECK_TABLE(st, index);
91 lua_rawgeti(st, index, n);
98 /*{{{ A cpcall wrapper */
101 typedef bool ExtlCPCallFn(lua_State *st, void *ptr);
111 static int extl_docpcall(lua_State *st)
113 ExtlCPCallParam *param=(ExtlCPCallParam*)lua_touserdata(st, -1);
115 /* Should be enough for most things */
116 if(!lua_checkstack(st, 8)){
117 extl_warn(TR("Lua stack full."));
121 param->retval=param->fn(st, param->udata);
126 static bool extl_cpcall(lua_State *st, ExtlCPCallFn *fn, void *ptr)
128 ExtlCPCallParam param;
129 int oldtop=lua_gettop(st);
137 err=lua_cpcall(st, extl_docpcall, ¶m);
139 extl_warn("%s", lua_tostring(st, -1));
140 }else if(err==LUA_ERRMEM){
141 extl_warn("%s", strerror(ENOMEM));
143 extl_warn(TR("Unknown Lua error."));
146 lua_settop(st, oldtop);
155 /*{{{ Obj userdata handling -- unsafe */
158 static int owned_cache_ref=LUA_NOREF;
161 static Obj *extl_get_obj(lua_State *st, int pos,
162 bool *invalid, bool *dead)
169 if(!lua_isuserdata(st, pos)){
170 *invalid=!lua_isnil(st, pos);
174 if(!lua_getmetatable(st, pos))
177 /* If the userdata object is a proper Obj, metatable[MAGIC] must
178 * have been set to MAGIC.
180 lua_pushnumber(st, MAGIC);
181 lua_gettable(st, -2);
182 val=lua_tonumber(st, -1);
186 ExtlProxy *proxy=(ExtlProxy*)lua_touserdata(st, pos);
191 Obj *obj=EXTL_PROXY_OBJ(proxy);
204 static void extl_uncache_(lua_State *st, Obj *obj)
206 if(EXTL_OBJ_OWNED(obj)){
207 lua_rawgeti(st, LUA_REGISTRYINDEX, owned_cache_ref);
208 lua_pushlightuserdata(st, obj);
212 lua_pushlightuserdata(st, obj);
214 lua_rawset(st, LUA_REGISTRYINDEX);
219 void extl_uncache(Obj *obj)
221 extl_cpcall(l_st, (ExtlCPCallFn*)extl_uncache_, obj);
225 static void extl_push_obj(lua_State *st, Obj *obj)
234 if(EXTL_OBJ_CACHED(obj)){
235 if(EXTL_OBJ_OWNED(obj)){
236 lua_rawgeti(st, LUA_REGISTRYINDEX, owned_cache_ref);
237 lua_pushlightuserdata(st, obj);
239 lua_remove(st, -2); /* owned_cache */
241 lua_pushlightuserdata(st, obj);
242 lua_rawget(st, LUA_REGISTRYINDEX);
244 if(lua_isuserdata(st, -1)){
245 D(fprintf(stderr, "found %p cached\n", obj));
251 D(fprintf(stderr, "Creating %p\n", obj));
253 proxy=(ExtlProxy*)lua_newuserdata(st, sizeof(ExtlProxy));
255 /* Lua shouldn't return if the allocation fails */
257 lua_pushfstring(st, "luaextl_%s_metatable", OBJ_TYPESTR(obj));
258 lua_gettable(st, LUA_REGISTRYINDEX);
259 if(lua_isnil(st, -1)){
263 lua_setmetatable(st, -2);
266 if(EXTL_OBJ_OWNED(obj)){
267 lua_rawgeti(st, LUA_REGISTRYINDEX, owned_cache_ref);
268 lua_pushlightuserdata(st, obj);
269 lua_pushvalue(st, -3); /* the WWatch */
270 lua_rawset_check(st, -3);
271 lua_pop(st, 1); /* owned_cache */
273 lua_pushlightuserdata(st, obj);
274 lua_pushvalue(st, -2); /* the WWatch */
275 lua_rawset_check(st, LUA_REGISTRYINDEX);
277 EXTL_BEGIN_PROXY_OBJ(proxy, obj);
282 /*{{{ Functions available to Lua code */
285 static int extl_obj_gc_handler(lua_State *st)
288 bool dead=FALSE, invalid=FALSE;
291 obj=extl_get_obj(st, 1, &invalid, &dead);
294 /* This should not happen, actually. Our object cache should
295 * hold references to all objects seen on the Lua side until
296 * they are destroyed.
301 proxy=(ExtlProxy*)lua_touserdata(st, 1);
304 EXTL_END_PROXY_OBJ(proxy, obj);
306 if(EXTL_OBJ_OWNED(obj))
307 EXTL_DESTROY_OWNED_OBJ(obj);
313 static int extl_obj_typename(lua_State *st)
317 if(!extl_stack_get(st, 1, 'o', FALSE, NULL, &obj) || obj==NULL)
320 lua_pushstring(st, EXTL_OBJ_TYPENAME(obj));
324 /* Dummy code for documentation generation. */
327 * Return type name of \var{obj}.
329 EXTL_EXPORT_AS(global, obj_typename)
330 const char *__obj_typename(Obj *obj);
333 static int extl_obj_exists(lua_State *st)
337 extl_stack_get(st, 1, 'o', FALSE, NULL, &obj);
339 lua_pushboolean(st, obj!=NULL);
344 /* Dummy code for documentation generation. */
347 * Does \var{obj} still exist on the C side of Ion?
349 EXTL_EXPORT_AS(global, obj_exists)
350 bool __obj_exists(Obj *obj);
353 static int extl_obj_is(lua_State *st)
358 extl_stack_get(st, 1, 'o', FALSE, NULL, &obj);
361 lua_pushboolean(st, 0);
363 tn=lua_tostring(st, 2);
364 lua_pushboolean(st, EXTL_OBJ_IS(obj, tn));
370 /* Dummy code for documentation generation. */
373 * Is \var{obj} of type \var{typename}.
375 EXTL_EXPORT_AS(global, obj_is)
376 bool __obj_is(Obj *obj, const char *typename);
379 static int extl_current_file_or_dir(lua_State *st, bool dir)
385 if(lua_getstack(st, 1, &ar)!=1)
387 if(lua_getinfo(st, "S", &ar)==0)
390 if(ar.source==NULL || ar.source[0]!='@')
391 return 0; /* not a file */
396 lua_pushstring(st, s);
400 lua_pushstring(st, ".");
402 lua_pushlstring(st, s, p-s);
408 extl_warn("Unable to get caller file from stack.");
413 static int extl_dopath(lua_State *st)
415 const char *toincl, *cfdir;
418 toincl=luaL_checkstring(st, 1);
419 complain=!lua_toboolean(st, 2);
421 if(extl_current_file_or_dir(st, TRUE)!=1){
422 res=extl_read_config(toincl, NULL, complain);
424 cfdir=lua_tostring(st, -1);
425 res=extl_read_config(toincl, cfdir, complain);
428 lua_pushboolean(st, res);
432 /* Dummy code for documentation generation. */
435 * Look up and execute another file with Lua code.
437 EXTL_EXPORT_AS(global, dopath)
438 bool dopath(const char *what);
444 static bool extl_init_obj_info(lua_State *st)
446 static ExtlExportedFnSpec dummy[]={
447 {NULL, NULL, NULL, NULL, NULL, FALSE, FALSE}
450 extl_register_class("Obj", dummy, NULL);
452 /* Create cache for proxies to objects owned by Lua-side.
453 * These need to be in a weak table to ever be collected.
457 lua_pushstring(st, "__mode");
458 lua_pushstring(st, "v");
459 lua_rawset_check(st, -3);
460 lua_setmetatable(st, -2);
461 owned_cache_ref=lua_ref(st, -1);
463 lua_pushcfunction(st, extl_obj_typename);
464 lua_setglobal(st, "obj_typename");
465 lua_pushcfunction(st, extl_obj_is);
466 lua_setglobal(st, "obj_is");
467 lua_pushcfunction(st, extl_obj_exists);
468 lua_setglobal(st, "obj_exists");
469 lua_pushcfunction(st, extl_dopath);
470 lua_setglobal(st, "dopath");
471 lua_pushcfunction(st, extl_protected);
472 lua_setglobal(st, "protected");
481 /*{{{ Error handling and reporting -- unsafe */
484 static int extl_stack_trace(lua_State *st)
490 lua_pushstring(st, TR("Stack trace:"));
492 for( ; lua_getstack(st, lvl, &ar); lvl++){
495 if(lua_getinfo(st, "Sln", &ar)==0){
497 TR("\n(Unable to get debug info for level %d)"),
503 is_c=(ar.what!=NULL && strcmp(ar.what, "C")==0);
505 if(!is_c || ar.name!=NULL){
506 lua_pushfstring(st, "\n%d %s", lvl, ar.short_src);
507 if(ar.currentline!=-1)
508 lua_pushfstring(st, ":%d", ar.currentline);
510 lua_pushfstring(st, ": in '%s'", ar.name);
511 lua_concat(st, 2+(ar.currentline!=-1)+(ar.name!=NULL));
515 lua_pushstring(st, TR("\n [Skipping unnamed C functions.]"));
516 /*lua_pushstring(st, "\n...skipping...");*/
526 #ifdef EXTL_LOG_ERRORS
528 static int extl_do_collect_errors(lua_State *st)
531 ErrorLog *el=(ErrorLog*)lua_touserdata(st, -1);
536 err=lua_pcall(st, n, 0, 0);
539 extl_warn("%s", lua_tostring(st, -1));
543 lua_pushstring(st, el->msgs);
548 int extl_collect_errors(lua_State *st)
551 int n=lua_gettop(st);
554 lua_pushcfunction(st, extl_do_collect_errors);
556 lua_pushlightuserdata(st, &el);
560 err=lua_pcall(st, n+1, 1, 0);
563 errorlog_deinit(&el);
566 extl_warn(TR("Internal error."));
577 /*{{{ Init -- unsafe, but it doesn't matter at this point */
582 l_st=luaL_newstate();
585 extl_warn(TR("Unable to initialize Lua."));
589 /* This is equivalent to calling all the ones below but it also includes
590 * the debug library, so I went with those in case there was a reason not
591 * to include the debug library.
595 lua_pushcfunction(l_st, luaopen_base);
596 lua_call(l_st, 0, 0);
598 lua_pushcfunction(l_st, luaopen_table);
599 lua_call(l_st, 0, 0);
601 lua_pushcfunction(l_st, luaopen_io);
602 lua_call(l_st, 0, 0);
604 lua_pushcfunction(l_st, luaopen_os);
605 lua_call(l_st, 0, 0);
607 lua_pushcfunction(l_st, luaopen_string);
608 lua_call(l_st, 0, 0);
610 lua_pushcfunction(l_st, luaopen_math);
611 lua_call(l_st, 0, 0);
613 lua_pushcfunction(l_st, luaopen_package);
614 lua_call(l_st, 0, 0);
616 if(!extl_init_obj_info(l_st)){
621 #ifdef EXTL_LOG_ERRORS
622 lua_pushcfunction(l_st, extl_collect_errors);
623 lua_setglobal(l_st, "collect_errors");
640 /*{{{ Stack get/push -- all unsafe */
643 static bool extl_stack_get(lua_State *st, int pos, char type,
644 bool copystring, bool *wasdeadobject,
650 if(wasdeadobject!=NULL)
651 *wasdeadobject=FALSE;
653 if(type=='i' || type=='d'){
654 if(lua_type(st, pos)!=LUA_TNUMBER)
657 d=lua_tonumber(st, pos);
666 *((double*)valret)=d;
673 *((bool*)valret)=lua_toboolean(st, pos);
677 if(lua_type(st, pos)==LUA_TNIL || lua_type(st, pos)==LUA_TNONE){
678 if(type=='t' || type=='f'){
680 *((int*)valret)=LUA_NOREF;
681 }else if(type=='s' || type=='S'){
683 *((char**)valret)=NULL;
686 *((Obj**)valret)=NULL;
693 if(type=='s' || type=='S'){
694 if(lua_type(st, pos)!=LUA_TSTRING)
697 str=lua_tostring(st, pos);
698 if(str!=NULL && copystring){
703 *((const char**)valret)=str;
709 if(!lua_isfunction(st, pos))
712 lua_pushvalue(st, pos);
713 *((int*)valret)=lua_ref(st, 1);
719 if(!lua_istable(st, pos))
722 lua_pushvalue(st, pos);
723 *((int*)valret)=lua_ref(st, 1);
729 bool invalid=FALSE, dead=FALSE;
730 Obj *obj=extl_get_obj(st, pos, &invalid, &dead);
731 if(wasdeadobject!=NULL)
734 *((Obj**)valret)=obj;
735 D(fprintf(stderr, "Got obj %p, ", obj);
736 fprintf(stderr, "%s\n", OBJ_TYPESTR(obj)));
745 static void extl_stack_push(lua_State *st, char spec, void *ptr)
748 lua_pushnumber(st, *(int*)ptr);
750 lua_pushnumber(st, *(double*)ptr);
752 lua_pushboolean(st, *(bool*)ptr);
754 extl_push_obj(st, *(Obj**)ptr);
755 }else if(spec=='s' || spec=='S'){
756 lua_pushstring(st, *(char**)ptr);
757 }else if(spec=='t' || spec=='f'){
758 lua_rawgeti(st, LUA_REGISTRYINDEX, *(int*)ptr);
765 static bool extl_stack_push_vararg(lua_State *st, char spec, va_list *argsp)
769 lua_pushnumber(st, (double)va_arg(*argsp, int));
772 lua_pushnumber(st, va_arg(*argsp, double));
775 lua_pushboolean(st, va_arg(*argsp, bool));
778 extl_push_obj(st, va_arg(*argsp, Obj*));
782 lua_pushstring(st, va_arg(*argsp, char*));
786 lua_rawgeti(st, LUA_REGISTRYINDEX, va_arg(*argsp, int));
802 enum{STRINGS_NONE, STRINGS_NONCONST, STRINGS_ALL};
805 static void extl_free(void *ptr, char spec, int strings)
807 if(((spec=='s' && strings!=STRINGS_NONE) ||
808 (spec=='S' && strings==STRINGS_ALL)) && *(char**)ptr!=NULL){
809 if(*(char**)ptr!=NULL)
813 extl_unref_table(*(ExtlTab*)ptr);
815 extl_unref_fn(*(ExtlFn*)ptr);
823 /*{{{ Table and function references. */
826 static bool extl_getref(lua_State *st, int ref)
828 lua_rawgeti(st, LUA_REGISTRYINDEX, ref);
829 if(lua_isnil(st, -1)){
838 static bool extl_do_unref(lua_State *st, int *refp)
840 lua_unref(st, *refp);
845 ExtlFn extl_unref_fn(ExtlFn ref)
847 extl_cpcall(l_st, (ExtlCPCallFn*)extl_do_unref, &ref);
852 ExtlFn extl_unref_table(ExtlTab ref)
854 extl_cpcall(l_st, (ExtlCPCallFn*)extl_do_unref, &ref);
861 ExtlFn extl_fn_none()
867 ExtlTab extl_table_none()
875 static bool extl_do_ref(lua_State *st, int *refp)
877 if(!extl_getref(st, *refp))
879 *refp=lua_ref(st, 1);
884 ExtlTab extl_ref_table(ExtlTab ref)
886 if(extl_cpcall(l_st, (ExtlCPCallFn*)extl_do_ref, &ref))
892 ExtlFn extl_ref_fn(ExtlFn ref)
894 if(extl_cpcall(l_st, (ExtlCPCallFn*)extl_do_ref, &ref))
902 static bool extl_do_create_table(lua_State *st, int *refp)
905 *refp=lua_ref(st, 1);
910 ExtlTab extl_create_table()
913 if(extl_cpcall(l_st, (ExtlCPCallFn*)extl_do_create_table, &ref))
927 static bool extl_do_eq(lua_State *st, EqParams *ep)
929 if(!extl_getref(st, ep->o1))
931 if(!extl_getref(st, ep->o2))
933 ep->ret=lua_equal(st, -1, -2);
938 bool extl_fn_eq(ExtlFn fn1, ExtlFn fn2)
944 extl_cpcall(l_st, (ExtlCPCallFn*)extl_do_eq, &ep);
949 bool extl_table_eq(ExtlTab t1, ExtlTab t2)
955 extl_cpcall(l_st, (ExtlCPCallFn*)extl_do_eq, &ep);
974 static bool extl_table_dodo_get2(lua_State *st, TableParams2 *params)
979 lua_rawgeti(st, LUA_REGISTRYINDEX, params->ref);
980 extl_stack_push_vararg(st, params->itype, params->argsp);
981 lua_gettable(st, -2);
982 if(lua_isnil(st, -1))
985 return extl_stack_get(st, -1, params->type, TRUE, NULL,
986 va_arg(*(params->argsp), void*));
990 bool extl_table_get_vararg(ExtlTab ref, char itype, char type, va_list *args)
999 return extl_cpcall(l_st, (ExtlCPCallFn*)extl_table_dodo_get2, ¶ms);
1003 bool extl_table_get(ExtlTab ref, char itype, char type, ...)
1008 va_start(args, type);
1009 retval=extl_table_get_vararg(ref, itype, type, &args);
1016 static bool extl_table_do_gets(ExtlTab ref, const char *entry,
1017 char type, void *valret)
1019 return extl_table_get(ref, 's', type, entry, valret);
1022 bool extl_table_gets_o(ExtlTab ref, const char *entry, Obj **ret)
1024 return extl_table_do_gets(ref, entry, 'o', (void*)ret);
1027 bool extl_table_gets_i(ExtlTab ref, const char *entry, int *ret)
1029 return extl_table_do_gets(ref, entry, 'i', (void*)ret);
1032 bool extl_table_gets_d(ExtlTab ref, const char *entry, double *ret)
1034 return extl_table_do_gets(ref, entry, 'd', (void*)ret);
1037 bool extl_table_gets_b(ExtlTab ref, const char *entry, bool *ret)
1039 return extl_table_do_gets(ref, entry, 'b', (void*)ret);
1042 bool extl_table_gets_s(ExtlTab ref, const char *entry, char **ret)
1044 return extl_table_do_gets(ref, entry, 's', (void*)ret);
1047 bool extl_table_gets_f(ExtlTab ref, const char *entry, ExtlFn *ret)
1049 return extl_table_do_gets(ref, entry, 'f', (void*)ret);
1052 bool extl_table_gets_t(ExtlTab ref, const char *entry, ExtlTab *ret)
1054 return extl_table_do_gets(ref, entry, 't', (void*)ret);
1058 static bool extl_table_do_geti(ExtlTab ref, int entry, char type, void *valret)
1060 return extl_table_get(ref, 'i', type, entry, valret);
1063 bool extl_table_geti_o(ExtlTab ref, int entry, Obj **ret)
1065 return extl_table_do_geti(ref, entry, 'o', (void*)ret);
1068 bool extl_table_geti_i(ExtlTab ref, int entry, int *ret)
1070 return extl_table_do_geti(ref, entry, 'i', (void*)ret);
1073 bool extl_table_geti_d(ExtlTab ref, int entry, double *ret)
1075 return extl_table_do_geti(ref, entry, 'd', (void*)ret);
1078 bool extl_table_geti_b(ExtlTab ref, int entry, bool *ret)
1080 return extl_table_do_geti(ref, entry, 'b', (void*)ret);
1083 bool extl_table_geti_s(ExtlTab ref, int entry, char **ret)
1085 return extl_table_do_geti(ref, entry, 's', (void*)ret);
1088 bool extl_table_geti_f(ExtlTab ref, int entry, ExtlFn *ret)
1090 return extl_table_do_geti(ref, entry, 'f', (void*)ret);
1093 bool extl_table_geti_t(ExtlTab ref, int entry, ExtlTab *ret)
1095 return extl_table_do_geti(ref, entry, 't', (void*)ret);
1105 static bool extl_table_do_get_n(lua_State *st, GetNParams *params)
1107 lua_rawgeti(st, LUA_REGISTRYINDEX, params->ref);
1108 params->n=luaL_getn_check(st, -1);
1113 int extl_table_get_n(ExtlTab ref)
1121 extl_cpcall(l_st, (ExtlCPCallFn*)extl_table_do_get_n, ¶ms);
1133 static bool extl_table_dodo_set2(lua_State *st, TableParams2 *params)
1135 lua_rawgeti(st, LUA_REGISTRYINDEX, params->ref);
1136 extl_stack_push_vararg(st, params->itype, params->argsp);
1137 extl_stack_push_vararg(st, params->type, params->argsp);
1138 lua_rawset_check(st, -3);
1143 bool extl_table_set_vararg(ExtlTab ref, char itype, char type, va_list *args)
1145 TableParams2 params;
1152 return extl_cpcall(l_st, (ExtlCPCallFn*)extl_table_dodo_set2, ¶ms);
1156 bool extl_table_set(ExtlTab ref, char itype, char type, ...)
1161 va_start(args, type);
1162 retval=extl_table_set_vararg(ref, itype, type, &args);
1169 bool extl_table_sets_o(ExtlTab ref, const char *entry, Obj *val)
1171 return extl_table_set(ref, 's', 'o', entry, val);
1174 bool extl_table_sets_i(ExtlTab ref, const char *entry, int val)
1176 return extl_table_set(ref, 's', 'i', entry, val);
1179 bool extl_table_sets_d(ExtlTab ref, const char *entry, double val)
1181 return extl_table_set(ref, 's', 'd', entry, val);
1184 bool extl_table_sets_b(ExtlTab ref, const char *entry, bool val)
1186 return extl_table_set(ref, 's', 'b', entry, val);
1189 bool extl_table_sets_s(ExtlTab ref, const char *entry, const char *val)
1191 return extl_table_set(ref, 's', 'S', entry, val);
1194 bool extl_table_sets_f(ExtlTab ref, const char *entry, ExtlFn val)
1196 return extl_table_set(ref, 's', 'f', entry, val);
1199 bool extl_table_sets_t(ExtlTab ref, const char *entry, ExtlTab val)
1201 return extl_table_set(ref, 's', 't', entry, val);
1205 bool extl_table_seti_o(ExtlTab ref, int entry, Obj *val)
1207 return extl_table_set(ref, 'i', 'o', entry, val);
1210 bool extl_table_seti_i(ExtlTab ref, int entry, int val)
1212 return extl_table_set(ref, 'i', 'i', entry, val);
1215 bool extl_table_seti_d(ExtlTab ref, int entry, double val)
1217 return extl_table_set(ref, 'i', 'd', entry, val);
1220 bool extl_table_seti_b(ExtlTab ref, int entry, bool val)
1222 return extl_table_set(ref, 'i', 'b', entry, val);
1225 bool extl_table_seti_s(ExtlTab ref, int entry, const char *val)
1227 return extl_table_set(ref, 'i', 'S', entry, val);
1230 bool extl_table_seti_f(ExtlTab ref, int entry, ExtlFn val)
1232 return extl_table_set(ref, 'i', 'f', entry, val);
1235 bool extl_table_seti_t(ExtlTab ref, int entry, ExtlTab val)
1237 return extl_table_set(ref, 'i', 't', entry, val);
1244 /*{{{Â Table/clear entry */
1247 static bool extl_table_dodo_clear2(lua_State *st, TableParams2 *params)
1249 lua_rawgeti(st, LUA_REGISTRYINDEX, params->ref);
1250 extl_stack_push_vararg(st, params->itype, params->argsp);
1252 lua_rawset_check(st, -3);
1256 bool extl_table_clear_vararg(ExtlTab ref, char itype, va_list *args)
1258 TableParams2 params;
1262 /*params.type='?';*/
1265 return extl_cpcall(l_st, (ExtlCPCallFn*)extl_table_dodo_clear2, ¶ms);
1268 bool extl_table_clear(ExtlTab ref, char itype, ...)
1273 va_start(args, itype);
1274 retval=extl_table_clear_vararg(ref, itype, &args);
1281 bool extl_table_clears(ExtlTab ref, const char *entry)
1283 return extl_table_clear(ref, 's', entry);
1286 bool extl_table_cleari(ExtlTab ref, int entry)
1288 return extl_table_clear(ref, 'i', entry);
1296 /*{{{ Function calls to Lua */
1299 static bool extl_push_args(lua_State *st, const char *spec, va_list *argsp)
1304 if(!extl_stack_push_vararg(st, *spec, argsp))
1320 #ifndef CF_HAS_VA_COPY
1321 void *ret_ptrs[MAX_PARAMS];
1326 static bool extl_get_retvals(lua_State *st, int m, ExtlDoCallParam *param)
1329 const char *spec=param->rspec;
1331 #ifdef CF_HAS_VA_COPY
1333 va_copy(args, *(param->args));
1336 extl_warn(TR("Too many return values. Use a C compiler that has "
1337 "va_copy to support more."));
1344 #ifdef CF_HAS_VA_COPY
1345 ptr=va_arg(args, void*);
1347 ptr=va_arg(*(param->args), void*);
1348 param->ret_ptrs[param->nret]=ptr;
1350 if(!extl_stack_get(st, -m, *spec, TRUE, &dead, ptr)){
1351 /* This is the only place where we allow nil-objects */
1352 /*if(*spec=='o' && lua_isnil(st, -m)){
1356 extl_warn(TR("Returned dead object."));
1359 extl_warn(TR("Invalid return value (expected '%c', "
1360 "got lua type \"%s\")."),
1361 *spec, lua_typename(st, lua_type(st, -m)));
1371 #ifdef CF_HAS_VA_COPY
1379 /* The function to be called is expected on the top of stack st.
1380 * This function should be cpcalled through extl_cpcall_call (below), which
1381 * will take care that we don't leak anything in case of error.
1383 static bool extl_dodo_call_vararg(lua_State *st, ExtlDoCallParam *param)
1388 if(lua_isnil(st, -1))
1391 if(param->spec!=NULL)
1392 n=strlen(param->spec);
1394 if(!lua_checkstack(st, n+8)){
1395 extl_warn(TR("Stack full."));
1400 if(!extl_push_args(st, param->spec, param->args))
1404 if(param->rspec!=NULL)
1405 m=strlen(param->rspec);
1409 if(lua_pcall(st, n, m, 0)!=0){
1410 extl_warn("%s", lua_tostring(st, -1));
1415 return extl_get_retvals(st, m, param);
1421 static bool extl_cpcall_call(lua_State *st, ExtlCPCallFn *fn,
1422 ExtlDoCallParam *param)
1429 if(extl_cpcall(st, fn, param))
1432 /* If param.nret>0, there was an error getting some return value and
1433 * we must free what we got.
1436 for(i=0; i<param->nret; i++){
1437 #ifdef CF_HAS_VA_COPY
1438 ptr=va_arg(*(param->args), void*);
1440 ptr=param->ret_ptrs[i];
1442 extl_free(ptr, *(param->rspec+i), STRINGS_ALL);
1449 static bool extl_do_call_vararg(lua_State *st, ExtlDoCallParam *param)
1451 if(!extl_getref(st, *(ExtlFn*)(param->misc)))
1453 return extl_dodo_call_vararg(st, param);
1457 bool extl_call_vararg(ExtlFn fnref, const char *spec,
1458 const char *rspec, va_list *args)
1460 ExtlDoCallParam param;
1462 if(fnref==LUA_NOREF || fnref==LUA_REFNIL)
1468 param.misc=(void*)&fnref;
1470 return extl_cpcall_call(l_st, (ExtlCPCallFn*)extl_do_call_vararg, ¶m);
1474 bool extl_call(ExtlFn fnref, const char *spec, const char *rspec, ...)
1479 va_start(args, rspec);
1480 retval=extl_call_vararg(fnref, spec, rspec, &args);
1490 /*{{{ extl_loadfile/string */
1493 static int call_loaded(lua_State *st)
1495 int i, nargs=lua_gettop(st);
1497 /* Get the loaded file/string as function */
1498 lua_pushvalue(st, lua_upvalueindex(1));
1501 lua_getfenv(st, -1);
1502 lua_pushstring(st, "arg");
1506 for(i=1; i<=nargs; i++){
1507 lua_pushvalue(st, i);
1508 lua_rawseti_check(st, -2, i);
1514 lua_rawset_check(st, -3);
1516 lua_call(st, 0, LUA_MULTRET);
1517 return (lua_gettop(st)-nargs);
1528 static bool extl_do_load(lua_State *st, ExtlLoadParam *param)
1533 res=luaL_loadfile(st, param->src);
1535 res=luaL_loadbuffer(st, param->src, strlen(param->src), param->src);
1539 extl_warn("%s", lua_tostring(st, -1));
1543 lua_newtable(st); /* Create new environment */
1544 /* Now there's fn, newenv in stack */
1545 lua_newtable(st); /* Create metatable */
1546 lua_pushstring(st, "__index");
1547 lua_getfenv(st, -4); /* Get old environment */
1548 lua_rawset_check(st, -3); /* Set metatable.__index */
1549 lua_pushstring(st, "__newindex");
1550 lua_getfenv(st, -4); /* Get old environment */
1551 lua_rawset_check(st, -3); /* Set metatable.__newindex */
1552 /* Now there's fn, newenv, meta in stack */
1553 lua_setmetatable(st, -2); /* Set metatable for new environment */
1554 lua_setfenv(st, -2);
1555 /* Now there should be just fn in stack */
1557 /* Callloaded will put any parameters it gets in the table 'arg' in
1558 * the newly created environment.
1560 lua_pushcclosure(st, call_loaded, 1);
1561 *(param->resptr)=lua_ref(st, -1);
1567 bool extl_loadfile(const char *file, ExtlFn *ret)
1569 ExtlLoadParam param;
1574 return extl_cpcall(l_st, (ExtlCPCallFn*)extl_do_load, ¶m);
1578 bool extl_loadstring(const char *str, ExtlFn *ret)
1580 ExtlLoadParam param;
1585 return extl_cpcall(l_st, (ExtlCPCallFn*)extl_do_load, ¶m);
1592 /*{{{ L1 CH error logging */
1594 #ifdef EXTL_LOG_ERRORS
1596 INTRSTRUCT(WarnChain);
1597 DECLSTRUCT(WarnChain){
1600 WarnHandler *old_handler;
1605 static WarnChain *warnchain=NULL;
1606 static int notrace=0;
1609 static void l1_warn_handler(const char *message)
1611 WarnChain *ch=warnchain;
1612 static int called=0;
1614 assert(warnchain!=NULL);
1616 if(called==0 && notrace==0)
1617 ch->need_trace=TRUE;
1621 ch->old_handler(message);
1627 static void do_trace(WarnChain *ch)
1634 extl_stack_trace(ch->st);
1635 p=lua_tostring(ch->st, -1);
1639 ch->need_trace=FALSE;
1643 static void flushtrace()
1645 if(warnchain && warnchain->need_trace)
1646 do_trace(warnchain);
1654 /*{{{ L1-CH safe functions */
1657 static int protect_count=0;
1658 static ExtlSafelist *safelists=NULL;
1661 void extl_protect(ExtlSafelist *l)
1666 LINK_ITEM(safelists, l, next, prev);
1673 void extl_unprotect(ExtlSafelist *l)
1675 assert(protect_count>0);
1682 UNLINK_ITEM(safelists, l, next, prev);
1688 static bool extl_check_protected(ExtlExportedFnSpec *spec)
1694 if(protect_count>0 && !spec->safe){
1695 for(l=safelists; l!=NULL; l=l->next){
1697 for(j=0; l->list[j]!=NULL; j++){
1698 if(l->list[j]==spec->fn)
1701 if(l->list[j]==NULL){
1717 /*{{{ L1 call handler */
1719 /* To get around potential memory leaks and corruption that could be caused
1720 * by Lua's longjmp-on-error lameness, The L1 call handler is divided into
1721 * two steps. In the first step we first setup a call to the second step.
1722 * At this point it is still fine if Lua raises an error. Then we set up
1723 * our warning handlers and stuff--at which point Lua's raising an error
1724 * would corrupt our data--and finally call the second step with lua_pcall.
1725 * Now the second step can safely call Lua's functions and do what is needed.
1726 * When the second step returns, we deallocate our data in the L1Param
1727 * structure that was passed to the second step and reset warning handlers.
1728 * After that it is again safe to call Lua's functions.
1732 ExtlL2Param ip[MAX_PARAMS];
1733 ExtlL2Param op[MAX_PARAMS];
1734 ExtlExportedFnSpec *spec;
1738 static L1Param *current_param=NULL;
1741 static int extl_l1_call_handler2(lua_State *st)
1743 L1Param *param=current_param;
1744 ExtlExportedFnSpec *spec=param->spec;
1747 D(fprintf(stderr, "%s called\n", spec->name));
1749 if(!lua_checkstack(st, MAX_PARAMS+1)){
1750 extl_warn(TR("Stack full."));
1754 param->ni=(spec->ispec==NULL ? 0 : strlen(spec->ispec));
1756 for(i=0; i<param->ni; i++){
1758 if(!extl_stack_get(st, i+1, spec->ispec[i], FALSE, &dead,
1759 (void*)&(param->ip[i]))){
1761 extl_warn(TR("Argument %d to %s is a dead object."),
1764 extl_warn(TR("Argument %d to %s is of invalid type. "
1765 "(Argument template is '%s', got lua type %s)."),
1766 i+1, spec->name, spec->ispec,
1767 lua_typename(st, lua_type(st, i+1)));
1778 if(!spec->l2handler(spec->fn, param->ip, param->op))
1784 param->no=(spec->ospec==NULL ? 0 : strlen(spec->ospec));
1786 for(i=0; i<param->no; i++)
1787 extl_stack_push(st, spec->ospec[i], (void*)&(param->op[i]));
1793 static void extl_l1_finalize(L1Param *param)
1795 ExtlExportedFnSpec *spec=param->spec;
1798 for(i=0; i<param->ii; i++)
1799 extl_free((void*)&(param->ip[i]), spec->ispec[i], STRINGS_NONE);
1801 for(i=0; i<param->no; i++)
1802 extl_free((void*)&(param->op[i]), spec->ospec[i], STRINGS_NONCONST);
1807 static bool extl_l1_just_check_protected=FALSE;
1810 static int extl_l1_call_handler(lua_State *st)
1812 #ifdef EXTL_LOG_ERRORS
1815 L1Param param={{NULL, }, {NULL, }, NULL, 0, 0, 0};
1818 int n=lua_gettop(st);
1821 /* Get the info we need on the function, check it's ok, and then set
1822 * up a safe environment for extl_l1_call_handler2.
1824 param.spec=(ExtlExportedFnSpec*)lua_touserdata(st, lua_upvalueindex(1));
1826 if(param.spec==NULL){
1827 extl_warn(TR("L1 call handler upvalues corrupt."));
1831 if(param.spec->fn==NULL){
1832 extl_warn(TR("Called function has been unregistered."));
1836 if(extl_l1_just_check_protected){
1837 /* Just checking whether the function may be called. */
1838 lua_pushboolean(st, !extl_check_protected(param.spec));
1842 if(!extl_check_protected(param.spec)){
1843 extl_warn(TR("Attempt to call an unsafe function \"%s\" in "
1844 "restricted mode."), param.spec->name);
1849 lua_pushcfunction(st, extl_l1_call_handler2);
1852 old_param=current_param;
1853 current_param=¶m;
1855 #ifdef EXTL_LOG_ERRORS
1856 ch.old_handler=set_warn_handler(l1_warn_handler);
1857 ch.need_trace=FALSE;
1863 /* Ok, Lua may now freely fail in extl_l1_call_handler2, we can handle
1866 ret=lua_pcall(st, n, LUA_MULTRET, 0);
1868 /* Now that the actual call handler has returned, we need to free
1869 * any of our data before calling Lua again.
1871 current_param=old_param;
1872 extl_l1_finalize(¶m);
1874 #ifdef EXTL_LOG_ERRORS
1876 set_warn_handler(ch.old_handler);
1878 /* Ok, we can now safely use Lua functions again without fear of
1884 p=lua_tostring(st, -1);
1890 if(ret!=0 || ch.need_trace)
1902 * Is calling the function \var{fn} not allowed now? If \var{fn} is nil,
1903 * tells if some functions are not allowed to be called now due to
1906 EXTL_EXPORT_AS(global, protected)
1907 bool __protected(ExtlFn fn);
1909 static int extl_protected(lua_State *st)
1913 if(lua_isnil(st, 1)){
1914 lua_pushboolean(st, protect_count>0);
1918 if(!lua_isfunction(st, 1)){
1919 lua_pushboolean(st, TRUE);
1923 if(lua_tocfunction(st, 1)!=(lua_CFunction)extl_l1_call_handler){
1924 lua_pushboolean(st, FALSE);
1928 extl_l1_just_check_protected=TRUE;
1929 ret=lua_pcall(st, 0, 1, 0);
1930 extl_l1_just_check_protected=FALSE;
1932 lua_pushboolean(st, TRUE);
1939 /*{{{ Function registration */
1943 ExtlExportedFnSpec *spec;
1949 static bool extl_do_register_function(lua_State *st, RegData *data)
1951 ExtlExportedFnSpec *spec=data->spec, *spec2;
1952 int ind=LUA_GLOBALSINDEX;
1954 if((spec->ispec!=NULL && strlen(spec->ispec)>MAX_PARAMS) ||
1955 (spec->ospec!=NULL && strlen(spec->ospec)>MAX_PARAMS)){
1956 extl_warn(TR("Function '%s' has more parameters than the level 1 "
1957 "call handler can handle"), spec->name);
1961 if(data->table!=LUA_NOREF){
1962 lua_rawgeti(st, LUA_REGISTRYINDEX, data->table);
1966 lua_pushstring(st, spec->name);
1968 spec2=lua_newuserdata(st, sizeof(ExtlExportedFnSpec));
1970 memcpy(spec2, spec, sizeof(ExtlExportedFnSpec));
1972 lua_getregistry(st);
1973 lua_pushvalue(st, -2); /* Get spec2 */
1974 lua_pushfstring(st, "luaextl_%s_%s_upvalue",
1975 data->cls, spec->name);
1976 lua_rawset_check(st, -3); /* Set registry.luaextl_fn_upvalue=spec2 */
1977 lua_pop(st, 1); /* Pop registry */
1978 lua_pushcclosure(st, extl_l1_call_handler, 1);
1979 lua_rawset_check(st, ind);
1985 static bool extl_do_register_functions(ExtlExportedFnSpec *spec, int max,
1986 const char *cls, int table)
1993 regdata.table=table;
1995 for(i=0; spec[i].name && i<max; i++){
1996 regdata.spec=&(spec[i]);
1997 if(!extl_cpcall(l_st, (ExtlCPCallFn*)extl_do_register_function,
2007 bool extl_register_function(ExtlExportedFnSpec *spec)
2009 return extl_do_register_functions(spec, 1, "", LUA_NOREF);
2013 bool extl_register_functions(ExtlExportedFnSpec *spec)
2015 return extl_do_register_functions(spec, INT_MAX, "", LUA_NOREF);
2019 static bool extl_do_unregister_function(lua_State *st, RegData *data)
2021 ExtlExportedFnSpec *spec=data->spec, *spec2;
2022 int ind=LUA_GLOBALSINDEX;
2024 lua_getregistry(st);
2025 lua_pushfstring(st, "luaextl_%s_%s_upvalue",
2026 data->cls, spec->name);
2027 lua_pushvalue(st, -1);
2028 lua_gettable(st, -3); /* Get registry.luaextl_fn_upvalue */
2029 spec2=lua_touserdata(st, -1);
2038 spec2->l2handler=NULL;
2040 lua_pop(st, 1); /* Pop the upvalue */
2042 lua_rawset_check(st, -3); /* Clear registry.luaextl_fn_upvalue */
2044 if(data->table!=LUA_NOREF){
2045 lua_rawgeti(st, LUA_REGISTRYINDEX, data->table);
2049 /* Clear table.fn */
2050 lua_pushstring(st, spec->name);
2052 lua_rawset_check(st, ind);
2058 static void extl_do_unregister_functions(ExtlExportedFnSpec *spec, int max,
2059 const char *cls, int table)
2066 regdata.table=table;
2068 for(i=0; spec[i].name && i<max; i++){
2069 regdata.spec=&(spec[i]);
2070 extl_cpcall(l_st, (ExtlCPCallFn*)extl_do_unregister_function,
2075 void extl_unregister_function(ExtlExportedFnSpec *spec)
2077 extl_do_unregister_functions(spec, 1, "", LUA_NOREF);
2081 void extl_unregister_functions(ExtlExportedFnSpec *spec)
2083 extl_do_unregister_functions(spec, INT_MAX, "", LUA_NOREF);
2090 /*{{{ Class registration */
2094 const char *cls, *parent;
2100 static bool extl_do_register_class(lua_State *st, ClassData *data)
2102 /* Create the globally visible WFoobar table in which the function
2103 * references reside.
2107 /* Set type information.
2109 lua_pushstring(st, "__typename");
2110 lua_pushstring(st, data->cls);
2111 lua_settable(st, -3);
2113 /* If we have a parent class (i.e. class!=Obj), we want also the parent's
2114 * functions visible in this table so set up a metatable to do so.
2116 if(data->parent!=NULL){
2117 /* Get luaextl_ParentClass_metatable */
2118 lua_pushfstring(st, "luaextl_%s_metatable", data->parent);
2119 lua_gettable(st, LUA_REGISTRYINDEX);
2120 if(!lua_istable(st, -1)){
2121 extl_warn("Could not find metatable for parent class %s of %s.\n",
2122 data->parent, data->cls);
2125 /* Create our metatable */
2127 /* Get parent_metatable.__index */
2128 lua_pushstring(st, "__index");
2129 lua_pushvalue(st, -1);
2130 /* Stack: cls, parent_meta, meta, "__index", "__index" */
2131 lua_gettable(st, -4);
2132 /* Stack: cls, parent_meta, meta, "__index", parent_meta.__index */
2133 lua_pushvalue(st, -1);
2135 /* Stack: cls, parent_meta, meta, parent_meta.__index, "__index", parent_meta.__index */
2136 lua_rawset_check(st, -4);
2137 /* Stack: cls, parent_meta, meta, parent_meta.__index */
2138 lua_pushstring(st, "__parentclass");
2140 /* Stack: cls, parent_meta, meta, "__parentclass", parent_meta.__index */
2141 lua_settable(st, -5);
2142 /* Stack: cls, parent_meta, meta, */
2143 lua_setmetatable(st, -3);
2148 /* Set the global WFoobar */
2149 lua_pushvalue(st, -1);
2150 data->refret=lua_ref(st, 1); /* TODO: free on failure */
2152 lua_pushstring(st, data->cls);
2153 lua_pushvalue(st, -2);
2154 lua_rawset(st, LUA_GLOBALSINDEX);
2157 /* New we create a metatable for the actual objects with __gc metamethod
2158 * and __index pointing to the table created above. The MAGIC entry is
2159 * used to check that userdatas passed to us really are Watches with a
2164 lua_pushnumber(st, MAGIC);
2165 lua_pushnumber(st, MAGIC);
2166 lua_rawset_check(st, -3);
2168 lua_pushstring(st, "__index");
2169 lua_pushvalue(st, -3);
2170 lua_rawset_check(st, -3); /* set metatable.__index=WFoobar created above */
2171 lua_pushstring(st, "__gc");
2172 lua_pushcfunction(st, extl_obj_gc_handler);
2173 lua_rawset_check(st, -3); /* set metatable.__gc=extl_obj_gc_handler */
2174 lua_pushfstring(st, "luaextl_%s_metatable", data->cls);
2176 lua_rawset(st, LUA_REGISTRYINDEX);
2182 bool extl_register_class(const char *cls, ExtlExportedFnSpec *fns,
2187 clsdata.parent=parent;
2188 clsdata.refret=LUA_NOREF;
2189 clsdata.hide=(strcmp(cls, "Obj")==0);/*(fns==NULL);*/
2191 D(assert(strcmp(cls, "Obj")==0 || parent!=NULL));
2193 if(!extl_cpcall(l_st, (ExtlCPCallFn*)extl_do_register_class, &clsdata))
2199 return extl_do_register_functions(fns, INT_MAX, cls, clsdata.refret);
2203 static void extl_do_unregister_class(lua_State *st, ClassData *data)
2205 /* Get reference from registry to the metatable. */
2206 lua_pushfstring(st, "luaextl_%s_metatable", data->cls);
2207 lua_pushvalue(st, -1);
2208 lua_gettable(st, LUA_REGISTRYINDEX);
2209 /* Get __index and return it for resetting the functions. */
2210 lua_pushstring(st, "__index");
2211 lua_gettable(st, -2);
2212 data->refret=lua_ref(st, -1);
2214 /* Set the entry from registry to nil. */
2216 lua_rawset(st, LUA_REGISTRYINDEX);
2218 /* Reset the global reference to the class to nil. */
2219 lua_pushstring(st, data->cls);
2221 lua_rawset(st, LUA_GLOBALSINDEX);
2225 void extl_unregister_class(const char *cls, ExtlExportedFnSpec *fns)
2229 clsdata.parent=NULL;
2230 clsdata.refret=LUA_NOREF;
2231 clsdata.hide=FALSE; /* unused, but initialise */
2233 if(!extl_cpcall(l_st, (ExtlCPCallFn*)extl_do_unregister_class,
2237 /* We still need to reset function upvalues. */
2239 extl_do_unregister_functions(fns, INT_MAX, cls, clsdata.refret);
2246 /*{{{ Module registration */
2249 static bool extl_do_register_module(lua_State *st, ClassData *clsdata)
2251 lua_getglobal(st, clsdata->cls);
2253 if(!lua_istable(st, -1)){
2255 lua_pushvalue(st, -1);
2256 lua_setglobal(st, clsdata->cls);
2258 lua_pushfstring(st, "luaextl_module_%s", clsdata->cls);
2259 lua_pushvalue(st, -2);
2260 lua_rawset(st, LUA_REGISTRYINDEX);
2262 clsdata->refret=lua_ref(st, -1);
2268 bool extl_register_module(const char *mdl, ExtlExportedFnSpec *fns)
2273 clsdata.parent=NULL;
2274 clsdata.refret=LUA_NOREF;
2275 clsdata.hide=FALSE; /* unused, but initialise */
2277 if(!extl_cpcall(l_st, (ExtlCPCallFn*)extl_do_register_module, &clsdata))
2283 return extl_do_register_functions(fns, INT_MAX, mdl, clsdata.refret);
2287 static bool extl_do_unregister_module(lua_State *st, ClassData *clsdata)
2289 lua_pushfstring(st, "luaextl_module_%s", clsdata->cls);
2290 lua_pushvalue(st, -1);
2292 lua_rawset(st, LUA_REGISTRYINDEX);
2293 clsdata->refret=lua_ref(st, -1);
2299 void extl_unregister_module(const char *mdl, ExtlExportedFnSpec *fns)
2304 clsdata.parent=NULL;
2305 clsdata.refret=LUA_NOREF;
2306 clsdata.hide=FALSE; /* unused, but initialise */
2308 if(!extl_cpcall(l_st, (ExtlCPCallFn*)extl_do_unregister_module, &clsdata))
2312 extl_do_unregister_functions(fns, INT_MAX, mdl, clsdata.refret);
2327 static void write_escaped_string(FILE *f, const char *str)
2332 if(((*str)&0x7f)<32 || *str=='"' || *str=='\\'){
2333 /* Lua uses decimal in escapes */
2334 fprintf(f, "\\%03d", (int)(uchar)(*str));
2345 static void indent(FILE *f, int lvl)
2348 for(i=0; i<lvl; i++)
2353 static bool ser(lua_State *st, FILE *f, int lvl)
2356 lua_checkstack(st, 5);
2358 switch(lua_type(st, -1)){
2360 fprintf(f, "%s", lua_toboolean(st, -1) ? "true" : "false");
2363 fprintf(f, "%s", lua_tostring(st, -1));
2369 write_escaped_string(f, lua_tostring(st, -1));
2372 if(lvl+1>=EXTL_MAX_SERIALISE_DEPTH){
2373 extl_warn(TR("Maximal serialisation depth reached."));
2381 while(lua_next(st, -2)!=0){
2382 lua_pushvalue(st, -2);
2394 extl_warn(TR("Unable to serialise type %s."),
2395 lua_typename(st, lua_type(st, -1)));
2402 static bool extl_do_serialise(lua_State *st, SerData *d)
2404 if(!extl_getref(st, d->tab))
2407 return ser(st, d->f, 0);
2411 /* Tab must not contain recursive references! */
2412 extern bool extl_serialise(const char *file, ExtlTab tab)
2418 d.f=fopen(file, "w");
2421 extl_warn_err_obj(file);
2425 fprintf(d.f, TR("-- This file has been generated by Ion. Do not edit.\n"));
2426 fprintf(d.f, "return ");
2428 ret=extl_cpcall(l_st, (ExtlCPCallFn*)extl_do_serialise, &d);
2430 fprintf(d.f, "\n\n");