Skip to content

Commit c8c60f8

Browse files
Fix path encoding issues (#1153) (#2654)
* Test Unicode functionality * Lua support for UTF-8 on Windows * Premake support for UTF-8
1 parent 43a26b7 commit c8c60f8

49 files changed

Lines changed: 1680 additions & 586 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Bootstrap.mak

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ mingw-clean: nix-clean
106106

107107
mingw: mingw-clean
108108
mkdir -p build/bootstrap
109-
$(CC) -o build/bootstrap/premake_bootstrap -DPREMAKE_NO_BUILTIN_SCRIPTS -DLUA_STATICLIB -I"$(LUA_DIR)" -I"$(LUASHIM_DIR)" $(SRC) -lole32 -lversion
109+
$(CC) -o build/bootstrap/premake_bootstrap -DPREMAKE_NO_BUILTIN_SCRIPTS -DLUA_STATICLIB -DUNICODE -D_UNICODE -municode -I"$(LUA_DIR)" -I"$(LUASHIM_DIR)" $(SRC) -lole32 -lversion
110110
./build/bootstrap/premake_bootstrap embed
111111
./build/bootstrap/premake_bootstrap --arch=$(PLATFORM) --os=windows --to=build/bootstrap --cc=gcc $(PREMAKE_OPTS) gmake
112112
$(MAKE) -C build/bootstrap -j`getconf _NPROCESSORS_ONLN` config=$(CONFIG)_$(PLATFORM:x86=win32)
@@ -162,7 +162,7 @@ haiku: haiku-clean
162162

163163
windows-base: windows-clean
164164
if not exist build\bootstrap (mkdir build\bootstrap)
165-
cl /Fo.\build\bootstrap\ /Fe.\build\bootstrap\premake_bootstrap.exe /DPREMAKE_NO_BUILTIN_SCRIPTS /DLUA_STATICLIB /I"$(LUA_DIR)" /I"$(LUASHIM_DIR)" user32.lib ole32.lib advapi32.lib $(SRC)
165+
cl /Fo.\build\bootstrap\ /Fe.\build\bootstrap\premake_bootstrap.exe /DPREMAKE_NO_BUILTIN_SCRIPTS /DLUA_STATICLIB /DUNICODE /D_UNICODE /I"$(LUA_DIR)" /I"$(LUASHIM_DIR)" user32.lib ole32.lib advapi32.lib $(SRC)
166166
.\build\bootstrap\premake_bootstrap.exe embed
167167
.\build\bootstrap\premake_bootstrap --arch=$(PLATFORM) --to=build/bootstrap $(PREMAKE_OPTS) $(MSDEV)
168168

binmodules/luasocket/src/inet.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@
1212

1313
#include "inet.h"
1414

15+
#ifdef _WIN32 /* PREMAKE: Fix for unicode Windows build */
16+
#undef gai_strerror
17+
#define gai_strerror gai_strerrorA
18+
#endif
19+
1520
/*=========================================================================*\
1621
* Internal function prototypes.
1722
\*=========================================================================*/

binmodules/luasocket/src/udp.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@
2323
#define MAX(x, y) ((x) > (y) ? x : y)
2424
#endif
2525

26+
#ifdef _WIN32 /* PREMAKE: Fix for unicode Windows build */
27+
#undef gai_strerror
28+
#define gai_strerror gai_strerrorA
29+
#endif
30+
2631
/*=========================================================================*\
2732
* Internal function prototypes
2833
\*=========================================================================*/

binmodules/luasocket/src/wsocket.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ const char *socket_gaistrerror(int err) {
427427
#ifdef EAI_SYSTEM
428428
case EAI_SYSTEM: return strerror(errno);
429429
#endif
430-
default: return gai_strerror(err);
430+
default: return gai_strerrorA(err);
431431
}
432432
}
433433

contrib/lua/src/lauxlib.c

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626

2727
#include "lauxlib.h"
2828

29+
#if defined(LUA_USE_WINDOWS) /* PREMAKE: UTF-8 support on Windows */
30+
#include <windows.h>
31+
#endif
2932

