11#ifndef KEPLER_PROJECT_COMPAT53_C_
12#define KEPLER_PROJECT_COMPAT53_C_
17#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501
19#ifndef COMPAT53_FOPEN_NO_LOCK
21#define COMPAT53_FOPEN_NO_LOCK 1
23#define COMPAT53_FOPEN_NO_LOCK 0
27#if defined(_MSC_VER) && COMPAT53_FOPEN_NO_LOCK
31#ifndef COMPAT53_HAVE_STRERROR_R
32#if defined(__GLIBC__) || defined(_POSIX_VERSION) || defined(__APPLE__) || (!defined(__MINGW32__) && defined(__GNUC__) && (__GNUC__ < 6))
33#define COMPAT53_HAVE_STRERROR_R 1
35#define COMPAT53_HAVE_STRERROR_R 0
39#ifndef COMPAT53_HAVE_STRERROR_S
40#if defined(_MSC_VER) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || (defined(__STDC_LIB_EXT1__) && __STDC_LIB_EXT1__)
41#define COMPAT53_HAVE_STRERROR_S 1
43#define COMPAT53_HAVE_STRERROR_S 0
47#ifndef COMPAT53_LUA_FILE_BUFFER_SIZE
48#define COMPAT53_LUA_FILE_BUFFER_SIZE 4096
52static char* compat53_strerror(
int en,
char* buff,
size_t sz) {
53#if COMPAT53_HAVE_STRERROR_R
58 if (strerror_r(en, buff, sz)) {
62 if (buff[0] ==
'\0') {
70#elif COMPAT53_HAVE_STRERROR_S
73 strerror_s(buff, sz, en);
88 if (i < 0 && i > LUA_REGISTRYINDEX)
89 i += lua_gettop(L) + 1;
94static void compat53_call_lua(lua_State* L,
char const code[],
size_t len,
int nargs,
int nret) {
95 lua_rawgetp(L, LUA_REGISTRYINDEX, (
void*)code);
96 if (lua_type(L, -1) != LUA_TFUNCTION) {
98 if (luaL_loadbuffer(L, code, len,
"=none"))
100 lua_pushvalue(L, -1);
101 lua_rawsetp(L, LUA_REGISTRYINDEX, (
void*)code);
103 lua_insert(L, -nargs - 1);
104 lua_call(L, nargs, nret);
109 static const char compat53_arith_code[]
110 =
"local op,a,b=...\n"
111 "if op==0 then return a+b\n"
112 "elseif op==1 then return a-b\n"
113 "elseif op==2 then return a*b\n"
114 "elseif op==3 then return a/b\n"
115 "elseif op==4 then return a%b\n"
116 "elseif op==5 then return a^b\n"
117 "elseif op==6 then return -a\n"
120 if (op < LUA_OPADD || op > LUA_OPUNM)
121 luaL_error(L,
"invalid 'op' argument for lua_arith");
122 luaL_checkstack(L, 5,
"not enough stack slots");
124 lua_pushvalue(L, -1);
125 lua_pushnumber(L, op);
127 compat53_call_lua(L, compat53_arith_code,
sizeof(compat53_arith_code) - 1, 3, 1);
131COMPAT53_API int lua_compare(lua_State* L,
int idx1,
int idx2,
int op) {
132 static const char compat53_compare_code[]
139 return lua_equal(L, idx1, idx2);
141 return lua_lessthan(L, idx1, idx2);
143 luaL_checkstack(L, 5,
"not enough stack slots");
144 idx1 = lua_absindex(L, idx1);
145 idx2 = lua_absindex(L, idx2);
146 lua_pushvalue(L, idx1);
147 lua_pushvalue(L, idx2);
148 compat53_call_lua(L, compat53_compare_code,
sizeof(compat53_compare_code) - 1, 2, 1);
149 result = lua_toboolean(L, -1);
153 luaL_error(L,
"invalid 'op' argument for lua_compare");
159COMPAT53_API void lua_copy(lua_State* L,
int from,
int to) {
160 int abs_to = lua_absindex(L, to);
161 luaL_checkstack(L, 1,
"not enough stack slots");
162 lua_pushvalue(L, from);
163 lua_replace(L, abs_to);
168 switch (lua_type(L, i)) {
170 lua_pushnumber(L, (lua_Number)lua_objlen(L, i));
173 if (!luaL_callmeta(L, i,
"__len"))
174 lua_pushnumber(L, (lua_Number)lua_objlen(L, i));
177 if (luaL_callmeta(L, i,
"__len"))
181 luaL_error(L,
"attempt to get length of a %s value", lua_typename(L, lua_type(L, i)));
186COMPAT53_API int lua_rawgetp(lua_State* L,
int i,
const void* p) {
187 int abs_i = lua_absindex(L, i);
188 lua_pushlightuserdata(L, (
void*)p);
189 lua_rawget(L, abs_i);
190 return lua_type(L, -1);
193COMPAT53_API void lua_rawsetp(lua_State* L,
int i,
const void* p) {
194 int abs_i = lua_absindex(L, i);
195 luaL_checkstack(L, 1,
"not enough stack slots");
196 lua_pushlightuserdata(L, (
void*)p);
198 lua_rawset(L, abs_i);
202COMPAT53_API lua_Number lua_tonumberx(lua_State* L,
int i,
int* isnum) {
203 lua_Number n = lua_tonumber(L, i);
205 *isnum = (n != 0 || lua_isnumber(L, i));
216COMPAT53_API void luaL_checkstack(lua_State* L,
int sp,
const char* msg) {
217 if (!lua_checkstack(L, sp + LUA_MINSTACK)) {
219 luaL_error(L,
"stack overflow (%s)", msg);
221 lua_pushliteral(L,
"stack overflow");
228COMPAT53_API int luaL_getsubtable(lua_State* L,
int i,
const char* name) {
229 int abs_i = lua_absindex(L, i);
230 luaL_checkstack(L, 3,
"not enough stack slots");
231 lua_pushstring(L, name);
232 lua_gettable(L, abs_i);
233 if (lua_istable(L, -1))
237 lua_pushstring(L, name);
238 lua_pushvalue(L, -2);
239 lua_settable(L, abs_i);
247 luaL_checkstack(L, 1,
"not enough stack slots");
249 res = lua_tointegerx(L, -1, &isnum);
252 luaL_error(L,
"object length is not an integer");
257COMPAT53_API void luaL_setfuncs(lua_State* L,
const luaL_Reg* l,
int nup) {
258 luaL_checkstack(L, nup + 1,
"too many upvalues");
259 for (; l->name != NULL; l++) {
261 lua_pushstring(L, l->name);
262 for (i = 0; i < nup; i++)
263 lua_pushvalue(L, -(nup + 1));
264 lua_pushcclosure(L, l->func, nup);
265 lua_settable(L, -(nup + 3));
271COMPAT53_API void luaL_setmetatable(lua_State* L,
const char* tname) {
272 luaL_checkstack(L, 1,
"not enough stack slots");
273 luaL_getmetatable(L, tname);
274 lua_setmetatable(L, -2);
278COMPAT53_API void* luaL_testudata(lua_State* L,
int i,
const char* tname) {
279 void* p = lua_touserdata(L, i);
280 luaL_checkstack(L, 2,
"not enough stack slots");
281 if (p == NULL || !lua_getmetatable(L, i))
285 luaL_getmetatable(L, tname);
286 res = lua_rawequal(L, -1, -2);
295static int compat53_countlevels(lua_State* L) {
299 while (lua_getstack(L, le, &ar)) {
305 int m = (li + le) / 2;
306 if (lua_getstack(L, m, &ar))
314static int compat53_findfield(lua_State* L,
int objidx,
int level) {
315 if (level == 0 || !lua_istable(L, -1))
318 while (lua_next(L, -2)) {
319 if (lua_type(L, -2) == LUA_TSTRING) {
320 if (lua_rawequal(L, objidx, -1)) {
324 else if (compat53_findfield(L, objidx, level - 1)) {
326 lua_pushliteral(L,
".");
337static int compat53_pushglobalfuncname(lua_State* L, lua_Debug* ar) {
338 int top = lua_gettop(L);
339 lua_getinfo(L,
"f", ar);
340 lua_pushvalue(L, LUA_GLOBALSINDEX);
341 if (compat53_findfield(L, top + 1, 2)) {
342 lua_copy(L, -1, top + 1);
352static void compat53_pushfuncname(lua_State* L, lua_Debug* ar) {
353 if (*ar->namewhat !=
'\0')
354 lua_pushfstring(L,
"function " LUA_QS, ar->name);
355 else if (*ar->what ==
'm')
356 lua_pushliteral(L,
"main chunk");
357 else if (*ar->what ==
'C') {
358 if (compat53_pushglobalfuncname(L, ar)) {
359 lua_pushfstring(L,
"function " LUA_QS, lua_tostring(L, -1));
363 lua_pushliteral(L,
"?");
366 lua_pushfstring(L,
"function <%s:%d>", ar->short_src, ar->linedefined);
369#define COMPAT53_LEVELS1 12
370#define COMPAT53_LEVELS2 10
372COMPAT53_API void luaL_traceback(lua_State* L, lua_State* L1,
const char* msg,
int level) {
374 int top = lua_gettop(L);
375 int numlevels = compat53_countlevels(L1);
376 int mark = (numlevels > COMPAT53_LEVELS1 + COMPAT53_LEVELS2) ? COMPAT53_LEVELS1 : 0;
378 lua_pushfstring(L,
"%s\n", msg);
379 lua_pushliteral(L,
"stack traceback:");
380 while (lua_getstack(L1, level++, &ar)) {
382 lua_pushliteral(L,
"\n\t...");
383 level = numlevels - COMPAT53_LEVELS2;
386 lua_getinfo(L1,
"Slnt", &ar);
387 lua_pushfstring(L,
"\n\t%s:", ar.short_src);
388 if (ar.currentline > 0)
389 lua_pushfstring(L,
"%d:", ar.currentline);
390 lua_pushliteral(L,
" in ");
391 compat53_pushfuncname(L, &ar);
392 lua_concat(L, lua_gettop(L) - top);
395 lua_concat(L, lua_gettop(L) - top);
399COMPAT53_API int luaL_fileresult(lua_State* L,
int stat,
const char* fname) {
400 const char* serr = NULL;
402 char buf[512] = { 0 };
404 lua_pushboolean(L, 1);
409 serr = compat53_strerror(en, buf,
sizeof(buf));
411 lua_pushfstring(L,
"%s: %s", fname, serr);
413 lua_pushstring(L, serr);
414 lua_pushnumber(L, (lua_Number)en);
420static int compat53_checkmode(lua_State* L,
const char* mode,
const char* modename,
int err) {
421 if (mode && strchr(mode, modename[0]) == NULL) {
422 lua_pushfstring(L,
"attempt to load a %s chunk (mode is '%s')", modename, mode);
433 const char* peeked_data;
434 size_t peeked_data_size;
435} compat53_reader_data;
438static const char* compat53_reader(lua_State* L,
void* ud,
size_t* size) {
439 compat53_reader_data* data = (compat53_reader_data*)ud;
440 if (data->has_peeked_data) {
441 data->has_peeked_data = 0;
442 *size = data->peeked_data_size;
443 return data->peeked_data;
446 return data->reader(L, data->ud, size);
450COMPAT53_API int lua_load(lua_State* L, lua_Reader reader,
void* data,
const char* source,
const char* mode) {
452 compat53_reader_data compat53_data = { reader, data, 1, 0, 0 };
453 compat53_data.peeked_data = reader(L, data, &(compat53_data.peeked_data_size));
454 if (compat53_data.peeked_data && compat53_data.peeked_data_size && compat53_data.peeked_data[0] == LUA_SIGNATURE[0])
455 status = compat53_checkmode(L, mode,
"binary", LUA_ERRSYNTAX);
457 status = compat53_checkmode(L, mode,
"text", LUA_ERRSYNTAX);
458 if (status != LUA_OK)
462 return lua_load(L, compat53_reader, &compat53_data, source);
463#define lua_load COMPAT53_CONCAT(COMPAT53_PREFIX, _load_53)
470 char buff[COMPAT53_LUA_FILE_BUFFER_SIZE];
474static const char* compat53_getF(lua_State* L,
void* ud,
size_t* size) {
475 compat53_LoadF* lf = (compat53_LoadF*)ud;
487 *size = fread(lf->buff, 1,
sizeof(lf->buff), lf->f);
493static int compat53_errfile(lua_State* L,
const char* what,
int fnameindex) {
494 char buf[512] = { 0 };
495 const char* serr = compat53_strerror(errno, buf,
sizeof(buf));
496 const char* filename = lua_tostring(L, fnameindex) + 1;
497 lua_pushfstring(L,
"cannot %s %s: %s", what, filename, serr);
498 lua_remove(L, fnameindex);
503static int compat53_skipBOM(compat53_LoadF* lf) {
504 const char* p =
"\xEF\xBB\xBF";
509 if (c == EOF || c != *(
const unsigned char*)p++)
511 lf->buff[lf->n++] = (char)c;
512 }
while (*p !=
'\0');
525static int compat53_skipcomment(compat53_LoadF* lf,
int* cp) {
526 int c = *cp = compat53_skipBOM(lf);
530 }
while (c != EOF && c !=
'\n');
539COMPAT53_API int luaL_loadfilex(lua_State* L,
const char* filename,
const char* mode) {
541 int status, readstatus;
543 int fnameindex = lua_gettop(L) + 1;
544 if (filename == NULL) {
545 lua_pushliteral(L,
"=stdin");
549 lua_pushfstring(L,
"@%s", filename);
561#if COMPAT53_FOPEN_NO_LOCK
562 lf.f = _fsopen(filename,
"r", _SH_DENYNO);
564 return compat53_errfile(L,
"open", fnameindex);
566 if (fopen_s(&lf.f, filename,
"r") != 0)
567 return compat53_errfile(L,
"open", fnameindex);
570 lf.f = fopen(filename,
"r");
572 return compat53_errfile(L,
"open", fnameindex);
575 if (compat53_skipcomment(&lf, &c))
576 lf.buff[lf.n++] =
'\n';
577 if (c == LUA_SIGNATURE[0] && filename) {
579 if (freopen_s(&lf.f, filename,
"rb", lf.f) != 0)
580 return compat53_errfile(L,
"reopen", fnameindex);
582 lf.f = freopen(filename,
"rb", lf.f);
584 return compat53_errfile(L,
"reopen", fnameindex);
586 compat53_skipcomment(&lf, &c);
589 lf.buff[lf.n++] = (char)c;
590 status = lua_load(L, &compat53_getF, &lf, lua_tostring(L, -1), mode);
591 readstatus = ferror(lf.f);
595 lua_settop(L, fnameindex);
596 return compat53_errfile(L,
"read", fnameindex);
598 lua_remove(L, fnameindex);
603COMPAT53_API int luaL_loadbufferx(lua_State* L,
const char* buff,
size_t sz,
const char* name,
const char* mode) {
605 if (sz > 0 && buff[0] == LUA_SIGNATURE[0]) {
606 status = compat53_checkmode(L, mode,
"binary", LUA_ERRSYNTAX);
609 status = compat53_checkmode(L, mode,
"text", LUA_ERRSYNTAX);
611 if (status != LUA_OK)
613 return luaL_loadbuffer(L, buff, sz, name);
617#if !defined(l_inspectstat) \
618 && (defined(unix) || defined(__unix) || defined(__unix__) || defined(__TOS_AIX__) || defined(_SYSTYPE_BSD) || (defined(__APPLE__) && defined(__MACH__)))
623#if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L
625#define l_inspectstat(stat, what) \
626 if (WIFEXITED(stat)) { \
627 stat = WEXITSTATUS(stat); \
629 else if (WIFSIGNALED(stat)) { \
630 stat = WTERMSIG(stat); \
637#if !defined(l_inspectstat)
638#define l_inspectstat(stat, what) ((void)0)
642COMPAT53_API int luaL_execresult(lua_State* L,
int stat) {
643 const char* what =
"exit";
645 return luaL_fileresult(L, 0, NULL);
647 l_inspectstat(stat, what);
648 if (*what ==
'e' && stat == 0)
649 lua_pushboolean(L, 1);
652 lua_pushstring(L, what);
653 lua_pushinteger(L, stat);
659COMPAT53_API void luaL_buffinit(lua_State* L, luaL_Buffer_53* B) {
665 B->ptr =
B->b.buffer;
666 B->capacity = LUAL_BUFFERSIZE;
672COMPAT53_API char* luaL_prepbuffsize(luaL_Buffer_53* B,
size_t s) {
673 if (
B->capacity -
B->nelems < s) {
675 size_t newcap =
B->capacity * 2;
676 if (newcap -
B->nelems < s)
677 newcap =
B->nelems + s;
678 if (newcap < B->capacity)
679 luaL_error(
B->L2,
"buffer too large");
680#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 504
681 newptr = (
char*)lua_newuserdatauv(
B->L2, newcap, 0);
683 newptr = (
char*)lua_newuserdata(
B->L2, newcap);
685 memcpy(newptr,
B->ptr,
B->nelems);
686 if (
B->ptr !=
B->b.buffer)
687 lua_replace(
B->L2, -2);
689 B->capacity = newcap;
691 return B->ptr +
B->nelems;
695COMPAT53_API void luaL_addlstring(luaL_Buffer_53* B,
const char* s,
size_t l) {
696 memcpy(luaL_prepbuffsize(B, l), s, l);
703 const char* s = lua_tolstring(
B->L2, -1, &len);
705 luaL_error(
B->L2,
"cannot convert value to string");
706 if (
B->ptr !=
B->b.buffer)
707 lua_insert(
B->L2, -2);
708 luaL_addlstring(B, s, len);
709 lua_remove(
B->L2,
B->ptr !=
B->b.buffer ? -2 : -1);
713void luaL_pushresult(luaL_Buffer_53* B) {
714 lua_pushlstring(
B->L2,
B->ptr,
B->nelems);
715 if (
B->ptr !=
B->b.buffer)
716 lua_replace(
B->L2, -2);
725#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM <= 502
728COMPAT53_API int lua_geti(lua_State* L,
int index, lua_Integer i) {
729 index = lua_absindex(L, index);
730 lua_pushinteger(L, i);
731 lua_gettable(L, index);
732 return lua_type(L, -1);
736COMPAT53_API int lua_isinteger(lua_State* L,
int index) {
737 if (lua_type(L, index) == LUA_TNUMBER) {
738 lua_Number n = lua_tonumber(L, index);
739 lua_Integer i = lua_tointeger(L, index);
747COMPAT53_API lua_Integer lua_tointegerx(lua_State* L,
int i,
int* isnum) {
749 lua_Number n = lua_tonumberx(L, i, &ok);
751 if (n == (lua_Integer)n) {
754 return (lua_Integer)n;
763static void compat53_reverse(lua_State* L,
int a,
int b) {
764 for (; a < b; ++a, --b) {
773COMPAT53_API void lua_rotate(lua_State* L,
int idx,
int n) {
775 idx = lua_absindex(L, idx);
776 n_elems = lua_gettop(L) - idx + 1;
779 if (n > 0 && n < n_elems) {
780 luaL_checkstack(L, 2,
"not enough stack slots available");
782 compat53_reverse(L, idx, idx + n - 1);
783 compat53_reverse(L, idx + n, idx + n_elems - 1);
784 compat53_reverse(L, idx, idx + n_elems - 1);
789COMPAT53_API void lua_seti(lua_State* L,
int index, lua_Integer i) {
790 luaL_checkstack(L, 1,
"not enough stack slots available");
791 index = lua_absindex(L, index);
792 lua_pushinteger(L, i);
794 lua_settable(L, index);
798#if !defined(lua_str2number)
799#define lua_str2number(s, p) strtod((s), (p))
802COMPAT53_API size_t lua_stringtonumber(lua_State* L,
const char* s) {
804 lua_Number n = lua_str2number(s, &endptr);
806 while (*endptr !=
'\0' && isspace((
unsigned char)*endptr))
808 if (*endptr ==
'\0') {
809 lua_pushnumber(L, n);
810 return endptr - s + 1;
817COMPAT53_API const char* luaL_tolstring(lua_State* L,
int idx,
size_t* len) {
818 if (!luaL_callmeta(L, idx,
"__tostring")) {
819 int t = lua_type(L, idx), tt = 0;
820 char const* name = NULL;
823 lua_pushliteral(L,
"nil");
827 lua_pushvalue(L, idx);
830 if (lua_toboolean(L, idx))
831 lua_pushliteral(L,
"true");
833 lua_pushliteral(L,
"false");
836 tt = luaL_getmetafield(L, idx,
"__name");
837 name = (tt == LUA_TSTRING) ? lua_tostring(L, -1) : lua_typename(L, t);
838 lua_pushfstring(L,
"%s: %p", name, lua_topointer(L, idx));
845 if (!lua_isstring(L, -1))
846 luaL_error(L,
"'__tostring' must return a string");
848 return lua_tolstring(L, -1, len);
852COMPAT53_API void luaL_requiref(lua_State* L,
const char* modname, lua_CFunction openf,
int glb) {
853 luaL_checkstack(L, 3,
"not enough stack slots available");
854 luaL_getsubtable(L, LUA_REGISTRYINDEX,
"_LOADED");
855 if (lua_getfield(L, -1, modname) == LUA_TNIL) {
857 lua_pushcfunction(L, openf);
858 lua_pushstring(L, modname);
860 lua_pushvalue(L, -1);
861 lua_setfield(L, -3, modname);
864 lua_pushvalue(L, -1);
865 lua_setglobal(L, modname);