From 3b52d81dcf1b5d6d49e1837612e207b2cab6b74d Mon Sep 17 00:00:00 2001 From: Philipp Janda Date: Sat, 16 Sep 2017 15:11:29 +0200 Subject: Add Lua 5.3 version of `lua_load`. Change `luaL_loadfilex` to use the modified `lua_load` function. Add more credits to the README.md. --- README.md | 3 ++ c-api/compat-5.3.c | 104 ++++++++++++++++++++++++++++++++++------------------- c-api/compat-5.3.h | 3 ++ 3 files changed, 73 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index dedd228..caaca22 100644 --- a/README.md +++ b/README.md @@ -151,6 +151,7 @@ For Lua 5.1 additionally: * `lua_arith` (see [here][20]) * `lua_compare` * `lua_len`, `lua_rawlen`, and `luaL_len` +* `lua_load` (mode argument) * `lua_pushstring`, `lua_pushlstring` (return value) * `lua_copy` * `lua_pushglobaltable` @@ -206,6 +207,8 @@ This package contains code written by: * Tomás Guisasola Gorham ([@tomasguisasola](http://github.com/tomasguisasola)) * Hisham Muhammad ([@hishamhm](http://github.com/hishamhm)) * Renato Maia ([@renatomaia](http://github.com/renatomaia)) +* [@ThePhD](http://github.com/ThePhD) +* [@Daurnimator](http://github.com/Daurnimator) [1]: http://www.inf.puc-rio.br/~roberto/struct/ diff --git a/c-api/compat-5.3.c b/c-api/compat-5.3.c index bd9e277..4bd984a 100644 --- a/c-api/compat-5.3.c +++ b/c-api/compat-5.3.c @@ -28,9 +28,12 @@ #endif /* VC++ _fsopen for share-allowed file read */ #ifndef COMPAT53_HAVE_STRERROR_R -# if defined(__GLIBC__) || defined(_POSIX_VERSION) || defined(__APPLE__) || (!defined (__MINGW32__) && defined(__GNUC__) && (__GNUC__ < 6)) +# if defined(__GLIBC__) || defined(_POSIX_VERSION) || defined(__APPLE__) || \ + (!defined (__MINGW32__) && defined(__GNUC__) && (__GNUC__ < 6)) # define COMPAT53_HAVE_STRERROR_R 1 -# if ((defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) || (defined(_XOPEN_SOURCE) || _XOPEN_SOURCE >= 600)) && (!defined(_GNU_SOURCE) || !_GNU_SOURCE) +# if ((defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) || \ + (defined(_XOPEN_SOURCE) || _XOPEN_SOURCE >= 600)) && \ + (!defined(_GNU_SOURCE) || !_GNU_SOURCE) # ifndef COMPAT53_HAVE_STRERROR_R_XSI # define COMPAT53_HAVE_STRERROR_R_XSI 1 # endif /* XSI-Compliant strerror_r */ @@ -57,7 +60,8 @@ #endif /* strerror_r */ #ifndef COMPAT53_HAVE_STRERROR_S -# if defined(_MSC_VER) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || (defined(__STDC_LIB_EXT1__) && __STDC_LIB_EXT1__) +# if defined(_MSC_VER) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || \ + (defined(__STDC_LIB_EXT1__) && __STDC_LIB_EXT1__) # define COMPAT53_HAVE_STRERROR_S 1 # else /* not VC++ or C11 */ # define COMPAT53_HAVE_STRERROR_S 0 @@ -68,7 +72,8 @@ #define COMPAT53_LUA_FILE_BUFFER_SIZE 4096 #endif /* Lua File Buffer Size */ -static char* compat53_strerror(int en, char* buff, size_t sz) { + +static char* compat53_strerror (int en, char* buff, size_t sz) { #if COMPAT53_HAVE_STRERROR_R /* use strerror_r here, because it's available on these specific platforms */ #if COMPAT53_HAVE_STRERROR_R_XSI @@ -98,6 +103,7 @@ static char* compat53_strerror(int en, char* buff, size_t sz) { #endif } + COMPAT53_API int lua_absindex (lua_State *L, int i) { if (i < 0 && i > LUA_REGISTRYINDEX) i += lua_gettop(L) + 1; @@ -448,7 +454,46 @@ static int compat53_checkmode (lua_State *L, const char *mode, const char *moden } -typedef struct compat53_LoadF { +typedef struct { + lua_Reader reader; + void *ud; + int has_peeked_data; + const char *peeked_data; + size_t peeked_data_size; +} compat53_reader_data; + + +static const char *compat53_reader (lua_State *L, void *ud, size_t *size) { + compat53_reader_data *data = (compat53_reader_data *)ud; + if (data->has_peeked_data) { + data->has_peeked_data = 0; + *size = data->peeked_data_size; + return data->peeked_data; + } else + return data->reader(L, data->ud, size); +} + + +COMPAT53_API int lua_load (lua_State *L, lua_Reader reader, void *data, const char *source, const char *mode) { + compat53_reader_data compat53_data = { reader, data, 1, 0, 0 }; + compat53_data.peeked_data = reader(L, data, &(compat53_data.peeked_data_size)); + if (compat53_data.peeked_data && compat53_data.peeked_data_size) { + int status = LUA_OK; + if (compat53_data.peeked_data[0] == LUA_SIGNATURE[0]) /* binary file? */ + status = compat53_checkmode(L, mode, "binary", LUA_ERRFILE); + else + status = compat53_checkmode(L, mode, "text", LUA_ERRFILE); + if (status != LUA_OK) + return status; + } + /* we need to call the original 5.1 version of lua_load! */ +#undef lua_load + return lua_load(L, compat53_reader, &compat53_data, source); +#define lua_load COMPAT53_CONCAT(COMPAT53_PREFIX, _load_53) +} + + +typedef struct { int n; /* number of pre-read characters */ FILE *f; /* file being read */ char buff[COMPAT53_LUA_FILE_BUFFER_SIZE]; /* area for reading file */ @@ -518,7 +563,6 @@ static int compat53_skipcomment (compat53_LoadF *lf, int *cp) { COMPAT53_API int luaL_loadfilex (lua_State *L, const char *filename, const char *mode) { - static const char lua_signature[] = "\x1bLua"; compat53_LoadF lf; int status, readstatus; int c; @@ -530,29 +574,25 @@ COMPAT53_API int luaL_loadfilex (lua_State *L, const char *filename, const char else { lua_pushfstring(L, "@%s", filename); #if defined(_MSC_VER) - /* this code is here to stop a deprecation error that - * stops builds if a certain macro is defined - * while normally not caring would be best, some - * header-only libraries and builds can't afford - * to dictate this to the user*/ - /* a quick check shows that fopen_s this goes back to VS 2005, - * and _fsopen goes back to VS 2003 .NET, possibly even before that - * so we don't need to do any version number checks, - * since this has been there since forever + /* This code is here to stop a deprecation error that stops builds + * if a certain macro is defined. While normally not caring would + * be best, some header-only libraries and builds can't afford to + * dictate this to the user. A quick check shows that fopen_s this + * goes back to VS 2005, and _fsopen goes back to VS 2003 .NET, + * possibly even before that so we don't need to do any version + * number checks, since this has been there since forever. */ - /* TO USER: if you want the behavior of typical fopen_s/fopen, + /* TO USER: if you want the behavior of typical fopen_s/fopen, * which does lock the file on VC++, define the macro used below to 0 - */ + */ #if COMPAT53_FOPEN_NO_LOCK lf.f = _fsopen(filename, "r", _SH_DENYNO); /* do not lock the file in any way */ - if (lf.f == NULL) { + if (lf.f == NULL) return compat53_errfile(L, "open", fnameindex); - } #else /* use default locking version */ - if (fopen_s(&lf.f, filename, "r") != 0) { + if (fopen_s(&lf.f, filename, "r") != 0) return compat53_errfile(L, "open", fnameindex); - } #endif /* Locking vs. No-locking fopen variants */ #else lf.f = fopen(filename, "r"); /* default stdlib doesn't forcefully lock files here */ @@ -561,30 +601,19 @@ COMPAT53_API int luaL_loadfilex (lua_State *L, const char *filename, const char } if (compat53_skipcomment(&lf, &c)) /* read initial portion */ lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */ - if (c == lua_signature[0]) { /* binary file? */ - status = compat53_checkmode(L, mode, "binary", LUA_ERRFILE); - if (status != LUA_OK) { - fclose(lf.f); - return compat53_errfile(L, "improper mode", fnameindex); - } + if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ #if defined(_MSC_VER) - if (freopen_s(&lf.f, filename, "r", lf.f) != 0) return compat53_errfile(L, "open", fnameindex); + if (freopen_s(&lf.f, filename, "rb", lf.f) != 0) + return compat53_errfile(L, "reopen", fnameindex); #else lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ if (lf.f == NULL) return compat53_errfile(L, "reopen", fnameindex); #endif compat53_skipcomment(&lf, &c); /* re-read initial portion */ } - else { /* text file */ - status = compat53_checkmode(L, mode, "text", LUA_ERRFILE); - if (status != LUA_OK) { - fclose(lf.f); - return compat53_errfile(L, "improper mode", fnameindex); - } - } if (c != EOF) lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */ - status = lua_load(L, &compat53_getF, &lf, lua_tostring(L, -1)); + status = lua_load(L, &compat53_getF, &lf, lua_tostring(L, -1), mode); readstatus = ferror(lf.f); if (filename) fclose(lf.f); /* close file (even in case of errors) */ if (readstatus) { @@ -598,7 +627,7 @@ COMPAT53_API int luaL_loadfilex (lua_State *L, const char *filename, const char COMPAT53_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t sz, const char *name, const char *mode) { int status = LUA_OK; - if (sz > 0 && buff[0] == '\x1b') { + if (sz > 0 && buff[0] == LUA_SIGNATURE[0]) { status = compat53_checkmode(L, mode, "binary", LUA_ERRSYNTAX); } else { @@ -609,6 +638,7 @@ COMPAT53_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t sz, co return luaL_loadbuffer(L, buff, sz, name); } + #if !defined(l_inspectstat) && \ (defined(unix) || defined(__unix) || defined(__unix__) || \ defined(__TOS_AIX__) || defined(_SYSTYPE_BSD) || \ diff --git a/c-api/compat-5.3.h b/c-api/compat-5.3.h index c62d6bf..755c23e 100644 --- a/c-api/compat-5.3.h +++ b/c-api/compat-5.3.h @@ -174,6 +174,9 @@ COMPAT53_API lua_Number lua_tonumberx (lua_State *L, int i, int *isnum); #define luaL_checkversion COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkversion) COMPAT53_API void luaL_checkversion (lua_State *L); +#define lua_load COMPAT53_CONCAT(COMPAT53_PREFIX, _load_53) +COMPAT53_API int lua_load (lua_State *L, lua_Reader reader, void *data, const char* source, const char* mode); + #define luaL_loadfilex COMPAT53_CONCAT(COMPAT53_PREFIX, L_loadfilex) COMPAT53_API int luaL_loadfilex (lua_State *L, const char *filename, const char *mode); -- cgit v1.2.3-55-g6feb