diff options
author | Dan Gudmundsson <[email protected]> | 2013-06-04 12:38:31 +0200 |
---|---|---|
committer | Dan Gudmundsson <[email protected]> | 2013-06-04 12:38:31 +0200 |
commit | e83fd8f94aba352b6cc055d2b4cfff007911b6d4 (patch) | |
tree | 66b22e7e79813d9ec2b0f5a9817a3908682a22ee /erts/etc/common | |
parent | e00d6bbbabd7b76c050665fc417e81554a83e341 (diff) | |
parent | ee23d4b549618044d4a4f800db839483b359cb9f (diff) | |
download | otp-e83fd8f94aba352b6cc055d2b4cfff007911b6d4.tar.gz otp-e83fd8f94aba352b6cc055d2b4cfff007911b6d4.tar.bz2 otp-e83fd8f94aba352b6cc055d2b4cfff007911b6d4.zip |
Merge branch 'dgud/win32_unicode'
* dgud/win32_unicode:
erts: Windows, convert erlsrv to use widestring
erts: Window start_erl now uses widechars/unicode
Quote windows paths with spaces
Handle space in paths in test Makefiles
erts: Fix windows widestring args and paths in tools
erts: Windows, use widechars for all paths during startup
OTP-11135
Diffstat (limited to 'erts/etc/common')
-rw-r--r-- | erts/etc/common/ct_run.c | 82 | ||||
-rw-r--r-- | erts/etc/common/dialyzer.c | 104 | ||||
-rw-r--r-- | erts/etc/common/erlc.c | 117 | ||||
-rw-r--r-- | erts/etc/common/erlexec.c | 76 | ||||
-rw-r--r-- | erts/etc/common/escript.c | 247 | ||||
-rw-r--r-- | erts/etc/common/heart.c | 117 | ||||
-rw-r--r-- | erts/etc/common/typer.c | 97 |
7 files changed, 530 insertions, 310 deletions
diff --git a/erts/etc/common/ct_run.c b/erts/etc/common/ct_run.c index 853785dcd1..bb59b93998 100644 --- a/erts/etc/common/ct_run.c +++ b/erts/etc/common/ct_run.c @@ -117,9 +117,14 @@ char *strerror(int errnum) } #endif /* !HAVE_STRERROR */ -int -main(int argc, char** argv) +#ifdef __WIN32__ +int wmain(int argc, wchar_t **wcargv) +{ + char** argv; +#else +int main(int argc, char** argv) { +#endif int eargv_size; int eargc_base; /* How many arguments in the base of eargv. */ char* emulator; @@ -129,7 +134,21 @@ main(int argc, char** argv) int dist_mode; int cnt; int erl_args; - char** argv0 = argv; + char** argv0; + +#ifdef __WIN32__ + int i; + int len; + /* Convert argv to utf8 */ + argv = malloc((argc+1) * sizeof(char*)); + for (i=0; i<argc; i++) { + len = WideCharToMultiByte(CP_UTF8, 0, wcargv[i], -1, NULL, 0, NULL, NULL); + argv[i] = malloc(len*sizeof(char)); + WideCharToMultiByte(CP_UTF8, 0, wcargv[i], -1, argv[i], len, NULL, NULL); + } + argv[argc] = NULL; +#endif + argv0 = argv; emulator = get_default_emulator(argv[0]); @@ -295,48 +314,50 @@ push_words(char* src) PUSH(strsave(sbuf)); } #ifdef __WIN32__ -char *make_commandline(char **argv) +wchar_t *make_commandline(char **argv) { - static char *buff = NULL; + static wchar_t *buff = NULL; static int siz = 0; - int num = 0; - char **arg, *p; + int num = 0, len; + char **arg; + wchar_t *p; - if (*argv == NULL) { - return ""; + if (*argv == NULL) { + return L""; } for (arg = argv; *arg != NULL; ++arg) { num += strlen(*arg)+1; } if (!siz) { siz = num; - buff = malloc(siz*sizeof(char)); + buff = (wchar_t *) emalloc(siz*sizeof(wchar_t)); } else if (siz < num) { siz = num; - buff = realloc(buff,siz*sizeof(char)); + buff = (wchar_t *) realloc(buff,siz*sizeof(wchar_t)); } p = buff; + num=0; for (arg = argv; *arg != NULL; ++arg) { - strcpy(p,*arg); - p+=strlen(*arg); - *p++=' '; + len = MultiByteToWideChar(CP_UTF8, 0, *arg, -1, p, siz); + p+=(len-1); + *p++=L' '; } - *(--p) = '\0'; + *(--p) = L'\0'; if (debug) { - printf("Processed commandline:%s\n",buff); + printf("Processed command line:%S\n",buff); } return buff; } int my_spawnvp(char **argv) { - STARTUPINFO siStartInfo; + STARTUPINFOW siStartInfo; PROCESS_INFORMATION piProcInfo; DWORD ec; - memset(&siStartInfo,0,sizeof(STARTUPINFO)); - siStartInfo.cb = sizeof(STARTUPINFO); + memset(&siStartInfo,0,sizeof(STARTUPINFOW)); + siStartInfo.cb = sizeof(STARTUPINFOW); siStartInfo.dwFlags = STARTF_USESTDHANDLES; siStartInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); siStartInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); @@ -345,7 +366,7 @@ int my_spawnvp(char **argv) siStartInfo.dwFlags |= STARTF_USESHOWWINDOW; - if (!CreateProcess(NULL, + if (!CreateProcessW(NULL, make_commandline(argv), NULL, NULL, @@ -432,6 +453,18 @@ strsave(char* string) return p; } +static int +file_exists(char *progname) +{ +#ifdef __WIN32__ + wchar_t wcsbuf[MAXPATHLEN]; + MultiByteToWideChar(CP_UTF8, 0, progname, -1, wcsbuf, MAXPATHLEN); + return (_waccess(wcsbuf, 0) != -1); +#else + return (access(progname, 1) != -1); +#endif +} + static char* get_default_emulator(char* progname) { @@ -445,15 +478,8 @@ get_default_emulator(char* progname) for (s = sbuf+strlen(sbuf); s >= sbuf; s--) { if (IS_DIRSEP(*s)) { strcpy(s+1, ERL_NAME); -#ifdef __WIN32__ - if (_access(sbuf, 0) != -1) { + if(file_exists(sbuf)) return strsave(sbuf); - } -#else - if (access(sbuf, 1) != -1) { - return strsave(sbuf); - } -#endif break; } } diff --git a/erts/etc/common/dialyzer.c b/erts/etc/common/dialyzer.c index b8a7a2bf03..09afb25182 100644 --- a/erts/etc/common/dialyzer.c +++ b/erts/etc/common/dialyzer.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2006-2012. All Rights Reserved. + * Copyright Ericsson AB 2006-2013. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in @@ -104,20 +104,31 @@ get_env(char *key) { #ifdef __WIN32__ DWORD size = 32; - char *value = NULL; + char *value=NULL; + wchar_t *wcvalue = NULL; + wchar_t wckey[256]; + int len; + + MultiByteToWideChar(CP_UTF8, 0, key, -1, wckey, 256); + while (1) { DWORD nsz; - if (value) - free(value); - value = emalloc(size); + if (wcvalue) + free(wcvalue); + wcvalue = (wchar_t*) emalloc(size*sizeof(wchar_t)); SetLastError(0); - nsz = GetEnvironmentVariable((LPCTSTR) key, (LPTSTR) value, size); + nsz = GetEnvironmentVariableW(wckey, wcvalue, size); if (nsz == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND) { - free(value); + free(wcvalue); return NULL; } - if (nsz <= size) + if (nsz <= size) { + len = WideCharToMultiByte(CP_UTF8, 0, wcvalue, -1, NULL, 0, NULL, NULL); + value = emalloc(len*sizeof(char)); + WideCharToMultiByte(CP_UTF8, 0, wcvalue, -1, value, len, NULL, NULL); + free(wcvalue); return value; + } size = nsz; } #else @@ -134,9 +145,14 @@ free_env_val(char *value) #endif } -int -main(int argc, char** argv) +#ifdef __WIN32__ +int wmain(int argc, wchar_t **wcargv) +{ + char** argv; +#else +int main(int argc, char** argv) { +#endif int eargv_size; int eargc_base; /* How many arguments in the base of eargv. */ char* emulator; @@ -144,6 +160,18 @@ main(int argc, char** argv) int i; int need_shell = 0; +#ifdef __WIN32__ + int len; + /* Convert argv to utf8 */ + argv = malloc((argc+1) * sizeof(char*)); + for (i=0; i<argc; i++) { + len = WideCharToMultiByte(CP_UTF8, 0, wcargv[i], -1, NULL, 0, NULL, NULL); + argv[i] = malloc(len*sizeof(char)); + WideCharToMultiByte(CP_UTF8, 0, wcargv[i], -1, argv[i], len, NULL, NULL); + } + argv[argc] = NULL; +#endif + env = get_env("DIALYZER_EMULATOR"); emulator = env ? env : get_default_emulator(argv[0]); @@ -260,49 +288,52 @@ push_words(char* src) if (sbuf[0]) PUSH(strsave(sbuf)); } + #ifdef __WIN32__ -char *make_commandline(char **argv) +wchar_t *make_commandline(char **argv) { - static char *buff = NULL; + static wchar_t *buff = NULL; static int siz = 0; - int num = 0; - char **arg, *p; + int num = 0, len; + char **arg; + wchar_t *p; if (*argv == NULL) { - return ""; + return L""; } for (arg = argv; *arg != NULL; ++arg) { num += strlen(*arg)+1; } if (!siz) { siz = num; - buff = malloc(siz*sizeof(char)); + buff = (wchar_t *) emalloc(siz*sizeof(wchar_t)); } else if (siz < num) { siz = num; - buff = realloc(buff,siz*sizeof(char)); + buff = (wchar_t *) realloc(buff,siz*sizeof(wchar_t)); } p = buff; + num=0; for (arg = argv; *arg != NULL; ++arg) { - strcpy(p,*arg); - p+=strlen(*arg); - *p++=' '; + len = MultiByteToWideChar(CP_UTF8, 0, *arg, -1, p, siz); + p+=(len-1); + *p++=L' '; } - *(--p) = '\0'; + *(--p) = L'\0'; if (debug) { - printf("Processed commandline:%s\n",buff); + printf("Processed command line:%S\n",buff); } return buff; } int my_spawnvp(char **argv) { - STARTUPINFO siStartInfo; + STARTUPINFOW siStartInfo; PROCESS_INFORMATION piProcInfo; DWORD ec; - memset(&siStartInfo,0,sizeof(STARTUPINFO)); - siStartInfo.cb = sizeof(STARTUPINFO); + memset(&siStartInfo,0,sizeof(STARTUPINFOW)); + siStartInfo.cb = sizeof(STARTUPINFOW); siStartInfo.dwFlags = STARTF_USESTDHANDLES; siStartInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); siStartInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); @@ -311,7 +342,7 @@ int my_spawnvp(char **argv) siStartInfo.dwFlags |= STARTF_USESHOWWINDOW; - if (!CreateProcess(NULL, + if (!CreateProcessW(NULL, make_commandline(argv), NULL, NULL, @@ -398,6 +429,18 @@ strsave(char* string) return p; } +static int +file_exists(char *progname) +{ +#ifdef __WIN32__ + wchar_t wcsbuf[MAXPATHLEN]; + MultiByteToWideChar(CP_UTF8, 0, progname, -1, wcsbuf, MAXPATHLEN); + return (_waccess(wcsbuf, 0) != -1); +#else + return (access(progname, 1) != -1); +#endif +} + static char* get_default_emulator(char* progname) { @@ -411,15 +454,8 @@ get_default_emulator(char* progname) for (s = sbuf+strlen(sbuf); s >= sbuf; s--) { if (IS_DIRSEP(*s)) { strcpy(s+1, ERL_NAME); -#ifdef __WIN32__ - if (_access(sbuf, 0) != -1) { + if(file_exists(sbuf)) return strsave(sbuf); - } -#else - if (access(sbuf, 1) != -1) { - return strsave(sbuf); - } -#endif break; } } diff --git a/erts/etc/common/erlc.c b/erts/etc/common/erlc.c index c2d7c7c76d..add65b87ca 100644 --- a/erts/etc/common/erlc.c +++ b/erts/etc/common/erlc.c @@ -114,20 +114,31 @@ get_env(char *key) { #ifdef __WIN32__ DWORD size = 32; - char *value = NULL; + char *value=NULL; + wchar_t *wcvalue = NULL; + wchar_t wckey[256]; + int len; + + MultiByteToWideChar(CP_UTF8, 0, key, -1, wckey, 256); + while (1) { DWORD nsz; - if (value) - free(value); - value = emalloc(size); + if (wcvalue) + free(wcvalue); + wcvalue = (wchar_t *) emalloc(size*sizeof(wchar_t)); SetLastError(0); - nsz = GetEnvironmentVariable((LPCTSTR) key, (LPTSTR) value, size); + nsz = GetEnvironmentVariableW(wckey, wcvalue, size); if (nsz == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND) { - free(value); + free(wcvalue); return NULL; } - if (nsz <= size) + if (nsz <= size) { + len = WideCharToMultiByte(CP_UTF8, 0, wcvalue, -1, NULL, 0, NULL, NULL); + value = emalloc(len*sizeof(char)); + WideCharToMultiByte(CP_UTF8, 0, wcvalue, -1, value, len, NULL, NULL); + free(wcvalue); return value; + } size = nsz; } #else @@ -144,16 +155,32 @@ free_env_val(char *value) #endif } - -int -main(int argc, char** argv) +#ifdef __WIN32__ +int wmain(int argc, wchar_t **wcargv) +{ + char** argv; +#else +int main(int argc, char** argv) { - char cwd[MAXPATHLEN]; /* Current working directory. */ +#endif int eargv_size; int eargc_base; /* How many arguments in the base of eargv. */ char* emulator; char *env; +#ifdef __WIN32__ + int i; + int len; + /* Convert argv to utf8 */ + argv = malloc((argc+1) * sizeof(char*)); + for (i=0; i<argc; i++) { + len = WideCharToMultiByte(CP_UTF8, 0, wcargv[i], -1, NULL, 0, NULL, NULL); + argv[i] = malloc(len*sizeof(char)); + WideCharToMultiByte(CP_UTF8, 0, wcargv[i], -1, argv[i], len, NULL, NULL); + } + argv[argc] = NULL; +#endif + env = get_env("ERLC_EMULATOR"); emulator = env ? env : get_default_emulator(argv[0]); @@ -194,20 +221,7 @@ main(int argc, char** argv) /* * Push standard arguments to Erlang. - * - * The @cwd argument was once needed, but from on R13B02 is optional. - * For maximum compatibility between erlc and erl of different versions, - * still provide the @cwd argument, unless it is too long to be - * represented as an atom. */ - if (getcwd(cwd, sizeof(cwd)) == NULL) - error("Failed to get current working directory: %s", strerror(errno)); -#ifdef __WIN32__ - (void) GetShortPathName(cwd, cwd, sizeof(cwd)); -#endif - if (strlen(cwd) < 256) { - PUSH2("@cwd", cwd); - } /* * Parse all command line switches. @@ -520,48 +534,50 @@ push_words(char* src) PUSH(strsave(sbuf)); } #ifdef __WIN32__ -char *make_commandline(char **argv) +wchar_t *make_commandline(char **argv) { - static char *buff = NULL; + static wchar_t *buff = NULL; static int siz = 0; - int num = 0; - char **arg, *p; + int num = 0, len; + char **arg; + wchar_t *p; if (*argv == NULL) { - return ""; + return L""; } for (arg = argv; *arg != NULL; ++arg) { num += strlen(*arg)+1; } if (!siz) { siz = num; - buff = malloc(siz*sizeof(char)); + buff = (wchar_t *) emalloc(siz*sizeof(wchar_t)); } else if (siz < num) { siz = num; - buff = realloc(buff,siz*sizeof(char)); + buff = (wchar_t *) realloc(buff,siz*sizeof(wchar_t)); } p = buff; + num=0; for (arg = argv; *arg != NULL; ++arg) { - strcpy(p,*arg); - p+=strlen(*arg); - *p++=' '; + len = MultiByteToWideChar(CP_UTF8, 0, *arg, -1, p, siz); + p+=(len-1); + *p++=L' '; } - *(--p) = '\0'; + *(--p) = L'\0'; if (debug) { - printf("Processed commandline:%s\n",buff); + printf("Processed command line:%S\n",buff); } return buff; } int my_spawnvp(char **argv) { - STARTUPINFO siStartInfo; + STARTUPINFOW siStartInfo; PROCESS_INFORMATION piProcInfo; DWORD ec; - memset(&siStartInfo,0,sizeof(STARTUPINFO)); - siStartInfo.cb = sizeof(STARTUPINFO); + memset(&siStartInfo,0,sizeof(STARTUPINFOW)); + siStartInfo.cb = sizeof(STARTUPINFOW); siStartInfo.dwFlags = STARTF_USESTDHANDLES; siStartInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); siStartInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); @@ -570,7 +586,7 @@ int my_spawnvp(char **argv) siStartInfo.dwFlags |= STARTF_USESHOWWINDOW; - if (!CreateProcess(NULL, + if (!CreateProcessW(NULL, make_commandline(argv), NULL, NULL, @@ -709,6 +725,18 @@ strsave(char* string) return p; } +static int +file_exists(char *progname) +{ +#ifdef __WIN32__ + wchar_t wcsbuf[MAXPATHLEN]; + MultiByteToWideChar(CP_UTF8, 0, progname, -1, wcsbuf, MAXPATHLEN); + return (_waccess(wcsbuf, 0) != -1); +#else + return (access(progname, 1) != -1); +#endif +} + static char* get_default_emulator(char* progname) { @@ -722,15 +750,8 @@ get_default_emulator(char* progname) for (s = sbuf+strlen(sbuf); s >= sbuf; s--) { if (IS_DIRSEP(*s)) { strcpy(s+1, ERL_NAME); -#ifdef __WIN32__ - if (_access(sbuf, 0) != -1) { + if(file_exists(sbuf)) return strsave(sbuf); - } -#else - if (access(sbuf, 1) != -1) { - return strsave(sbuf); - } -#endif break; } } diff --git a/erts/etc/common/erlexec.c b/erts/etc/common/erlexec.c index 01134dd718..f72930ea2a 100644 --- a/erts/etc/common/erlexec.c +++ b/erts/etc/common/erlexec.c @@ -42,7 +42,7 @@ #define DEFAULT_PROGNAME "erl" #ifdef __WIN32__ -#define INI_FILENAME "erl.ini" +#define INI_FILENAME L"erl.ini" #define INI_SECTION "erlang" #define DIRSEP "\\" #define PATHSEP ";" @@ -1173,11 +1173,14 @@ start_epmd(char *epmd) strcat(epmd, arg1); } { - STARTUPINFO start; + wchar_t wcepmd[MAXPATHLEN+100]; + STARTUPINFOW start; PROCESS_INFORMATION pi; memset(&start, 0, sizeof (start)); start.cb = sizeof (start); - if (!CreateProcess(NULL, epmd, NULL, NULL, FALSE, + MultiByteToWideChar(CP_UTF8, 0, epmd, -1, wcepmd, MAXPATHLEN+100); + + if (!CreateProcessW(NULL, wcepmd, NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE | DETACHED_PROCESS, NULL, NULL, &start, &pi)) result = -1; @@ -1371,53 +1374,49 @@ static void get_start_erl_data(char *file) } -static char *replace_filename(char *path, char *new_base) +static wchar_t *replace_filename(wchar_t *path, wchar_t *new_base) { - int plen = strlen(path); - char *res = emalloc((plen+strlen(new_base)+1)*sizeof(char)); - char *p; + int plen = wcslen(path); + wchar_t *res = (wchar_t *) emalloc((plen+wcslen(new_base)+1)*sizeof(wchar_t)); + wchar_t *p; - strcpy(res,path); - for (p = res+plen-1 ;p >= res && *p != '\\'; --p) + wcscpy(res,path); + for (p = res+plen-1 ;p >= res && *p != L'\\'; --p) ; - *(p+1) ='\0'; - strcat(res,new_base); + *(p+1) =L'\0'; + wcscat(res,new_base); return res; } -static char *path_massage(char *long_path) +static char *path_massage(wchar_t *long_path) { char *p; - - p = emalloc(MAX_PATH+1); - strcpy(p, long_path); - GetShortPathName(p, p, MAX_PATH); + int len; + len = WideCharToMultiByte(CP_UTF8, 0, long_path, -1, NULL, 0, NULL, NULL); + p = emalloc(len*sizeof(char)); + WideCharToMultiByte(CP_UTF8, 0, long_path, -1, p, len, NULL, NULL); return p; } static char *do_lookup_in_section(InitSection *inis, char *name, - char *section, char *filename, int is_path) + char *section, wchar_t *filename, int is_path) { char *p = lookup_init_entry(inis, name); if (p == NULL) { - error("Could not find key %s in section %s of file %s", + error("Could not find key %s in section %s of file %S", name,section,filename); } - if (is_path) { - return path_massage(p); - } else { - return strsave(p); - } + return strsave(p); } - +// Setup bindir, rootdir and progname as utf8 buffers static void get_parameters(int argc, char** argv) { - char *p; - char buffer[MAX_PATH]; - char *ini_filename; + wchar_t *p; + wchar_t buffer[MAX_PATH]; + wchar_t *ini_filename; HANDLE module = GetModuleHandle(NULL); /* This might look strange, but we want the erl.ini that resides in the same dir as erl.exe, not an erl.ini in our directory */ @@ -1428,34 +1427,35 @@ static void get_parameters(int argc, char** argv) error("Cannot GetModuleHandle()"); } - if (GetModuleFileName(module,buffer,MAX_PATH) == 0) { + if (GetModuleFileNameW(module,buffer,MAX_PATH) == 0) { error("Could not GetModuleFileName"); } ini_filename = replace_filename(buffer,INI_FILENAME); if ((inif = load_init_file(ini_filename)) == NULL) { + wchar_t wbindir[MAX_PATH]; + wchar_t wrootdir[MAX_PATH]; + /* Assume that the path is absolute and that it does not contain any symbolic link */ - - char buffer[MAX_PATH]; - + /* Determine bindir */ - if (GetEnvironmentVariable("ERLEXEC_DIR", buffer, MAX_PATH) == 0) { - strcpy(buffer, ini_filename); - for (p = buffer+strlen(buffer)-1; p >= buffer && *p != '\\'; --p) + if (GetEnvironmentVariableW(L"ERLEXEC_DIR", buffer, MAX_PATH) == 0) { + wcscpy(buffer, ini_filename); + for (p = buffer+wcslen(buffer)-1; p >= buffer && *p != L'\\'; --p) ; - *p ='\0'; + *p = L'\0'; } bindir = path_massage(buffer); /* Determine rootdir */ - for (p = buffer+strlen(buffer)-1; p >= buffer && *p != '\\'; --p) + for (p = buffer+wcslen(buffer)-1; p >= buffer && *p != L'\\'; --p) ; p--; - for (;p >= buffer && *p != '\\'; --p) + for (;p >= buffer && *p != L'\\'; --p) ; - *p ='\0'; + *p =L'\0'; rootdir = path_massage(buffer); /* Hardcoded progname */ diff --git a/erts/etc/common/escript.c b/erts/etc/common/escript.c index 118bc6ef90..c92fedee4b 100644 --- a/erts/etc/common/escript.c +++ b/erts/etc/common/escript.c @@ -45,7 +45,8 @@ static int eargc; /* Number of arguments in eargv. */ # define QUOTE(s) possibly_quote(s) # define IS_DIRSEP(c) ((c) == '/' || (c) == '\\') # define DIRSEPSTR "\\" -# define PATHSEPSTR ";" +# define LDIRSEPSTR L"\\" +# define LPATHSEPSTR L";" # define PMAX MAX_PATH # define ERL_NAME "erl.exe" #else @@ -112,20 +113,31 @@ get_env(char *key) { #ifdef __WIN32__ DWORD size = 32; - char *value = NULL; + char *value=NULL; + wchar_t *wcvalue = NULL; + wchar_t wckey[256]; + int len; + + MultiByteToWideChar(CP_UTF8, 0, key, -1, wckey, 256); + while (1) { DWORD nsz; - if (value) - efree(value); - value = emalloc(size); + if (wcvalue) + efree(wcvalue); + wcvalue = (wchar_t *) emalloc(size*sizeof(wchar_t)); SetLastError(0); - nsz = GetEnvironmentVariable((LPCTSTR) key, (LPTSTR) value, size); + nsz = GetEnvironmentVariableW(wckey, wcvalue, size); if (nsz == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND) { - efree(value); + efree(wcvalue); return NULL; } - if (nsz <= size) + if (nsz <= size) { + len = WideCharToMultiByte(CP_UTF8, 0, wcvalue, -1, NULL, 0, NULL, NULL); + value = emalloc(len*sizeof(char)); + WideCharToMultiByte(CP_UTF8, 0, wcvalue, -1, value, len, NULL, NULL); + efree(wcvalue); return value; + } size = nsz; } #else @@ -145,6 +157,88 @@ free_env_val(char *value) * Find absolute path to this program */ +#ifdef __WIN32__ +static char * +find_prog(char *origpath) +{ + wchar_t relpath[PMAX]; + wchar_t abspath[PMAX]; + + if (strlen(origpath) >= PMAX) + error("Path too long"); + + MultiByteToWideChar(CP_UTF8, 0, origpath, -1, relpath, PMAX); + + if (wcsstr(relpath, LDIRSEPSTR) == NULL) { + /* Just a base name */ + int sz; + wchar_t *envpath; + sz = GetEnvironmentVariableW(L"PATH", NULL, 0); + if (sz) { + /* Try to find the executable in the path */ + wchar_t dir[PMAX]; + wchar_t *beg; + wchar_t *end; + + HANDLE dir_handle; /* Handle to directory. */ + wchar_t wildcard[PMAX]; /* Wildcard to search for. */ + WIN32_FIND_DATAW find_data; /* Data found by FindFirstFile() or FindNext(). */ + + BOOL look_for_sep = TRUE; + + envpath = (wchar_t *) emalloc(sz * sizeof(wchar_t*)); + GetEnvironmentVariableW(L"PATH", envpath, sz); + beg = envpath; + + while (look_for_sep) { + end = wcsstr(beg, LPATHSEPSTR); + if (end != NULL) { + sz = end - beg; + } else { + sz = wcslen(beg); + look_for_sep = FALSE; + } + if (sz >= PMAX) { + beg = end + 1; + continue; + } + wcsncpy(dir, beg, sz); + dir[sz] = L'\0'; + beg = end + 1; + + swprintf(wildcard, PMAX, L"%s" LDIRSEPSTR L"%s", + dir, relpath /* basename */); + dir_handle = FindFirstFileW(wildcard, &find_data); + if (dir_handle == INVALID_HANDLE_VALUE) { + /* Try next directory in path */ + continue; + } else { + /* Wow we found the executable. */ + wcscpy(relpath, wildcard); + FindClose(dir_handle); + look_for_sep = FALSE; + break; + } + } + efree(envpath); + } + } + + { + DWORD size; + wchar_t *absrest; + size = GetFullPathNameW(relpath, PMAX, abspath, &absrest); + if ((size == 0) || (size > PMAX)) { + /* Cannot determine absolute path to escript. Try the origin. */ + return strsave(origpath); + } else { + char utf8abs[PMAX]; + WideCharToMultiByte(CP_UTF8, 0, abspath, -1, utf8abs, PMAX, NULL, NULL); + return strsave(utf8abs); + } + } +} +#else static char * find_prog(char *origpath) { @@ -168,14 +262,8 @@ find_prog(char *origpath) char *end; int sz; -#ifdef __WIN32__ - HANDLE dir_handle; /* Handle to directory. */ - char wildcard[PMAX]; /* Wildcard to search for. */ - WIN32_FIND_DATA find_data; /* Data found by FindFirstFile() or FindNext(). */ -#else DIR *dp; /* Pointer to directory structure. */ struct dirent* dirp; /* Pointer to directory entry. */ -#endif /* __WIN32__ */ BOOL look_for_sep = TRUE; @@ -195,21 +283,6 @@ find_prog(char *origpath) dir[sz] = '\0'; beg = end + 1; -#ifdef __WIN32__ - erts_snprintf(wildcard, sizeof(wildcard), "%s" DIRSEPSTR "%s", - dir, relpath /* basename */); - dir_handle = FindFirstFile(wildcard, &find_data); - if (dir_handle == INVALID_HANDLE_VALUE) { - /* Try next directory in path */ - continue; - } else { - /* Wow we found the executable. */ - strcpy(relpath, wildcard); - FindClose(dir_handle); - look_for_sep = FALSE; - break; - } -#else dp = opendir(dir); if (dp != NULL) { while (TRUE) { @@ -230,21 +303,12 @@ find_prog(char *origpath) } } } -#endif /* __WIN32__ */ } } } { -#ifdef __WIN32__ - DWORD size; - char *absrest; - size = GetFullPathName(relpath, PMAX, abspath, &absrest); - if ((size == 0) || (size > PMAX)) { - -#else if (!realpath(relpath, abspath)) { -#endif /* __WIN32__ */ /* Cannot determine absolute path to escript. Try the origin. */ return strsave(origpath); } else { @@ -252,12 +316,21 @@ find_prog(char *origpath) } } } +#endif static void append_shebang_args(char* scriptname) { /* Open script file */ - FILE* fd = fopen (scriptname,"r"); + FILE* fd; +#ifdef __WIN32__ + wchar_t wcscriptname[PMAX]; + + MultiByteToWideChar(CP_UTF8, 0, scriptname, -1, wcscriptname, PMAX); + fd = _wfopen(wcscriptname, L"r"); +#else + fd = fopen (scriptname,"r"); +#endif if (fd != NULL) { /* Read first line in script file */ @@ -321,9 +394,15 @@ append_shebang_args(char* scriptname) } } +#ifdef __WIN32__ +int wmain(int argc, wchar_t **wcargv) +{ + char** argv; +#else int main(int argc, char** argv) { +#endif int eargv_size; int eargc_base; /* How many arguments in the base of eargv. */ char* emulator; @@ -333,6 +412,19 @@ main(int argc, char** argv) char scriptname[PMAX]; char** last_opt; char** first_opt; + +#ifdef __WIN32__ + int i; + int len; + /* Convert argv to utf8 */ + argv = malloc((argc+1) * sizeof(char*)); + for (i=0; i<argc; i++) { + len = WideCharToMultiByte(CP_UTF8, 0, wcargv[i], -1, NULL, 0, NULL, NULL); + argv[i] = malloc(len*sizeof(char)); + WideCharToMultiByte(CP_UTF8, 0, wcargv[i], -1, argv[i], len, NULL, NULL); + } + argv[argc] = NULL; +#endif emulator = env = get_env("ESCRIPT_EMULATOR"); if (emulator == NULL) { @@ -412,9 +504,8 @@ main(int argc, char** argv) #endif erts_snprintf(scriptname, sizeof(scriptname), "%s.escript", - absname); + absname); efree(absname); - } /* @@ -483,63 +574,65 @@ push_words(char* src) PUSH(strsave(sbuf)); } #ifdef __WIN32__ -char *make_commandline(char **argv) +wchar_t *make_commandline(char **argv) { - static char *buff = NULL; + static wchar_t *buff = NULL; static int siz = 0; - int num = 0; - char **arg, *p; + int num = 0, len; + char **arg; + wchar_t *p; if (*argv == NULL) { - return ""; + return L""; } for (arg = argv; *arg != NULL; ++arg) { num += strlen(*arg)+1; } if (!siz) { siz = num; - buff = emalloc(siz*sizeof(char)); + buff = (wchar_t *) emalloc(siz*sizeof(wchar_t)); } else if (siz < num) { siz = num; - buff = realloc(buff,siz*sizeof(char)); + buff = (wchar_t *) realloc(buff,siz*sizeof(wchar_t)); } p = buff; + num=0; for (arg = argv; *arg != NULL; ++arg) { - strcpy(p,*arg); - p+=strlen(*arg); - *p++=' '; + len = MultiByteToWideChar(CP_UTF8, 0, *arg, -1, p, siz); + p+=(len-1); + *p++=L' '; } - *(--p) = '\0'; + *(--p) = L'\0'; if (debug) { - printf("Processed command line:%s\n",buff); + printf("Processed command line:%S\n",buff); } return buff; } int my_spawnvp(char **argv) { - STARTUPINFO siStartInfo; + STARTUPINFOW siStartInfo; PROCESS_INFORMATION piProcInfo; DWORD ec; - memset(&siStartInfo,0,sizeof(STARTUPINFO)); - siStartInfo.cb = sizeof(STARTUPINFO); + memset(&siStartInfo,0,sizeof(STARTUPINFOW)); + siStartInfo.cb = sizeof(STARTUPINFOW); siStartInfo.dwFlags = STARTF_USESTDHANDLES; siStartInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); siStartInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); siStartInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE); - if (!CreateProcess(NULL, - make_commandline(argv), - NULL, - NULL, - TRUE, - 0, - NULL, - NULL, - &siStartInfo, - &piProcInfo)) { + if (!CreateProcessW(NULL, + make_commandline(argv), + NULL, + NULL, + TRUE, + 0, + NULL, + NULL, + &siStartInfo, + &piProcInfo)) { return -1; } CloseHandle(piProcInfo.hThread); @@ -623,6 +716,18 @@ strsave(char* string) return p; } +static int +file_exists(char *progname) +{ +#ifdef __WIN32__ + wchar_t wcsbuf[MAXPATHLEN]; + MultiByteToWideChar(CP_UTF8, 0, progname, -1, wcsbuf, MAXPATHLEN); + return (_waccess(wcsbuf, 0) != -1); +#else + return (access(progname, 1) != -1); +#endif +} + static char* get_default_emulator(char* progname) { @@ -636,15 +741,11 @@ get_default_emulator(char* progname) for (s = sbuf+strlen(sbuf); s >= sbuf; s--) { if (IS_DIRSEP(*s)) { strcpy(s+1, ERL_NAME); -#ifdef __WIN32__ - if (_access(sbuf, 0) != -1) { + if(file_exists(sbuf)) return strsave(sbuf); - } -#else - if (access(sbuf, 1) != -1) { + strcpy(s+1, "bin" DIRSEPSTR ERL_NAME); + if(file_exists(sbuf)) return strsave(sbuf); - } -#endif break; } } diff --git a/erts/etc/common/heart.c b/erts/etc/common/heart.c index 81d797dc7e..2830641802 100644 --- a/erts/etc/common/heart.c +++ b/erts/etc/common/heart.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 1996-2012. All Rights Reserved. + * Copyright Ericsson AB 1996-2013. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in @@ -201,7 +201,6 @@ static BOOL do_shutdown(int); static void print_last_error(void); static HANDLE start_reader_thread(void); static DWORD WINAPI reader(LPVOID); -static int test_win95(void); #define read _read #define write _write #endif @@ -239,24 +238,39 @@ get_env(char *key) { #ifdef __WIN32__ DWORD size = 32; - char *value = NULL; + char *value=NULL; + wchar_t *wcvalue = NULL; + wchar_t wckey[256]; + int len; + + MultiByteToWideChar(CP_UTF8, 0, key, -1, wckey, 256); + while (1) { DWORD nsz; - if (value) - free(value); - value = malloc(size); - if (!value) { + if (wcvalue) + free(wcvalue); + wcvalue = malloc(size*sizeof(wchar_t)); + if (!wcvalue) { print_error("Failed to allocate memory. Terminating..."); exit(1); } SetLastError(0); - nsz = GetEnvironmentVariable((LPCTSTR) key, (LPTSTR) value, size); + nsz = GetEnvironmentVariableW(wckey, wcvalue, size); if (nsz == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND) { - free(value); + free(wcvalue); return NULL; } - if (nsz <= size) + if (nsz <= size) { + len = WideCharToMultiByte(CP_UTF8, 0, wcvalue, -1, NULL, 0, NULL, NULL); + value = malloc(len*sizeof(char)); + if (!value) { + print_error("Failed to allocate memory. Terminating..."); + exit(1); + } + WideCharToMultiByte(CP_UTF8, 0, wcvalue, -1, value, len, NULL, NULL); + free(wcvalue); return value; + } size = nsz; } #else @@ -564,13 +578,22 @@ void win_system(char *command) char *comspec; char * cmdbuff; char * extra = " /C "; + wchar_t *wccmdbuff; char *env; - STARTUPINFO start; + STARTUPINFOW start; SECURITY_ATTRIBUTES attr; PROCESS_INFORMATION info; + int len; - if (!debug_on || test_win95()) { - system(command); + if (!debug_on) { + len = MultiByteToWideChar(CP_UTF8, 0, command, -1, NULL, 0); + wccmdbuff = malloc(len*sizeof(wchar_t)); + if (!wccmdbuff) { + print_error("Failed to allocate memory. Terminating..."); + exit(1); + } + MultiByteToWideChar(CP_UTF8, 0, command, -1, wccmdbuff, len); + _wsystem(wccmdbuff); return; } comspec = env = get_env("COMSPEC"); @@ -602,20 +625,29 @@ void win_system(char *command) fflush(stderr); - if (!CreateProcess(NULL, - cmdbuff, - &attr, - NULL, - TRUE, - 0, - NULL, - NULL, - &start, - &info)) { + len = MultiByteToWideChar(CP_UTF8, 0, cmdbuff, -1, NULL, 0); + wccmdbuff = malloc(len*sizeof(wchar_t)); + if (!wccmdbuff) { + print_error("Failed to allocate memory. Terminating..."); + exit(1); + } + MultiByteToWideChar(CP_UTF8, 0, cmdbuff, -1, wccmdbuff, len); + + if (!CreateProcessW(NULL, + wccmdbuff, + &attr, + NULL, + TRUE, + 0, + NULL, + NULL, + &start, + &info)) { debugf("Could not create process for the command %s.\r\n", cmdbuff); } WaitForSingleObject(info.hProcess,INFINITE); free(cmdbuff); + free(wccmdbuff); } #endif /* defined(__WIN32__) */ @@ -966,16 +998,6 @@ void print_last_error() { LocalFree( lpMsgBuf ); } -static int test_win95(void) -{ - OSVERSIONINFO osinfo; - osinfo.dwOSVersionInfoSize=sizeof(OSVERSIONINFO); - GetVersionEx(&osinfo); - if (osinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) - return 1; - else - return 0; -} static BOOL enable_privilege() { HANDLE ProcessHandle; @@ -993,27 +1015,18 @@ static BOOL enable_privilege() { } static BOOL do_shutdown(int really_shutdown) { - if (test_win95()) { - if (ExitWindowsEx(EWX_REBOOT,0)) { - return TRUE; - } else { - print_last_error(); - return FALSE; - } - } else { - enable_privilege(); - if (really_shutdown) { - if (InitiateSystemShutdown(NULL,"shutdown by HEART",10,TRUE,TRUE)) - return TRUE; - } else if (InitiateSystemShutdown(NULL, - "shutdown by HEART\n" - "will be interrupted", - 30,TRUE,TRUE)) { - AbortSystemShutdown(NULL); + enable_privilege(); + if (really_shutdown) { + if (InitiateSystemShutdown(NULL,"shutdown by HEART",10,TRUE,TRUE)) return TRUE; - } - return FALSE; + } else if (InitiateSystemShutdown(NULL, + "shutdown by HEART\n" + "will be interrupted", + 30,TRUE,TRUE)) { + AbortSystemShutdown(NULL); + return TRUE; } + return FALSE; } DWORD WINAPI reader(LPVOID lpvParam) { diff --git a/erts/etc/common/typer.c b/erts/etc/common/typer.c index c95959d52d..b45867f845 100644 --- a/erts/etc/common/typer.c +++ b/erts/etc/common/typer.c @@ -99,14 +99,33 @@ char *strerror(int errnum) } #endif /* !HAVE_STRERROR */ +#ifdef __WIN32__ +int wmain(int argc, wchar_t **wcargv) +{ + char** argv; +#else int main(int argc, char** argv) { +#endif int eargv_size; int eargc_base; /* How many arguments in the base of eargv. */ char* emulator; int need_shell = 0; +#ifdef __WIN32__ + int i; + int len; + /* Convert argv to utf8 */ + argv = malloc((argc+1) * sizeof(char*)); + for (i=0; i<argc; i++) { + len = WideCharToMultiByte(CP_UTF8, 0, wcargv[i], -1, NULL, 0, NULL, NULL); + argv[i] = malloc(len*sizeof(char)); + WideCharToMultiByte(CP_UTF8, 0, wcargv[i], -1, argv[i], len, NULL, NULL); + } + argv[argc] = NULL; +#endif + emulator = get_default_emulator(argv[0]); /* @@ -193,66 +212,65 @@ push_words(char* src) PUSH(strsave(sbuf)); } #ifdef __WIN32__ -char *make_commandline(char **argv) +wchar_t *make_commandline(char **argv) { - static char *buff = NULL; + static wchar_t *buff = NULL; static int siz = 0; - int num = 0; - char **arg, *p; + int num = 0, len; + char **arg; + wchar_t *p; if (*argv == NULL) { - return ""; + return L""; } for (arg = argv; *arg != NULL; ++arg) { num += strlen(*arg)+1; } if (!siz) { siz = num; - buff = malloc(siz*sizeof(char)); + buff = (wchar_t *) emalloc(siz*sizeof(wchar_t)); } else if (siz < num) { siz = num; - buff = realloc(buff,siz*sizeof(char)); + buff = (wchar_t *) realloc(buff,siz*sizeof(wchar_t)); } p = buff; + num=0; for (arg = argv; *arg != NULL; ++arg) { - strcpy(p,*arg); - p+=strlen(*arg); - *p++=' '; + len = MultiByteToWideChar(CP_UTF8, 0, *arg, -1, p, siz); + p+=(len-1); + *p++=L' '; } - *(--p) = '\0'; + *(--p) = L'\0'; if (debug) { - printf("Processed commandline:%s\n",buff); + printf("Processed command line:%S\n",buff); } return buff; } int my_spawnvp(char **argv) { - STARTUPINFO siStartInfo; + STARTUPINFOW siStartInfo; PROCESS_INFORMATION piProcInfo; DWORD ec; - memset(&siStartInfo,0,sizeof(STARTUPINFO)); - siStartInfo.cb = sizeof(STARTUPINFO); + memset(&siStartInfo,0,sizeof(STARTUPINFOW)); + siStartInfo.cb = sizeof(STARTUPINFOW); siStartInfo.dwFlags = STARTF_USESTDHANDLES; siStartInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); siStartInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); siStartInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE); - siStartInfo.wShowWindow = SW_HIDE; - siStartInfo.dwFlags |= STARTF_USESHOWWINDOW; - - - if (!CreateProcess(NULL, - make_commandline(argv), - NULL, - NULL, - TRUE, - 0, - NULL, - NULL, - &siStartInfo, - &piProcInfo)) { + + if (!CreateProcessW(NULL, + make_commandline(argv), + NULL, + NULL, + TRUE, + 0, + NULL, + NULL, + &siStartInfo, + &piProcInfo)) { return -1; } CloseHandle(piProcInfo.hThread); @@ -330,6 +348,18 @@ strsave(char* string) return p; } +static int +file_exists(char *progname) +{ +#ifdef __WIN32__ + wchar_t wcsbuf[MAXPATHLEN]; + MultiByteToWideChar(CP_UTF8, 0, progname, -1, wcsbuf, MAXPATHLEN); + return (_waccess(wcsbuf, 0) != -1); +#else + return (access(progname, 1) != -1); +#endif +} + static char* get_default_emulator(char* progname) { @@ -343,15 +373,8 @@ get_default_emulator(char* progname) for (s = sbuf+strlen(sbuf); s >= sbuf; s--) { if (IS_DIRSEP(*s)) { strcpy(s+1, ERL_NAME); -#ifdef __WIN32__ - if (_access(sbuf, 0) != -1) { - return strsave(sbuf); - } -#else - if (access(sbuf, 1) != -1) { + if(file_exists(sbuf)) return strsave(sbuf); - } -#endif break; } } |