Переглянути джерело

From Lua 5.2: Extended results from os.execute() and pipe:close().

Needs -DLUAJIT_ENABLE_LUA52COMPAT.
Mike Pall 13 роки тому
батько
коміт
cfca926cc2
4 змінених файлів з 95 додано та 52 видалено
  1. 2 0
      src/lauxlib.h
  2. 55 0
      src/lib_aux.c
  3. 21 35
      src/lib_io.c
  4. 17 17
      src/lib_os.c

+ 2 - 0
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,

+ 55 - 0
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 <sys/wait.h>
+#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,

+ 21 - 35
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
+    lua_assert(0);
+    return 0;
+#endif
+#if LJ_52
+    iof->fp = NULL;
+    return luaL_execresult(L, stat);
 #else
-    ok = 0;
+    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)

+ 17 - 17
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
+#if LJ_52
+  errno = ENOSYS;
+  return luaL_fileresult(L, 0, NULL);
+#else
   lua_pushinteger(L, -1);
+  return 1;
+#endif
 #else
-  lua_pushinteger(L, system(luaL_optstring(L, 1, NULL)));
+  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)