From 3dcae2ce0cee862ee21353e27fbfdbd46dd0260a Mon Sep 17 00:00:00 2001 From: Katayama Hirofumi MZ Date: Tue, 9 Jul 2024 04:25:30 +0900 Subject: [PATCH] [CMD] Support dynamic trace (#7093) Based on Hans Harder's patch. Realize tracing cmd on console output. JIRA issue: CORE-6669 - Add FEATURE_DYNAMIC_TRACE feature. - Add CmdTrace function. - Re-define FIXME, ERR, WARN, and TRACE macros. - Check CMDTRACE environment variable. If it was "ON", then enable dynamic trace. --- base/shell/cmd/CMakeLists.txt | 1 + base/shell/cmd/config.h | 6 +-- base/shell/cmd/precomp.h | 24 ++++++++++++ base/shell/cmd/set.c | 7 ++++ base/shell/cmd/trace.c | 72 +++++++++++++++++++++++++++++++++++ 5 files changed, 106 insertions(+), 4 deletions(-) create mode 100644 base/shell/cmd/trace.c diff --git a/base/shell/cmd/CMakeLists.txt b/base/shell/cmd/CMakeLists.txt index b1cf669c03a..a2f741414b4 100644 --- a/base/shell/cmd/CMakeLists.txt +++ b/base/shell/cmd/CMakeLists.txt @@ -54,6 +54,7 @@ list(APPEND SOURCE time.c timer.c title.c + trace.c type.c ver.c verify.c diff --git a/base/shell/cmd/config.h b/base/shell/cmd/config.h index 3a5b70b221a..09fb65d7e8e 100644 --- a/base/shell/cmd/config.h +++ b/base/shell/cmd/config.h @@ -18,26 +18,24 @@ /* Define to enable the alias command, and aliases.*/ #define FEATURE_ALIASES - /* Define to enable history */ #define FEATURE_HISTORY /*Define to enable history wrap (4nt's style)*/ #define WRAP_HISTORY - /* Define one of these to enable filename completion */ //#define FEATURE_UNIX_FILENAME_COMPLETION #define FEATURE_4NT_FILENAME_COMPLETION - /* Define to enable the directory stack */ #define FEATURE_DIRECTORY_STACK - /* Define to activate redirections and piping */ #define FEATURE_REDIRECTION +/* Define to enable dynamic switching of TRACE output in console */ +#define FEATURE_DYNAMIC_TRACE /* Define one of these to select the used locale. */ /* (date and time formats etc.) used in DATE, TIME, */ diff --git a/base/shell/cmd/precomp.h b/base/shell/cmd/precomp.h index 7c0e76dc3da..f2c663c712e 100644 --- a/base/shell/cmd/precomp.h +++ b/base/shell/cmd/precomp.h @@ -37,10 +37,34 @@ #include WINE_DEFAULT_DEBUG_CHANNEL(cmd); + #ifdef UNICODE #define debugstr_aw debugstr_w #else #define debugstr_aw debugstr_a #endif +#ifdef FEATURE_DYNAMIC_TRACE + +extern BOOL g_bDynamicTrace; +void CmdTrace(INT type, LPCSTR file, INT line, LPCSTR func, LPCSTR fmt, ...); + +#undef FIXME +#define FIXME(fmt, ...) \ + CmdTrace(__WINE_DBCL_FIXME, __FILE__, __LINE__, __FUNCTION__, fmt, ## __VA_ARGS__) + +#undef ERR +#define ERR(fmt, ...) \ + CmdTrace(__WINE_DBCL_ERR, __FILE__, __LINE__, __FUNCTION__, fmt, ## __VA_ARGS__) + +#undef WARN +#define WARN(fmt, ...) \ + CmdTrace(__WINE_DBCL_WARN, __FILE__, __LINE__, __FUNCTION__, fmt, ## __VA_ARGS__) + +#undef TRACE +#define TRACE(fmt, ...) \ + CmdTrace(__WINE_DBCL_TRACE, __FILE__, __LINE__, __FUNCTION__, fmt, ## __VA_ARGS__) + +#endif /* def FEATURE_DYNAMIC_TRACE */ + #endif /* __CMD_PRECOMP_H */ diff --git a/base/shell/cmd/set.c b/base/shell/cmd/set.c index 1adf091ad84..9028a181a96 100644 --- a/base/shell/cmd/set.c +++ b/base/shell/cmd/set.c @@ -175,6 +175,13 @@ INT cmd_set(LPTSTR param) } *p++ = _T('\0'); + +#ifdef FEATURE_DYNAMIC_TRACE + /* Check for dynamic TRACE ON/OFF */ + if (!_tcsicmp(param, _T("CMDTRACE"))) + g_bDynamicTrace = !_tcsicmp(p, _T("ON")); +#endif + if (!SetEnvironmentVariable(param, *p ? p : NULL)) { retval = 1; diff --git a/base/shell/cmd/trace.c b/base/shell/cmd/trace.c new file mode 100644 index 00000000000..92eb740c087 --- /dev/null +++ b/base/shell/cmd/trace.c @@ -0,0 +1,72 @@ +/* + * PROJECT: ReactOS Command Shell + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) + * PURPOSE: Dynamic trace (generates debugging output to console output) + * COPYRIGHT: Copyright 2011 Hans Harder + * Copyright 2024 Katayama Hirofumi MZ + */ + +#include "precomp.h" + +#ifdef FEATURE_DYNAMIC_TRACE + +BOOL g_bDynamicTrace = FALSE; + +VOID CmdTrace(INT type, LPCSTR file, INT line, LPCSTR func, LPCSTR fmt, ...) +{ + va_list va; + int cch; + char szTextA[800]; +#ifdef _UNICODE + wchar_t szTextW[800]; +#endif + static struct __wine_debug_functions s_Debug; + + va_start(va, fmt); + + /* Console output */ + if (g_bDynamicTrace) + { + StringCchPrintfA(szTextA, _countof(szTextA), "%s (%d): ", file, line); + cch = lstrlenA(szTextA); + StringCchVPrintfA(&szTextA[cch], _countof(szTextA) - cch, fmt, va); + +#ifdef _UNICODE + MultiByteToWideChar(OutputCodePage, 0, szTextA, -1, szTextW, _countof(szTextW)); + szTextW[_countof(szTextW) - 1] = UNICODE_NULL; /* Avoid buffer overrun */ + ConOutPuts(szTextW); +#else + ConOutPuts(szTextA); +#endif + } + + if (!s_Debug.dbg_vlog) + __wine_dbg_set_functions(NULL, &s_Debug, sizeof(s_Debug)); + + /* Debug logging */ + switch (type) + { + case __WINE_DBCL_FIXME: + if (__WINE_IS_DEBUG_ON(_FIXME, __wine_dbch___default)) + s_Debug.dbg_vlog(__WINE_DBCL_FIXME, __wine_dbch___default, file, func, line, fmt, va); + break; + case __WINE_DBCL_ERR: + if (__WINE_IS_DEBUG_ON(_ERR, __wine_dbch___default)) + s_Debug.dbg_vlog(__WINE_DBCL_ERR, __wine_dbch___default, file, func, line, fmt, va); + break; + case __WINE_DBCL_WARN: + if (__WINE_IS_DEBUG_ON(_WARN, __wine_dbch___default)) + s_Debug.dbg_vlog(__WINE_DBCL_WARN, __wine_dbch___default, file, func, line, fmt, va); + break; + case __WINE_DBCL_TRACE: + if (__WINE_IS_DEBUG_ON(_TRACE, __wine_dbch___default)) + s_Debug.dbg_vlog(__WINE_DBCL_TRACE, __wine_dbch___default, file, func, line, fmt, va); + break; + default: + break; + } + + va_end(va); +} + +#endif /* def FEATURE_DYNAMIC_TRACE */