lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Now (a change since lua-5.2.0-beta), like 'load', 'loadfile' accepts
extra arguments : mode & env.

loadfile & load do the same check with mode. Unfortunately, in 2
different functions : checkright in lbaselib.c and checkmode in
lauxlib.c.

I try with 2 different ways (see attached patches) to refactor the
code which handles the parameter mode.

François
From: Francois Perrad <francois.perrad@gadz.org>
Date: Mon, 28 Nov 2011
Subject: [PATCH] with luaL_checkmode

---
 src/lauxlib.c  |   15 +++++++++------
 src/lauxlib.h  |    5 ++++-
 src/lbaselib.c |    9 ++-------
 3 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/src/lauxlib.c b/src/lauxlib.c
index d61a8ef..44902a4 100644
--- a/src/lauxlib.c
+++ b/src/lauxlib.c
@@ -592,13 +592,12 @@ static int errfile (lua_State *L, const char *what, int fnameindex) {
 }
 
 
-static int checkmode (lua_State *L, const char *mode, const char *x) {
+const char * luaL_checkmode (lua_State *L, const char *mode, const char *x) {
   if (mode && strchr(mode, x[0]) == NULL) {
-    lua_pushfstring(L,
+    return lua_pushfstring(L,
        "attempt to load a %s chunk (mode is " LUA_QS ")", x, mode);
-    return LUA_ERRFILE;
   }
-  else return LUA_OK;
+  else return NULL;
 }
 
 
@@ -652,8 +651,10 @@ LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename,
   if (skipcomment(&lf, &c))  /* read initial portion */
     lf.buff[lf.n++] = '\n';  /* add line to correct line numbers */
   if (c == LUA_SIGNATURE[0]) {  /* binary file? */
-    if ((status = checkmode(L, mode, "binary")) != LUA_OK)
+    if (luaL_checkmode(L, mode, "binary") != NULL) {
+      status = LUA_ERRFILE;
       goto closefile;
+    }
     if (filename) {
       lf.f = freopen(filename, "rb", lf.f);  /* reopen in binary mode */
       if (lf.f == NULL) return errfile(L, "reopen", fnameindex);
@@ -661,8 +662,10 @@ LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename,
     }
   }
   else {  /* text file */
-    if ((status = checkmode(L, mode, "text")) != LUA_OK)
+    if (luaL_checkmode(L, mode, "text") != NULL) {
+      status = LUA_ERRFILE;
       goto closefile;
+    }
   }
   if (c != EOF)
     lf.buff[lf.n++] = c;  /* 'c' is the first character of the stream */
diff --git a/src/lauxlib.h b/src/lauxlib.h
index 48b1afa..1e4c55c 100644
--- a/src/lauxlib.h
+++ b/src/lauxlib.h
@@ -72,10 +72,13 @@ LUALIB_API int (luaL_execresult) (lua_State *L, int stat);
 LUALIB_API int (luaL_ref) (lua_State *L, int t);
 LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref);
 
+LUALIB_API const char * (luaL_checkmode) (lua_State *L, const char *mode,
+                                                        const char *x);
+
 LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename,
                                                const char *mode);
 
-#define luaL_loadfile(L,f)	luaL_loadfilex(L,f,NULL)
+#define luaL_loadfile(L,f)	luaL_loadfilex((L) ,(f), NULL)
 
 LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz,
                                   const char *name);