3033
/*
3134
** {======================================================
@@ -706,19 +709,34 @@ LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename,
706709
int status, readstatus;
707710
int c;
708711
int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */
712+
#if defined(LUA_USE_WINDOWS) /* PREMAKE: UTF-8 character support on windows */
713+
const wchar_t *wfilename = NULL;
714+
#endif
709715
if (filename == NULL) {
710716
lua_pushliteral(L, "=stdin");
711717
lf.f = stdin;
712718
}
713719
else {
714720
lua_pushfstring(L, "@%s", filename);
721+
#if defined(LUA_USE_WINDOWS) /* PREMAKE: UTF-8 character support on windows */
722+
wfilename = luaL_convertstring(L, filename);
723+
lf.f = wfilename ? _wfopen(wfilename, L"r") : NULL;
724+
if (wfilename) lua_pop(L, 1);
725+
#else
715726
lf.f = fopen(filename, "r");
727+
#endif
716728
if (lf.f == NULL) return errfile(L, "open", fnameindex);
717729
}
718730
if (skipcomment(&lf, &c)) /* read initial portion */
719731
lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */
720732
if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */
733+
#if defined(LUA_USE_WINDOWS) /* PREMAKE: UTF-8 character support on windows */
734+
wfilename = luaL_convertstring(L, filename);
735+
lf.f = wfilename ? _wfreopen(wfilename, L"rb", lf.f) : NULL; /* reopen in binary mode */
736+
if (wfilename) lua_pop(L, 1);
737+
#else
721738
lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */
739+
#endif
722740
if (lf.f == NULL) return errfile(L, "reopen", fnameindex);
723741
skipcomment(&lf, &c); /* re-read initial portion */
724742
}
@@ -988,6 +1006,36 @@ LUALIB_API void luaL_requiref (lua_State *L, const char *modname,
9881006
}
9891007

9901008

1009+
LUALIB_API const char *luaL_getenv (lua_State *L, const char *name) {
1010+
#if defined(LUA_USE_WINDOWS)
1011+
const wchar_t *wname = luaL_convertstring(L, name);
1012+
const char *s;
1013+
wchar_t *wvar;
1014+
DWORD rc;
1015+
luaL_Buffer wbuf;
1016+
if (wname == NULL) return NULL;
1017+
rc = GetEnvironmentVariableW(wname, NULL, 0);
1018+
if (!rc) {
1019+
lua_pop(L, 1);
1020+
return NULL;
1021+
}
1022+
wvar = (wchar_t *)luaL_buffinitsize(L, &wbuf, rc * sizeof(wchar_t));
1023+
GetEnvironmentVariableW(wname, wvar, rc);
1024+
luaL_pushresultsize(&wbuf, rc * sizeof(wchar_t));
1025+
wvar = (wchar_t *)lua_tostring(L, -1);
1026+
s = luaL_convertlwstring(L, wvar, rc - 1, NULL);
1027+
lua_remove(L, -2); /* remove the string from wbuf */
1028+
lua_remove(L, -2); /* remove the string from wname */
1029+
return s;
1030+
#else
1031+
const char *value = getenv(name);
1032+
if (!value) return NULL;
1033+
lua_pushstring(L, value);
1034+
return lua_tostring(L, -1);
1035+
#endif
1036+
}
1037+
1038+
9911039
LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p,
9921040
const char *r) {
9931041
const char *wild;
@@ -1041,3 +1089,116 @@ LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver, size_t sz) {
10411089
(LUAI_UACNUMBER)ver, (LUAI_UACNUMBER)*v);
10421090
}
10431091

