Add support of unicode to all file operations

This commit is contained in:
Lynix 2017-04-02 16:57:50 +02:00
parent 00aa7e3673
commit 98c381468b
14 changed files with 87 additions and 21 deletions

View File

@ -14,7 +14,8 @@ int do_chdir(lua_State* L, const char* path)
(void)(L); /* warning: unused parameter */
#if PLATFORM_WINDOWS
z = SetCurrentDirectoryA(path);
z = SetCurrentDirectoryW(utf8_towide(L, path));
lua_pop(L, 1);
#else
z = !chdir(path);
#endif

View File

@ -14,7 +14,8 @@ int os_copyfile(lua_State* L)
const char* dst = luaL_checkstring(L, 2);
#if PLATFORM_WINDOWS
z = CopyFileA(src, dst, FALSE);
z = CopyFileW(utf8_towide(L, src), utf8_towide(L, dst), FALSE);
lua_pop(L, 2);
#else
lua_pushfstring(L, "cp \"%s\" \"%s\"", src, dst);
z = (system(lua_tostring(L, -1)) == 0);

View File

@ -5,6 +5,7 @@
*/
#include "premake.h"
#include "assert.h"
int os_getcwd(lua_State* L)
{
@ -24,8 +25,13 @@ int do_getcwd(char* buffer, size_t size)
int result;
#if PLATFORM_WINDOWS
result = (GetCurrentDirectoryA(size, buffer) != 0);
assert(size == 0x4000);
wchar_t wbuffer[0x4000];
result = (GetCurrentDirectoryW(size, wbuffer) != 0);
if (result) {
WideCharToMultiByte(CP_UTF8, 0, wbuffer, -1, buffer, size, NULL, NULL);
do_translate(buffer, '/');
}
#else

View File

@ -18,6 +18,8 @@ int os_isdir(lua_State* L)
const char* path = luaL_checkstring(L, 1);
#ifdef _WIN32
int attr;
const wchar_t* wide_path = utf8_towide(L, path);
#endif
/* empty path is equivalent to ".", must be true */
@ -27,7 +29,7 @@ int os_isdir(lua_State* L)
}
#ifdef _WIN32
// Use Windows-specific GetFileAttributes since it deals with symbolic links.
else if ((attr = GetFileAttributesA(path)) != INVALID_FILE_ATTRIBUTES)
else if ((attr = GetFileAttributesW(wide_path)) != INVALID_FILE_ATTRIBUTES)
{
int isdir = (attr & FILE_ATTRIBUTE_DIRECTORY) != 0;
lua_pushboolean(L, isdir);
@ -42,6 +44,10 @@ int os_isdir(lua_State* L)
{
lua_pushboolean(L, 0);
}
#ifdef _WIN32
lua_pop(L, -2); /* pop wide string */
#endif
return 1;
}

View File

