1 /**
2  * \file   os_match.c
3  * \brief  Match files and directories.
4  * \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
5  */
6 
7 #include <stdlib.h>
8 #include <string.h>
9 #include "premake.h"
10 
11 
12 #if PLATFORM_WINDOWS
13 
14 #define WIN32_LEAN_AND_MEAN
15 #include <windows.h>
16 
17 typedef struct struct_MatchInfo
18 {
19 	HANDLE handle;
20 	int    is_first;
21 	WIN32_FIND_DATA entry;
22 } MatchInfo;
23 
os_matchstart(lua_State * L)24 int os_matchstart(lua_State* L)
25 {
26 	const char* mask = luaL_checkstring(L, 1);
27 	MatchInfo* m = (MatchInfo*)malloc(sizeof(MatchInfo));
28 	m->handle = FindFirstFile(mask, &m->entry);
29 	m->is_first = 1;
30 	lua_pushlightuserdata(L, m);
31 	return 1;
32 }
33 
os_matchdone(lua_State * L)34 int os_matchdone(lua_State* L)
35 {
36 	MatchInfo* m = (MatchInfo*)lua_touserdata(L, 1);
37 	if (m->handle != INVALID_HANDLE_VALUE)
38 		FindClose(m->handle);
39 	free(m);
40 	return 0;
41 }
42 
os_matchname(lua_State * L)43 int os_matchname(lua_State* L)
44 {
45 	MatchInfo* m = (MatchInfo*)lua_touserdata(L, 1);
46 	lua_pushstring(L, m->entry.cFileName);
47 	return 1;
48 }
49 
os_matchisfile(lua_State * L)50 int os_matchisfile(lua_State* L)
51 {
52 	MatchInfo* m = (MatchInfo*)lua_touserdata(L, 1);
53 	lua_pushboolean(L, (m->entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0);
54 	return 1;
55 }
56 
os_matchnext(lua_State * L)57 int os_matchnext(lua_State* L)
58 {
59 	MatchInfo* m = (MatchInfo*)lua_touserdata(L, 1);
60 	if (m->handle == INVALID_HANDLE_VALUE)
61 		return 0;
62 
63 	while (m)  /* loop forever */
64 	{
65 		if (!m->is_first)
66 		{
67 			if (!FindNextFile(m->handle, &m->entry))
68 				return 0;
69 		}
70 
71 		m->is_first = 0;
72 		if (m->entry.cFileName[0] != '.')
73 		{
74 			lua_pushboolean(L, 1);
75 			return 1;
76 		}
77 	}
78 
79 	return 0;
80 }
81 
82 #else
83 
84 #include <dirent.h>
85 #include <fnmatch.h>
86 #include <sys/stat.h>
87 
88 typedef struct struct_MatchInfo
89 {
90 	DIR* handle;
91 	struct dirent* entry;
92 	char* path;
93 	char* mask;
94 } MatchInfo;
95 
os_matchstart(lua_State * L)96 int os_matchstart(lua_State* L)
97 {
98 	const char* split;
99 	const char* mask = luaL_checkstring(L, 1);
100 	MatchInfo* m = (MatchInfo*)malloc(sizeof(MatchInfo));
101 
102 	/* split the mask into path and filename components */
103 	split = strrchr(mask, '/');
104 	if (split)
105 	{
106 		m->path = (char*)malloc(split - mask + 1);
107 		strncpy(m->path, mask, split - mask);
108 		m->path[split - mask] = '\0';
109 		m->mask = (char*)malloc(mask + strlen(mask) - split);
110 		strcpy(m->mask, split + 1);
111 	}
112 	else
113 	{
114 		m->path = (char*)malloc(2);
115 		strcpy(m->path, ".");
116 		m->mask = (char*)malloc(strlen(mask)+1);
117 		strcpy(m->mask, mask);
118 	}
119 
120 	m->handle = opendir(m->path);
121 	lua_pushlightuserdata(L, m);
122 	return 1;
123 }
124 
os_matchdone(lua_State * L)125 int os_matchdone(lua_State* L)
126 {
127 	MatchInfo* m = (MatchInfo*)lua_touserdata(L, 1);
128 	if (m->handle != NULL)
129 		closedir(m->handle);
130 	free(m->path);
131 	free(m->mask);
132 	free(m);
133 	return 0;
134 }
135 
os_matchname(lua_State * L)136 int os_matchname(lua_State* L)
137 {
138 	MatchInfo* m = (MatchInfo*)lua_touserdata(L, 1);
139 	lua_pushstring(L, m->entry->d_name);
140 	return 1;
141 }
142 
os_matchisfile(lua_State * L)143 int os_matchisfile(lua_State* L)
144 {
145 	struct stat info;
146 	const char* fname;
147 
148 	MatchInfo* m = (MatchInfo*)lua_touserdata(L, 1);
149 	lua_pushfstring(L, "%s/%s", m->path, m->entry->d_name);
150 	fname = lua_tostring(L, -1);
151 	lua_pop(L, 1);
152 
153 	if (stat(fname, &info) == 0)
154 	{
155 		lua_pushboolean(L, S_ISREG(info.st_mode));
156 		return 1;
157 	}
158 
159 	return 0;
160 }
161 
os_matchnext(lua_State * L)162 int os_matchnext(lua_State* L)
163 {
164 	MatchInfo* m = (MatchInfo*)lua_touserdata(L, 1);
165 	if (m->handle == NULL)
166 		return 0;
167 
168 	m->entry = readdir(m->handle);
169 	while (m->entry != NULL)
170 	{
171 		const char* name = m->entry->d_name;
172 		if (name[0] != '.' && fnmatch(m->mask, name, 0) == 0)
173 		{
174 			lua_pushboolean(L, 1);
175 			return 1;
176 		}
177 		m->entry = readdir(m->handle);
178 	}
179 
180 	return 0;
181 }
182 
183 #endif
184