diff --git a/src/lbaselib.c b/src/lbaselib.c
index 472a96c..f63ff37 100644
--- a/src/lbaselib.c
+++ b/src/lbaselib.c
@@ -283,13 +283,8 @@ typedef struct {
 ** ('t' for text, 'b' for binary). Returns error message (also
 ** pushed on the stack) in case of errors.
 */
-static const char *checkrights (lua_State *L, const char *mode, const char *s) {
-  const char *x = (*s == LUA_SIGNATURE[0]) ? "binary" : "text";
-  if (strchr(mode, x[0]) == NULL)
-    return lua_pushfstring(L,
-       "attempt to load a %s chunk (mode is " LUA_QS ")", x, mode);
-  else return NULL;
-}
+#define checkrights(L, mode, s) luaL_checkmode((L), (mode), \
+	(*(s) == LUA_SIGNATURE[0]) ? "binary" : "text")
 
 
 /*
-- 
1.7.6.0

From: Francois Perrad <francois.perrad@gadz.org>
Date: Mon, 28 Nov 2011
Subject: [PATCH] with lua_loadx

---
 src/lapi.c     |    6 +++---
 src/lauxlib.c  |   27 +++++----------------------
 src/lauxlib.h  |   14 ++++++--------
 src/lbaselib.c |   25 ++-----------------------
 src/ldo.c      |   13 +++++++++++--
 src/ldo.h      |    2 +-
 src/lua.h      |    7 +++++--
 7 files changed, 33 insertions(+), 61 deletions(-)

diff --git a/src/lapi.c b/src/lapi.c
index 5437fb0..a7aa38d 100644
--- a/src/lapi.c
+++ b/src/lapi.c
@@ -967,14 +967,14 @@ LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc,
 }
 
 
-LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,
-                      const char *chunkname) {
+LUA_API int lua_loadx (lua_State *L, lua_Reader reader, void *data,
+                       const char *chunkname, const char *mode) {
   ZIO z;
   int status;
   lua_lock(L);
   if (!chunkname) chunkname = "?";
   luaZ_init(L, &z, reader, data);
-  status = luaD_protectedparser(L, &z, chunkname);
+  status = luaD_protectedparser(L, &z, chunkname, mode);
   if (status == LUA_OK) {  /* no errors? */
     LClosure *f = clLvalue(L->top - 1);  /* get newly created function */
     if (f->nupvalues == 1) {  /* does it have one upvalue? */
diff --git a/src/lauxlib.c b/src/lauxlib.c
index d61a8ef..2090327 100644
--- a/src/lauxlib.c
+++ b/src/lauxlib.c
@@ -592,16 +592,6 @@ static int errfile (lua_State *L, const char *what, int fnameindex) {
 }
 
 
-static int checkmode (lua_State *L, const char *mode, const char *x) {
-  if (mode && strchr(mode, x[0]) == NULL) {
-    lua_pushfstring(L,
-       "attempt to load a %s chunk (mode is " LUA_QS ")", x, mode);
-    return LUA_ERRFILE;
-  }
-  else return LUA_OK;
-}
-
-
 static int skipBOM (LoadF *lf) {
   const char *p = "\xEF\xBB\xBF";  /* Utf8 BOM mark */
   int c;
@@ -652,22 +642,15 @@ LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename,
   if (skipcomment(&lf, &c))  /* read initial portion */
     lf.buff[lf.n++] = '\n';  /* add line to correct line numbers */
   if (c == LUA_SIGNATURE[0]) {  /* binary file? */
-    if ((status = checkmode(L, mode, "binary")) != LUA_OK)
-      goto closefile;
     if (filename) {
       lf.f = freopen(filename, "rb", lf.f);  /* reopen in binary mode */
       if (lf.f == NULL) return errfile(L, "reopen", fnameindex);
       skipcomment(&lf, &c);  /* re-read initial portion */
     }
   }
-  else {  /* text file */
-    if ((status = checkmode(L, mode, "text")) != LUA_OK)
-      goto closefile;
-  }
   if (c != EOF)
     lf.buff[lf.n++] = c;  /* 'c' is the first character of the stream */
-  status = lua_load(L, getF, &lf, lua_tostring(L, -1));
- closefile:
+  status = lua_loadx(L, 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) {
@@ -695,17 +678,17 @@ static const char *getS (lua_State *L, void *ud, size_t *size) {
 }
 
 
-LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size,
-                                const char *name) {
+LUALIB_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t size,
+                                const char *name, const char *mode) {
   LoadS ls;
   ls.s = buff;
   ls.size = size;
-  return lua_load(L, getS, &ls, name);
+  return lua_loadx(L, getS, &ls, name, mode);
 }
 
 
 LUALIB_API int luaL_loadstring (lua_State *L, const char *s) {
-  return luaL_loadbuffer(L, s, strlen(s), s);
+  return luaL_loadbufferx(L, s, strlen(s), s, NULL);
 }
 
 /* }====================================================== */
diff --git a/src/lauxlib.h b/src/lauxlib.h
index 48b1afa..fa097bc 100644
--- a/src/lauxlib.h
+++ b/src/lauxlib.h
@@ -15,11 +15,6 @@
 #include "lua.h"
 
 
-
-/* extra error code for `luaL_load' */
-#define LUA_ERRFILE     (LUA_ERRERR+1)
-
-
 typedef struct luaL_Reg {
   const char *name;
   lua_CFunction func;
@@ -75,10 +70,13 @@ LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref);
 LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename,
                                                const char *mode);
 
-#define luaL_loadfile(L,f)	luaL_loadfilex(L,f,NULL)
+#define luaL_loadfile(L,f)	luaL_loadfilex((L), (f), NULL)
+
+LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz,
+                                   const char *name, const char *mode);
+
+#define luaL_loadbuffer(L,b,s,n)	luaL_loadbufferx((L), (b), (s), (n), NULL)
 
-LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz,
-                                  const char *name);
 LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s);
 
 LUALIB_API lua_State *(luaL_newstate) (void);
diff --git a/src/lbaselib.c b/src/lbaselib.c
index 472a96c..7ac3ae1 100644
--- a/src/lbaselib.c
+++ b/src/lbaselib.c
@@ -279,20 +279,6 @@ typedef struct {
 
 
 /*
-** check whether a chunk (prefix in 's') satisfies given 'mode'
-** ('t' for text, 'b' for binary). Returns error message (also
-** pushed on the stack) in case of errors.
-*/
-static const char *checkrights (lua_State *L, const char *mode, const char *s) {
-  const char *x = (*s == LUA_SIGNATURE[0]) ? "binary" : "text";
-  if (strchr(mode, x[0]) == NULL)
-    return lua_pushfstring(L,
-       "attempt to load a %s chunk (mode is " LUA_QS ")", x, mode);
-  else return NULL;
-}
-
-
-/*
 ** reserved slot, above all arguments, to hold a copy of the returned
 ** string to avoid it being collected while parsed. 'load' has four
 ** optional arguments (chunk, source name, mode, and environment).
@@ -308,7 +294,6 @@ static const char *checkrights (lua_State *L, const char *mode, const char *s) {
 */
 static const char *generic_reader (lua_State *L, void *ud, size_t *size) {
   const char *s;
-  loaddata *ld = (loaddata *)ud;
   luaL_checkstack(L, 2, "too many nested functions");
   lua_pushvalue(L, 1);  /* get function */
   lua_call(L, 0, 1);  /* call it */
@@ -317,11 +302,6 @@ static const char *generic_reader (lua_State *L, void *ud, size_t *size) {
     return NULL;
   }
   else if ((s = lua_tostring(L, -1)) != NULL) {
-    if (ld->mode != NULL) {  /* first time? */
-      s = checkrights(L, ld->mode, s);  /* check mode */
-      ld->mode = NULL;  /* to avoid further checks */
-      if (s) luaL_error(L, s);
-    }
     lua_replace(L, RESERVEDSLOT);  /* save string in reserved slot */
     return lua_tolstring(L, RESERVEDSLOT, size);
   }
@@ -340,8 +320,7 @@ static int luaB_load (lua_State *L) {
   const char *mode = luaL_optstring(L, 3, "bt");
   if (s != NULL) {  /* loading a string? */
     const char *chunkname = luaL_optstring(L, 2, s);
-    status = (checkrights(L, mode, s) != NULL)
-           || luaL_loadbuffer(L, s, l, chunkname);
+    status = luaL_loadbufferx(L, s, l, chunkname, mode);
   }
   else {  /* loading from a reader function */
     const char *chunkname = luaL_optstring(L, 2, "=(load)");
@@ -349,7 +328,7 @@ static int luaB_load (lua_State *L) {
     ld.mode = mode;
     luaL_checktype(L, 1, LUA_TFUNCTION);
     lua_settop(L, RESERVEDSLOT);  /* create reserved slot */
-    status = lua_load(L, generic_reader, &ld, chunkname);
+    status = lua_loadx(L, generic_reader, &ld, chunkname, mode);
   }
   if (status == LUA_OK && top >= 4) {  /* is there an 'env' argument */
     lua_pushvalue(L, 4);  /* environment for loaded function */
diff --git a/src/ldo.c b/src/ldo.c
index 0f8c26e..f0b59df 100644
--- a/src/ldo.c
+++ b/src/ldo.c
@@ -612,6 +612,7 @@ struct SParser {  /* data to `f_parser' */
   Mbuffer buff;  /* dynamic structure used by the scanner */
   Dyndata dyd;  /* dynamic structures used by the parser */
   const char *name;
+  const char *mode;
 };
 
 static void f_parser (lua_State *L, void *ud) {
@@ -620,6 +621,13 @@ static void f_parser (lua_State *L, void *ud) {
   Closure *cl;
   struct SParser *p = cast(struct SParser *, ud);
   int c = zgetc(p->z);  /* read first character */
+  if (p->mode) {
+    const char *x = (c == LUA_SIGNATURE[0]) ? "binary" : "text";
+    if (strchr(p->mode, x[0]) == NULL) {
+      luaO_pushfstring(L, "attempt to load a %s chunk (mode is " LUA_QS ")", x, p->mode);
+      luaD_throw(L, LUA_ERRFILE);
+    }
+  }
   tf = (c == LUA_SIGNATURE[0])
            ? luaU_undump(L, p->z, &p->buff, p->name)
            : luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c);
@@ -632,11 +640,12 @@ static void f_parser (lua_State *L, void *ud) {
 }
 
 
-int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) {
+int luaD_protectedparser (lua_State *L, ZIO *z, const char *name,
+                                                const char *mode) {
   struct SParser p;
   int status;
   L->nny++;  /* cannot yield during parsing */
-  p.z = z; p.name = name;
+  p.z = z; p.name = name; p.mode = mode;
   p.dyd.actvar.arr = NULL; p.dyd.actvar.size = 0;
   p.dyd.gt.arr = NULL; p.dyd.gt.size = 0;
   p.dyd.label.arr = NULL; p.dyd.label.size = 0;
diff --git a/src/ldo.h b/src/ldo.h
index edfe007..e70b2d8 100644
--- a/src/ldo.h
+++ b/src/ldo.h
@@ -26,7 +26,7 @@
 /* type of protected functions, to be ran by `runprotected' */
 typedef void (*Pfunc) (lua_State *L, void *ud);
 
-LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name);
+LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, const char *mode);
 LUAI_FUNC void luaD_hook (lua_State *L, int event, int line);
 LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults);
 LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults,
diff --git a/src/lua.h b/src/lua.h
index 2d94f08..8ab0f8a 100644
--- a/src/lua.h
+++ b/src/lua.h
@@ -49,6 +49,7 @@
 #define LUA_ERRMEM	4
 #define LUA_ERRGCMM	5
 #define LUA_ERRERR	6
+#define LUA_ERRFILE	7
 
 
 typedef struct lua_State lua_State;
@@ -253,8 +254,10 @@ LUA_API int   (lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc,
                             int ctx, lua_CFunction k);
 #define lua_pcall(L,n,r,f)	lua_pcallk(L, (n), (r), (f), 0, NULL)
 
-LUA_API int   (lua_load) (lua_State *L, lua_Reader reader, void *dt,
-                                        const char *chunkname);
+LUA_API int   (lua_loadx) (lua_State *L, lua_Reader reader, void *dt,
+                                         const char *chunkname, const char *mode);
+
+#define lua_load(L,r,d,c)	lua_loadx((L), (r), (d), (c), NULL)
 
 LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data);
 
-- 
1.7.6.0