@@ -214,18 +214,71 @@ static int file_open( lua_State* L )
214214static int file_list ( lua_State * L )
215215{
216216 vfs_dir * dir ;
217+ const char * pattern ;
218+ static const char * emptystr = "" ;
219+ struct vfs_stat stat ;
220+ int pcres ;
221+ int res = 1 ;
222+
223+ pattern = luaL_optlstring (L , 1 , emptystr , NULL );
224+
225+ dir = vfs_opendir ("" );
226+ if (dir == NULL ) {
227+ return 0 ;
228+ }
229+
230+ /* Allocate result table T */
231+ lua_newtable ( L );
232+
233+ /* If we're doing a match, push the Pattern and Function */
234+ if (pattern != emptystr ) {
235+ lua_pushstring ( L , pattern );
236+ /*
237+ * We know that pattern is a string, and so the "match" method will always
238+ * exist. No need to check return value here
239+ */
240+ luaL_getmetafield ( L , -1 , "match" );
241+ }
242+
243+ while (vfs_readdir (dir , & stat ) == VFS_RES_OK ) {
244+ if (pattern != emptystr ) {
245+ /* Stack: T P F . Duplicate F, push Name, duplicate P */
246+ lua_pushvalue ( L , -1 );
247+ lua_pushstring ( L , stat .name );
248+ lua_pushvalue ( L , -4 );
249+ /* Call transforms stack from T P F F N P to T P F Result */
250+ pcres = lua_pcall ( L , 2 , 1 , 0 );
251+ if (pcres != 0 ) {
252+ /* Abort! Stack is T P F Error; clear out and push nil under Error */
253+ lua_pushnil ( L );
254+ lua_replace ( L , -5 );
255+ lua_remove ( L , -2 );
256+ lua_remove ( L , -2 );
257+ res = 2 ;
258+ goto out ;
259+ }
217260
218- if (dir = vfs_opendir ("" )) {
219- lua_newtable ( L );
220- struct vfs_stat stat ;
221- while (vfs_readdir (dir , & stat ) == VFS_RES_OK ) {
222- lua_pushinteger (L , stat .size );
223- lua_setfield (L , -2 , stat .name );
261+ /* Check and pop Result, restoring stack to T P F */
262+ if (!lua_isnil ( L , -1 )) {
263+ lua_pushinteger ( L , stat .size );
264+ lua_setfield ( L , -5 , stat .name );
265+ }
266+ lua_pop ( L , 1 );
267+ } else {
268+ /* Stack just holds result table at the top; add result */
269+ lua_pushinteger ( L , stat .size );
270+ lua_setfield ( L , -2 , stat .name );
224271 }
225- vfs_closedir (dir );
226- return 1 ;
227272 }
228- return 0 ;
273+
274+ /* Pop the Pattern and Function we pushed above */
275+ if (pattern != emptystr ) {
276+ lua_pop ( L , 2 );
277+ }
278+
279+ out :
280+ vfs_closedir (dir );
281+ return res ;
229282}
230283
231284static int get_file_obj ( lua_State * L , int * argpos )
0 commit comments