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

This commit is contained in:
be5invis 2017-01-31 16:57:26 +08:00
parent 66f4ddd2aa
commit 7d6316b651
5 changed files with 88 additions and 16 deletions

View File

@ -1,7 +1,32 @@
#include "idris_opts.h"
#include "idris_stats.h"
#include "idris_rts.h"
#include "idris_gmp.h"
#include "idris_opts.h"
#include "idris_rts.h"
#include "idris_stats.h"
#if defined(WIN32) || defined(__WIN32) || defined(__WIN32__)
#include <Windows.h>
int win32_get_argv_utf8(int *argc_ptr, char ***argv_ptr)
{
int argc;
char **argv;
wchar_t **argv_utf16 = CommandLineToArgvW(GetCommandLineW(), &argc);
int i;
int offset = (argc + 1) * sizeof(char *);
int size = offset;
for (i = 0; i < argc; i++) {
size += WideCharToMultiByte(CP_UTF8, 0, argv_utf16[i], -1, 0, 0, 0, 0);
}
argv = (char **)malloc(size);
for (i = 0; i < argc; i++) {
argv[i] = (char *)argv + offset;
offset += WideCharToMultiByte(CP_UTF8, 0, argv_utf16[i], -1, argv[i], size - offset, 0, 0);
}
*argc_ptr = argc;
*argv_ptr = argv;
return 0;
}
#endif
// The default options should give satisfactory results under many circumstances.
RTSOpts opts = {
.init_heap_size = 16384000,
@ -9,7 +34,14 @@ RTSOpts opts = {
.show_summary = 0
};
int main(int argc, char* argv[]) {
#if defined(WIN32) || defined(__WIN32) || defined(__WIN32__)
int main() {
int argc;
char **argv;
win32_get_argv_utf8(&argc, &argv);
#else
int main(int argc, char **argv) {
#endif
parse_shift_args(&opts, &argc, &argv);
__idris_argc = argc;

View File

@ -99,7 +99,7 @@ int parse_args(RTSOpts * opts, int argc, char *argv[])
return argc;
}
void parse_shift_args(RTSOpts * opts, int * argc, char ** argv[]) {
void parse_shift_args(RTSOpts * opts, int * argc, char *** argv) {
size_t shift = parse_args(opts, (*argc) - 1, (*argv) + 1);
char *prg = (*argv)[0];

View File

@ -14,6 +14,6 @@ void print_usage(FILE * s);
// Parse rts options and shift arguments such that rts options becomes invisible
// for main program.
void parse_shift_args(RTSOpts * opts, int * argc, char ** argv[]);
void parse_shift_args(RTSOpts * opts, int * argc, char *** argv);
#endif

View File

@ -11,6 +11,8 @@
#if defined(WIN32) || defined(__WIN32) || defined(__WIN32__)
int win_fpoll(void* h);
FILE *win32_u8fopen(const char *path, const char *mode);
FILE *win32_u8popen(const char *path, const char *mode);
#else
#include <sys/select.h>
#endif
@ -21,9 +23,13 @@ void putStr(char* str) {
printf("%s", str);
}
void* fileOpen(char* name, char* mode) {
FILE* f = fopen(name, mode);
return (void*)f;
void *fileOpen(char *name, char *mode) {
#if defined(WIN32) || defined(__WIN32) || defined(__WIN32__)
FILE *f = win32_u8fopen(name, mode);
#else
FILE *f = fopen(name, mode);
#endif
return (void *)f;
}
void fileClose(void* h) {
@ -82,10 +88,14 @@ int fpoll(void* h)
#endif
}
void* do_popen(const char* cmd, const char* mode) {
FILE* f = popen(cmd, mode);
// int d = fileno(f);
// fcntl(d, F_SETFL, O_NONBLOCK);
void *do_popen(const char *cmd, const char *mode) {
#if defined(WIN32) || defined(__WIN32) || defined(__WIN32__)
FILE *f = win32_u8popen(cmd, mode);
#else
FILE *f = popen(cmd, mode);
// int d = fileno(f);
// fcntl(d, F_SETFL, O_NONBLOCK);
#endif
return f;
}

View File

@ -1,13 +1,13 @@
#include <windows.h>
#include <io.h>
#include <stdio.h>
#include <windows.h>
// THis file exists to avoid clashes between windows.h and idris_rts.h
//
int win_fpoll(void* h)
int win_fpoll(void *h)
{
HANDLE wh =(HANDLE) _get_osfhandle(_fileno((FILE*)h));
HANDLE wh =(HANDLE) _get_osfhandle(_fileno((FILE *)h));
if (wh == INVALID_HANDLE_VALUE) {
return -1;
}
@ -19,3 +19,33 @@ int win_fpoll(void* h)
return 0;
return -1;
}
int widen_utf8(const char *filename_utf8, LPWSTR *filename_w)
{
int num_chars = MultiByteToWideChar(CP_UTF8, 0, filename_utf8, -1, 0, 0);
int size = sizeof(WCHAR);
*filename_w = (LPWSTR)malloc(size * num_chars);
MultiByteToWideChar(CP_UTF8, 0, filename_utf8, -1, *filename_w, num_chars);
return num_chars;
}
FILE *win32_u8fopen(const char *path, const char *mode)
{
LPWSTR wpath, wmode;
widen_utf8(path, &wpath);
widen_utf8(mode, &wmode);
FILE *f = _wfopen(wpath, wmode);
free(wpath);
free(wmode);
return f;
}
FILE *win32_u8popen(const char *path, const char *mode)
{
LPWSTR wpath, wmode;
widen_utf8(path, &wpath);
widen_utf8(mode, &wmode);
FILE *f = _wpopen(wpath, wmode);
free(wpath);
free(wmode);
return f;
}