diff --git a/src/lauxlib.h b/src/lauxlib.h index 80585f64..b0f66d68 100644 --- a/src/lauxlib.h +++ b/src/lauxlib.h @@ -76,6 +76,8 @@ LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx, const char *fname, int szhint); /* From Lua 5.2. */ +LUALIB_API int luaL_fileresult(lua_State *L, int stat, const char *fname); +LUALIB_API int luaL_execresult(lua_State *L, int stat); LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename, const char *mode); LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, diff --git a/src/lib_aux.c b/src/lib_aux.c index 8fbee71b..4419fde9 100644 --- a/src/lib_aux.c +++ b/src/lib_aux.c @@ -19,8 +19,63 @@ #include "lj_obj.h" #include "lj_err.h" #include "lj_state.h" +#include "lj_trace.h" #include "lj_lib.h" +#if LJ_TARGET_POSIX +#include +#endif + +/* -- I/O error handling -------------------------------------------------- */ + +LUALIB_API int luaL_fileresult(lua_State *L, int stat, const char *fname) +{ + if (stat) { + setboolV(L->top++, 1); + return 1; + } else { + int en = errno; /* Lua API calls may change this value. */ + setnilV(L->top++); + if (fname) + lua_pushfstring(L, "%s: %s", fname, strerror(en)); + else + lua_pushfstring(L, "%s", strerror(en)); + setintV(L->top++, en); + lj_trace_abort(G(L)); + return 3; + } +} + +LUALIB_API int luaL_execresult(lua_State *L, int stat) +{ + if (stat != -1) { +#if LJ_TARGET_POSIX + if (WIFSIGNALED(stat)) { + stat = WTERMSIG(stat); + setnilV(L->top++); + lua_pushliteral(L, "signal"); + } else { + if (WIFEXITED(stat)) + stat = WEXITSTATUS(stat); + if (stat == 0) + setboolV(L->top++, 1); + else + setnilV(L->top++); + lua_pushliteral(L, "exit"); + } +#else + if (stat == 0) + setboolV(L->top++, 1); + else + setnilV(L->top++); + lua_pushliteral(L, "exit"); +#endif + setintV(L->top++, stat); + return 3; + } + return luaL_fileresult(L, 0, NULL); +} + /* -- Module registration ------------------------------------------------- */ LUALIB_API const char *luaL_findtable(lua_State *L, int idx, diff --git a/src/lib_io.c b/src/lib_io.c index ad99b9b7..142bfae5 100644 --- a/src/lib_io.c +++ b/src/lib_io.c @@ -17,11 +17,9 @@ #include "lualib.h" #include "lj_obj.h" -#include "lj_gc.h" #include "lj_err.h" #include "lj_str.h" #include "lj_ff.h" -#include "lj_trace.h" #include "lj_lib.h" /* Userdata payload for I/O file. */ @@ -40,26 +38,6 @@ typedef struct IOFileUD { #define IOSTDF_UD(L, id) (&gcref(G(L)->gcroot[(id)])->ud) #define IOSTDF_IOF(L, id) ((IOFileUD *)uddata(IOSTDF_UD(L, (id)))) -/* -- Error handling ------------------------------------------------------ */ - -static int io_pushresult(lua_State *L, int ok, const char *fname) -{ - if (ok) { - setboolV(L->top++, 1); - return 1; - } else { - int en = errno; /* Lua API calls may change this value. */ - setnilV(L->top++); - if (fname) - lua_pushfstring(L, "%s: %s", fname, strerror(en)); - else - lua_pushfstring(L, "%s", strerror(en)); - setintV(L->top++, en); - lj_trace_abort(G(L)); - return 3; - } -} - /* -- Open/close helpers -------------------------------------------------- */ static IOFileUD *io_tofilep(lua_State *L) @@ -114,12 +92,20 @@ static int io_file_close(lua_State *L, IOFileUD *iof) if ((iof->type & IOFILE_TYPE_MASK) == IOFILE_TYPE_FILE) { ok = (fclose(iof->fp) == 0); } else if ((iof->type & IOFILE_TYPE_MASK) == IOFILE_TYPE_PIPE) { + int stat = -1; #if LJ_TARGET_POSIX - ok = (pclose(iof->fp) != -1); + stat = pclose(iof->fp); #elif LJ_TARGET_WINDOWS - ok = (_pclose(iof->fp) != -1); + stat = _pclose(iof->fp); #else - ok = 0; + lua_assert(0); + return 0; +#endif +#if LJ_52 + iof->fp = NULL; + return luaL_execresult(L, stat); +#else + ok = (stat != -1); #endif } else { lua_assert((iof->type & IOFILE_TYPE_MASK) == IOFILE_TYPE_STDF); @@ -128,7 +114,7 @@ static int io_file_close(lua_State *L, IOFileUD *iof) return 2; } iof->fp = NULL; - return io_pushresult(L, ok, NULL); + return luaL_fileresult(L, ok, NULL); } /* -- Read/write helpers -------------------------------------------------- */ @@ -233,7 +219,7 @@ static int io_file_read(lua_State *L, FILE *fp, int start) } } if (ferror(fp)) - return io_pushresult(L, 0, NULL); + return luaL_fileresult(L, 0, NULL); if (!ok) setnilV(L->top-1); /* Replace last result with nil. */ return n - start; @@ -258,7 +244,7 @@ static int io_file_write(lua_State *L, FILE *fp, int start) lj_err_argt(L, (int)(tv - L->base) + 1, LUA_TSTRING); } } - return io_pushresult(L, status, NULL); + return luaL_fileresult(L, status, NULL); } /* -- I/O file methods ---------------------------------------------------- */ @@ -284,7 +270,7 @@ LJLIB_CF(io_method_write) LJLIB_REC(io_write 0) LJLIB_CF(io_method_flush) LJLIB_REC(io_flush 0) { - return io_pushresult(L, fflush(io_tofile(L)->fp) == 0, NULL); + return luaL_fileresult(L, fflush(io_tofile(L)->fp) == 0, NULL); } LJLIB_CF(io_method_seek) @@ -316,7 +302,7 @@ LJLIB_CF(io_method_seek) res = fseek(fp, (long)ofs, opt); #endif if (res) - return io_pushresult(L, 0, NULL); + return luaL_fileresult(L, 0, NULL); #if LJ_TARGET_POSIX ofs = ftello(fp); #elif _MSC_VER >= 1400 @@ -338,7 +324,7 @@ LJLIB_CF(io_method_setvbuf) if (opt == 0) opt = _IOFBF; else if (opt == 1) opt = _IOLBF; else if (opt == 2) opt = _IONBF; - return io_pushresult(L, setvbuf(fp, NULL, opt, sz) == 0, NULL); + return luaL_fileresult(L, setvbuf(fp, NULL, opt, sz) == 0, NULL); } LJLIB_PUSH(top-2) /* io_lines_iter */ @@ -386,7 +372,7 @@ LJLIB_CF(io_open) const char *mode = s ? strdata(s) : "r"; IOFileUD *iof = io_file_new(L); iof->fp = fopen(fname, mode); - return iof->fp != NULL ? 1 : io_pushresult(L, 0, fname); + return iof->fp != NULL ? 1 : luaL_fileresult(L, 0, fname); } LJLIB_CF(io_popen) @@ -403,7 +389,7 @@ LJLIB_CF(io_popen) #else iof->fp = _popen(fname, mode); #endif - return iof->fp != NULL ? 1 : io_pushresult(L, 0, fname); + return iof->fp != NULL ? 1 : luaL_fileresult(L, 0, fname); #else return luaL_error(L, LUA_QL("popen") " not supported"); #endif @@ -417,7 +403,7 @@ LJLIB_CF(io_tmpfile) #else iof->fp = tmpfile(); #endif - return iof->fp != NULL ? 1 : io_pushresult(L, 0, NULL); + return iof->fp != NULL ? 1 : luaL_fileresult(L, 0, NULL); } LJLIB_CF(io_close) @@ -437,7 +423,7 @@ LJLIB_CF(io_write) LJLIB_REC(io_write GCROOT_IO_OUTPUT) LJLIB_CF(io_flush) LJLIB_REC(io_flush GCROOT_IO_OUTPUT) { - return io_pushresult(L, fflush(io_stdfile(L, GCROOT_IO_OUTPUT)) == 0, NULL); + return luaL_fileresult(L, fflush(io_stdfile(L, GCROOT_IO_OUTPUT)) == 0, NULL); } static int io_std_getset(lua_State *L, ptrdiff_t id, const char *mode) diff --git a/src/lib_os.c b/src/lib_os.c index 2412d47b..21774975 100644 --- a/src/lib_os.c +++ b/src/lib_os.c @@ -31,41 +31,41 @@ #define LJLIB_MODULE_os -static int os_pushresult(lua_State *L, int i, const char *filename) -{ - int en = errno; /* calls to Lua API may change this value */ - if (i) { - setboolV(L->top-1, 1); - return 1; - } else { - setnilV(L->top-1); - lua_pushfstring(L, "%s: %s", filename, strerror(en)); - lua_pushinteger(L, en); - return 3; - } -} - LJLIB_CF(os_execute) { #if LJ_TARGET_CONSOLE - lua_pushinteger(L, -1); +#if LJ_52 + errno = ENOSYS; + return luaL_fileresult(L, 0, NULL); #else - lua_pushinteger(L, system(luaL_optstring(L, 1, NULL))); + lua_pushinteger(L, -1); + return 1; +#endif +#else + const char *cmd = luaL_optstring(L, 1, NULL); + int stat = system(cmd); +#if LJ_52 + if (cmd) + return luaL_execresult(L, stat); + setboolV(L->top++, 1); +#else + setintV(L->top++, stat); #endif return 1; +#endif } LJLIB_CF(os_remove) { const char *filename = luaL_checkstring(L, 1); - return os_pushresult(L, remove(filename) == 0, filename); + return luaL_fileresult(L, remove(filename) == 0, filename); } LJLIB_CF(os_rename) { const char *fromname = luaL_checkstring(L, 1); const char *toname = luaL_checkstring(L, 2); - return os_pushresult(L, rename(fromname, toname) == 0, fromname); + return luaL_fileresult(L, rename(fromname, toname) == 0, fromname); } LJLIB_CF(os_tmpname)