diff options
| author | ruki <[email protected]> | 2015-05-19 11:42:14 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2015-05-19 11:42:14 +0800 |
| commit | 050d1882cf578ca81f92666d42bc005b7c0eb914 (patch) | |
| tree | 3da2dadd83c155ab2e07811d703172918e03159f | |
| parent | f1de3034b9afbb88f83501730bf27c31078818ed (diff) | |
find and match files or directories
| -rw-r--r-- | core/pkg/tbox.pkg/inc/mac/x64/tbox.config.h | 2 | ||||
| -rwxr-xr-x | core/pkg/tbox.pkg/inc/tbox/platform/directory.h | 12 | ||||
| -rwxr-xr-x | core/src/xmake/machine.c | 4 | ||||
| -rwxr-xr-x | core/src/xmake/makefile | 1 | ||||
| -rwxr-xr-x | core/src/xmake/os/find.c | 131 | ||||
| -rw-r--r-- | xmake/scripts/action/_config.lua | 2 | ||||
| -rw-r--r-- | xmake/scripts/base/os.lua | 45 |
7 files changed, 192 insertions, 5 deletions
diff --git a/core/pkg/tbox.pkg/inc/mac/x64/tbox.config.h b/core/pkg/tbox.pkg/inc/mac/x64/tbox.config.h index 7c2999bb0..6779345a4 100644 --- a/core/pkg/tbox.pkg/inc/mac/x64/tbox.config.h +++ b/core/pkg/tbox.pkg/inc/mac/x64/tbox.config.h @@ -14,7 +14,7 @@ #define TB_CONFIG_VERSION_ALTER 8 // build version -#define TB_CONFIG_VERSION_BUILD 201505181139 +#define TB_CONFIG_VERSION_BUILD 201505190824 // small #define TB_CONFIG_SMALL (0) diff --git a/core/pkg/tbox.pkg/inc/tbox/platform/directory.h b/core/pkg/tbox.pkg/inc/tbox/platform/directory.h index ea474114e..23df0b329 100755 --- a/core/pkg/tbox.pkg/inc/tbox/platform/directory.h +++ b/core/pkg/tbox.pkg/inc/tbox/platform/directory.h @@ -38,8 +38,16 @@ __tb_extern_c_enter__ /* ////////////////////////////////////////////////////////////////////////////////////// * types */ -/// the directory walk func type -typedef tb_void_t (*tb_directory_walk_func_t)(tb_char_t const* path, tb_file_info_t const* info, tb_cpointer_t priv); + +/*! the directory walk func type + * + * @param path the file path + * @param info the file info + * @param priv the user private data + * + * @return continue: tb_true, break: tb_false + */ +typedef tb_bool_t (*tb_directory_walk_func_t)(tb_char_t const* path, tb_file_info_t const* info, tb_cpointer_t priv); /* ////////////////////////////////////////////////////////////////////////////////////// * interfaces diff --git a/core/src/xmake/machine.c b/core/src/xmake/machine.c index 3fc303002..476a6a7eb 100755 --- a/core/src/xmake/machine.c +++ b/core/src/xmake/machine.c @@ -50,6 +50,7 @@ typedef struct __xm_machine_impl_t */ // the os functions +tb_int_t xm_os_find(lua_State* lua); tb_int_t xm_os_isdir(lua_State* lua); tb_int_t xm_os_rmdir(lua_State* lua); tb_int_t xm_os_mkdir(lua_State* lua); @@ -82,7 +83,8 @@ tb_int_t xm_preprocessor_loadx(lua_State* lua); // the os functions static luaL_Reg const g_os_functions[] = { - { "isdir", xm_os_isdir } + { "find", xm_os_find } +, { "isdir", xm_os_isdir } , { "rmdir", xm_os_rmdir } , { "mkdir", xm_os_mkdir } , { "cpdir", xm_os_cpdir } diff --git a/core/src/xmake/makefile b/core/src/xmake/makefile index 8d848e904..dc4c1cee5 100755 --- a/core/src/xmake/makefile +++ b/core/src/xmake/makefile @@ -14,6 +14,7 @@ xmake_CONFIG = y xmake_C_FILES += \ xmake \ machine \ + os/find \ os/isdir \ os/rmdir \ os/mkdir \ diff --git a/core/src/xmake/os/find.c b/core/src/xmake/os/find.c new file mode 100755 index 000000000..c891b9146 --- /dev/null +++ b/core/src/xmake/os/find.c @@ -0,0 +1,131 @@ +/*!The Automatic Cross-platform Build Tool + * + * XMake is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * XMake is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with XMake; + * If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a> + * + * Copyright (C) 2009 - 2015, ruki All rights reserved. + * + * @author ruki + * @file find.c + * + */ + +/* ////////////////////////////////////////////////////////////////////////////////////// + * trace + */ +#define TB_TRACE_MODULE_NAME "find" +#define TB_TRACE_MODULE_DEBUG (0) + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "prefix.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * private implementation + */ +static tb_bool_t xm_os_find_walk(tb_char_t const* path, tb_file_info_t const* info, tb_cpointer_t priv) +{ + // check + tb_value_ref_t tuple = (tb_value_ref_t)priv; + tb_assert_and_check_return_val(path && info && tuple, tb_false); + + // the lua + lua_State* lua = (lua_State*)tuple[0].ptr; + tb_assert_and_check_return_val(lua, tb_false); + + // the pattern + tb_char_t const* pattern = (tb_char_t const*)tuple[1].cstr; + tb_assert_and_check_return_val(pattern, tb_false); + + // find directory? + tb_bool_t findir = tuple[2].b; + + // the count + tb_size_t* pcount = &(tuple[3].ul); + + // trace + tb_trace_d("path[%c]: %s", info->type == TB_FILE_TYPE_DIRECTORY? 'd' : 'f', path); + + // find file or directory? + if ((findir && info->type == TB_FILE_TYPE_DIRECTORY) || (!findir && info->type == TB_FILE_TYPE_FILE)) + { + // done string.match(pattern) + lua_getfield(lua, -1, "match"); + lua_pushstring(lua, path); + lua_pushstring(lua, pattern); + if (lua_pcall(lua, 2, 1, 0)) + { + // trace + tb_printf("error: call string.match(%s, %s) failed: %s!\n", path, pattern, lua_tostring(lua, -1)); + + // failed + return tb_false; + } + + // match ok? save this path + if (lua_isstring(lua, -1) && !tb_strcmp(path, lua_tostring(lua, -1))) + lua_rawseti(lua, -3, ++*pcount); + // pop this return value + else lua_pop(lua, 1); + } + + // continue + return tb_true; +} +/* ////////////////////////////////////////////////////////////////////////////////////// + * implementation + */ +tb_int_t xm_os_find(lua_State* lua) +{ + // check + tb_assert_and_check_return_val(lua, 0); + + // get the root directory + tb_char_t const* rootdir = luaL_checkstring(lua, 1); + tb_check_return_val(rootdir, 0); + + // get the pattern + tb_char_t const* pattern = luaL_checkstring(lua, 2); + tb_check_return_val(pattern, 0); + + // is recurse? + tb_bool_t recurse = lua_toboolean(lua, 3); + + // find directory? + tb_bool_t findir = lua_toboolean(lua, 4); + + // init table + lua_newtable(lua); + + // get string package + lua_getglobal(lua, "string"); + + // done os.find(root, name) + tb_value_t tuple[4]; + tuple[0].ptr = lua; + tuple[1].cstr = pattern; + tuple[2].b = findir; + tuple[3].ul = 0; + tb_directory_walk(rootdir, recurse, tb_true, xm_os_find_walk, tuple); + + // pop string package + lua_pop(lua, 1); + + // return count + lua_pushinteger(lua, tuple[3].ul); + + // ok + return 2; +} diff --git a/xmake/scripts/action/_config.lua b/xmake/scripts/action/_config.lua index 1af22d27e..46e123800 100644 --- a/xmake/scripts/action/_config.lua +++ b/xmake/scripts/action/_config.lua @@ -27,7 +27,7 @@ local _config = _config or {} local utils = require("base/utils") local config = require("base/config") local makefile = require("base/makefile") - + -- done the given config function _config.done() diff --git a/xmake/scripts/base/os.lua b/xmake/scripts/base/os.lua index 7da3d9dcd..31434f37c 100644 --- a/xmake/scripts/base/os.lua +++ b/xmake/scripts/base/os.lua @@ -23,6 +23,10 @@ -- define module: os local os = os or {} +-- load modules +local path = require("base/path") +local utils = require("base/utils") + -- copy file or directory function os.cp(src, dst) @@ -139,5 +143,46 @@ function os.cd(path) return true end +-- match files or directories +-- +-- @param pattern the search pattern +-- uses "*" to match any part of a file or directory name, +-- uses "**" to recurse into subdirectories. +-- +-- @param findir true: find directory, false: find file +-- @return the result array and count +-- +-- @code +-- local dirs, count = os.match("./src/*", true) +-- local files, count = os.match("./src/**.c") +-- @endcode +-- +function os.match(pattern, findir) + + -- translate path and remove some repeat separators + pattern = path.translate(pattern) + + -- get the root directory + local rootdir = pattern + local starpos = pattern:find("%*") + if starpos then + rootdir = rootdir:sub(1, starpos - 1) + end + rootdir = path.directory(rootdir) + + -- is recurse? + local recurse = pattern:find("**", nil, true) + + -- convert pattern to a lua pattern + pattern = pattern:gsub("([%+%.%-%^%$%(%)%%])", "%%%1") + pattern = pattern:gsub("%*%*", "\001") + pattern = pattern:gsub("%*", "\002") + pattern = pattern:gsub("\001", ".*") + pattern = pattern:gsub("\002", "[^/]*") + + -- find it + return os.find(rootdir, pattern, recurse, findir) +end + -- return module: os return os |
