diff --git a/bake-test.cmd b/bake-test.cmd index 2942d9d..fd74a8e 100644 --- a/bake-test.cmd +++ b/bake-test.cmd @@ -1 +1 @@ -clang test\test_%test%.c -Iinc -g -luser32 -lkernel32 -lshell32 -lDbghelp -lciabatta.lib \ No newline at end of file +clang test\test_%test%.c -Iinc -g -luser32 -lkernel32 -lDbghelp -lciabatta.lib \ No newline at end of file diff --git a/src/_win/environment.c b/src/_win/environment.c index 84ba8ae..fb14c1b 100644 --- a/src/_win/environment.c +++ b/src/_win/environment.c @@ -2,6 +2,9 @@ // Windows symbols because windows int _fltused=0; +#define CMDLINE_CMD_MAX 32767 +#define CMDLINE_ARGV_MAX (16384+(98298+(int)sizeof(char*))/(int)sizeof(char*)) + extern int main(int argc, char** argv); // Exit routines @@ -173,26 +176,123 @@ static bool wchar_to_ansi(char* out, const wchar_t* str, size_t len) { return true; } +static int cmdline_to_argv8(const wchar_t *cmd, char **argv); + static char **get_command_args(int *argc_ptr) { - int argc; - char** args; - - LPCWSTR command_line = GetCommandLineW(); - LPWSTR* args_wide = CommandLineToArgvW(command_line, &argc); - if (!args_wide || argc <= 0) { - ExitProcess(-69420); - } - - args = calloc(argc, sizeof(char*)); - - // Convert wide chars into ANSI - for (int i = 0; i < argc; i++) { - size_t arg_len = count_wide_chars(args_wide[i]); - args[i] = malloc(arg_len+1); - wchar_to_ansi(args[i], args_wide[i], arg_len+1); - } - - *argc_ptr = argc; - return args; + static char *argv_buffer[CMDLINE_ARGV_MAX]; + // That's right, that's where windows hid the command line + TEB *teb = (TEB *)__readgsqword(offsetof(NT_TIB, Self)); + PEB *peb = teb->ProcessEnvironmentBlock; + RTL_USER_PROCESS_PARAMETERS *params = peb->ProcessParameters; + UNICODE_STRING command_line_str = params->CommandLine; + wchar_t *cmdline = command_line_str.Buffer; + // Now we can do the actual job + *argc_ptr = cmdline_to_argv8(cmdline, argv_buffer); + return argv_buffer; } +// https://github.com/skeeto/scratch/blob/master/misc/cmdline.c#L27 +static int cmdline_to_argv8(const wchar_t *cmd, char **argv) { + int argc = 1; // worst case: argv[0] is an empty string + int state = 6; // special argv[0] state + int slash = 0; + char *buf = (char *)(argv + 16384); // second half: byte buffer + + argv[0] = buf; + while (*cmd) { + int c = *cmd++; + if (c>>10 == 0x36 && *cmd>>10 == 0x37) { // surrogates? + c = 0x10000 + ((c - 0xd800)<<10) + (*cmd++ - 0xdc00); + } + + switch (state) { + case 0: switch (c) { // outside token + case 0x09: + case 0x20: continue; + case 0x22: argv[argc++] = buf; + state = 2; + continue; + case 0x5c: argv[argc++] = buf; + slash = 1; + state = 3; + break; + default : argv[argc++] = buf; + state = 1; + } break; + case 1: switch (c) { // inside unquoted token + case 0x09: + case 0x20: *buf++ = 0; + state = 0; + continue; + case 0x22: state = 2; + continue; + case 0x5c: slash = 1; + state = 3; + break; + } break; + case 2: switch (c) { // inside quoted token + case 0x22: state = 5; + continue; + case 0x5c: slash = 1; + state = 4; + break; + } break; + case 3: + case 4: switch (c) { // backslash sequence + case 0x22: buf -= (1 + slash) >> 1; + if (slash & 1) { + state -= 2; + break; + } // fallthrough + default : cmd--; + state -= 2; + continue; + case 0x5c: slash++; + } break; + case 5: switch (c) { // quoted token exit + default : cmd--; + state = 1; + continue; + case 0x22: state = 1; + } break; + case 6: switch (c) { // begin argv[0] + case 0x09: + case 0x20: *buf++ = 0; + state = 0; + continue; + case 0x22: state = 8; + continue; + default : state = 7; + } break; + case 7: switch (c) { // unquoted argv[0] + case 0x09: + case 0x20: *buf++ = 0; + state = 0; + continue; + } break; + case 8: switch (c) { // quoted argv[0] + case 0x22: *buf++ = 0; + state = 0; + continue; + } break; + } + + switch (c & 0x1f0880) { // WTF-8/UTF-8 encoding + case 0x00000: *buf++ = 0x00 | ((c >> 0) ); break; + case 0x00080: *buf++ = 0xc0 | ((c >> 6) ); + *buf++ = 0x80 | ((c >> 0) & 63); break; + case 0x00800: + case 0x00880: *buf++ = 0xe0 | ((c >> 12) ); + *buf++ = 0x80 | ((c >> 6) & 63); + *buf++ = 0x80 | ((c >> 0) & 63); break; + default : *buf++ = 0xf0 | ((c >> 18) ); + *buf++ = 0x80 | ((c >> 12) & 63); + *buf++ = 0x80 | ((c >> 6) & 63); + *buf++ = 0x80 | ((c >> 0) & 63); + } + } + + *buf = 0; + argv[argc] = 0; + return argc; +} diff --git a/src/_win/win.h b/src/_win/win.h index c0d23c1..a1c5d7f 100644 --- a/src/_win/win.h +++ b/src/_win/win.h @@ -4,8 +4,8 @@ #define WIN32_LEAN_AND_MEAN #include #include -#include #include +#include void _setup_timer(void); void _setup_eh(); diff --git a/src/ciabatta.c b/src/ciabatta.c index 335e803..ac37e40 100644 --- a/src/ciabatta.c +++ b/src/ciabatta.c @@ -21,6 +21,19 @@ #include #include +// Intrinsics +#if !defined(__FMA__) + #error "Get a better CPU (the kind that supports FMA) or enable -mfma" +#endif +// xmmintrin.h depends on mm_malloc.h, which itself includes other CRT headers +// Which introduces compiler errors. Actually does it really matter? I would +// need to check again +#undef __STDC_HOSTED__ +#include +#include + +#include "intrin.h" + // Dependencies #include "fdec64/fdec64.h" #include "unicope/inc/unicope.h" diff --git a/src/math/basic.c b/src/math/basic.c index aedf01a..522a8bf 100644 --- a/src/math/basic.c +++ b/src/math/basic.c @@ -2,17 +2,6 @@ #include #include -#if !defined(__FMA__) - #error "Get a better CPU (the kind that supports FMA) or enable -mfma" -#endif - -// xmmintrin.h depends on mm_malloc.h, which itself includes other CRT headers -// Which introduces compiler errors. Actually does it really matter? I would -// need to check again -#undef __STDC_HOSTED__ -#include -#include - double fabs(double x) { union {double f; uint64_t i;} u = {x}; u.i &= -1ULL/2; diff --git a/test/test_os.c b/test/test_os.c index 5f28815..44d71c5 100644 --- a/test/test_os.c +++ b/test/test_os.c @@ -1,8 +1,10 @@ +#include + int main(int argc, char **argv) { for(int i = 0; i != argc; ++i) { char *arg = argv[i]; - arg = arg; + printf("% 2d: %s\n", i, arg); } return 0; }