mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-17 11:35:08 -04:00
Log error message on separate line. Also start work on describing internal classicube errors.
This commit is contained in:
parent
cc3ae79136
commit
87f1677e62
@ -367,7 +367,7 @@ ReturnCode Png_Decode(Bitmap* bmp, struct Stream* stream) {
|
||||
|
||||
switch (fourCC) {
|
||||
case PNG_FourCC('I','H','D','R'): {
|
||||
if (dataSize != PNG_IHDR_SIZE) return PNG_ERR_INVALID_HEADER_SIZE;
|
||||
if (dataSize != PNG_IHDR_SIZE) return PNG_ERR_INVALID_HDR_SIZE;
|
||||
res = Stream_Read(stream, tmp, PNG_IHDR_SIZE);
|
||||
if (res) return res;
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
Copyright 2017 ClassicalSharp | Licensed under BSD-3
|
||||
*/
|
||||
|
||||
/* NOTE: When changing these, remember to keep Logger.C up to date! */
|
||||
enum ERRORS_ALL {
|
||||
ERROR_BASE = 0xCCDED000UL,
|
||||
ERR_END_OF_STREAM,
|
||||
@ -23,7 +24,7 @@ enum ERRORS_ALL {
|
||||
VORBIS_ERR_MAPPING_CHANS, VORBIS_ERR_MAPPING_RESERVED,
|
||||
VORBIS_ERR_FRAME_TYPE,
|
||||
/* PNG image decoding errors */
|
||||
PNG_ERR_INVALID_SIG, PNG_ERR_INVALID_HEADER_SIZE, PNG_ERR_TOO_WIDE, PNG_ERR_TOO_TALL,
|
||||
PNG_ERR_INVALID_SIG, PNG_ERR_INVALID_HDR_SIZE, PNG_ERR_TOO_WIDE, PNG_ERR_TOO_TALL,
|
||||
PNG_ERR_INVALID_COL_BPP, PNG_ERR_COMP_METHOD, PNG_ERR_FILTER, PNG_ERR_INTERLACED,
|
||||
PNG_ERR_PAL_ENTRIES, PNG_ERR_PAL_SIZE, PNG_ERR_TRANS_COUNT, PNG_ERR_TRANS_INVALID,
|
||||
PNG_ERR_INVALID_END_SIZE, PNG_ERR_NO_DATA,
|
||||
|
11
src/Game.c
11
src/Game.c
@ -314,7 +314,14 @@ static void Game_OnLowVRAMDetected(void* obj) {
|
||||
Chat_AddRaw("&cOut of VRAM! Halving view distance..");
|
||||
}
|
||||
|
||||
static void Game_WarnFunc(const String* msg) { Chat_Add1("&c%s", msg); }
|
||||
static void Game_WarnFunc(const String* msg) {
|
||||
String str = *msg, line;
|
||||
while (str.length) {
|
||||
String_UNSAFE_SplitBy(&str, '\n', &line);
|
||||
Chat_Add1("&c%s", &line);
|
||||
}
|
||||
}
|
||||
|
||||
static void Game_ExtractInitialTexturePack(void) {
|
||||
String texPack; char texPackBuffer[STRING_SIZE];
|
||||
|
||||
@ -405,7 +412,7 @@ static void Game_LoadPlugins(void) {
|
||||
ReturnCode res;
|
||||
|
||||
res = Directory_Enum(&dir, NULL, Game_LoadPlugin);
|
||||
if (res) Logger_OldWarn(res, "enumerating plugins directory");
|
||||
if (res) Logger_Warn(res, "enumerating plugins directory");
|
||||
}
|
||||
|
||||
void Game_Free(void* obj);
|
||||
|
@ -1567,10 +1567,10 @@ static void UpdatesScreen_Init(struct LScreen* s_) {
|
||||
|
||||
String_InitArray(path, pathBuffer);
|
||||
res = Process_GetExePath(&path);
|
||||
if (res) { Logger_OldWarn(res, "getting .exe path"); return; }
|
||||
if (res) { Logger_Warn(res, "getting .exe path"); return; }
|
||||
|
||||
res = File_GetModifiedTime(&path, &buildTime);
|
||||
if (res) { Logger_OldWarn(res, "getting build time"); return; }
|
||||
if (res) { Logger_Warn(res, "getting build time"); return; }
|
||||
|
||||
UpdatesScreen_Format(&s->LblYour, "Your build: ", buildTime);
|
||||
}
|
||||
|
@ -494,13 +494,13 @@ static void FetchUpdateTask_Handle(uint8_t* data, uint32_t len) {
|
||||
ReturnCode res;
|
||||
|
||||
res = Stream_WriteAllTo(&path, data, len);
|
||||
if (res) { Logger_OldWarn(res, "saving update"); return; }
|
||||
if (res) { Logger_Warn(res, "saving update"); return; }
|
||||
|
||||
res = File_SetModifiedTime(&path, FetchUpdateTask.Timestamp);
|
||||
if (res) Logger_OldWarn(res, "setting update time");
|
||||
if (res) Logger_Warn(res, "setting update time");
|
||||
|
||||
res = Platform_MarkExecutable(&path);
|
||||
if (res) Logger_OldWarn(res, "making update executable");
|
||||
if (res) Logger_Warn(res, "making update executable");
|
||||
}
|
||||
|
||||
void FetchUpdateTask_Run(bool release, bool d3d9) {
|
||||
@ -565,7 +565,7 @@ static void FetchFlagsTask_Handle(uint8_t* data, uint32_t len) {
|
||||
|
||||
Stream_ReadonlyMemory(&s, data, len);
|
||||
res = Png_Decode(&flags[FetchFlagsTask.Count].Bmp, &s);
|
||||
if (res) Logger_OldWarn(res, "decoding flag");
|
||||
if (res) Logger_Warn(res, "decoding flag");
|
||||
|
||||
FetchFlagsTask.Count++;
|
||||
FetchFlagsTask_DownloadNext();
|
||||
|
@ -364,7 +364,7 @@ static ReturnCode Launcher_ProcessZipEntry(const String* path, struct Stream* da
|
||||
res = Png_Decode(&fontBmp, data);
|
||||
|
||||
if (res) {
|
||||
Logger_OldWarn(res, "decoding default.png"); return res;
|
||||
Logger_Warn(res, "decoding default.png"); return res;
|
||||
} else {
|
||||
Drawer2D_SetFontBitmap(&fontBmp);
|
||||
useBitmappedFont = !Options_GetBool(OPT_USE_CHAT_FONT, false);
|
||||
@ -374,7 +374,7 @@ static ReturnCode Launcher_ProcessZipEntry(const String* path, struct Stream* da
|
||||
res = Png_Decode(&bmp, data);
|
||||
|
||||
if (res) {
|
||||
Logger_OldWarn(res, "decoding terrain.png"); return res;
|
||||
Logger_Warn(res, "decoding terrain.png"); return res;
|
||||
} else {
|
||||
Launcher_LoadTextures(&bmp);
|
||||
}
|
||||
@ -388,18 +388,14 @@ static void Launcher_ExtractTexturePack(const String* path) {
|
||||
ReturnCode res;
|
||||
|
||||
res = Stream_OpenFile(&stream, path);
|
||||
if (res) {
|
||||
Logger_OldWarn(res, "opening texture pack"); return;
|
||||
}
|
||||
if (res) { Logger_Warn(res, "opening texture pack"); return; }
|
||||
|
||||
Zip_Init(&state, &stream);
|
||||
state.SelectEntry = Launcher_SelectZipEntry;
|
||||
state.ProcessEntry = Launcher_ProcessZipEntry;
|
||||
res = Zip_Extract(&state);
|
||||
|
||||
if (res) {
|
||||
Logger_OldWarn(res, "extracting texture pack");
|
||||
}
|
||||
if (res) { Logger_Warn(res, "extracting texture pack"); }
|
||||
stream.Close(&stream);
|
||||
}
|
||||
|
||||
@ -534,7 +530,7 @@ bool Launcher_StartGame(const String* user, const String* mppass, const String*
|
||||
|
||||
String_InitArray(path, pathBuffer);
|
||||
res = Process_GetExePath(&path);
|
||||
if (res) { Logger_OldWarn(res, "getting .exe path"); return false; }
|
||||
if (res) { Logger_Warn(res, "getting .exe path"); return false; }
|
||||
|
||||
String_InitArray(args, argsBuffer);
|
||||
String_AppendString(&args, user);
|
||||
@ -546,7 +542,7 @@ bool Launcher_StartGame(const String* user, const String* mppass, const String*
|
||||
/* HRESULT when user clicks 'cancel' to 'are you sure you want to run ClassiCube.exe' */
|
||||
if (res == 0x80004005) return;
|
||||
#endif
|
||||
if (res) { Logger_OldWarn(res, "starting game"); return false; }
|
||||
if (res) { Logger_Warn(res, "starting game"); return false; }
|
||||
|
||||
Launcher_ShouldExit = Options_GetBool(OPT_AUTO_CLOSE_LAUNCHER, false);
|
||||
return true;
|
||||
@ -614,7 +610,7 @@ static void Launcher_ApplyUpdate(void) {
|
||||
|
||||
String_InitArray(exe, exeBuffer);
|
||||
res = Process_GetExePath(&exe);
|
||||
if (res) { Logger_OldWarn(res, "getting executable path"); return; }
|
||||
if (res) { Logger_Warn(res, "getting executable path"); return; }
|
||||
|
||||
Utils_UNSAFE_GetFilename(&exe);
|
||||
String_InitArray(str, strBuffer);
|
||||
@ -622,12 +618,12 @@ static void Launcher_ApplyUpdate(void) {
|
||||
|
||||
/* Can't use WriteLine, want \n as actual newline not code page 437 */
|
||||
res = Stream_WriteAllTo(&scriptPath, (const uint8_t*)str.buffer, str.length);
|
||||
if (res) { Logger_OldWarn(res, "saving update script"); return; }
|
||||
if (res) { Logger_Warn(res, "saving update script"); return; }
|
||||
|
||||
res = Platform_MarkExecutable(&scriptPath);
|
||||
if (res) Logger_OldWarn(res, "making update script executable");
|
||||
if (res) Logger_Warn(res, "making update script executable");
|
||||
|
||||
res = Process_Start(&scriptName, &scriptArgs);
|
||||
if (res) { Logger_OldWarn(res, "starting update script"); return; }
|
||||
if (res) { Logger_Warn(res, "starting update script"); return; }
|
||||
}
|
||||
#endif
|
||||
|
608
src/Logger.c
608
src/Logger.c
@ -4,23 +4,11 @@
|
||||
#include "Window.h"
|
||||
#include "Funcs.h"
|
||||
#include "Stream.h"
|
||||
|
||||
static void Logger_AbortCommon(ReturnCode result, const char* raw_msg, void* ctx);
|
||||
#include "Errors.h"
|
||||
|
||||
#ifdef CC_BUILD_WEB
|
||||
/* Can't see native CPU state with javascript */
|
||||
#undef CC_BUILD_POSIX
|
||||
|
||||
static void Logger_DumpBacktrace(String* str, void* ctx) { }
|
||||
static void Logger_DumpRegisters(void* ctx) { }
|
||||
static void Logger_DumpMisc(void* ctx) { }
|
||||
|
||||
void Logger_Hook(void) { }
|
||||
void Logger_Abort2(ReturnCode result, const char* raw_msg) {
|
||||
Logger_AbortCommon(result, raw_msg, NULL);
|
||||
}
|
||||
#undef CC_BUILD_POSIX /* Can't see native CPU state with javascript */
|
||||
#endif
|
||||
|
||||
#ifdef CC_BUILD_WIN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOSERVICE
|
||||
@ -28,49 +16,198 @@ void Logger_Abort2(ReturnCode result, const char* raw_msg) {
|
||||
#define NOIME
|
||||
#include <windows.h>
|
||||
#include <imagehlp.h>
|
||||
#endif
|
||||
/* POSIX can be shared between Linux/BSD/OSX */
|
||||
#ifdef CC_BUILD_POSIX
|
||||
#ifndef CC_BUILD_OPENBSD
|
||||
#include <ucontext.h>
|
||||
#endif
|
||||
#include <execinfo.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
struct StackPointers { uintptr_t Instruction, Frame, Stack; };
|
||||
struct SymbolAndName { IMAGEHLP_SYMBOL Symbol; char Name[256]; };
|
||||
|
||||
/*########################################################################################################################*
|
||||
*----------------------------------------------------------Warning--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
void Logger_DialogWarn(const String* msg) {
|
||||
String dst; char dstBuffer[512];
|
||||
String_InitArray_NT(dst, dstBuffer);
|
||||
|
||||
String_AppendString(&dst, msg);
|
||||
dst.buffer[dst.length] = '\0';
|
||||
Window_ShowDialog(Logger_DialogTitle, dst.buffer);
|
||||
}
|
||||
const char* Logger_DialogTitle = "Error";
|
||||
Logger_DoWarn Logger_WarnFunc = Logger_DialogWarn;
|
||||
|
||||
void Logger_OldWarn(ReturnCode res, const char* place) {
|
||||
String msg; char msgBuffer[128];
|
||||
String_InitArray(msg, msgBuffer);
|
||||
|
||||
String_Format2(&msg, "Error %h when %c", &res, place);
|
||||
Logger_WarnFunc(&msg);
|
||||
}
|
||||
|
||||
void Logger_OldWarn2(ReturnCode res, const char* place, const String* path) {
|
||||
String msg; char msgBuffer[256];
|
||||
String_InitArray(msg, msgBuffer);
|
||||
|
||||
String_Format3(&msg, "Error %h when %c '%s'", &res, place, path);
|
||||
Logger_WarnFunc(&msg);
|
||||
}
|
||||
|
||||
/* Returns a description for ClassiCube specific error codes */
|
||||
static const char* Logger_GetCCErrorDesc(ReturnCode res) {
|
||||
switch (res) {
|
||||
case ERR_END_OF_STREAM: return "End of stream";
|
||||
case OGG_ERR_INVALID_SIG: return "Invalid OGG signature";
|
||||
case OGG_ERR_VERSION: return "Invalid OGG format version";
|
||||
|
||||
/*WAV_ERR_STREAM_HDR,
|
||||
WAV_ERR_STREAM_TYPE,
|
||||
WAV_ERR_DATA_TYPE,
|
||||
WAV_ERR_NO_DATA,
|
||||
/* Vorbis audio decoding errors */ /*
|
||||
VORBIS_ERR_HEADER,
|
||||
VORBIS_ERR_WRONG_HEADER,
|
||||
VORBIS_ERR_FRAMING,
|
||||
VORBIS_ERR_VERSION,
|
||||
VORBIS_ERR_BLOCKSIZE,
|
||||
VORBIS_ERR_CHANS,
|
||||
VORBIS_ERR_TIME_TYPE,
|
||||
VORBIS_ERR_FLOOR_TYPE,
|
||||
VORBIS_ERR_RESIDUE_TYPE,
|
||||
VORBIS_ERR_MAPPING_TYPE,
|
||||
VORBIS_ERR_MODE_TYPE,
|
||||
VORBIS_ERR_CODEBOOK_SYNC,
|
||||
VORBIS_ERR_CODEBOOK_ENTRY,
|
||||
VORBIS_ERR_CODEBOOK_LOOKUP,
|
||||
VORBIS_ERR_MODE_WINDOW,
|
||||
VORBIS_ERR_MODE_TRANSFORM,
|
||||
VORBIS_ERR_MAPPING_CHANS,
|
||||
VORBIS_ERR_MAPPING_RESERVED,
|
||||
VORBIS_ERR_FRAME_TYPE,
|
||||
/* PNG image decoding errors */ /*
|
||||
PNG_ERR_INVALID_SIG,
|
||||
PNG_ERR_INVALID_HDR_SIZE,
|
||||
PNG_ERR_TOO_WIDE,
|
||||
PNG_ERR_TOO_TALL,
|
||||
PNG_ERR_INVALID_COL_BPP,
|
||||
PNG_ERR_COMP_METHOD,
|
||||
PNG_ERR_FILTER,
|
||||
PNG_ERR_INTERLACED,
|
||||
PNG_ERR_PAL_ENTRIES,
|
||||
PNG_ERR_PAL_SIZE,
|
||||
PNG_ERR_TRANS_COUNT,
|
||||
PNG_ERR_TRANS_INVALID,
|
||||
PNG_ERR_INVALID_END_SIZE,
|
||||
PNG_ERR_NO_DATA,
|
||||
/* ZIP archive decoding errors */ /*
|
||||
ZIP_ERR_TOO_MANY_ENTRIES,
|
||||
ZIP_ERR_SEEK_END_OF_CENTRAL_DIR,
|
||||
ZIP_ERR_NO_END_OF_CENTRAL_DIR,
|
||||
ZIP_ERR_SEEK_CENTRAL_DIR,
|
||||
ZIP_ERR_INVALID_CENTRAL_DIR,
|
||||
ZIP_ERR_SEEK_LOCAL_DIR,
|
||||
ZIP_ERR_INVALID_LOCAL_DIR,
|
||||
ZIP_ERR_FILENAME_LEN,
|
||||
/* GZIP header decoding errors */ /*
|
||||
GZIP_ERR_HEADER1,
|
||||
GZIP_ERR_HEADER2,
|
||||
GZIP_ERR_METHOD,
|
||||
GZIP_ERR_FLAGS,
|
||||
/* ZLIB header decoding errors */ /*
|
||||
ZLIB_ERR_METHOD,
|
||||
ZLIB_ERR_WINDOW_SIZE,
|
||||
ZLIB_ERR_FLAGS,
|
||||
/* FCM map decoding errors */ /*
|
||||
FCM_ERR_IDENTIFIER,
|
||||
FCM_ERR_REVISION,
|
||||
/* LVL map decoding errors */ /*
|
||||
LVL_ERR_VERSION,
|
||||
/* DAT map decoding errors */ /*
|
||||
DAT_ERR_IDENTIFIER,
|
||||
DAT_ERR_VERSION,
|
||||
DAT_ERR_JIDENTIFIER,
|
||||
DAT_ERR_JVERSION,
|
||||
DAT_ERR_ROOT_TYPE,
|
||||
DAT_ERR_JSTRING_LEN,
|
||||
DAT_ERR_JFIELD_CLASS_NAME,
|
||||
DAT_ERR_JCLASS_TYPE,
|
||||
DAT_ERR_JCLASS_FIELDS,
|
||||
DAT_ERR_JCLASS_ANNOTATION,
|
||||
DAT_ERR_JOBJECT_TYPE,
|
||||
DAT_ERR_JARRAY_TYPE,
|
||||
DAT_ERR_JARRAY_CONTENT,
|
||||
/* CW map decoding errors */ /*
|
||||
NBT_ERR_INT32S,
|
||||
NBT_ERR_UNKNOWN,
|
||||
CW_ERR_ROOT_TAG,
|
||||
CW_ERR_STRING_LEN
|
||||
*/
|
||||
|
||||
case PNG_ERR_INVALID_SIG: return "Invalid PNG signature";
|
||||
case PNG_ERR_INVALID_HDR_SIZE: return "Invalid PNG header size";
|
||||
case PNG_ERR_TOO_WIDE: return "PNG image too wide";
|
||||
case PNG_ERR_TOO_TALL: return "PNG image too tall";
|
||||
case PNG_ERR_INTERLACED: return "Interlaced PNGs unsupported";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Appends more detailed information about an error if possible */
|
||||
static void Logger_AppendErrorDesc(String* msg, ReturnCode res, Logger_DescribeError describeErr) {
|
||||
const char* cc_err;
|
||||
String err; char errBuffer[128];
|
||||
String_InitArray(err, errBuffer);
|
||||
|
||||
cc_err = Logger_GetCCErrorDesc(res);
|
||||
if (cc_err) {
|
||||
String_Format1(msg, "\n Error meaning: %c", cc_err);
|
||||
} else if (describeErr(res, &err)) {
|
||||
String_Format1(msg, "\n Error meaning: %s", &err);
|
||||
}
|
||||
}
|
||||
|
||||
void Logger_SysWarn(ReturnCode res, const char* place, Logger_DescribeError describeErr) {
|
||||
String msg; char msgBuffer[256];
|
||||
String_InitArray(msg, msgBuffer);
|
||||
|
||||
String_Format2(&msg, "Error %h when %c", &res, place);
|
||||
Logger_AppendErrorDesc(&msg, res, describeErr);
|
||||
Logger_WarnFunc(&msg);
|
||||
}
|
||||
|
||||
void Logger_SysWarn2(ReturnCode res, const char* place, const String* path, Logger_DescribeError describeErr) {
|
||||
String msg; char msgBuffer[256];
|
||||
String_InitArray(msg, msgBuffer);
|
||||
|
||||
String_Format3(&msg, "Error %h when %c '%s'", &res, place, path);
|
||||
Logger_AppendErrorDesc(&msg, res, describeErr);
|
||||
Logger_WarnFunc(&msg);
|
||||
}
|
||||
|
||||
void Logger_DynamicLibWarn2(ReturnCode res, const char* place, const String* path) {
|
||||
Logger_SysWarn2(res, place, path, DynamicLib_DescribeError);
|
||||
}
|
||||
void Logger_Warn(ReturnCode res, const char* place) {
|
||||
Logger_SysWarn(res, place, Platform_DescribeError);
|
||||
}
|
||||
void Logger_Warn2(ReturnCode res, const char* place, const String* path) {
|
||||
Logger_SysWarn2(res, place, path, Platform_DescribeError);
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*-------------------------------------------------------Info dumping------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static void Logger_DumpRegisters(void* ctx) {
|
||||
String str; char strBuffer[512];
|
||||
CONTEXT* r = (CONTEXT*)ctx;
|
||||
|
||||
String_InitArray(str, strBuffer);
|
||||
String_AppendConst(&str, "-- registers --\r\n");
|
||||
|
||||
#if defined _M_IX86
|
||||
String_Format3(&str, "eax=%x ebx=%x ecx=%x\r\n", &r->Eax, &r->Ebx, &r->Ecx);
|
||||
String_Format3(&str, "edx=%x esi=%x edi=%x\r\n", &r->Edx, &r->Esi, &r->Edi);
|
||||
String_Format3(&str, "eip=%x ebp=%x esp=%x\r\n", &r->Eip, &r->Ebp, &r->Esp);
|
||||
#elif defined _M_X64
|
||||
String_Format3(&str, "rax=%x rbx=%x rcx=%x\r\n", &r->Rax, &r->Rbx, &r->Rcx);
|
||||
String_Format3(&str, "rdx=%x rsi=%x rdi=%x\r\n", &r->Rdx, &r->Rsi, &r->Rdi);
|
||||
String_Format3(&str, "rip=%x rbp=%x rsp=%x\r\n", &r->Rip, &r->Rbp, &r->Rsp);
|
||||
String_Format3(&str, "r8 =%x r9 =%x r10=%x\r\n", &r->R8, &r->R9, &r->R10);
|
||||
String_Format3(&str, "r11=%x r12=%x r13=%x\r\n", &r->R11, &r->R12, &r->R13);
|
||||
String_Format2(&str, "r14=%x r15=%x\r\n" , &r->R14, &r->R15);
|
||||
#elif defined _M_IA64
|
||||
String_Format3(&str, "r1 =%x r2 =%x r3 =%x\r\n", &r->IntGp, &r->IntT0, &r->IntT1);
|
||||
String_Format3(&str, "r4 =%x r5 =%x r6 =%x\r\n", &r->IntS0, &r->IntS1, &r->IntS2);
|
||||
String_Format3(&str, "r7 =%x r8 =%x r9 =%x\r\n", &r->IntS3, &r->IntV0, &r->IntT2);
|
||||
String_Format3(&str, "r10=%x r11=%x r12=%x\r\n", &r->IntT3, &r->IntT4, &r->IntSp);
|
||||
String_Format3(&str, "r13=%x r14=%x r15=%x\r\n", &r->IntTeb, &r->IntT5, &r->IntT6);
|
||||
String_Format3(&str, "r16=%x r17=%x r18=%x\r\n", &r->IntT7, &r->IntT8, &r->IntT9);
|
||||
String_Format3(&str, "r19=%x r20=%x r21=%x\r\n", &r->IntT10, &r->IntT11, &r->IntT12);
|
||||
String_Format3(&str, "r22=%x r23=%x r24=%x\r\n", &r->IntT13, &r->IntT14, &r->IntT15);
|
||||
String_Format3(&str, "r25=%x r26=%x r27=%x\r\n", &r->IntT16, &r->IntT17, &r->IntT18);
|
||||
String_Format3(&str, "r28=%x r29=%x r30=%x\r\n", &r->IntT19, &r->IntT20, &r->IntT21);
|
||||
String_Format3(&str, "r31=%x nat=%x pre=%x\r\n", &r->IntT22, &r->IntNats,&r->Preds);
|
||||
#else
|
||||
#error "Unknown machine type"
|
||||
#endif
|
||||
Logger_Log(&str);
|
||||
}
|
||||
#if defined CC_BUILD_WIN
|
||||
struct StackPointers { uintptr_t Instruction, Frame, Stack; };
|
||||
struct SymbolAndName { IMAGEHLP_SYMBOL Symbol; char Name[256]; };
|
||||
|
||||
static int Logger_GetFrames(CONTEXT* ctx, struct StackPointers* pointers, int max) {
|
||||
STACKFRAME frame = { 0 };
|
||||
@ -170,6 +307,42 @@ static void Logger_DumpBacktrace(String* str, void* ctx) {
|
||||
Logger_Backtrace(str, ctx);
|
||||
}
|
||||
|
||||
static void Logger_DumpRegisters(void* ctx) {
|
||||
String str; char strBuffer[512];
|
||||
CONTEXT* r = (CONTEXT*)ctx;
|
||||
|
||||
String_InitArray(str, strBuffer);
|
||||
String_AppendConst(&str, "-- registers --\r\n");
|
||||
|
||||
#if defined _M_IX86
|
||||
String_Format3(&str, "eax=%x ebx=%x ecx=%x\r\n", &r->Eax, &r->Ebx, &r->Ecx);
|
||||
String_Format3(&str, "edx=%x esi=%x edi=%x\r\n", &r->Edx, &r->Esi, &r->Edi);
|
||||
String_Format3(&str, "eip=%x ebp=%x esp=%x\r\n", &r->Eip, &r->Ebp, &r->Esp);
|
||||
#elif defined _M_X64
|
||||
String_Format3(&str, "rax=%x rbx=%x rcx=%x\r\n", &r->Rax, &r->Rbx, &r->Rcx);
|
||||
String_Format3(&str, "rdx=%x rsi=%x rdi=%x\r\n", &r->Rdx, &r->Rsi, &r->Rdi);
|
||||
String_Format3(&str, "rip=%x rbp=%x rsp=%x\r\n", &r->Rip, &r->Rbp, &r->Rsp);
|
||||
String_Format3(&str, "r8 =%x r9 =%x r10=%x\r\n", &r->R8, &r->R9, &r->R10);
|
||||
String_Format3(&str, "r11=%x r12=%x r13=%x\r\n", &r->R11, &r->R12, &r->R13);
|
||||
String_Format2(&str, "r14=%x r15=%x\r\n" , &r->R14, &r->R15);
|
||||
#elif defined _M_IA64
|
||||
String_Format3(&str, "r1 =%x r2 =%x r3 =%x\r\n", &r->IntGp, &r->IntT0, &r->IntT1);
|
||||
String_Format3(&str, "r4 =%x r5 =%x r6 =%x\r\n", &r->IntS0, &r->IntS1, &r->IntS2);
|
||||
String_Format3(&str, "r7 =%x r8 =%x r9 =%x\r\n", &r->IntS3, &r->IntV0, &r->IntT2);
|
||||
String_Format3(&str, "r10=%x r11=%x r12=%x\r\n", &r->IntT3, &r->IntT4, &r->IntSp);
|
||||
String_Format3(&str, "r13=%x r14=%x r15=%x\r\n", &r->IntTeb, &r->IntT5, &r->IntT6);
|
||||
String_Format3(&str, "r16=%x r17=%x r18=%x\r\n", &r->IntT7, &r->IntT8, &r->IntT9);
|
||||
String_Format3(&str, "r19=%x r20=%x r21=%x\r\n", &r->IntT10, &r->IntT11, &r->IntT12);
|
||||
String_Format3(&str, "r22=%x r23=%x r24=%x\r\n", &r->IntT13, &r->IntT14, &r->IntT15);
|
||||
String_Format3(&str, "r25=%x r26=%x r27=%x\r\n", &r->IntT16, &r->IntT17, &r->IntT18);
|
||||
String_Format3(&str, "r28=%x r29=%x r30=%x\r\n", &r->IntT19, &r->IntT20, &r->IntT21);
|
||||
String_Format3(&str, "r31=%x nat=%x pre=%x\r\n", &r->IntT22, &r->IntNats,&r->Preds);
|
||||
#else
|
||||
#error "Unknown machine type"
|
||||
#endif
|
||||
Logger_Log(&str);
|
||||
}
|
||||
|
||||
static BOOL CALLBACK Logger_DumpModule(const char* name, ULONG_PTR base, ULONG size, void* ctx) {
|
||||
String str; char strBuffer[256];
|
||||
uintptr_t beg, end;
|
||||
@ -190,94 +363,8 @@ static void Logger_DumpMisc(void* ctx) {
|
||||
EnumerateLoadedModules(process, Logger_DumpModule, NULL);
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*------------------------------------------------------Error handling-----------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static LONG WINAPI Logger_UnhandledFilter(struct _EXCEPTION_POINTERS* pInfo) {
|
||||
String msg; char msgBuffer[STRING_SIZE * 2 + 1];
|
||||
uint32_t code;
|
||||
uintptr_t addr;
|
||||
|
||||
code = (uint32_t)pInfo->ExceptionRecord->ExceptionCode;
|
||||
addr = (uintptr_t)pInfo->ExceptionRecord->ExceptionAddress;
|
||||
|
||||
String_InitArray_NT(msg, msgBuffer);
|
||||
String_Format2(&msg, "Unhandled exception 0x%h at 0x%x", &code, &addr);
|
||||
msg.buffer[msg.length] = '\0';
|
||||
|
||||
Logger_AbortCommon(0, msg.buffer, pInfo->ContextRecord);
|
||||
return EXCEPTION_EXECUTE_HANDLER; /* TODO: different flag */
|
||||
}
|
||||
|
||||
void Logger_Hook(void) {
|
||||
SetUnhandledExceptionFilter(Logger_UnhandledFilter);
|
||||
}
|
||||
|
||||
/* Don't want compiler doing anything fancy with registers */
|
||||
#if _MSC_VER
|
||||
#pragma optimize ("", off)
|
||||
#endif
|
||||
void Logger_Abort2(ReturnCode result, const char* raw_msg) {
|
||||
CONTEXT ctx;
|
||||
#ifndef _M_IX86
|
||||
/* This method is guaranteed to exist on 64 bit windows */
|
||||
/* It is missing in 32 bit Windows 2000 however */
|
||||
RtlCaptureContext(&ctx);
|
||||
#elif _MSC_VER
|
||||
/* Stack frame layout on x86: */
|
||||
/* [ebp] is previous frame's EBP */
|
||||
/* [ebp+4] is previous frame's EIP (return address) */
|
||||
/* address of [ebp+8] is previous frame's ESP */
|
||||
__asm {
|
||||
mov eax, [ebp]
|
||||
mov [ctx.Ebp], eax
|
||||
mov eax, [ebp+4]
|
||||
mov [ctx.Eip], eax
|
||||
lea eax, [ebp+8]
|
||||
mov [ctx.Esp], eax
|
||||
mov [ctx.ContextFlags], CONTEXT_CONTROL
|
||||
}
|
||||
#else
|
||||
int32_t _ebp, _eip, _esp;
|
||||
/* TODO: I think this is right, not sure.. */
|
||||
__asm__(
|
||||
"mov 0(%%ebp), %%eax \n\t"
|
||||
"mov %%eax, %0 \n\t"
|
||||
"mov 4(%%ebp), %%eax \n\t"
|
||||
"mov %%eax, %1 \n\t"
|
||||
"lea 8(%%ebp), %%eax \n\t"
|
||||
"mov %%eax, %2"
|
||||
: "=m" (_ebp), "=m" (_eip), "=m" (_esp)
|
||||
:
|
||||
: "eax", "memory");
|
||||
|
||||
ctx.Ebp = _ebp;
|
||||
ctx.Eip = _eip;
|
||||
ctx.Esp = _esp;
|
||||
ctx.ContextFlags = CONTEXT_CONTROL;
|
||||
#endif
|
||||
|
||||
Logger_AbortCommon(result, raw_msg, &ctx);
|
||||
}
|
||||
#if _MSC_VER
|
||||
#pragma optimize ("", on)
|
||||
#endif
|
||||
#endif
|
||||
/* POSIX can be shared between Linux/BSD/OSX */
|
||||
#ifdef CC_BUILD_POSIX
|
||||
#ifndef CC_BUILD_OPENBSD
|
||||
#include <ucontext.h>
|
||||
#endif
|
||||
#include <execinfo.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
|
||||
/*########################################################################################################################*
|
||||
*-------------------------------------------------------Info dumping------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static void Logger_Backtrace(String* backtrace_, void* ctx) {
|
||||
String str; char strBuffer[384];
|
||||
void* addrs[40];
|
||||
@ -314,58 +401,6 @@ static void Logger_DumpBacktrace(String* str, void* ctx) {
|
||||
Logger_Backtrace(str, ctx);
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*------------------------------------------------------Error handling-----------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static void Logger_SignalHandler(int sig, siginfo_t* info, void* ctx) {
|
||||
String msg; char msgBuffer[STRING_SIZE * 2 + 1];
|
||||
int type, code;
|
||||
uintptr_t addr;
|
||||
|
||||
/* Uninstall handler to avoid chance of infinite loop */
|
||||
signal(SIGSEGV, SIG_DFL);
|
||||
signal(SIGBUS, SIG_DFL);
|
||||
signal(SIGILL, SIG_DFL);
|
||||
signal(SIGABRT, SIG_DFL);
|
||||
signal(SIGFPE, SIG_DFL);
|
||||
|
||||
type = info->si_signo;
|
||||
code = info->si_code;
|
||||
addr = (uintptr_t)info->si_addr;
|
||||
|
||||
String_InitArray_NT(msg, msgBuffer);
|
||||
String_Format3(&msg, "Unhandled signal %i (code %i) at 0x%x", &type, &code, &addr);
|
||||
msg.buffer[msg.length] = '\0';
|
||||
|
||||
Logger_AbortCommon(0, msg.buffer, ctx);
|
||||
}
|
||||
|
||||
void Logger_Hook(void) {
|
||||
struct sigaction sa, old;
|
||||
sa.sa_sigaction = Logger_SignalHandler;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = SA_RESTART | SA_SIGINFO;
|
||||
|
||||
sigaction(SIGSEGV, &sa, &old);
|
||||
sigaction(SIGBUS, &sa, &old);
|
||||
sigaction(SIGILL, &sa, &old);
|
||||
sigaction(SIGABRT, &sa, &old);
|
||||
sigaction(SIGFPE, &sa, &old);
|
||||
}
|
||||
|
||||
void Logger_Abort2(ReturnCode result, const char* raw_msg) {
|
||||
ucontext_t ctx;
|
||||
getcontext(&ctx);
|
||||
Logger_AbortCommon(result, raw_msg, &ctx);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*-------------------------------------------------------Info dumping------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
#ifdef CC_BUILD_POSIX
|
||||
static void Logger_DumpRegisters(void* ctx) {
|
||||
String str; char strBuffer[512];
|
||||
#ifdef CC_BUILD_OPENBSD
|
||||
@ -451,8 +486,8 @@ static void Logger_DumpRegisters(void* ctx) {
|
||||
|
||||
Logger_Log(&str);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* OS specific stuff */
|
||||
#if defined CC_BUILD_LINUX || defined CC_BUILD_SOLARIS
|
||||
static void Logger_DumpMisc(void* ctx) {
|
||||
const static String memMap = String_FromConst("-- memory map --\n");
|
||||
@ -472,76 +507,143 @@ static void Logger_DumpMisc(void* ctx) {
|
||||
|
||||
close(fd);
|
||||
}
|
||||
#elif defined CC_BUILD_OSX || defined CC_BUILD_FREEBSD || defined CC_BUILD_OPENBSD
|
||||
#else
|
||||
static void Logger_DumpMisc(void* ctx) { }
|
||||
#endif
|
||||
#endif
|
||||
#ifdef CC_BUILD_WEB
|
||||
static void Logger_DumpBacktrace(String* str, void* ctx) { }
|
||||
static void Logger_DumpRegisters(void* ctx) { }
|
||||
static void Logger_DumpMisc(void* ctx) { }
|
||||
#endif
|
||||
|
||||
/*########################################################################################################################*
|
||||
*------------------------------------------------------Error handling-----------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static void Logger_AbortCommon(ReturnCode result, const char* raw_msg, void* ctx);
|
||||
|
||||
#ifdef CC_BUILD_WIN
|
||||
static LONG WINAPI Logger_UnhandledFilter(struct _EXCEPTION_POINTERS* pInfo) {
|
||||
String msg; char msgBuffer[STRING_SIZE * 2 + 1];
|
||||
uint32_t code;
|
||||
uintptr_t addr;
|
||||
|
||||
code = (uint32_t)pInfo->ExceptionRecord->ExceptionCode;
|
||||
addr = (uintptr_t)pInfo->ExceptionRecord->ExceptionAddress;
|
||||
|
||||
String_InitArray_NT(msg, msgBuffer);
|
||||
String_Format2(&msg, "Unhandled exception 0x%h at 0x%x", &code, &addr);
|
||||
msg.buffer[msg.length] = '\0';
|
||||
|
||||
Logger_AbortCommon(0, msg.buffer, pInfo->ContextRecord);
|
||||
return EXCEPTION_EXECUTE_HANDLER; /* TODO: different flag */
|
||||
}
|
||||
void Logger_Hook(void) { SetUnhandledExceptionFilter(Logger_UnhandledFilter); }
|
||||
|
||||
/* Don't want compiler doing anything fancy with registers */
|
||||
#if _MSC_VER
|
||||
#pragma optimize ("", off)
|
||||
#endif
|
||||
void Logger_Abort2(ReturnCode result, const char* raw_msg) {
|
||||
CONTEXT ctx;
|
||||
#ifndef _M_IX86
|
||||
/* This method is guaranteed to exist on 64 bit windows */
|
||||
/* It is missing in 32 bit Windows 2000 however */
|
||||
RtlCaptureContext(&ctx);
|
||||
#elif _MSC_VER
|
||||
/* Stack frame layout on x86: */
|
||||
/* [ebp] is previous frame's EBP */
|
||||
/* [ebp+4] is previous frame's EIP (return address) */
|
||||
/* address of [ebp+8] is previous frame's ESP */
|
||||
__asm {
|
||||
mov eax, [ebp]
|
||||
mov [ctx.Ebp], eax
|
||||
mov eax, [ebp+4]
|
||||
mov [ctx.Eip], eax
|
||||
lea eax, [ebp+8]
|
||||
mov [ctx.Esp], eax
|
||||
mov [ctx.ContextFlags], CONTEXT_CONTROL
|
||||
}
|
||||
#else
|
||||
int32_t _ebp, _eip, _esp;
|
||||
/* TODO: I think this is right, not sure.. */
|
||||
__asm__(
|
||||
"mov 0(%%ebp), %%eax \n\t"
|
||||
"mov %%eax, %0 \n\t"
|
||||
"mov 4(%%ebp), %%eax \n\t"
|
||||
"mov %%eax, %1 \n\t"
|
||||
"lea 8(%%ebp), %%eax \n\t"
|
||||
"mov %%eax, %2"
|
||||
: "=m" (_ebp), "=m" (_eip), "=m" (_esp)
|
||||
:
|
||||
: "eax", "memory");
|
||||
|
||||
ctx.Ebp = _ebp;
|
||||
ctx.Eip = _eip;
|
||||
ctx.Esp = _esp;
|
||||
ctx.ContextFlags = CONTEXT_CONTROL;
|
||||
#endif
|
||||
|
||||
Logger_AbortCommon(result, raw_msg, &ctx);
|
||||
}
|
||||
#if _MSC_VER
|
||||
#pragma optimize ("", on)
|
||||
#endif
|
||||
#endif
|
||||
#ifdef CC_BUILD_POSIX
|
||||
static void Logger_SignalHandler(int sig, siginfo_t* info, void* ctx) {
|
||||
String msg; char msgBuffer[STRING_SIZE * 2 + 1];
|
||||
int type, code;
|
||||
uintptr_t addr;
|
||||
|
||||
/* Uninstall handler to avoid chance of infinite loop */
|
||||
signal(SIGSEGV, SIG_DFL);
|
||||
signal(SIGBUS, SIG_DFL);
|
||||
signal(SIGILL, SIG_DFL);
|
||||
signal(SIGABRT, SIG_DFL);
|
||||
signal(SIGFPE, SIG_DFL);
|
||||
|
||||
type = info->si_signo;
|
||||
code = info->si_code;
|
||||
addr = (uintptr_t)info->si_addr;
|
||||
|
||||
String_InitArray_NT(msg, msgBuffer);
|
||||
String_Format3(&msg, "Unhandled signal %i (code %i) at 0x%x", &type, &code, &addr);
|
||||
msg.buffer[msg.length] = '\0';
|
||||
|
||||
Logger_AbortCommon(0, msg.buffer, ctx);
|
||||
}
|
||||
|
||||
void Logger_Hook(void) {
|
||||
struct sigaction sa, old;
|
||||
sa.sa_sigaction = Logger_SignalHandler;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = SA_RESTART | SA_SIGINFO;
|
||||
|
||||
sigaction(SIGSEGV, &sa, &old);
|
||||
sigaction(SIGBUS, &sa, &old);
|
||||
sigaction(SIGILL, &sa, &old);
|
||||
sigaction(SIGABRT, &sa, &old);
|
||||
sigaction(SIGFPE, &sa, &old);
|
||||
}
|
||||
|
||||
void Logger_Abort2(ReturnCode result, const char* raw_msg) {
|
||||
ucontext_t ctx;
|
||||
getcontext(&ctx);
|
||||
Logger_AbortCommon(result, raw_msg, &ctx);
|
||||
}
|
||||
#endif
|
||||
#ifdef CC_BUILD_WEB
|
||||
void Logger_Hook(void) { }
|
||||
void Logger_Abort2(ReturnCode result, const char* raw_msg) {
|
||||
Logger_AbortCommon(result, raw_msg, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*----------------------------------------------------------Common---------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
void Logger_OldWarn(ReturnCode res, const char* place) {
|
||||
String msg; char msgBuffer[128];
|
||||
String_InitArray(msg, msgBuffer);
|
||||
|
||||
String_Format2(&msg, "Error %h when %c", &res, place);
|
||||
Logger_WarnFunc(&msg);
|
||||
}
|
||||
|
||||
void Logger_OldWarn2(ReturnCode res, const char* place, const String* path) {
|
||||
String msg; char msgBuffer[256];
|
||||
String_InitArray(msg, msgBuffer);
|
||||
|
||||
String_Format3(&msg, "Error %h when %c '%s'", &res, place, path);
|
||||
Logger_WarnFunc(&msg);
|
||||
}
|
||||
|
||||
void Logger_SysWarn(ReturnCode res, const char* place, Logger_DescribeError describeErr) {
|
||||
String msg; char msgBuffer[256];
|
||||
String_InitArray(msg, msgBuffer);
|
||||
String_Append(&msg, '"');
|
||||
|
||||
if (describeErr(res, &msg)) {
|
||||
String_Format2(&msg, "\" (i) error when %c", &res, place);
|
||||
} else {
|
||||
String_DeleteAt(&msg, 0);
|
||||
String_Format2(&msg, "Error %h when %c", &res, place);
|
||||
}
|
||||
Logger_WarnFunc(&msg);
|
||||
}
|
||||
|
||||
void Logger_SysWarn2(ReturnCode res, const char* place, const String* path, Logger_DescribeError describeErr) {
|
||||
String msg; char msgBuffer[256];
|
||||
String_InitArray(msg, msgBuffer);
|
||||
String_Append(&msg, '"');
|
||||
|
||||
if (describeErr(res, &msg)) {
|
||||
String_Format3(&msg, "\" (%i) error when %c '%s'", &res, place, path);
|
||||
} else {
|
||||
String_DeleteAt(&msg, 0);
|
||||
String_Format3(&msg, "Error %h when %c '%s'", &res, place, path);
|
||||
}
|
||||
Logger_WarnFunc(&msg);
|
||||
}
|
||||
|
||||
void Logger_DynamicLibWarn2(ReturnCode res, const char* place, const String* path) {
|
||||
Logger_SysWarn2(res, place, path, DynamicLib_DescribeError);
|
||||
}
|
||||
void Logger_Warn2(ReturnCode res, const char* place, const String* path) {
|
||||
Logger_SysWarn2(res, place, path, Platform_DescribeError);
|
||||
}
|
||||
|
||||
void Logger_DialogWarn(const String* msg) {
|
||||
String dst; char dstBuffer[256];
|
||||
String_InitArray_NT(dst, dstBuffer);
|
||||
|
||||
String_AppendString(&dst, msg);
|
||||
dst.buffer[dst.length] = '\0';
|
||||
Window_ShowDialog(Logger_DialogTitle, dst.buffer);
|
||||
}
|
||||
const char* Logger_DialogTitle = "Error";
|
||||
Logger_DoWarn Logger_WarnFunc = Logger_DialogWarn;
|
||||
|
||||
static FileHandle logFile;
|
||||
static struct Stream logStream;
|
||||
static bool logOpen;
|
||||
|
@ -27,6 +27,8 @@ void Logger_SysWarn2(ReturnCode res, const char* place, const String* path, Logg
|
||||
|
||||
/* Shortcut for Logger_SysWarn2 with DynamicLib_DescribeError */
|
||||
void Logger_DynamicLibWarn2(ReturnCode res, const char* place, const String* path);
|
||||
/* Shortcut for Logger_SysWarn with Platform_DescribeError */
|
||||
void Logger_Warn(ReturnCode res, const char* place);
|
||||
/* Shortcut for Logger_SysWarn2 with Platform_DescribeError */
|
||||
void Logger_Warn2(ReturnCode res, const char* place, const String* path);
|
||||
|
||||
|
@ -2028,7 +2028,7 @@ void Platform_Init(void) {
|
||||
heap = GetProcessHeap();
|
||||
|
||||
res = WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||
if (res) Logger_OldWarn(res, "starting WSA");
|
||||
if (res) Logger_Warn(res, "starting WSA");
|
||||
|
||||
hasDebugger = IsDebuggerPresent();
|
||||
/* For when user runs from command prompt */
|
||||
|
@ -72,14 +72,14 @@ static void Program_SetCurrentDirectory(void) {
|
||||
String_InitArray(path, pathBuffer);
|
||||
|
||||
res = Process_GetExePath(&path);
|
||||
if (res) { Logger_OldWarn(res, "getting exe path"); return; }
|
||||
if (res) { Logger_Warn(res, "getting exe path"); return; }
|
||||
|
||||
/* get rid of filename at end of directory */
|
||||
for (i = path.length - 1; i >= 0; i--, path.length--) {
|
||||
if (path.buffer[i] == '/' || path.buffer[i] == '\\') break;
|
||||
}
|
||||
res = Platform_SetCurrentDirectory(&path);
|
||||
if (res) { Logger_OldWarn(res, "setting current directory"); return; }
|
||||
if (res) { Logger_Warn(res, "setting current directory"); return; }
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -83,13 +83,13 @@ static void Resources_CheckTextures(void) {
|
||||
if (!File_Exists(&path)) return;
|
||||
res = Stream_OpenFile(&stream, &path);
|
||||
|
||||
if (res) { Logger_OldWarn(res, "checking default.zip"); return; }
|
||||
if (res) { Logger_Warn(res, "checking default.zip"); return; }
|
||||
Zip_Init(&state, &stream);
|
||||
state.SelectEntry = Resources_SelectZipEntry;
|
||||
|
||||
res = Zip_Extract(&state);
|
||||
stream.Close(&stream);
|
||||
if (res) Logger_OldWarn(res, "inspecting default.zip");
|
||||
if (res) Logger_Warn(res, "inspecting default.zip");
|
||||
|
||||
/* if somehow have say "gui.png", "GUI.png" */
|
||||
Textures_AllExist = texturesFound >= Array_Elems(Resources_Textures);
|
||||
@ -558,13 +558,13 @@ static void TexPatcher_MakeDefaultZip(void) {
|
||||
|
||||
res = Stream_CreateFile(&s, &path);
|
||||
if (res) {
|
||||
Logger_OldWarn(res, "creating default.zip");
|
||||
Logger_Warn(res, "creating default.zip");
|
||||
} else {
|
||||
res = TexPatcher_WriteEntries(&s);
|
||||
if (res) Logger_OldWarn(res, "making default.zip");
|
||||
if (res) Logger_Warn(res, "making default.zip");
|
||||
|
||||
res = s.Close(&s);
|
||||
if (res) Logger_OldWarn(res, "closing default.zip");
|
||||
if (res) Logger_Warn(res, "closing default.zip");
|
||||
}
|
||||
|
||||
for (i = 0; i < Array_Elems(Resources_Files); i++) {
|
||||
@ -585,9 +585,9 @@ static void SoundPatcher_FixupHeader(struct Stream* s, struct VorbisState* ctx)
|
||||
ReturnCode res;
|
||||
|
||||
res = s->Length(s, &length);
|
||||
if (res) { Logger_OldWarn(res, "getting .wav length"); return; }
|
||||
if (res) { Logger_Warn(res, "getting .wav length"); return; }
|
||||
res = s->Seek(s, 0);
|
||||
if (res) { Logger_OldWarn(res, "seeking to .wav start"); return; }
|
||||
if (res) { Logger_Warn(res, "seeking to .wav start"); return; }
|
||||
|
||||
Stream_SetU32_BE(&header[0], WAV_FourCC('R','I','F','F'));
|
||||
Stream_SetU32_LE(&header[4], length - 8);
|
||||
@ -605,7 +605,7 @@ static void SoundPatcher_FixupHeader(struct Stream* s, struct VorbisState* ctx)
|
||||
Stream_SetU32_LE(&header[40], length - sizeof(header));
|
||||
|
||||
res = Stream_Write(s, header, sizeof(header));
|
||||
if (res) Logger_OldWarn(res, "fixing .wav header");
|
||||
if (res) Logger_Warn(res, "fixing .wav header");
|
||||
}
|
||||
|
||||
static void SoundPatcher_DecodeAudio(struct Stream* s, struct VorbisState* ctx) {
|
||||
@ -615,21 +615,21 @@ static void SoundPatcher_DecodeAudio(struct Stream* s, struct VorbisState* ctx)
|
||||
|
||||
/* ctx is all 0, so reuse it here for header */
|
||||
res = Stream_Write(s, ctx, 44);
|
||||
if (res) { Logger_OldWarn(res, "writing .wav header"); return; }
|
||||
if (res) { Logger_Warn(res, "writing .wav header"); return; }
|
||||
|
||||
res = Vorbis_DecodeHeaders(ctx);
|
||||
if (res) { Logger_OldWarn(res, "decoding .ogg header"); return; }
|
||||
if (res) { Logger_Warn(res, "decoding .ogg header"); return; }
|
||||
samples = Mem_Alloc(ctx->BlockSizes[1] * ctx->Channels, 2, ".ogg samples");
|
||||
|
||||
for (;;) {
|
||||
res = Vorbis_DecodeFrame(ctx);
|
||||
if (res == ERR_END_OF_STREAM) break;
|
||||
if (res) { Logger_OldWarn(res, "decoding .ogg"); break; }
|
||||
if (res) { Logger_Warn(res, "decoding .ogg"); break; }
|
||||
|
||||
count = Vorbis_OutputFrame(ctx, samples);
|
||||
/* TODO: Do we need to account for big endian */
|
||||
res = Stream_Write(s, samples, count * 2);
|
||||
if (res) { Logger_OldWarn(res, "writing samples"); break; }
|
||||
if (res) { Logger_Warn(res, "writing samples"); break; }
|
||||
}
|
||||
Mem_Free(samples);
|
||||
}
|
||||
@ -646,7 +646,7 @@ static void SoundPatcher_Save(struct ResourceSound* sound, struct HttpRequest* r
|
||||
String_Format1(&path, "audio/%c.wav", sound->Name);
|
||||
|
||||
res = Stream_CreateFile(&dst, &path);
|
||||
if (res) { Logger_OldWarn(res, "creating .wav file"); return; }
|
||||
if (res) { Logger_Warn(res, "creating .wav file"); return; }
|
||||
|
||||
Ogg_MakeStream(&ogg, buffer, &src);
|
||||
ctx.Source = &ogg;
|
||||
@ -655,7 +655,7 @@ static void SoundPatcher_Save(struct ResourceSound* sound, struct HttpRequest* r
|
||||
SoundPatcher_FixupHeader(&dst, &ctx);
|
||||
|
||||
res = dst.Close(&dst);
|
||||
if (res) Logger_OldWarn(res, "closing .wav file");
|
||||
if (res) Logger_Warn(res, "closing .wav file");
|
||||
}
|
||||
|
||||
static void MusicPatcher_Save(struct ResourceMusic* music, struct HttpRequest* req) {
|
||||
@ -666,7 +666,7 @@ static void MusicPatcher_Save(struct ResourceMusic* music, struct HttpRequest* r
|
||||
String_Format1(&path, "audio/%c", music->Name);
|
||||
|
||||
res = Stream_WriteAllTo(&path, req->Data, req->Size);
|
||||
if (res) Logger_OldWarn(res, "saving music file");
|
||||
if (res) Logger_Warn(res, "saving music file");
|
||||
}
|
||||
|
||||
|
||||
|
11
src/String.c
11
src/String.c
@ -74,6 +74,17 @@ int String_UNSAFE_Split(STRING_REF const String* str, char c, String* subs, int
|
||||
return count;
|
||||
}
|
||||
|
||||
CC_API void String_UNSAFE_SplitBy(STRING_REF String* str, char c, String* part) {
|
||||
int idx = String_IndexOf(str, c);
|
||||
if (idx == -1) {
|
||||
*part = *str;
|
||||
*str = String_Empty;
|
||||
} else {
|
||||
*part = String_UNSAFE_Substring(str, 0, idx); idx++;
|
||||
*str = String_UNSAFE_SubstringAt(str, idx);
|
||||
}
|
||||
}
|
||||
|
||||
bool String_UNSAFE_Separate(STRING_REF const String* str, char c, String* key, String* value) {
|
||||
int idx = String_IndexOf(str, c);
|
||||
if (idx == -1) {
|
||||
|
@ -64,6 +64,9 @@ CC_API String String_UNSAFE_Substring(STRING_REF const String* str, int offset,
|
||||
/* UNSAFE: Splits a string of the form [str1][c][str2][c][str3].. into substrings. */
|
||||
/* e.g., "abc:id:xyz" becomes "abc","id","xyz" */
|
||||
CC_API int String_UNSAFE_Split(STRING_REF const String* str, char c, String* subs, int maxSubs);
|
||||
/* UNSAFE: Splits a string of the form [part][c][rest], returning whether [c] was found or not. */
|
||||
/* NOTE: This is intended to be repeatedly called until str->length is 0. (unbounded String_UNSAFE_Split) */
|
||||
CC_API void String_UNSAFE_SplitBy(STRING_REF String* str, char c, String* part);
|
||||
/* UNSAFE: Splits a string of the form [key][c][value] into two substrings. */
|
||||
/* e.g., "allowed =true" becomes "allowed" and "true", and excludes the space. */
|
||||
/* If c is not found, sets key to str and value to String_Empty, returns false. */
|
||||
|
12
src/Window.c
12
src/Window.c
@ -1462,16 +1462,12 @@ static void X11Textbox_Measure(X11Textbox* t, XFontStruct* font) {
|
||||
}
|
||||
|
||||
static void X11Textbox_Draw(X11Textbox* t, X11Window* w) {
|
||||
String str = String_FromReadonly(t->Text);
|
||||
String str = String_FromReadonly(t->Text), line;
|
||||
int y = t->Y + t->LineHeight - t->Descent; /* TODO: is -Descent even right? */
|
||||
int end, len;
|
||||
|
||||
for (end = 0; end >= 0; y += t->LineHeight) {
|
||||
end = String_IndexOf(&str, '\n');
|
||||
len = end == -1 ? str.length : end;
|
||||
|
||||
XDrawString(dpy, w->win, w->gc, t->X, y, str.buffer, len);
|
||||
if (end >= 0) str = String_UNSAFE_SubstringAt(&str, end + 1);
|
||||
while (str.length) {
|
||||
String_UNSAFE_SplitBy(&str, '\n', &line);
|
||||
XDrawString(dpy, w->win, w->gc, t->X, y, line.buffer, line.length);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user