1092+
/*
1093+
** {======================================================
1094+
** Lua wide-string support (Windows only)
1095+
** =======================================================
1096+
*/
1097+
#if defined(LUA_USE_WINDOWS)
1098+
typedef struct UWideString {
1099+
size_t len;
1100+
wchar_t s[1]; /* actual size is len + 1 */
1101+
} UWideString;
1102+
1103+
#define LUA_WIDESTRING "LUA_WIDESTRING"
1104+
1105+
static UWideString *newwidestr (lua_State *L, const wchar_t *s, size_t len) {
1106+
UWideString *ws = (UWideString *)lua_newuserdata(L, sizeof(UWideString) + len * sizeof(wchar_t));
1107+
luaL_newmetatable(L, LUA_WIDESTRING);
1108+
lua_setmetatable(L, -2);
1109+
if (s) memcpy(ws->s, s, len * sizeof(wchar_t));
1110+
ws->s[len] = L'\0';
1111+
ws->len = len;
1112+
return ws;
1113+
}
1114+
1115+
LUALIB_API const wchar_t *luaL_convertlstringi (lua_State *L, int idx, size_t *len)
1116+
{
1117+
size_t nlen;
1118+
const char *s = lua_tolstring(L, idx, &nlen);
1119+
return luaL_convertlstring(L, s, nlen, len);
1120+
}
1121+
1122+
LUALIB_API const char *luaL_convertlwstring (lua_State *L, const wchar_t *ws, size_t wlen, size_t *len)
1123+
{
1124+
int size;
1125+
luaL_Buffer buf;
1126+
char *s;
1127+
if (ws == NULL) {
1128+
if (len != NULL) *len = 0;
1129+
return NULL;
1130+
}
1131+
size = WideCharToMultiByte(CP_UTF8, 0, ws, wlen, NULL, 0, NULL, NULL);
1132+
if (size == 0) { /* conversion failure */
1133+
if (len != NULL) *len = 0;
1134+
return NULL;
1135+
}
1136+
s = luaL_buffinitsize(L, &buf, size);
1137+
WideCharToMultiByte(CP_UTF8, 0, ws, wlen, s, size, NULL, NULL);
1138+
luaL_pushresultsize(&buf, size);
1139+
if (len != NULL) *len = size;
1140+
return lua_tostring(L, -1);
1141+
}
1142+
1143+
LUALIB_API const wchar_t *luaL_convertlstring (lua_State *L, const char *s, size_t nlen, size_t *len)
1144+
{
1145+
int size;
1146+
UWideString *ws;
1147+
if (s == NULL) {
1148+
if (len != NULL) *len = 0;
1149+
return NULL;
1150+
}
1151+
size = MultiByteToWideChar(CP_UTF8, 0, s, nlen, NULL, 0);
1152+
if (size == 0) { /* conversion failure */
1153+
if (len != NULL) *len = 0;
1154+
return NULL;
1155+
}
1156+
1157+
ws = newwidestr(L, NULL, size);
1158+
MultiByteToWideChar(CP_UTF8, 0, s, nlen, ws->s, size);
1159+
if (len != NULL) *len = size;
1160+
return ws->s;
1161+
}
1162+
1163+
LUALIB_API const char *(luaL_convertwstring) (lua_State *L, const wchar_t *ws, size_t *len)
1164+
{
1165+
int size, wlen;
1166+
luaL_Buffer buf;
1167+
char *s;
1168+
if (ws == NULL) {
1169+
if (len != NULL) *len = 0;
1170+
return NULL;
1171+
}
1172+
wlen = wcslen(ws);
1173+
size = WideCharToMultiByte(CP_UTF8, 0, ws, wlen, NULL, 0, NULL, NULL);
1174+
if (size == 0) { /* conversion failure */
1175+
if (len != NULL) *len = 0;
1176+
return NULL;
1177+
}
1178+
s = luaL_buffinitsize(L, &buf, size);
1179+
WideCharToMultiByte(CP_UTF8, 0, ws, wlen, s, size, NULL, NULL);
1180+
luaL_pushresultsize(&buf, size);
1181+
if (len != NULL) *len = size;
1182+
return lua_tostring(L, -1);
1183+
}
1184+
1185+
LUALIB_API const wchar_t *luaL_checkconvertlstring (lua_State *L, int idx, size_t *len)
1186+
{
1187+
size_t nlen;
1188+
const char *s = luaL_checklstring(L, idx, &nlen);
1189+
const wchar_t *ws = luaL_convertlstring(L, s, nlen, len);
1190+
if (ws == NULL) luaL_error(L, "conversion failure");
1191+
return ws;
1192+
}
1193+
1194+
LUALIB_API const wchar_t *luaL_optconvertlstring (lua_State *L, int idx, const wchar_t *def, size_t *len)
1195+
{
1196+
if (lua_isnoneornil(L, idx)) {
1197+
if (len != NULL) *len = (def ? wcslen(def) : 0);
1198+
return def;
1199+
}
1200+
return luaL_checkconvertlstring(L, idx, len);
1201+
}
1202+
1203+
#endif
1204+
/* }====================================================== */

contrib/lua/src/lauxlib.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ LUALIB_API void (luaL_traceback) (lua_State *L, lua_State *L1,
106106
LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname,
107107
lua_CFunction openf, int glb);
108108

109+
LUALIB_API const char *(luaL_getenv) (lua_State *L, const char *name);
110+
109111
/*
110112
** ===============================================================
111113
** some useful macros
@@ -258,6 +260,32 @@ LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname,
258260
/* }============================================================ */
259261

260262

263+
/*
264+
** {============================================================
265+
** Lua wide-string support (Windows only)
266+
** =============================================================
267+
*/
268+
#if defined(LUA_USE_WINDOWS)
269+
/* converts a UTF-8 Lua string at `idx` to a wide string */
270+
LUALIB_API const wchar_t *(luaL_convertlstringi) (lua_State *L, int idx, size_t *len);
271+
/* converts a wide string at `idx` to a UTF-8 Lua string */
272+
LUALIB_API const char *(luaL_convertlwstring) (lua_State *L, const wchar_t *ws, size_t wlen, size_t *len);
273+
/* converts a UTF-8 Lua string at `idx` to a wide string */
274+
LUALIB_API const wchar_t *(luaL_convertlstring) (lua_State *L, const char *s, size_t nlen, size_t *len);
275+
/* converts a UTF-8 Lua string at `idx` to a wide string */
276+
LUALIB_API const wchar_t *(luaL_checkconvertlstring) (lua_State *L, int idx, size_t *len);
277+
/* converts a UTF-8 Lua string at `idx` to a wide string */
278+
LUALIB_API const wchar_t *(luaL_optconvertlstring) (lua_State *L, int idx, const wchar_t *def, size_t *len);
279+
280+
LUALIB_API const char *(luaL_convertwstring) (lua_State *l, const wchar_t *ws, size_t *len);
281+
282+
#define luaL_convertstringi(L,i) (luaL_convertlstringi(L, (i), NULL))
283+
#define luaL_convertstring(L,s) (luaL_convertlstring(L, (s), (s ? strlen(s) : 0), NULL))
284+
#define luaL_checkconvertstring(L,i) (luaL_checkconvertlstring(L, (i), NULL))
285+
#define luaL_optconvertstring(L,i,d) (luaL_optconvertlstring(L, (i), (d), NULL))
286+
#endif
287+
/* }============================================================ */
288+
261289

