From acd28fa4952c00f1548041ede945493114969dcd Mon Sep 17 00:00:00 2001 From: F1ssi0N Date: Sat, 27 Jul 2019 16:28:22 +0100 Subject: [PATCH] Support for the printf optimisation for windows and wide strings --- compiler/fn.v | 10 +++++++++- compiler/main.v | 4 ++-- compiler/parser.v | 16 +++++++++++++--- vlib/builtin/builtin.v | 4 +++- 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/compiler/fn.v b/compiler/fn.v index 19ef378ab3..2f11287da5 100644 --- a/compiler/fn.v +++ b/compiler/fn.v @@ -400,7 +400,9 @@ fn (p mut Parser) fn_decl() { p.genln('pthread_mutex_lock(&live_fn_mutex);') } if f.name == 'main' || f.name == 'WinMain' { + p.genln('') p.genln('init_consts();') + p.genln('#ifdef _WIN32\n fflush(stdout); _setmode(_fileno(stdout), _O_U8TEXT); \n#endif\n') if p.table.imports.contains('os') { if f.name == 'main' { p.genln('os__args = os__init_os_args(argc, argv);') @@ -810,7 +812,13 @@ fn (p mut Parser) fn_call_args(f mut Fn) *Fn { T := p.table.find_type(typ) fmt := p.typ_to_fmt(typ, 0) if fmt != '' { - p.cgen.resetln(p.cgen.cur_line.replace('println (', '/*opt*/printf ("' + fmt + '\\n", ')) + // Fix for win32 unicode support + if p.os == .windows || p.os == .msvc { + //p.cgen.resetln(p.cgen.cur_line.replace('println (', '/*opt*/printf ("' + fmt + '\\n", ')) + p.cgen.resetln(p.cgen.cur_line.replace('println (', '/*opt*/wprintf (L"' + fmt.replace('%.*s', '%.*S') + '\\n", ')) + } else { + p.cgen.resetln(p.cgen.cur_line.replace('println (', '/*opt*/printf ("' + fmt + '\\n", ')) + } continue } if typ.ends_with('*') { diff --git a/compiler/main.v b/compiler/main.v index 0430e67199..48355db538 100644 --- a/compiler/main.v +++ b/compiler/main.v @@ -404,7 +404,7 @@ string _STR_TMP(const char *fmt, ...) { // It can be skipped in single file programs if v.pref.is_script { //println('Generating main()...') - cgen.genln('int main() { \n#ifdef _WIN32\n _setmode(_fileno(stdout), _O_U8TEXT); \n#endif\n init_consts(); $cgen.fn_main; return 0; }') + cgen.genln('int main() { \n#ifdef _WIN32\n fflush(stdout); _setmode(_fileno(stdout), _O_U8TEXT); \n#endif\n init_consts(); $cgen.fn_main; return 0; }') } else { println('panic: function `main` is undeclared in the main module') @@ -413,7 +413,7 @@ string _STR_TMP(const char *fmt, ...) { } // Generate `main` which calls every single test function else if v.pref.is_test { - cgen.genln('int main() { \n#ifdef _WIN32\n _setmode(_fileno(stdout), _O_U8TEXT); \n#endif\n init_consts();') + cgen.genln('int main() { \n#ifdef _WIN32\n fflush(stdout); _setmode(_fileno(stdout), _O_U8TEXT); \n#endif\n init_consts();') for key, f in v.table.fns { if f.name.starts_with('test_') { cgen.genln('$f.name();') diff --git a/compiler/parser.v b/compiler/parser.v index 4af1225726..19ce3256d2 100644 --- a/compiler/parser.v +++ b/compiler/parser.v @@ -2398,9 +2398,19 @@ fn (p mut Parser) string_expr() { cur_line := p.cgen.cur_line.trim_space() if cur_line.contains('println (') && p.tok != .plus && !cur_line.contains('string_add') && !cur_line.contains('eprintln') { - p.cgen.resetln(cur_line.replace('println (', 'printf(')) - p.gen('$format\\n$args') - return + if p.os == .windows || p.os == .msvc { + p.cgen.resetln(cur_line.replace('println (', 'wprintf( TEXT('))// .replace('%.*s', '%.*S')) + + // Emily: HACKY HACK + real_format := format.replace('%.*s', '%.*S') + real_args := args.right(1) + p.gen('$real_format\\n")$real_args') + } else { + p.cgen.resetln(cur_line.replace('println (', 'printf(')) + p.gen('$format\\n$args') + } + + return } // '$age'! means the user wants this to be a tmp string (uses global buffer, no allocation, // won't be used again) diff --git a/vlib/builtin/builtin.v b/vlib/builtin/builtin.v index d6041dcc30..39eea0581a 100644 --- a/vlib/builtin/builtin.v +++ b/vlib/builtin/builtin.v @@ -51,7 +51,9 @@ pub fn println(s string) { panic('println(NIL)') } $if windows { - C._putws(s.to_wide()) + // HACKY HACK + // use capital s for printing regular ascii strings + C.wprintf(C.TEXT('%.*S\n'), s.len, s) } $else { C.printf('%.*s\n', s.len, s.str) }