@@ -29,6 +29,10 @@ LUALIB_API int luaL_loadfilex (lua_State* L, const char* filename, const char* m
29
29
const char * script_dir ;
30
30
const char * test_name ;
31
31
32
+ /* this function can be called with from 1 to 3 arguments on the stack,
33
+ * the filename, the mode and an environment table */
34
+
35
+ int env = (!lua_isnone (L , 3 ) ? 1 : 0 ); /* 1 if there is an env or 0 if no 'env' */
32
36
int bottom = lua_gettop (L );
33
37
int z = !OKAY ;
34
38
@@ -60,11 +64,11 @@ LUALIB_API int luaL_loadfilex (lua_State* L, const char* filename, const char* m
60
64
z = premake_load_embedded_script (L , test_name + 2 ); /* Skip over leading "$/" */
61
65
62
66
/* remove test_name */
63
- lua_remove (L , bottom + 1 );
67
+ lua_remove (L , -3 );
64
68
}
65
69
66
70
/* remove _SCRIPT_DIR */
67
- lua_remove (L , bottom );
71
+ lua_remove (L , bottom + env );
68
72
}
69
73
70
74
/* Try to locate the script on the filesystem */
@@ -100,7 +104,15 @@ LUALIB_API int luaL_loadfilex (lua_State* L, const char* filename, const char* m
100
104
* script chunk on the stack. Turn these into a closure that will call my
101
105
* wrapper below when the loaded script needs to be executed. */
102
106
if (z == OKAY ) {
103
- lua_pushcclosure (L , chunk_wrapper , 2 );
107
+ /* if we are called with an env, then our caller, luaB_loadfile, will
108
+ * call load_aux, which sets up our env as the first up value via
109
+ * lua_setupvalue, which would overwrite the one we are setting up here.
110
+ * workaround this by pushing a nil value as our first up value */
111
+ if (env ) {
112
+ lua_pushnil (L );
113
+ lua_insert (L , -3 );
114
+ }
115
+ lua_pushcclosure (L , chunk_wrapper , 2 + (env ? 1 : 0 ));
104
116
}
105
117
else if (z == LUA_ERRFILE ) {
106
118
lua_pushfstring (L , "cannot open %s: No such file or directory" , filename );
@@ -124,9 +136,14 @@ static int chunk_wrapper(lua_State* L)
124
136
const char * filename ;
125
137
char * ptr ;
126
138
int i , args ;
139
+ int upvalue_offset ;
127
140
128
141
args = lua_gettop (L );
129
142
143
+ /* if the first up value is a table, then we have an env upvalue
144
+ * and should take that into account by offsetting the rest of the up values */
145
+ upvalue_offset = (lua_type (L , lua_upvalueindex (1 )) == LUA_TTABLE ) ? 1 : 0 ;
146
+
130
147
/* Remember the current _SCRIPT and working directory so I can
131
148
* restore them after this new chunk has been run. */
132
149
@@ -136,12 +153,12 @@ static int chunk_wrapper(lua_State* L)
136
153
137
154
/* Set the new _SCRIPT variable */
138
155
139
- lua_pushvalue (L , lua_upvalueindex (1 ));
156
+ lua_pushvalue (L , lua_upvalueindex (1 + upvalue_offset ));
140
157
lua_setglobal (L , "_SCRIPT" );
141
158
142
159
/* And the new _SCRIPT_DIR variable (const cheating) */
143
160
144
- filename = lua_tostring (L , lua_upvalueindex (1 ));
161
+ filename = lua_tostring (L , lua_upvalueindex (1 + upvalue_offset ));
145
162
ptr = strrchr (filename , '/' );
146
163
if (ptr ) * ptr = '\0' ;
147
164
lua_pushlstring (L , filename , strlen (filename ));
@@ -157,7 +174,15 @@ static int chunk_wrapper(lua_State* L)
157
174
/* Move the function's arguments to the top of the stack and
158
175
* execute the function created by luaL_loadfile() */
159
176
160
- lua_pushvalue (L , lua_upvalueindex (2 ));
177
+ lua_pushvalue (L , lua_upvalueindex (2 + upvalue_offset ));
178
+
179
+ /* forward the env table to the closure as 1st upvalue */
180
+ if (upvalue_offset ) {
181
+ lua_pushvalue (L , -1 );
182
+ lua_pushvalue (L , lua_upvalueindex (1 ));
183
+ lua_setupvalue (L , -2 , 1 );
184
+ }
185
+
161
186
for (i = 1 ; i <= args ; ++ i ) {
162
187
lua_pushvalue (L , i );
163
188
}
0 commit comments