262290
#endif
263291

contrib/lua/src/liolib.c

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
/*
2626
* PREMAKE change: UTF-8 character support on windows.
2727
*/
28-
#if defined(LUA_WIN)
28+
#if defined(LUA_USE_WINDOWS) /* PREMAKE: UTF-8 support on Windows */
2929
#include <windows.h>
3030
#endif
3131

@@ -253,7 +253,14 @@ static LStream *newfile (lua_State *L) {
253253

254254
static void opencheck (lua_State *L, const char *fname, const char *mode) {
255255
LStream *p = newfile(L);
256+
#if defined(LUA_USE_WINDOWS) /* PREMAKE: UTF-8 support on Windows */
257+
const wchar_t *wfname = luaL_convertstring(L, fname), *wmode = luaL_convertstring(L, mode);
258+
if (wfname == NULL || wmode == NULL) luaL_error(L, "encoding error");
259+
p->f = _wfopen(wfname, wmode);
260+
lua_pop(L, 2); /* pop converted strings */
261+
#else
256262
p->f = fopen(fname, mode);
263+
#endif
257264
if (p->f == NULL)
258265
luaL_error(L, "cannot open file '%s' (%s)", fname, strerror(errno));
259266
}
@@ -265,26 +272,14 @@ static int io_open (lua_State *L) {
265272
LStream *p = newfile(L);
266273
const char *md = mode; /* to traverse/check mode */
267274
luaL_argcheck(L, l_checkmode(md), 2, "invalid mode");
268-
269-
/*
270-
* PREMAKE change: UTF-8 character support on windows.
271-
*/
272-
#if defined(LUA_WIN)
273-
wchar_t wide_path[4096];
274-
if (MultiByteToWideChar(CP_UTF8, 0, filename, -1, wide_path, 4096) == 0)
275-
{
276-
lua_pushstring(L, "unable to encode path");
277-
return lua_error(L);
278-
}
279-
280-
wchar_t wide_mode[64];
281-
if (MultiByteToWideChar(CP_UTF8, 0, mode, -1, wide_mode, 64) == 0)
275+
#if defined(LUA_USE_WINDOWS) /* PREMAKE: UTF-8 support on Windows */
282276
{
283-
lua_pushstring(L, "unable to encode open mode");
284-
return lua_error(L);
277+
const wchar_t *wfilename = luaL_convertstring(L, filename), *wmode = luaL_convertstring(L, md);
278+
if (wfilename == NULL || wmode == NULL)
279+
return (errno = EINVAL, luaL_fileresult(L, 0, filename)); /* encoding error */
280+
p->f = _wfopen(wfilename, wmode);
281+
lua_pop(L, 2); /* pop converted strings */
285282
}
286-
287-
p->f = _wfopen(wide_path, wide_mode);
288283
#else
289284
p->f = fopen(filename, mode);
290285
#endif
@@ -303,12 +298,21 @@ static int io_pclose (lua_State *L) {
303298

304299

305300
static int io_popen (lua_State *L) {
301+
#if defined(LUA_USE_WINDOWS)
302+
const wchar_t* wmode = luaL_optconvertstring(L, 2, L"r");
303+
const wchar_t *wfilename = luaL_checkconvertstring(L, 1);
304+
LStream* p = newprefile(L);
305+
p->f = _wpopen(wfilename, wmode);
306+
p->closef = &io_pclose;
307+
return (p->f == NULL) ? luaL_fileresult(L, 0, lua_tostring(L, 1)) : 1;
308+
#else
306309
const char *filename = luaL_checkstring(L, 1);
307310
const char *mode = luaL_optstring(L, 2, "r");
308311
LStream *p = newprefile(L);
309312
p->f = l_popen(L, filename, mode);
310313
p->closef = &io_pclose;
311314
return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
315+
#endif
312316
}
313317

314318

0 commit comments

Comments
 (0)