GUI assert + WinMain handling

This commit is contained in:
bumbread 2022-08-05 17:27:46 +11:00
parent 33719988c4
commit b349443f8a
10 changed files with 197 additions and 52 deletions

View File

@ -1,15 +1,11 @@
#pragma once #pragma once
#if !defined(__func__)
#define __func__ __FUNCTION__
#endif
#if defined(_MSC_VER) && !defined(__clang__) #if defined(_MSC_VER) && !defined(__clang__)
#define _Noreturn #define _Noreturn
#endif #endif
void _Noreturn _assert( void _assert(
char const *cond, char const *cond,
char const *func, char const *func,
char const *file, char const *file,

View File

@ -1,6 +1,9 @@
#include <assert.h> #include <assert.h>
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "DbgHelp.lib")
static void _print_stack_trace() { static void _print_stack_trace() {
HANDLE process = GetCurrentProcess(); HANDLE process = GetCurrentProcess();
SymInitialize(process, NULL, TRUE); SymInitialize(process, NULL, TRUE);
@ -26,12 +29,30 @@ static void _print_stack_trace() {
} }
void _Noreturn _assert( void _assert(
char const *cond, char const *cond,
char const *func, char const *func,
char const *file, char const *file,
int line int line
) { ) {
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("Assertion failed: %s\n", cond);
printf(" Function: %s\n", func); printf(" Function: %s\n", func);
printf(" File: %s\n", file); printf(" File: %s\n", file);
@ -40,3 +61,4 @@ void _Noreturn _assert(
_print_stack_trace(); _print_stack_trace();
abort(); abort();
} }
}

40
src/_win/entry.c Normal file
View File

@ -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);
}

View File

@ -2,11 +2,7 @@
// Windows symbols because windows // Windows symbols because windows
int _fltused=0; 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, "kernel32.lib")
#pragma comment(lib, "DbgHelp.lib")
// Exit routines // Exit routines
#define ATEXIT_FUNC_COUNT 64 #define ATEXIT_FUNC_COUNT 64
@ -18,27 +14,6 @@ static int atqexit_func_count;
static char **get_command_args(int *argc_ptr); 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) { _Noreturn void _Exit(int status) {
ExitProcess(status); ExitProcess(status);
#if defined(_MSC_VER) #if defined(_MSC_VER)

View File

@ -66,6 +66,7 @@
#include "_win/win.h" #include "_win/win.h"
#include "_win/assert.c" #include "_win/assert.c"
#include "_win/cmdline.c" #include "_win/cmdline.c"
#include "_win/entry.c"
#include "_win/environment.c" #include "_win/environment.c"
#include "_win/heap.c" #include "_win/heap.c"
#include "_win/signal.c" #include "_win/signal.c"

View File

@ -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; int32_t e2;
uint64_t m2; uint64_t m2;
if (ieeeExponent == 0) { if (ieeeExponent == 0) {

View File

@ -6,4 +6,4 @@ typedef struct {
int32_t exponent; int32_t exponent;
} decfloat_t; } 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);

View File

@ -11,11 +11,35 @@
#undef ctype #undef ctype
#undef pfx #undef pfx
static int fprintfcb(void *ctx, char ch) { static int fprintfcb(void *ctx, char ch) {
FILE *f = ctx; FILE *f = ctx;
return fputc(ch, f) != EOF; 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) { int vfprintf(FILE *stream, const char *fmt, va_list args) {
return vprintfcb(stream, fprintfcb, fmt, args); return vprintfcb(stream, fprintfcb, fmt, args);
} }
@ -39,3 +63,33 @@ int printf(const char *fmt, ...) {
va_end(args); va_end(args);
return len; 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;
}

View File

@ -270,7 +270,7 @@ static int pfx(vprintfcb)(
E = 0; E = 0;
} }
else { else {
decfloat_t f = todecfloat(m2, e2); decfloat_t f = dtodecfloat(m2, e2);
E = f.exponent; E = f.exponent;
} }
} }
@ -321,15 +321,15 @@ static int pfx(vprintfcb)(
out(wstr[i]); out(wstr[i]);
} }
else { else {
char utf8[5]; // char utf8[5];
char *s = utf8; // char *s = utf8;
size_t r = c16rtomb(s, wstr[i], &ps); // size_t r = c16rtomb(s, wstr[i], &ps);
if(r == (size_t)(-1)) return -1; // if(r == (size_t)(-1)) return -1;
if(r != 0) { // if(r != 0) {
while(*s != 0) { // while(*s != 0) {
out(*s++); // out(*s++);
} // }
} // }
} }
} }
// Print right-pad // Print right-pad
@ -697,7 +697,7 @@ static inline int pfx(_dtoa)(
exp = 0; exp = 0;
} }
else { else {
decfloat_t f = todecfloat(m2, e2); decfloat_t f = dtodecfloat(m2, e2);
mant = f.mantissa; mant = f.mantissa;
exp = f.exponent; exp = f.exponent;
} }
@ -822,7 +822,7 @@ static inline int pfx(_etoa)(
exp = 0; exp = 0;
} }
else { else {
decfloat_t f = todecfloat(m2, e2); decfloat_t f = dtodecfloat(m2, e2);
mant = f.mantissa; mant = f.mantissa;
exp = f.exponent; exp = f.exponent;
} }

57
test/winmain.c Normal file
View File

@ -0,0 +1,57 @@
#include <assert.h>
#include <windows.h>
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);
}