@ -11,15 +11,19 @@
int os_isfile(lua_State* L)
{
const char* filename = luaL_checkstring(L, 1);
lua_pushboolean(L, do_isfile(filename));
lua_pushboolean(L, do_isfile(L, filename));
return 1;
}
int do_isfile(const char* filename)
int do_isfile(lua_State* L, const char* filename)
{
(void)(L); /* warning: unused parameter */
#if PLATFORM_WINDOWS
DWORD attrib = GetFileAttributesA(filename);
DWORD attrib = GetFileAttributesW(utf8_towide(L, filename));
lua_pop(L, 1);
if (attrib != INVALID_FILE_ATTRIBUTES)
{
return (attrib & FILE_ATTRIBUTE_DIRECTORY) == 0;

View File

@ -14,7 +14,9 @@ int os_islink(lua_State* L)
#if PLATFORM_WINDOWS
{
DWORD attr = GetFileAttributesA(path);
DWORD attr = GetFileAttributesW(utf8_towide(L, path));
lua_pop(L, 1);
if (attr != INVALID_FILE_ATTRIBUTES) {
lua_pushboolean(L, (attr & FILE_ATTRIBUTE_REPARSE_POINT) != 0);
return 1;

View File

@ -37,7 +37,7 @@ int os_locate(lua_State* L)
const char* name = lua_tostring(L, i);
/* Direct path to file? Return as absolute path */
if (do_isfile(name)) {
if (do_isfile(L, name)) {
lua_pushcfunction(L, path_getabsolute);
lua_pushvalue(L, i);
lua_call(L, 1, 1);

View File

@ -15,14 +15,17 @@ typedef struct struct_MatchInfo
{
HANDLE handle;
int is_first;
WIN32_FIND_DATAA entry;
WIN32_FIND_DATAW entry;
} MatchInfo;
int os_matchstart(lua_State* L)
{
const char* mask = luaL_checkstring(L, 1);
MatchInfo* m = (MatchInfo*)malloc(sizeof(MatchInfo));
m->handle = FindFirstFileA(mask, &m->entry);
m->handle = FindFirstFileW(utf8_towide(L, mask), &m->entry);
lua_pop(L, 1);
m->is_first = 1;
lua_pushlightuserdata(L, m);
return 1;
@ -40,7 +43,7 @@ int os_matchdone(lua_State* L)
int os_matchname(lua_State* L)
{
MatchInfo* m = (MatchInfo*)lua_touserdata(L, 1);
lua_pushstring(L, m->entry.cFileName);
utf8_fromwide(L, m->entry.cFileName);
return 1;
}
@ -64,11 +67,11 @@ int os_matchnext(lua_State* L)
m->is_first = 0;
else
{
if (!FindNextFileA(m->handle, &m->entry))
if (!FindNextFileW(m->handle, &m->entry))
return 0;
}
if (strcmp(m->entry.cFileName, ".") != 0 && strcmp(m->entry.cFileName, "..") != 0)
if (wcscmp(m->entry.cFileName, L".") != 0 && wcscmp(m->entry.cFileName, L"..") != 0)
{
lua_pushboolean(L, 1);
return 1;
@ -159,7 +162,7 @@ int os_matchisfile(lua_State* L)
fname = lua_tostring(L, -1);
lua_pop(L, 1);
lua_pushboolean(L, do_isfile(fname));
lua_pushboolean(L, do_isfile(L, fname));
}
return 1;
}

View File

@ -58,7 +58,7 @@ int do_pathsearch(lua_State* L, const char* filename, const char* path)
lua_concat(L, 3);
/* test it - if it exists, return the absolute path */
if (do_isfile(lua_tostring(L, -1)))
if (do_isfile(L, lua_tostring(L, -1)))
{
lua_pop(L, 1);
lua_pushcfunction(L, path_getabsolute);

View File

@ -14,7 +14,8 @@ int os_rmdir(lua_State* L)
const char* path = luaL_checkstring(L, 1);
#if PLATFORM_WINDOWS
z = RemoveDirectoryA(path);
z = RemoveDirectoryW(utf8_towide(L, path));
lua_pop(L, 1);
#else
z = (0 == rmdir(path));
#endif

View File

@ -75,7 +75,7 @@ int os_writefile_ifnotequal(lua_State* L)
const char* dst = luaL_checkstring(L, 2);
// if destination exist, and they are the same, no need to copy.
if (do_isfile(dst) && compare_file(content, length, dst))
if (do_isfile(L, dst) && compare_file(content, length, dst))
{
lua_pushinteger(L, 0);
return 1;

View File

@ -229,9 +229,13 @@ int premake_locate_executable(lua_State* L, const char* argv0)
const char* path = NULL;
#if PLATFORM_WINDOWS
DWORD len = GetModuleFileNameA(NULL, buffer, PATH_MAX);
wchar_t widebuffer[PATH_MAX];
DWORD len = GetModuleFileNameW(NULL, widebuffer, PATH_MAX);
if (len > 0)
{
WideCharToMultiByte(CP_UTF8, 0, widebuffer, len, buffer, PATH_MAX, NULL, NULL);
buffer[len] = 0;
path = buffer;
}
@ -320,7 +324,7 @@ int premake_locate_executable(lua_State* L, const char* argv0)
int premake_test_file(lua_State* L, const char* filename, int searchMask)
{
if (searchMask & TEST_LOCAL) {
if (do_isfile(filename)) {
if (do_isfile(L, filename)) {
lua_pushcfunction(L, path_getabsolute);
lua_pushstring(L, filename);
lua_call(L, 1, 1);

View File

@ -80,12 +80,17 @@ unsigned long do_hash(const char* str, int seed);
void do_getabsolute(char* result, const char* value, const char* relative_to);
int do_getcwd(char* buffer, size_t size);
int do_isabsolute(const char* path);
int do_isfile(const char* filename);
int do_isfile(lua_State* L, const char* filename);
int do_locate(lua_State* L, const char* filename, const char* path);
void do_normalize(lua_State* L, char* buffer, const char* path);
int do_pathsearch(lua_State* L, const char* filename, const char* path);
void do_translate(char* value, const char sep);
/* Unicode conversion helper functions (required for Windows systems) */
#ifdef PLATFORM_WINDOWS
const char* utf8_fromwide(lua_State* L, const wchar_t* wstr);
const wchar_t* utf8_towide(lua_State* L, const char* str);
#endif
/* Built-in functions */
int criteria_compile(lua_State* L);

33
src/host/utf8handling.c Normal file
View File

@ -0,0 +1,33 @@
/**
* \file utf8handking.c
* \brief Handles conversions between Unicode (UTF-8) and system native encoding (wide chars on Windows)
* \author Copyright (c) 2017 Jérôme Leclercq and the Premake project
*/
#include "premake.h"
#include "stdlib.h"
#ifdef PLATFORM_WINDOWS
const char* utf8_fromwide(lua_State* L, const wchar_t* wstr)
{
int size_required = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
char* unicode_str = (char*) malloc(size_required * sizeof(char));
WideCharToMultiByte(CP_UTF8, 0, wstr, -1, unicode_str, size_required, NULL, NULL);
lua_pushstring(L, unicode_str);
free(unicode_str);
return unicode_str;
}
const wchar_t* utf8_towide(lua_State* L, const char* str)
{
int size_required = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
wchar_t* wide_string = (wchar_t*) lua_newuserdata(L, size_required * sizeof(wchar_t));
MultiByteToWideChar(CP_UTF8, 0, str, -1, wide_string, size_required);
return wide_string;
}
#endif