From b349443f8a97516d729e7fe4ff614df13aa581a0 Mon Sep 17 00:00:00 2001 From: bumbread Date: Fri, 5 Aug 2022 17:27:46 +1100 Subject: [PATCH] GUI assert + WinMain handling --- inc/assert.h | 6 +---- src/_win/assert.c | 38 +++++++++++++++++++++------ src/_win/entry.c | 40 +++++++++++++++++++++++++++++ src/_win/environment.c | 25 ------------------ src/ciabatta.c | 1 + src/decfloat/decfloat.c | 2 +- src/decfloat/decfloat.h | 2 +- src/fmt/gen_fmt.c | 54 ++++++++++++++++++++++++++++++++++++++ src/fmt/gen_fmt.h | 24 ++++++++--------- test/winmain.c | 57 +++++++++++++++++++++++++++++++++++++++++ 10 files changed, 197 insertions(+), 52 deletions(-) create mode 100644 src/_win/entry.c create mode 100644 test/winmain.c diff --git a/inc/assert.h b/inc/assert.h index ccd9f65..f1c5507 100644 --- a/inc/assert.h +++ b/inc/assert.h @@ -1,15 +1,11 @@ #pragma once -#if !defined(__func__) - #define __func__ __FUNCTION__ -#endif - #if defined(_MSC_VER) && !defined(__clang__) #define _Noreturn #endif -void _Noreturn _assert( +void _assert( char const *cond, char const *func, char const *file, diff --git a/src/_win/assert.c b/src/_win/assert.c index c28f307..6fb7456 100644 --- a/src/_win/assert.c +++ b/src/_win/assert.c @@ -1,6 +1,9 @@ #include +#pragma comment(lib, "user32.lib") +#pragma comment(lib, "DbgHelp.lib") + static void _print_stack_trace() { HANDLE process = GetCurrentProcess(); SymInitialize(process, NULL, TRUE); @@ -26,17 +29,36 @@ static void _print_stack_trace() { } -void _Noreturn _assert( +void _assert( char const *cond, char const *func, char const *file, int line ) { - printf("Assertion failed: %s\n", cond); - printf(" Function: %s\n", func); - printf(" File: %s\n", file); - printf(" Line: %d\n", line); - printf("Trace:\n"); - _print_stack_trace(); - abort(); + if(GetConsoleWindow() == NULL) { + // For GUI application we display the info into a messagebox + char buf[1024]; + int i = 0; + i += snprintf(buf+i, sizeof buf-i, "Assertion failed: %s\n", cond); + i += snprintf(buf+i, sizeof buf-i, " Function: %s\n", func); + i += snprintf(buf+i, sizeof buf-i, " File: %s\n", file); + i += snprintf(buf+i, sizeof buf-i, " Line: %d\n", line); +display_msg: + int reaction = MessageBoxA(NULL, buf, "Assertion Failed", 0x00000032L); + switch(reaction) { + case IDABORT: abort(); + case IDRETRY: goto display_msg; + case IDCONTINUE: return; + } + } + else { + // For console application we print the info to console + printf("Assertion failed: %s\n", cond); + printf(" Function: %s\n", func); + printf(" File: %s\n", file); + printf(" Line: %d\n", line); + printf("Trace:\n"); + _print_stack_trace(); + abort(); + } } diff --git a/src/_win/entry.c b/src/_win/entry.c new file mode 100644 index 0000000..bd2b406 --- /dev/null +++ b/src/_win/entry.c @@ -0,0 +1,40 @@ + +#pragma weak main +#pragma weak wmain +#pragma weak WinMain + +int main(int argc, char** argv); +int wmain(int argc, wchar_t** argv, wchar_t **envp); +int WinMain(HINSTANCE inst, HINSTANCE pinst, LPSTR cmdline, int showcmd); + +_Noreturn void mainCRTStartup() { + _setup_eh(); + _setup_heap(); + _setup_timer(); + _setup_io(); + + srand(0); + setlocale(LC_ALL, "C"); + + int argc; + char **args = get_command_args(&argc); + int exit_code = main(argc, args); + + exit(exit_code); +} + +_Noreturn void WinMainCRTStartup() { + _setup_eh(); + _setup_heap(); + _setup_timer(); + _setup_io(); + + srand(0); + setlocale(LC_ALL, "C"); + + HINSTANCE inst = GetModuleHandle(NULL); + LPSTR cmdline = GetCommandLineA(); + int exit_code = WinMain(inst, 0, cmdline, SW_SHOWDEFAULT); + + exit(exit_code); +} diff --git a/src/_win/environment.c b/src/_win/environment.c index 9285fa3..08a828a 100644 --- a/src/_win/environment.c +++ b/src/_win/environment.c @@ -2,11 +2,7 @@ // Windows symbols because windows int _fltused=0; -extern int main(int argc, char** argv); -extern int wmain(int argc, wchar_t** argv, wchar_t **envp); - #pragma comment(lib, "kernel32.lib") -#pragma comment(lib, "DbgHelp.lib") // Exit routines #define ATEXIT_FUNC_COUNT 64 @@ -18,27 +14,6 @@ static int atqexit_func_count; static char **get_command_args(int *argc_ptr); -_Noreturn void mainCRTStartup() { - // Set-up some platform stuff - _setup_eh(); - _setup_heap(); - _setup_timer(); - _setup_io(); - - // Set-up CRT stuff - srand(0); - setlocale(LC_ALL, "C"); - - // Parse command-line arguments - int argc; - char **args = get_command_args(&argc); - int exit_code = main(argc, args); - - // we call exit because we want atexit routines run - // and all the file handles to be freed - exit(exit_code); -} - _Noreturn void _Exit(int status) { ExitProcess(status); #if defined(_MSC_VER) diff --git a/src/ciabatta.c b/src/ciabatta.c index b39e1d4..7605d66 100644 --- a/src/ciabatta.c +++ b/src/ciabatta.c @@ -66,6 +66,7 @@ #include "_win/win.h" #include "_win/assert.c" #include "_win/cmdline.c" + #include "_win/entry.c" #include "_win/environment.c" #include "_win/heap.c" #include "_win/signal.c" diff --git a/src/decfloat/decfloat.c b/src/decfloat/decfloat.c index c68f200..767b2f3 100644 --- a/src/decfloat/decfloat.c +++ b/src/decfloat/decfloat.c @@ -135,7 +135,7 @@ static inline uint64_t div1e8(const uint64_t x) { -decfloat_t dtodecfloat(const uint64_t ieeeMantissa, const uint32_t ieeeExponent) { +static decfloat_t dtodecfloat(const uint64_t ieeeMantissa, const uint32_t ieeeExponent) { int32_t e2; uint64_t m2; if (ieeeExponent == 0) { diff --git a/src/decfloat/decfloat.h b/src/decfloat/decfloat.h index 0e7b330..6384dc7 100644 --- a/src/decfloat/decfloat.h +++ b/src/decfloat/decfloat.h @@ -6,4 +6,4 @@ typedef struct { int32_t exponent; } decfloat_t; -decfloat_t todecfloat(const uint64_t ieeeMant, const uint32_t ieeeExp); +static decfloat_t todecfloat(const uint64_t ieeeMant, const uint32_t ieeeExp); diff --git a/src/fmt/gen_fmt.c b/src/fmt/gen_fmt.c index 3691ef4..c857ff5 100644 --- a/src/fmt/gen_fmt.c +++ b/src/fmt/gen_fmt.c @@ -11,11 +11,35 @@ #undef ctype #undef pfx + static int fprintfcb(void *ctx, char ch) { FILE *f = ctx; return fputc(ch, f) != EOF; } +struct str_ctx_t typedef str_ctx_t; +struct str_ctx_t { + char *str; + size_t n; + size_t i; +}; + +static int sprintfcb(void *ctx, char ch) { + str_ctx_t *stream = ctx; + stream->str[stream->i++] = ch; + return 1; +} + +static int snprintfcb(void *ctx, char ch) { + str_ctx_t *stream = ctx; + if(stream->i >= stream->n) { + return 0; + } + stream->str[stream->i++] = ch; + return 1; +} + + int vfprintf(FILE *stream, const char *fmt, va_list args) { return vprintfcb(stream, fprintfcb, fmt, args); } @@ -39,3 +63,33 @@ int printf(const char *fmt, ...) { va_end(args); return len; } + + +int vsprintf(char *buf, char const *fmt, va_list args) { + str_ctx_t ctx = {0}; + ctx.str = buf; + return vprintfcb(&ctx, sprintfcb, fmt, args); +} + +int vsnprintf(char *buf, size_t sz, char const *fmt, va_list args) { + str_ctx_t ctx = {0}; + ctx.str = buf; + ctx.n = sz; + return vprintfcb(&ctx, snprintfcb, fmt, args); +} + +int sprintf(char *buf, char const *fmt, ...) { + va_list args; + va_start(args, fmt); + int len = vsprintf(buf, fmt, args); + va_end(args); + return len; +} + +int snprintf(char *buf, size_t sz, char const *fmt, ...) { + va_list args; + va_start(args, fmt); + int len = vsnprintf(buf, sz, fmt, args); + va_end(args); + return len; +} diff --git a/src/fmt/gen_fmt.h b/src/fmt/gen_fmt.h index 956596a..e8362d2 100644 --- a/src/fmt/gen_fmt.h +++ b/src/fmt/gen_fmt.h @@ -270,7 +270,7 @@ static int pfx(vprintfcb)( E = 0; } else { - decfloat_t f = todecfloat(m2, e2); + decfloat_t f = dtodecfloat(m2, e2); E = f.exponent; } } @@ -321,15 +321,15 @@ static int pfx(vprintfcb)( out(wstr[i]); } else { - char utf8[5]; - char *s = utf8; - size_t r = c16rtomb(s, wstr[i], &ps); - if(r == (size_t)(-1)) return -1; - if(r != 0) { - while(*s != 0) { - out(*s++); - } - } + // char utf8[5]; + // char *s = utf8; + // size_t r = c16rtomb(s, wstr[i], &ps); + // if(r == (size_t)(-1)) return -1; + // if(r != 0) { + // while(*s != 0) { + // out(*s++); + // } + // } } } // Print right-pad @@ -697,7 +697,7 @@ static inline int pfx(_dtoa)( exp = 0; } else { - decfloat_t f = todecfloat(m2, e2); + decfloat_t f = dtodecfloat(m2, e2); mant = f.mantissa; exp = f.exponent; } @@ -822,7 +822,7 @@ static inline int pfx(_etoa)( exp = 0; } else { - decfloat_t f = todecfloat(m2, e2); + decfloat_t f = dtodecfloat(m2, e2); mant = f.mantissa; exp = f.exponent; } diff --git a/test/winmain.c b/test/winmain.c new file mode 100644 index 0000000..4af4f73 --- /dev/null +++ b/test/winmain.c @@ -0,0 +1,57 @@ + +#include +#include + +LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE p, LPSTR pCmdLine, int nCmdShow) { + const char CLASS_NAME[] = "Sample Window Class"; + assert(0); + WNDCLASS wc = { + .lpfnWndProc = WindowProc, + .hInstance = hInstance, + .lpszClassName = CLASS_NAME, + }; + RegisterClass(&wc); + HWND hwnd = CreateWindowEx( + 0, + CLASS_NAME, + "Learn to Program Windows", + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + NULL, + NULL, + hInstance, + NULL + ); + if (hwnd == NULL) { + return 0; + } + ShowWindow(hwnd, nCmdShow); + MSG msg; + while (GetMessage(&msg, NULL, 0, 0)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + return 0; +} + +LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { + switch (uMsg) + { + case WM_DESTROY: + PostQuitMessage(0); + return 0; + case WM_PAINT: + { + PAINTSTRUCT ps; + HDC hdc = BeginPaint(hwnd, &ps); + + // All painting occurs here, between BeginPaint and EndPaint. + FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_WINDOW+1)); + EndPaint(hwnd, &ps); + } + return 0; + } + return DefWindowProc(hwnd, uMsg, wParam, lParam); +} \ No newline at end of file