From 1074293aad2261e5bfa77bd8362e4272a29eaa18 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Mon, 29 Jul 2019 14:19:58 +0300 Subject: [PATCH] C: properly print stack trace when application crashes in Windows --- .../backend/c/intrinsic/ConsoleIntrinsic.java | 5 +- .../resources/org/teavm/backend/c/runtime.c | 57 +++++++++++++++++-- .../resources/org/teavm/backend/c/runtime.h | 2 +- 3 files changed, 56 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/org/teavm/backend/c/intrinsic/ConsoleIntrinsic.java b/core/src/main/java/org/teavm/backend/c/intrinsic/ConsoleIntrinsic.java index 377d64dba..d596d2f6c 100644 --- a/core/src/main/java/org/teavm/backend/c/intrinsic/ConsoleIntrinsic.java +++ b/core/src/main/java/org/teavm/backend/c/intrinsic/ConsoleIntrinsic.java @@ -37,13 +37,14 @@ public class ConsoleIntrinsic implements Intrinsic { switch (invocation.getMethod().getName()) { case "printString": { context.includes().addInclude(""); - context.writer().print("fprintf(stderr, \"%s\", "); + context.writer().print("teavm_printString("); Expr arg = invocation.getArguments().get(0); String literal = extractStringConstant(arg); if (literal != null) { + context.writer().print("u"); StringPoolGenerator.generateSimpleStringLiteral(context.writer(), literal); } else { - context.writer().print("teavm_stringToC("); + context.writer().print("teavm_stringToC16("); context.emit(arg); context.writer().print(")"); } diff --git a/core/src/main/resources/org/teavm/backend/c/runtime.c b/core/src/main/resources/org/teavm/backend/c/runtime.c index 5101bb93e..63cf99848 100644 --- a/core/src/main/resources/org/teavm/backend/c/runtime.c +++ b/core/src/main/resources/org/teavm/backend/c/runtime.c @@ -263,17 +263,64 @@ void teavm_interrupt() { #endif +#ifndef TEAVM_WINDOWS_LOG + #define TEAVM_OUTPUT_STRING(s) fprintf(stderr, s) +#else + #define TEAVM_OUTPUT_STRING(s) OutputDebugStringW(L##s) +#endif + void teavm_outOfMemory() { - fprintf(stderr, "Application crashed due to lack of free memory\n"); - exit(1); + TEAVM_OUTPUT_STRING("Application crashed due to lack of free memory\n"); + abort(); } -void teavm_printString(char* s) { - fprintf(stderr, "%s", s); +static char16_t* teavm_utf16ToUtf32(char16_t* source, char32_t* target) { + char16_t c = *source; + if (c & 0xFC00 == 0xD800) { + char16_t n = *(source + 1); + if (n & 0xFC00 == 0xDC00) { + *target = (((c & ~0xFC00) << 10) | (n & ~0xFC00)) + 0x10000; + return source + 2; + } + } + *target = c; + return source + 1; +} + +void teavm_printString(char16_t* s) { + #ifndef TEAVM_WINDOWS_LOG + #ifdef _MSC_VER + fprintf(stderr, "%ls", s); + #else + int32_t cap = 128; + wchar_t* buf = malloc(sizeof(wchar_t) * cap); + wchar_t* out = buf; + int32_t sz = 0; + wchar_t c; + do { + s = teavm_utf16ToUtf32(s, out++); + if (++sz == cap) { + cap *= 2; + buf = realloc(buf, sizeof(wchar_t) * cap); + out = buf + sz; + } + } while (c != '\0'); + fprintf(stderr, "%ls", buf); + free(buf); + #endif + #else + OutputDebugStringW(s); + #endif } void teavm_printInt(int32_t i) { - fprintf(stderr, "%" PRId32, i); + #ifndef TEAVM_WINDOWS_LOG + fprintf(stderr, "%" PRId32, i); + #else + wchar_t str[10]; + swprintf(str, 10, L"%d", i); + OutputDebugStringW(str); + #endif } int32_t teavm_hashCode(TeaVM_String* string) { diff --git a/core/src/main/resources/org/teavm/backend/c/runtime.h b/core/src/main/resources/org/teavm/backend/c/runtime.h index 0deac2877..232e37373 100644 --- a/core/src/main/resources/org/teavm/backend/c/runtime.h +++ b/core/src/main/resources/org/teavm/backend/c/runtime.h @@ -270,7 +270,7 @@ extern void teavm_waitFor(int64_t timeout); extern void teavm_interrupt(); extern void teavm_outOfMemory(); -extern void teavm_printString(char*); +extern void teavm_printString(char16_t*); extern void teavm_printInt(int32_t); extern TeaVM_Array* teavm_parseArguments(int, char**);