on master help sign in
Merge pull request #3644 from be5invis/be5invis-patch-win32-encoding

Fix encoding issue on Windows corresponded with `fopen`, `popen` and `argv`.

commitd08fc3bcad0b4212e6fb9bdb66782a465df47fd3 authorNiklas Larsson <metaniklas@gmail.com> dateTue 31 Jan 2017, 14:41 (10 years ago) parent4fd5fb77d6316b
5 files changed+87−15
rts/idris_main.c+35−3 rts/idris_opts.c+1−1 rts/idris_opts.h+1−1 rts/idris_stdfgn.c+17−7 rts/windows/win_utils.c+33−3
rts/idris_main.c+35−3
@@ -1,7 +1,32 @@
1+#include "idris_gmp.h"
12#include "idris_opts.h"
2−#include "idris_stats.h"
33#include "idris_rts.h"
4−#include "idris_gmp.h"
4+#include "idris_stats.h"
5+
6+#if defined(WIN32) || defined(__WIN32) || defined(__WIN32__)
7+#include <Windows.h>
8+int win32_get_argv_utf8(int *argc_ptr, char ***argv_ptr)
9+{
10+ int argc;
11+ char **argv;
12+ wchar_t **argv_utf16 = CommandLineToArgvW(GetCommandLineW(), &argc);
13+ int i;
14+ int offset = (argc + 1) * sizeof(char *);
15+ int size = offset;
16+ for (i = 0; i < argc; i++) {
17+ size += WideCharToMultiByte(CP_UTF8, 0, argv_utf16[i], -1, 0, 0, 0, 0);
18+ }
19+ argv = (char **)malloc(size);
20+ for (i = 0; i < argc; i++) {
21+ argv[i] = (char *)argv + offset;
22+ offset += WideCharToMultiByte(CP_UTF8, 0, argv_utf16[i], -1, argv[i], size - offset, 0, 0);
23+ }
24+ *argc_ptr = argc;
25+ *argv_ptr = argv;
26+ return 0;
27+}
28+#endif
29+
530// The default options should give satisfactory results under many circumstances.
631RTSOpts opts = {
732 .init_heap_size = 16384000,
@@ -9,7 +34,14 @@ RTSOpts opts = {
934 .show_summary = 0
1035};
1136
12−int main(int argc, char* argv[]) {
37+#if defined(WIN32) || defined(__WIN32) || defined(__WIN32__)
38+int main() {
39+ int argc;
40+ char **argv;
41+ win32_get_argv_utf8(&argc, &argv);
42+#else
43+int main(int argc, char **argv) {
44+#endif
1345 parse_shift_args(&opts, &argc, &argv);
1446
1547 __idris_argc = argc;
rts/idris_opts.c+1−1
@@ -99,7 +99,7 @@ int parse_args(RTSOpts * opts, int argc, char *argv[])
9999 return argc;
100100}
101101
102−void parse_shift_args(RTSOpts * opts, int * argc, char ** argv[]) {
102+void parse_shift_args(RTSOpts * opts, int * argc, char *** argv) {
103103 size_t shift = parse_args(opts, (*argc) - 1, (*argv) + 1);
104104
105105 char *prg = (*argv)[0];
rts/idris_opts.h+1−1
@@ -14,6 +14,6 @@ void print_usage(FILE * s);
1414
1515// Parse rts options and shift arguments such that rts options becomes invisible
1616// for main program.
17−void parse_shift_args(RTSOpts * opts, int * argc, char ** argv[]);
17+void parse_shift_args(RTSOpts * opts, int * argc, char *** argv);
1818
1919#endif
rts/idris_stdfgn.c+17−7
@@ -11,6 +11,8 @@
1111
1212#if defined(WIN32) || defined(__WIN32) || defined(__WIN32__)
1313int win_fpoll(void* h);
14+FILE *win32_u8fopen(const char *path, const char *mode);
15+FILE *win32_u8popen(const char *path, const char *mode);
1416#else
1517#include <sys/select.h>
1618#endif
@@ -21,9 +23,13 @@ void putStr(char* str) {
2123 printf("%s", str);
2224}
2325
24−void* fileOpen(char* name, char* mode) {
25− FILE* f = fopen(name, mode);
26− return (void*)f;
26+void *fileOpen(char *name, char *mode) {
27+#if defined(WIN32) || defined(__WIN32) || defined(__WIN32__)
28+ FILE *f = win32_u8fopen(name, mode);
29+#else
30+ FILE *f = fopen(name, mode);
31+#endif
32+ return (void *)f;
2733}
2834
2935void fileClose(void* h) {
@@ -82,10 +88,14 @@ int fpoll(void* h)
8288#endif
8389}
8490
85−void* do_popen(const char* cmd, const char* mode) {
86− FILE* f = popen(cmd, mode);
87−// int d = fileno(f);
88−// fcntl(d, F_SETFL, O_NONBLOCK);
91+void *do_popen(const char *cmd, const char *mode) {
92+#if defined(WIN32) || defined(__WIN32) || defined(__WIN32__)
93+ FILE *f = win32_u8popen(cmd, mode);
94+#else
95+ FILE *f = popen(cmd, mode);
96+ // int d = fileno(f);
97+ // fcntl(d, F_SETFL, O_NONBLOCK);
98+#endif
8999 return f;
90100}
91101
rts/windows/win_utils.c+33−3
@@ -1,13 +1,13 @@
1−#include <windows.h>
21#include <io.h>
32#include <stdio.h>
3+#include <windows.h>
44
55// THis file exists to avoid clashes between windows.h and idris_rts.h
66//
77
8−int win_fpoll(void* h)
8+int win_fpoll(void *h)
99{
10− HANDLE wh =(HANDLE) _get_osfhandle(_fileno((FILE*)h));
10+ HANDLE wh =(HANDLE) _get_osfhandle(_fileno((FILE *)h));
1111 if (wh == INVALID_HANDLE_VALUE) {
1212 return -1;
1313 }
@@ -19,3 +19,33 @@ int win_fpoll(void* h)
1919 return 0;
2020 return -1;
2121}
22+
23+int widen_utf8(const char *filename_utf8, LPWSTR *filename_w)
24+{
25+ int num_chars = MultiByteToWideChar(CP_UTF8, 0, filename_utf8, -1, 0, 0);
26+ int size = sizeof(WCHAR);
27+ *filename_w = (LPWSTR)malloc(size * num_chars);
28+ MultiByteToWideChar(CP_UTF8, 0, filename_utf8, -1, *filename_w, num_chars);
29+ return num_chars;
30+}
31+FILE *win32_u8fopen(const char *path, const char *mode)
32+{
33+ LPWSTR wpath, wmode;
34+ widen_utf8(path, &wpath);
35+ widen_utf8(mode, &wmode);
36+ FILE *f = _wfopen(wpath, wmode);
37+ free(wpath);
38+ free(wmode);
39+ return f;
40+}
41+
42+FILE *win32_u8popen(const char *path, const char *mode)
43+{
44+ LPWSTR wpath, wmode;
45+ widen_utf8(path, &wpath);
46+ widen_utf8(mode, &wmode);
47+ FILE *f = _wpopen(wpath, wmode);
48+ free(wpath);
49+ free(wmode);
50+ return f;
51+}