Added support for wildcard matching (r391:396)
This commit is contained in:
parent
ee5b93015c
commit
bce9ab296c
@ -28,7 +28,7 @@ int gmake_project_shell_detect(Session sess, Project prj, Stream strm)
|
|||||||
z |= stream_writeline(strm, "ifeq (,$(ComSpec)$(COMSPEC))");
|
z |= stream_writeline(strm, "ifeq (,$(ComSpec)$(COMSPEC))");
|
||||||
z |= stream_writeline(strm, " SHELLTYPE := posix");
|
z |= stream_writeline(strm, " SHELLTYPE := posix");
|
||||||
z |= stream_writeline(strm, "endif");
|
z |= stream_writeline(strm, "endif");
|
||||||
z |= stream_writeline(strm, "ifeq (/bin/sh.exe,$(SHELL))");
|
z |= stream_writeline(strm, "ifeq (/bin,$(findstring /bin,$(SHELL)))");
|
||||||
z |= stream_writeline(strm, " SHELLTYPE := posix");
|
z |= stream_writeline(strm, " SHELLTYPE := posix");
|
||||||
z |= stream_writeline(strm, "endif");
|
z |= stream_writeline(strm, "endif");
|
||||||
z |= stream_writeline(strm, "");
|
z |= stream_writeline(strm, "");
|
||||||
|
@ -223,8 +223,11 @@ int make_project_objects(Session sess, Project prj, Stream strm)
|
|||||||
for (i = 0; i < n; ++i)
|
for (i = 0; i < n; ++i)
|
||||||
{
|
{
|
||||||
const char* filename = strings_item(files, i);
|
const char* filename = strings_item(files, i);
|
||||||
const char* obj_name = make_get_obj_filename(filename);
|
if (path_is_cpp_source(filename))
|
||||||
z |= stream_writeline(strm, "\t%s \\", obj_name);
|
{
|
||||||
|
const char* obj_name = make_get_obj_filename(filename);
|
||||||
|
z |= stream_writeline(strm, "\t%s \\", obj_name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
z |= stream_writeline(strm, "");
|
z |= stream_writeline(strm, "");
|
||||||
@ -288,11 +291,14 @@ int make_project_source_rules(Session sess, Project prj, Stream strm)
|
|||||||
for (i = 0; i < n; ++i)
|
for (i = 0; i < n; ++i)
|
||||||
{
|
{
|
||||||
const char* filename = strings_item(files, i);
|
const char* filename = strings_item(files, i);
|
||||||
const char* obj_name = make_get_obj_filename(filename);
|
if (path_is_cpp_source(filename))
|
||||||
z |= stream_writeline(strm, "%s: %s", obj_name, filename);
|
{
|
||||||
z |= stream_writeline(strm, "\t@echo $(notdir $<)");
|
const char* obj_name = make_get_obj_filename(filename);
|
||||||
z |= stream_writeline(strm, "\t@$(CXX) $(CXXFLAGS) -o $@ -c $<");
|
z |= stream_writeline(strm, "%s: %s", obj_name, filename);
|
||||||
z |= stream_writeline(strm, "");
|
z |= stream_writeline(strm, "\t@echo $(notdir $<)");
|
||||||
|
z |= stream_writeline(strm, "\t@$(CXX) $(CXXFLAGS) -o $@ -c $<");
|
||||||
|
z |= stream_writeline(strm, "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return z;
|
return z;
|
||||||
@ -308,7 +314,7 @@ int make_project_target(Session sess, Project prj, Stream strm)
|
|||||||
UNUSED(sess);
|
UNUSED(sess);
|
||||||
z |= stream_writeline(strm, "$(OUTFILE): $(OUTDIR) $(OBJDIR) $(OBJECTS) $(LDDEPS) $(RESOURCES)");
|
z |= stream_writeline(strm, "$(OUTFILE): $(OUTDIR) $(OBJDIR) $(OBJECTS) $(LDDEPS) $(RESOURCES)");
|
||||||
z |= stream_writeline(strm, "\t@echo Linking %s", project_get_name(prj));
|
z |= stream_writeline(strm, "\t@echo Linking %s", project_get_name(prj));
|
||||||
z |= stream_writeline(strm, "\t$(CXX) -o $@ $(LDFLAGS) $(ARCHFLAGS) $(OBJECTS) $(RESOURCES)");
|
z |= stream_writeline(strm, "\t@$(CXX) -o $@ $(LDFLAGS) $(ARCHFLAGS) $(OBJECTS) $(RESOURCES)");
|
||||||
z |= stream_writeline(strm, "");
|
z |= stream_writeline(strm, "");
|
||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
|
@ -169,7 +169,7 @@ SUITE(action)
|
|||||||
CHECK_EQUAL(
|
CHECK_EQUAL(
|
||||||
"$(OUTFILE): $(OUTDIR) $(OBJDIR) $(OBJECTS) $(LDDEPS) $(RESOURCES)\n"
|
"$(OUTFILE): $(OUTDIR) $(OBJDIR) $(OBJECTS) $(LDDEPS) $(RESOURCES)\n"
|
||||||
"\t@echo Linking MyProject\n"
|
"\t@echo Linking MyProject\n"
|
||||||
"\t$(CXX) -o $@ $(LDFLAGS) $(ARCHFLAGS) $(OBJECTS) $(RESOURCES)\n"
|
"\t@$(CXX) -o $@ $(LDFLAGS) $(ARCHFLAGS) $(OBJECTS) $(RESOURCES)\n"
|
||||||
"\n",
|
"\n",
|
||||||
buffer);
|
buffer);
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,18 @@
|
|||||||
#include "base/cstr.h"
|
#include "base/cstr.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if the sequence appears anywhere in the target string.
|
||||||
|
* \param str The string to test.
|
||||||
|
* \param expected The sequence to search for.
|
||||||
|
* \returns True if the sequence is contained in the string.
|
||||||
|
*/
|
||||||
|
int cstr_contains(const char* str, const char* expected)
|
||||||
|
{
|
||||||
|
return (strstr(str, expected) != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines if the string ends with a particular sequence.
|
* Determines if the string ends with a particular sequence.
|
||||||
* \param str The string to test.
|
* \param str The string to test.
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#if !defined(PREMAKE_CSTR_H)
|
#if !defined(PREMAKE_CSTR_H)
|
||||||
#define PREMAKE_CSTR_H
|
#define PREMAKE_CSTR_H
|
||||||
|
|
||||||
|
int cstr_contains(const char* str, const char* expected);
|
||||||
int cstr_ends_with(const char* str, const char* expected);
|
int cstr_ends_with(const char* str, const char* expected);
|
||||||
int cstr_eq(const char* str, const char* expected);
|
int cstr_eq(const char* str, const char* expected);
|
||||||
int cstr_eqi(const char* str, const char* expected);
|
int cstr_eqi(const char* str, const char* expected);
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#include "base/string.h"
|
#include "base/string.h"
|
||||||
|
|
||||||
|
|
||||||
DEFINE_CLASS(string)
|
DEFINE_CLASS(String)
|
||||||
{
|
{
|
||||||
char* contents;
|
char* contents;
|
||||||
int capacity;
|
int capacity;
|
||||||
@ -22,11 +22,11 @@ DEFINE_CLASS(string)
|
|||||||
* \param value The C string value.
|
* \param value The C string value.
|
||||||
* \returns A new dynamic string object containing a copy of the string.
|
* \returns A new dynamic string object containing a copy of the string.
|
||||||
*/
|
*/
|
||||||
string string_create(const char* value)
|
String string_create(const char* value)
|
||||||
{
|
{
|
||||||
if (value != NULL)
|
if (value != NULL)
|
||||||
{
|
{
|
||||||
string str = ALLOC_CLASS(string);
|
String str = ALLOC_CLASS(String);
|
||||||
str->capacity = strlen(value) + 1;
|
str->capacity = strlen(value) + 1;
|
||||||
str->contents = (char*)malloc(str->capacity);
|
str->contents = (char*)malloc(str->capacity);
|
||||||
strcpy(str->contents, value);
|
strcpy(str->contents, value);
|
||||||
@ -43,7 +43,7 @@ string string_create(const char* value)
|
|||||||
* Destroy a dynamic string object and free the associated memory.
|
* Destroy a dynamic string object and free the associated memory.
|
||||||
* \param str The string to destroy.
|
* \param str The string to destroy.
|
||||||
*/
|
*/
|
||||||
void string_destroy(string str)
|
void string_destroy(String str)
|
||||||
{
|
{
|
||||||
if (str != NULL)
|
if (str != NULL)
|
||||||
{
|
{
|
||||||
@ -58,7 +58,7 @@ void string_destroy(string str)
|
|||||||
* \param str The string to query.
|
* \param str The string to query.
|
||||||
* \returns The C string value.
|
* \returns The C string value.
|
||||||
*/
|
*/
|
||||||
const char* string_cstr(string str)
|
const char* string_cstr(String str)
|
||||||
{
|
{
|
||||||
if (str != NULL)
|
if (str != NULL)
|
||||||
return str->contents;
|
return str->contents;
|
||||||
|
@ -13,11 +13,11 @@
|
|||||||
#if !defined(PREMAKE_STRING_H)
|
#if !defined(PREMAKE_STRING_H)
|
||||||
#define PREMAKE_STRING_H
|
#define PREMAKE_STRING_H
|
||||||
|
|
||||||
DECLARE_CLASS(string);
|
DECLARE_CLASS(String);
|
||||||
|
|
||||||
string string_create(const char* value);
|
String string_create(const char* value);
|
||||||
void string_destroy(string str);
|
void string_destroy(String str);
|
||||||
const char* string_cstr(string str);
|
const char* string_cstr(String str);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
/** @} */
|
/** @} */
|
||||||
|
@ -12,6 +12,21 @@ extern "C" {
|
|||||||
|
|
||||||
SUITE(cstr)
|
SUITE(cstr)
|
||||||
{
|
{
|
||||||
|
/**************************************************************************
|
||||||
|
* cstr_contains() tests
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
TEST(CStrContains_ReturnsTrue_OnMatch)
|
||||||
|
{
|
||||||
|
CHECK(cstr_contains("Abcdef", "cd"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CStrContains_ReturnsFalse_OnMismatch)
|
||||||
|
{
|
||||||
|
CHECK(!cstr_contains("Abcdef", "xy"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* cstr_ends_with() tests
|
* cstr_ends_with() tests
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
@ -18,7 +18,7 @@ SUITE(base)
|
|||||||
|
|
||||||
TEST(StringCreate_ReturnsNull_OnNull)
|
TEST(StringCreate_ReturnsNull_OnNull)
|
||||||
{
|
{
|
||||||
string str = string_create(NULL);
|
String str = string_create(NULL);
|
||||||
CHECK(str == NULL);
|
CHECK(str == NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,6 +38,8 @@ enum Platform
|
|||||||
#define PLATFORM_WINDOWS (1)
|
#define PLATFORM_WINDOWS (1)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
DECLARE_CLASS(PlatformSearch)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a directory, if it doesn't exist already.
|
* Create a directory, if it doesn't exist already.
|
||||||
@ -76,6 +78,37 @@ int platform_dir_set_current(const char* path);
|
|||||||
enum Platform platform_get(void);
|
enum Platform platform_get(void);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new platform file search context.
|
||||||
|
*/
|
||||||
|
PlatformSearch platform_search_create(const char* mask);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy a platform search context.
|
||||||
|
*/
|
||||||
|
void platform_search_destroy(PlatformSearch search);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the name of the current match in the search.
|
||||||
|
*/
|
||||||
|
const char* platform_search_get_name(PlatformSearch search);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the current match is a file or a directory.
|
||||||
|
*/
|
||||||
|
int platform_search_is_file(PlatformSearch search);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the next match in a file system search.
|
||||||
|
* \returns True if another match is available.
|
||||||
|
*/
|
||||||
|
int platform_search_next(PlatformSearch search);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the platform identification string, forcing a platform-specific
|
* Set the platform identification string, forcing a platform-specific
|
||||||
* behavior regardless of the actual current platform.
|
* behavior regardless of the actual current platform.
|
||||||
|
@ -6,6 +6,9 @@
|
|||||||
|
|
||||||
#include "premake.h"
|
#include "premake.h"
|
||||||
#include "platform/platform.h"
|
#include "platform/platform.h"
|
||||||
|
#include "base/path.h"
|
||||||
|
#include "base/string.h"
|
||||||
|
|
||||||
#if !defined(PLATFORM_WINDOWS)
|
#if !defined(PLATFORM_WINDOWS)
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -18,6 +21,14 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
|
DEFINE_CLASS(PlatformSearch)
|
||||||
|
{
|
||||||
|
String directory;
|
||||||
|
String mask;
|
||||||
|
DIR* handle;
|
||||||
|
struct dirent* entry;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
int platform_create_dir(const char* path)
|
int platform_create_dir(const char* path)
|
||||||
{
|
{
|
||||||
@ -47,5 +58,79 @@ int platform_dir_set_current(const char* path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PlatformSearch platform_search_create(const char* mask)
|
||||||
|
{
|
||||||
|
PlatformSearch search;
|
||||||
|
const char* dir;
|
||||||
|
|
||||||
|
dir = path_directory(mask);
|
||||||
|
mask = path_filename(mask);
|
||||||
|
if (strlen(dir) == 0)
|
||||||
|
{
|
||||||
|
dir = ".";
|
||||||
|
}
|
||||||
|
|
||||||
|
search = ALLOC_CLASS(PlatformSearch);
|
||||||
|
search->directory = string_create(dir);
|
||||||
|
search->mask = string_create(mask);
|
||||||
|
search->handle = opendir(dir);
|
||||||
|
search->entry = NULL;
|
||||||
|
return search;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void platform_search_destroy(PlatformSearch search)
|
||||||
|
{
|
||||||
|
if (search->handle != NULL)
|
||||||
|
{
|
||||||
|
closedir(search->handle);
|
||||||
|
}
|
||||||
|
free(search);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char* platform_search_get_name(PlatformSearch search)
|
||||||
|
{
|
||||||
|
return search->entry->d_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int platform_search_is_file(PlatformSearch search)
|
||||||
|
{
|
||||||
|
struct stat info;
|
||||||
|
|
||||||
|
const char* dir = string_cstr(search->directory);
|
||||||
|
const char* path = path_join(dir, search->entry->d_name);
|
||||||
|
if (stat(path, &info) == 0)
|
||||||
|
{
|
||||||
|
return S_ISREG(info.st_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int platform_search_next(PlatformSearch search)
|
||||||
|
{
|
||||||
|
const char* mask = string_cstr(search->mask);
|
||||||
|
|
||||||
|
if (search->handle == NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
search->entry = readdir(search->handle);
|
||||||
|
while (search->entry != NULL)
|
||||||
|
{
|
||||||
|
if (fnmatch(mask, search->entry->d_name, 0) == 0)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
search->entry = readdir(search->handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
* \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
|
* \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
#include "premake.h"
|
#include "premake.h"
|
||||||
#include "platform/platform.h"
|
#include "platform/platform.h"
|
||||||
#if defined(PLATFORM_WINDOWS)
|
#if defined(PLATFORM_WINDOWS)
|
||||||
@ -12,6 +13,14 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
|
|
||||||
|
DEFINE_CLASS(PlatformSearch)
|
||||||
|
{
|
||||||
|
HANDLE handle;
|
||||||
|
int is_first;
|
||||||
|
WIN32_FIND_DATA entry;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
int platform_create_dir(const char* path)
|
int platform_create_dir(const char* path)
|
||||||
{
|
{
|
||||||
return CreateDirectory(path, NULL) ? OKAY : !OKAY;
|
return CreateDirectory(path, NULL) ? OKAY : !OKAY;
|
||||||
@ -44,4 +53,53 @@ int platform_dir_set_current(const char* path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PlatformSearch platform_search_create(const char* mask)
|
||||||
|
{
|
||||||
|
PlatformSearch search = ALLOC_CLASS(PlatformSearch);
|
||||||
|
search->handle = FindFirstFile(mask, &search->entry);
|
||||||
|
search->is_first = 1;
|
||||||
|
return search;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void platform_search_destroy(PlatformSearch search)
|
||||||
|
{
|
||||||
|
if (search->handle != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
FindClose(search->handle);
|
||||||
|
}
|
||||||
|
free(search);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char* platform_search_get_name(PlatformSearch search)
|
||||||
|
{
|
||||||
|
return search->entry.cFileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int platform_search_is_file(PlatformSearch search)
|
||||||
|
{
|
||||||
|
return (search->entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int platform_search_next(PlatformSearch search)
|
||||||
|
{
|
||||||
|
if (search->handle == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (search->is_first)
|
||||||
|
{
|
||||||
|
search->is_first = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return FindNextFile(search->handle, &search->entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -18,7 +18,8 @@
|
|||||||
enum FieldKind
|
enum FieldKind
|
||||||
{
|
{
|
||||||
StringField,
|
StringField,
|
||||||
ListField
|
ListField,
|
||||||
|
FilesField
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -36,7 +37,7 @@ typedef int (*FieldValidator)(const char* value);
|
|||||||
struct FieldInfo
|
struct FieldInfo
|
||||||
{
|
{
|
||||||
const char* name; /**< The name of the field. */
|
const char* name; /**< The name of the field. */
|
||||||
enum FieldKind kind; /**< StringField or ListField */
|
enum FieldKind kind; /**< StringField, ListField, etc. */
|
||||||
FieldValidator validator; /**< The field validation function */
|
FieldValidator validator; /**< The field validation function */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
struct FieldInfo ProjectFieldInfo[] =
|
struct FieldInfo ProjectFieldInfo[] =
|
||||||
{
|
{
|
||||||
{ "basedir", StringField, NULL },
|
{ "basedir", StringField, NULL },
|
||||||
{ "files", ListField, NULL },
|
{ "files", FilesField, NULL },
|
||||||
{ "guid", StringField, guid_is_valid },
|
{ "guid", StringField, guid_is_valid },
|
||||||
{ "language", StringField, project_is_valid_language },
|
{ "language", StringField, project_is_valid_language },
|
||||||
{ "location", StringField, NULL },
|
{ "location", StringField, NULL },
|
||||||
|
@ -16,7 +16,7 @@ static int fn_accessor_register(lua_State* L, struct FieldInfo* fields);
|
|||||||
static int fn_accessor_register_field(lua_State* L, struct FieldInfo* field);
|
static int fn_accessor_register_field(lua_State* L, struct FieldInfo* field);
|
||||||
static int fn_accessor_set_string_value(lua_State* L, struct FieldInfo* field);
|
static int fn_accessor_set_string_value(lua_State* L, struct FieldInfo* field);
|
||||||
static int fn_accessor_set_list_value(lua_State* L, struct FieldInfo* field);
|
static int fn_accessor_set_list_value(lua_State* L, struct FieldInfo* field);
|
||||||
static void fn_accessor_append_values(lua_State* L, int destIndex, int srcIndex);
|
static void fn_accessor_append_value(lua_State* L, struct FieldInfo* field, int tbl, int idx);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -177,17 +177,8 @@ static int fn_accessor_set_list_value(lua_State* L, struct FieldInfo* field)
|
|||||||
/* get the current value of the field */
|
/* get the current value of the field */
|
||||||
lua_getfield(L, -1, field->name);
|
lua_getfield(L, -1, field->name);
|
||||||
|
|
||||||
/* if the value passed in is a table, append all of its contents to the current
|
/* move the values into the field */
|
||||||
* field value. If the value passed in is a single string, add it at the end */
|
fn_accessor_append_value(L, field, lua_gettop(L), 1);
|
||||||
if (lua_istable(L, 1))
|
|
||||||
{
|
|
||||||
fn_accessor_append_values(L, lua_gettop(L), 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lua_pushvalue(L, 1);
|
|
||||||
lua_rawseti(L, -2, luaL_getn(L, -2) + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* remove the field value from the stack */
|
/* remove the field value from the stack */
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
@ -196,26 +187,43 @@ static int fn_accessor_set_list_value(lua_State* L, struct FieldInfo* field)
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copy values from one table to the end of another table.
|
* Append a value to table. If the value is itself a table, it is "flattened" into the
|
||||||
* \param destIndex The absolute stack index of the destination table.
|
* destination table by iterating over each of its items and adding each in turn to the
|
||||||
* \param srcIndex The absolute stack index of the source table.
|
* target table.
|
||||||
|
* \param L The current Lua state.
|
||||||
|
* \param field A description of the field being populated.
|
||||||
|
* \param tbl The table to contain the values.
|
||||||
|
* \param idx The value to add to the table.
|
||||||
*/
|
*/
|
||||||
static void fn_accessor_append_values(lua_State* L, int destIndex, int srcIndex)
|
static void fn_accessor_append_value(lua_State* L, struct FieldInfo* field, int tbl, int idx)
|
||||||
{
|
{
|
||||||
int i;
|
int i, n;
|
||||||
int src_n = luaL_getn(L, srcIndex);
|
if (lua_istable(L, idx))
|
||||||
int dst_n = luaL_getn(L, destIndex);
|
|
||||||
for (i = 1; i <= src_n; ++i)
|
|
||||||
{
|
{
|
||||||
lua_rawgeti(L, srcIndex, i);
|
n = luaL_getn(L, idx);
|
||||||
if (lua_istable(L, -1))
|
for (i = 1; i <= n; ++i)
|
||||||
{
|
{
|
||||||
fn_accessor_append_values(L, destIndex, lua_gettop(L));
|
lua_rawgeti(L, idx, i);
|
||||||
dst_n = luaL_getn(L, destIndex);
|
fn_accessor_append_value(L, field, tbl, lua_gettop(L));
|
||||||
|
}
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* if this field contains files, check for and expand wildcards by calling match() */
|
||||||
|
const char* value = lua_tostring(L, -1);
|
||||||
|
if (field->kind == FilesField && cstr_contains(value, "*"))
|
||||||
|
{
|
||||||
|
lua_getglobal(L, "match");
|
||||||
|
lua_pushvalue(L, -2);
|
||||||
|
lua_call(L, 1, 1);
|
||||||
|
fn_accessor_append_value(L, field, tbl, lua_gettop(L));
|
||||||
|
lua_pop(L, 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lua_rawseti(L, destIndex, ++dst_n);
|
n = luaL_getn(L, tbl);
|
||||||
|
lua_rawseti(L, tbl, n + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,8 @@ int fn_dofile(lua_State* L)
|
|||||||
const char *filename;
|
const char *filename;
|
||||||
const char* full_path;
|
const char* full_path;
|
||||||
const char* script_dir;
|
const char* script_dir;
|
||||||
string old_file;
|
String old_file;
|
||||||
string old_working_dir;
|
String old_working_dir;
|
||||||
int top, result;
|
int top, result;
|
||||||
|
|
||||||
filename = luaL_checkstring(L, 1);
|
filename = luaL_checkstring(L, 1);
|
||||||
|
101
src/script/fn_match.c
Normal file
101
src/script/fn_match.c
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/**
|
||||||
|
* \file fn_match.c
|
||||||
|
* \brief Perform a wildcard match for files.
|
||||||
|
* \author Copyright (c) 2008 Jason Perkins and the Premake project
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "premake.h"
|
||||||
|
#include "script_internal.h"
|
||||||
|
#include "platform/platform.h"
|
||||||
|
#include "base/cstr.h"
|
||||||
|
#include "base/path.h"
|
||||||
|
#include "base/string.h"
|
||||||
|
|
||||||
|
static void do_scan(lua_State* L, const char* mask);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform a wildcard match for files; returns a table of file names which
|
||||||
|
* match the supplied pattern.
|
||||||
|
*/
|
||||||
|
int fn_match(lua_State* L)
|
||||||
|
{
|
||||||
|
int i, n;
|
||||||
|
|
||||||
|
/* table to hold the results */
|
||||||
|
lua_newtable(L);
|
||||||
|
|
||||||
|
/* scan each mask in the provided list */
|
||||||
|
n = lua_gettop(L);
|
||||||
|
for (i = 1; i < n; ++i)
|
||||||
|
{
|
||||||
|
const char* mask = luaL_checkstring(L, i);
|
||||||
|
do_scan(L, mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does the real work of scanning the file system and matching the supplied patterns.
|
||||||
|
*/
|
||||||
|
void do_scan(lua_State* L, const char* mask)
|
||||||
|
{
|
||||||
|
/* mark the end of the results lists so I know where to add new entries */
|
||||||
|
int n = luaL_getn(L, -1);
|
||||||
|
|
||||||
|
/* the search will only return file names; remember the path so I can add it back */
|
||||||
|
String dir = string_create(path_directory(mask));
|
||||||
|
|
||||||
|
/* search */
|
||||||
|
PlatformSearch search = platform_search_create(mask);
|
||||||
|
while (platform_search_next(search))
|
||||||
|
{
|
||||||
|
const char* filename = platform_search_get_name(search);
|
||||||
|
int is_file = platform_search_is_file(search);
|
||||||
|
|
||||||
|
if (is_file)
|
||||||
|
{
|
||||||
|
/* add it to the results */
|
||||||
|
const char* path = path_join(string_cstr(dir), filename);
|
||||||
|
lua_pushstring(L, path);
|
||||||
|
lua_rawseti(L, -2, ++n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
platform_search_destroy(search);
|
||||||
|
|
||||||
|
/* if the mask uses the ** pattern, recurse into subdirectories */
|
||||||
|
if (cstr_contains(mask, "**"))
|
||||||
|
{
|
||||||
|
mask = path_filename(mask);
|
||||||
|
|
||||||
|
/* look for subdirectories */
|
||||||
|
search = platform_search_create(path_join(string_cstr(dir), "*"));
|
||||||
|
while (platform_search_next(search))
|
||||||
|
{
|
||||||
|
if (!platform_search_is_file(search))
|
||||||
|
{
|
||||||
|
const char* dirname = platform_search_get_name(search);
|
||||||
|
if (dirname[0] != '.')
|
||||||
|
{
|
||||||
|
/* build a new mask from the original directory, this new subdirectory,
|
||||||
|
* and the original search mask. Need to put it in a string to ensure
|
||||||
|
* its buffer doesn't get overwritten */
|
||||||
|
String subsearch;
|
||||||
|
const char* path = path_join(string_cstr(dir), dirname);
|
||||||
|
path = path_join(path, mask);
|
||||||
|
subsearch = string_create(path);
|
||||||
|
|
||||||
|
/* recurse to search this subdirectory */
|
||||||
|
do_scan(L, string_cstr(subsearch));
|
||||||
|
|
||||||
|
string_destroy(subsearch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
platform_search_destroy(search);
|
||||||
|
}
|
||||||
|
|
||||||
|
string_destroy(dir);
|
||||||
|
}
|
@ -15,9 +15,10 @@
|
|||||||
|
|
||||||
/** Functions to add to the global namespace */
|
/** Functions to add to the global namespace */
|
||||||
static const luaL_Reg global_funcs[] = {
|
static const luaL_Reg global_funcs[] = {
|
||||||
{ "dofile", fn_dofile },
|
{ "dofile", fn_dofile },
|
||||||
{ "include", fn_include },
|
{ "include", fn_include },
|
||||||
{ "project", fn_project },
|
{ "match", fn_match },
|
||||||
|
{ "project", fn_project },
|
||||||
{ "solution", fn_solution },
|
{ "solution", fn_solution },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
@ -159,7 +159,7 @@ void script_internal_populate_object(lua_State* L, struct FieldInfo* fields)
|
|||||||
/* set all list-type configuration values to empty tables */
|
/* set all list-type configuration values to empty tables */
|
||||||
for (field = fields; field->name != NULL; ++field)
|
for (field = fields; field->name != NULL; ++field)
|
||||||
{
|
{
|
||||||
if (field->kind == ListField)
|
if (field->kind != StringField)
|
||||||
{
|
{
|
||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
lua_setfield(L, -2, field->name);
|
lua_setfield(L, -2, field->name);
|
||||||
|
@ -52,6 +52,7 @@ int fn_dofile(lua_State* L);
|
|||||||
int fn_error(lua_State* L);
|
int fn_error(lua_State* L);
|
||||||
int fn_getcwd(lua_State* L);
|
int fn_getcwd(lua_State* L);
|
||||||
int fn_include(lua_State* L);
|
int fn_include(lua_State* L);
|
||||||
|
int fn_match(lua_State* L);
|
||||||
int fn_project(lua_State* L);
|
int fn_project(lua_State* L);
|
||||||
int fn_solution(lua_State* L);
|
int fn_solution(lua_State* L);
|
||||||
|
|
||||||
|
@ -117,4 +117,17 @@ SUITE(script)
|
|||||||
"return (prj.files[1] == 'Hello.c' and prj.files[2] == 'Goodbye.c')" );
|
"return (prj.files[1] == 'Hello.c' and prj.files[2] == 'Goodbye.c')" );
|
||||||
CHECK_EQUAL("true", result);
|
CHECK_EQUAL("true", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
* List field tests
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
TEST_FIXTURE(FxAccessor, Accessor_ExpandsWildcards)
|
||||||
|
{
|
||||||
|
const char* result = script_run_string(script,
|
||||||
|
"files { 'testing/test_files/*.lua' };"
|
||||||
|
"return (#prj.files > 0)");
|
||||||
|
CHECK_EQUAL("true", result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
58
src/script/tests/fn_match_tests.cpp
Normal file
58
src/script/tests/fn_match_tests.cpp
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/**
|
||||||
|
* \file fn_match_tests.cpp
|
||||||
|
* \brief Automated test for the match() function.
|
||||||
|
* \author Copyright (c) 2008 Jason Perkins and the Premake project
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "premake.h"
|
||||||
|
#include "script_tests.h"
|
||||||
|
extern "C" {
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FxMatch : FxScript
|
||||||
|
{
|
||||||
|
FxMatch()
|
||||||
|
{
|
||||||
|
script_run_string(script,
|
||||||
|
"function contains(tbl,val)"
|
||||||
|
" for i,v in ipairs(files) do"
|
||||||
|
" if (v == val) then return true end"
|
||||||
|
" end"
|
||||||
|
" return false;"
|
||||||
|
"end");
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
SUITE(script)
|
||||||
|
{
|
||||||
|
TEST_FIXTURE(FxMatch, Match_Exists_OnStartup)
|
||||||
|
{
|
||||||
|
const char* result = script_run_string(script,
|
||||||
|
"return (match ~= nil)");
|
||||||
|
CHECK_EQUAL("true", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_FIXTURE(FxMatch, Match_ReturnsEmptyTable_OnNoMatches)
|
||||||
|
{
|
||||||
|
const char* result = script_run_string(script,
|
||||||
|
"return #match('*.xyz')");
|
||||||
|
CHECK_EQUAL("0", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_FIXTURE(FxMatch, Match_ReturnsMatches_OnMatch)
|
||||||
|
{
|
||||||
|
const char* result = script_run_string(script,
|
||||||
|
"files = match('testing/test_files/*.lua');"
|
||||||
|
"return contains(files, 'testing/test_files/true.lua');");
|
||||||
|
CHECK_EQUAL("true", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_FIXTURE(FxMatch, Match_Recurses_OnDoubleStar)
|
||||||
|
{
|
||||||
|
const char* result = script_run_string(script,
|
||||||
|
"files = match('testing/test_files/**.lua');"
|
||||||
|
"return contains(files, 'testing/test_files/nested/getcwd.lua');");
|
||||||
|
CHECK_EQUAL("true", result);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user