/* File: cwasm_debug.c Author: Taylor Robbins Date: 08\29\2025 Description: ** Holds functions and macros for the debug output API we use in the application */ typedef enum DbgLevel DbgLevel; enum DbgLevel { DbgLevel_Debug = 0, DbgLevel_Info, DbgLevel_Warning, DbgLevel_Error, DbgLevel_Count, }; static DbgLevel DebugOutputLineBufferLevel = DbgLevel_Debug; static u32 DebugOutputLineBufferLength = 0; static char DebugOutputLineBuffer[CWASM_DEBUG_OUTPUT_LINE_BUFFER_SIZE]; static char DebugOutputPrintBuffer[CWASM_DEBUG_OUTPUT_PRINT_BUFFER_SIZE]; #if CWASM_DEBUG void CwasmDebugOutput(const char* filePath, u32 lineNumber, const char* functionName, DbgLevel level, bool newLine, const char* messageNt) #else void CwasmDebugOutput(DbgLevel level, bool newLine, const char* messageNt) #endif { if (level == DbgLevel_Debug && !CWASM_ENABLE_DBG_LEVEL_DEBUG) { return; } if (level == DbgLevel_Info && !CWASM_ENABLE_DBG_LEVEL_INFO) { return; } if (level == DbgLevel_Warning && !CWASM_ENABLE_DBG_LEVEL_WARNING) { return; } if (level == DbgLevel_Error && !CWASM_ENABLE_DBG_LEVEL_ERROR) { return; } u32 lineStart = 0; int messageLength = (messageNt != nullptr) ? strlen(messageNt) : 0; for (int cIndex = 0; cIndex < messageLength + (newLine ? 1 : 0); cIndex++) { char character = (cIndex < messageLength) ? messageNt[cIndex] : '\n'; if (character == '\n') { if (DebugOutputLineBufferLength > 0) { DebugOutputLineBufferLevel = (level > DebugOutputLineBufferLevel) ? level : DebugOutputLineBufferLevel; u32 numCharsToCopy = ((cIndex - lineStart) < (CWASM_DEBUG_OUTPUT_LINE_BUFFER_SIZE - DebugOutputLineBufferLength)) ? (cIndex - lineStart) : (CWASM_DEBUG_OUTPUT_LINE_BUFFER_SIZE - DebugOutputLineBufferLength); if (numCharsToCopy > 0) { memcpy(&DebugOutputLineBuffer[DebugOutputLineBufferLength], &messageNt[lineStart], numCharsToCopy); DebugOutputLineBufferLength += numCharsToCopy; } jsStdPrint((int)DebugOutputLineBufferLevel, &DebugOutputLineBuffer[0], DebugOutputLineBufferLength); DebugOutputLineBufferLength = 0; DebugOutputLineBufferLevel = DbgLevel_Debug; } else { jsStdPrint((int)level, &messageNt[lineStart], messageLength - lineStart); } lineStart = cIndex+1; } } if (lineStart < messageLength) { u32 numCharsToCopy = ((messageLength - lineStart) < (CWASM_DEBUG_OUTPUT_LINE_BUFFER_SIZE - DebugOutputLineBufferLength)) ? (messageLength - lineStart) : (CWASM_DEBUG_OUTPUT_LINE_BUFFER_SIZE - DebugOutputLineBufferLength); if (numCharsToCopy > 0) { DebugOutputLineBufferLevel = (level > DebugOutputLineBufferLevel) ? level : DebugOutputLineBufferLevel; memcpy(&DebugOutputLineBuffer[DebugOutputLineBufferLength], &messageNt[lineStart], numCharsToCopy); DebugOutputLineBufferLength += numCharsToCopy; } } } #if CWASM_DEBUG void CwasmDebugOutputPrint(const char* filePath, u32 lineNumber, const char* functionName, DbgLevel level, bool newLine, const char* formatStrNt, ...) #else void CwasmDebugOutputPrint(DbgLevel level, bool newLine, const char* formatStrNt, ...) #endif { va_list args; va_start(args, formatStrNt); int printResult = vsnprintf(&DebugOutputPrintBuffer[0], CWASM_DEBUG_OUTPUT_PRINT_BUFFER_SIZE, formatStrNt, args); va_end(args); if (printResult >= 0) { DebugOutputPrintBuffer[CWASM_DEBUG_OUTPUT_PRINT_BUFFER_SIZE-1] = '\0'; #if CWASM_DEBUG CwasmDebugOutput(filePath, lineNumber, functionName, level, newLine, &DebugOutputPrintBuffer[0]); #else CwasmDebugOutput(level, newLine, &DebugOutputPrintBuffer[0]); #endif } else { #if CWASM_DEBUG CwasmDebugOutput(filePath, lineNumber, functionName, level, false, "CWASM_PRINT_ERROR("); CwasmDebugOutput(filePath, lineNumber, functionName, level, false, formatStrNt); CwasmDebugOutput(filePath, lineNumber, functionName, level, true, ")"); #else CwasmDebugOutput(level, false, "CWASM_PRINT_ERROR("); CwasmDebugOutput(level, false, formatStrNt); CwasmDebugOutput(level, true, ")"); #endif } } #if CWASM_ENABLE_DBG_LEVEL_DEBUG #if CWASM_DEBUG #define Write_D(messageNt) CwasmDebugOutput(__FILE__, __LINE__, __func__, DbgLevel_Debug, false, (messageNt)) #define Print_D(formatStrNt, ...) CwasmDebugOutputPrint(__FILE__, __LINE__, __func__, DbgLevel_Debug, false, (formatStrNt), ##__VA_ARGS__) #define WriteLine_D(messageNt) CwasmDebugOutput(__FILE__, __LINE__, __func__, DbgLevel_Debug, true, (messageNt)) #define PrintLine_D(formatStrNt, ...) CwasmDebugOutputPrint(__FILE__, __LINE__, __func__, DbgLevel_Debug, true, (formatStrNt), ##__VA_ARGS__) #else #define Write_D(messageNt) CwasmDebugOutput(DbgLevel_Debug, false, (messageNt)) #define Print_D(formatStrNt, ...) CwasmDebugOutputPrint(DbgLevel_Debug, false, (formatStrNt), ##__VA_ARGS__) #define WriteLine_D(messageNt) CwasmDebugOutput(DbgLevel_Debug, true, (messageNt)) #define PrintLine_D(formatStrNt, ...) CwasmDebugOutputPrint(DbgLevel_Debug, true, (formatStrNt), ##__VA_ARGS__) #endif #else #define Write_D(messageNt) //nothing #define Print_D(formatStrNt, ...) //nothing #define WriteLine_D(messageNt) //nothing #define PrintLine_D(formatStrNt, ...) //nothing #endif #if CWASM_ENABLE_DBG_LEVEL_INFO #if CWASM_DEBUG #define Write_I(messageNt) CwasmDebugOutput(__FILE__, __LINE__, __func__, DbgLevel_Info, false, (messageNt)) #define Print_I(formatStrNt, ...) CwasmDebugOutputPrint(__FILE__, __LINE__, __func__, DbgLevel_Info, false, (formatStrNt), ##__VA_ARGS__) #define WriteLine_I(messageNt) CwasmDebugOutput(__FILE__, __LINE__, __func__, DbgLevel_Info, true, (messageNt)) #define PrintLine_I(formatStrNt, ...) CwasmDebugOutputPrint(__FILE__, __LINE__, __func__, DbgLevel_Info, true, (formatStrNt), ##__VA_ARGS__) #else #define Write_I(messageNt) CwasmDebugOutput(DbgLevel_Info, false, (messageNt)) #define Print_I(formatStrNt, ...) CwasmDebugOutputPrint(DbgLevel_Info, false, (formatStrNt), ##__VA_ARGS__) #define WriteLine_I(messageNt) CwasmDebugOutput(DbgLevel_Info, true, (messageNt)) #define PrintLine_I(formatStrNt, ...) CwasmDebugOutputPrint(DbgLevel_Info, true, (formatStrNt), ##__VA_ARGS__) #endif #else #define Write_I(messageNt) //nothing #define Print_I(formatStrNt, ...) //nothing #define WriteLine_I(messageNt) //nothing #define PrintLine_I(formatStrNt, ...) //nothing #endif #if CWASM_ENABLE_DBG_LEVEL_WARNING #if CWASM_DEBUG #define Write_W(messageNt) CwasmDebugOutput(__FILE__, __LINE__, __func__, DbgLevel_Warning, false, (messageNt)) #define Print_W(formatStrNt, ...) CwasmDebugOutputPrint(__FILE__, __LINE__, __func__, DbgLevel_Warning, false, (formatStrNt), ##__VA_ARGS__) #define WriteLine_W(messageNt) CwasmDebugOutput(__FILE__, __LINE__, __func__, DbgLevel_Warning, true, (messageNt)) #define PrintLine_W(formatStrNt, ...) CwasmDebugOutputPrint(__FILE__, __LINE__, __func__, DbgLevel_Warning, true, (formatStrNt), ##__VA_ARGS__) #else #define Write_W(messageNt) CwasmDebugOutput(DbgLevel_Warning, false, (messageNt)) #define Print_W(formatStrNt, ...) CwasmDebugOutputPrint(DbgLevel_Warning, false, (formatStrNt), ##__VA_ARGS__) #define WriteLine_W(messageNt) CwasmDebugOutput(DbgLevel_Warning, true, (messageNt)) #define PrintLine_W(formatStrNt, ...) CwasmDebugOutputPrint(DbgLevel_Warning, true, (formatStrNt), ##__VA_ARGS__) #endif #else #define Write_W(messageNt) //nothing #define Print_W(formatStrNt, ...) //nothing #define WriteLine_W(messageNt) //nothing #define PrintLine_W(formatStrNt, ...) //nothing #endif #if CWASM_ENABLE_DBG_LEVEL_ERROR #if CWASM_DEBUG #define Write_E(messageNt) CwasmDebugOutput(__FILE__, __LINE__, __func__, DbgLevel_Error, false, (messageNt)) #define Print_E(formatStrNt, ...) CwasmDebugOutputPrint(__FILE__, __LINE__, __func__, DbgLevel_Error, false, (formatStrNt), ##__VA_ARGS__) #define WriteLine_E(messageNt) CwasmDebugOutput(__FILE__, __LINE__, __func__, DbgLevel_Error, true, (messageNt)) #define PrintLine_E(formatStrNt, ...) CwasmDebugOutputPrint(__FILE__, __LINE__, __func__, DbgLevel_Error, true, (formatStrNt), ##__VA_ARGS__) #else #define Write_E(messageNt) CwasmDebugOutput(DbgLevel_Error, false, (messageNt)) #define Print_E(formatStrNt, ...) CwasmDebugOutputPrint(DbgLevel_Error, false, (formatStrNt), ##__VA_ARGS__) #define WriteLine_E(messageNt) CwasmDebugOutput(DbgLevel_Error, true, (messageNt)) #define PrintLine_E(formatStrNt, ...) CwasmDebugOutputPrint(DbgLevel_Error, true, (formatStrNt), ##__VA_ARGS__) #endif #else #define Write_E(messageNt) //nothing #define Print_E(formatStrNt, ...) //nothing #define WriteLine_E(messageNt) //nothing #define PrintLine_E(formatStrNt, ...) //nothing #endif