From 5ea15eb7082e84549ec3f0e0584c045881bf9dbf Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Sat, 28 Jan 2023 21:04:25 +0100 Subject: [PATCH] Make Windows use wWinMain always. Support /SUBSYSTEM:WINDOWS --- lib/std/core/private/main_stub.c3 | 156 +++++++ lib/std/{ => core}/runtime.c3 | 2 +- resources/examples/fasta.c3 | 3 +- resources/examples/mandelbrot.c3 | 3 +- src/build/build_options.c | 6 + src/build/build_options.h | 2 + src/build/builder.c | 1 + src/build/project.c | 3 + src/compiler/compiler_internal.h | 2 + src/compiler/enums.h | 10 + src/compiler/linker.c | 2 + src/compiler/sema_decls.c | 383 ++++++++++++++---- src/compiler/symtab.c | 4 + src/version.h | 2 +- test/test_suite/initializer_lists/fasta.c3t | 11 +- test/test_suite/macros/macro_body_defer.c3t | 25 +- test/test_suite14/initializer_lists/fasta.c3t | 12 +- test/test_suite14/macros/macro_body_defer.c3t | 23 +- 18 files changed, 512 insertions(+), 138 deletions(-) create mode 100644 lib/std/core/private/main_stub.c3 rename lib/std/{ => core}/runtime.c3 (98%) diff --git a/lib/std/core/private/main_stub.c3 b/lib/std/core/private/main_stub.c3 new file mode 100644 index 000000000..1226702de --- /dev/null +++ b/lib/std/core/private/main_stub.c3 @@ -0,0 +1,156 @@ +module std::core::main_stub; + +private macro usz _strlen(ptr) +{ + usz len = 0; + while (ptr[len]) len++; + return len; +} + +macro int @main_to_err_main(#m, int, char**) => catch(#m()) ? 1 : 0; +macro int @main_to_int_main(#m, int, char**) => #m(); +macro int @main_to_void_main(#m, int, char**) +{ + #m(); + return 0; +} + +private macro String[] args_to_strings(int argc, char** argv) +{ + String *list = malloc(String.sizeof * argc); + for (int i = 0; i < argc; i++) + { + char* arg = argv[i]; + usz len = 0; + list[i] = arg[:_strlen(arg)]; + } + return list[:argc]; +} + + +macro int @main_to_err_main_args(#m, int argc, char** argv) +{ + String[] list = args_to_strings(argc, argv); + defer free(list.ptr); + return catch(#m(list)) ? 1 : 0; +} + +macro int @main_to_int_main_args(#m, int argc, char** argv) +{ + String[] list = args_to_strings(argc, argv); + defer free(list.ptr); + return #m(list); +} + +macro int @main_to_void_main_args(#m, int argc, char** argv) +{ + String[] list = args_to_strings(argc, argv); + defer free(list.ptr); + #m(list); + return 0; +} + +$if (env::OS_TYPE == OsType.WIN32): + +extern fn Char16** _win_command_line_to_argv_w(ushort* cmd_line, int* argc_ptr) @extname("CommandLineToArgvW"); + +private macro String[] win_command_line_to_strings(ushort* cmd_line) +{ + int argc; + Char16** argv = _win_command_line_to_argv_w(cmd_line, &argc); + return wargs_strings(argc, argv); +} + +private macro String[] wargs_strings(int argc, Char16** argv) +{ + String *list = malloc(String.sizeof * argc); + for (int i = 0; i < argc; i++) + { + Char16* arg = argv[i]; + Char16[] argstring = arg[:_strlen(arg)]; + list[i] = str::utf16to8(argstring) ?? str::copy("?"); + } + return list[:argc]; +} + +private macro void release_wargs(String[] list) +{ + foreach (s : list) free(s.ptr); + free(list.ptr); +} + +macro int @win_to_err_main_noargs(#m, void* handle, Char16* cmd_line, int show_cmd) => catch(#m()) ? 1 : 0; +macro int @win_to_int_main_noargs(#m, void* handle, Char16* cmd_line, int show_cmd) => #m(); +macro int @win_to_void_main_noargs(#m, void* handle, Char16* cmd_line, int show_cmd) +{ + #m(); + return 0; +} + +macro int @win_to_err_main_args(#m, void* handle, Char16* cmd_line, int show_cmd) +{ + String[] args = win_command_line_to_strings(cmd_line); + defer release_wargs(args); + return catch(#m(args)) ? 1 : 0; +} + +macro int @win_to_int_main_args(#m, void* handle, Char16* cmd_line, int show_cmd) +{ + String[] args = win_command_line_to_strings(cmd_line); + defer release_wargs(args); + return #m(args); +} + +macro int @win_to_void_main_args(#m, void* handle, Char16* cmd_line, int show_cmd) +{ + String[] args = win_command_line_to_strings(cmd_line); + defer release_wargs(args); + #m(args); + return 0; +} + +macro int @win_to_err_main(#m, void* handle, Char16* cmd_line, int show_cmd) +{ + String[] args = win_command_line_to_strings(cmd_line); + defer release_wargs(args); + return catch(#m(handle, args, show_cmd)) ? 1 : 0; +} + +macro int @win_to_int_main(#m, void* handle, Char16* cmd_line, int show_cmd) +{ + String[] args = win_command_line_to_strings(cmd_line); + defer release_wargs(args); + return #m(handle, args, show_cmd); +} + +macro int @win_to_void_main(#m, void* handle, Char16* cmd_line, int show_cmd) +{ + String[] args = win_command_line_to_strings(cmd_line); + defer release_wargs(args); + #m(handle, args, show_cmd); + return 0; +} + +macro int @wmain_to_err_main_args(#m, int argc, Char16** argv) +{ + String[] args = wargs_strings(argc, argv); + defer release_wargs(args); + return catch(#m(args)) ? 1 : 0; +} + +macro int @wmain_to_int_main_args(#m, int argc, Char16** argv) +{ + String[] args = wargs_strings(argc, argv); + defer release_wargs(args); + return #m(args); +} + +macro int @wmain_to_void_main_args(#m, int argc, Char16** argv) +{ + String[] args = wargs_strings(argc, argv); + defer release_wargs(args); + #m(args); + return 0; +} + +$endif; \ No newline at end of file diff --git a/lib/std/runtime.c3 b/lib/std/core/runtime.c3 similarity index 98% rename from lib/std/runtime.c3 rename to lib/std/core/runtime.c3 index 47f762f54..b7ed3632d 100644 --- a/lib/std/runtime.c3 +++ b/lib/std/core/runtime.c3 @@ -1,7 +1,7 @@ // Copyright (c) 2021 Christoffer Lerno. All rights reserved. // Use of this source code is governed by the MIT license // a copy of which can be found in the LICENSE_STDLIB file. -module std::runtime; +module std::core::runtime; struct VirtualAny { diff --git a/resources/examples/fasta.c3 b/resources/examples/fasta.c3 index 8069a93d2..876c15221 100644 --- a/resources/examples/fasta.c3 +++ b/resources/examples/fasta.c3 @@ -87,7 +87,7 @@ fn void random_fasta(String symb, double[] probability, int n) if (i % LINELEN != 0) io::putchar('\n'); } -fn void main(int argc, char **argv) +fn int main(int argc, char **argv) { int n = 1000; if (argc > 1) n = libc::atoi(argv[1]); @@ -101,4 +101,5 @@ fn void main(int argc, char **argv) io::printf(">THREE Homo sapiens frequency\n"); random_fasta(homosapiens, homosapiens_p, n * 5); + return 0; } diff --git a/resources/examples/mandelbrot.c3 b/resources/examples/mandelbrot.c3 index 78b5dc929..d3197f280 100644 --- a/resources/examples/mandelbrot.c3 +++ b/resources/examples/mandelbrot.c3 @@ -4,7 +4,7 @@ extern fn int atoi(char *s); extern fn int printf(char *s, ...); extern fn void putchar(int c); -fn void main(int argc, char **argv) +fn int main(int argc, char **argv) { int w = atoi(argv[1]); int h = w; @@ -55,4 +55,5 @@ fn void main(int argc, char **argv) } } } + return 0; } diff --git a/src/build/build_options.c b/src/build/build_options.c index 5ad6074ff..f3c0b7db8 100644 --- a/src/build/build_options.c +++ b/src/build/build_options.c @@ -129,6 +129,7 @@ static void usage(void) OUTPUT(" -z - Send the as a parameter to the linker."); OUTPUT(" --forcelinker - Force built in linker usage when doing non-cross linking."); OUTPUT(""); + OUTPUT(" --gui - Build a 'gui' variant of the executable (e.g. '/SUBSYSTEM:WINDOWS' on Win32)."); OUTPUT(" --reloc=