Skip to content

Commit

Permalink
Debug guards: add documentation
Browse files Browse the repository at this point in the history
- Documentation added to explain what is the purpose of the function debug guards
  and their intended use.

[#8 state:needs_ack]

Signed-off-by: Jocelyn Legault <jocelynlegault@gmail.com>
  • Loading branch information
joce authored and Thell Fowler committed Dec 6, 2009
1 parent fc77c06 commit 9b0cc77
Showing 1 changed file with 137 additions and 20 deletions.
157 changes: 137 additions & 20 deletions PowerEditor/src/MISC/Debug/npp_debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@

#ifndef SHIPPING

#define MAX_DEBUG_INDENT 1024
namespace NppDebug
{
#define MAX_DEBUG_INDENT 1024
namespace NppDebug
{
typedef void (__stdcall *outputFunction)(const TCHAR*);

outputFunction setOutputFunction(outputFunction newOutputFunction);
Expand Down Expand Up @@ -56,33 +56,150 @@
static TCHAR _indent[MAX_DEBUG_INDENT];
};

} // namespace NppDebug
} // namespace NppDebug

#define debugf(format, ...) NppDebug::outputF(format, __VA_ARGS__)
// JOCE: modify to make that a single call to OutputF
#define line_debugf(format, ...) NppDebug::outputF(TEXT("%s(%d): "), TEXT(__FILE__), __LINE__); NppDebug::outputF(format, __VA_ARGS__)
// debugf() works just at printf(), except that it outputs to the debug console in MSVC
#define debugf(format, ...) NppDebug::outputF(format, __VA_ARGS__)

#define func_guard_declare_cat(cat) extern NppDebug::FuncGuard::State __func_guard_category_##cat
#define func_guard_enable_cat(cat) NppDebug::FuncGuard::State __func_guard_category_##cat = NppDebug::FuncGuard::Enabled
#define func_guard_disable_cat(cat) NppDebug::FuncGuard::State __func_guard_category_##cat = NppDebug::FuncGuard::Disabled
// line_debugf() works just as debugf, but it prefixes the text message with the file name
// and line number of the call in a way that MSVC recognizes so you can double click on the
// line in the debug output and be taken to the source file.
//
// For example:
// source\folder\file.cpp(42): Hello World!!!

#define func_guard(cat) NppDebug::FuncGuard __npp_func_guard__( TEXT(__FUNCSIG__), TEXT(__FUNCTION__), TEXT(__FILE__), __LINE__, __func_guard_category_##cat, TEXT( #cat ))
#define line_debugf(format, ...) \
/* JOCE: modify to make that a single call to OutputF */ \
NppDebug::outputF(TEXT("%s(%d): "), TEXT(__FILE__), __LINE__); \
NppDebug::outputF(format, __VA_ARGS__)

// JOCE: modify to make that a single call to OutputF (should make guard_debugf part of the function guard
#define guard_debugf(format, ...) __npp_func_guard__.outputIndent(); NppDebug::outputF(format, __VA_ARGS__)
//
// Debug Guards
// ==============
//
// Debug guards are debugging tools meant to help the programmers figure out the path the
// code is taking in real time by displaying info in the debug console.
// The different guarded functions will show up in the console as the program enters them.
// They will also be indented in a way that a called function will be indented in from a
// caller function.
//
// For example, given the following function calls:
//
// void FooOne()
// {
// func_guard(foo); // The 'foo' parameter is explained below...
// }
// void FooTwo()
// {
// func_guard(foo); // The 'foo' parameter is explained below...
// // ...
// FooOne();
// }
//
// one would get the following output:
//
// file.cpp(42):
// Entering[ void __cdecl FooTwo(void) ]
// file.cpp(21):
// Entering[ void __cdecl FooOne(void) ]
// Leaving[ FooOne ]
// Leaving[ FooTwo ]
//
//
// Now, it's also understandable that programmers who sprinkled func_guard()'s all over the place
// will not want to remove these calls before commiting a branch, just to have to put them back
// for the next feature they'll start. But on the other hand, if the output console is flooded with
// calls from all around the place, this tool loses it utility as the programmer will not be able
// to tell the function that he cares about from the noise. This is why the function guards can be
// turned on and off simply by declaring a category to which a guard belongs as enabled or disabled.
//
// For example:
//
// func_guard_enable_cat(foo); // enables the 'foo' category
// func_guard_disable_cat(bar); // disable the 'bar' category
//
// void FooOne()
// {
// func_guard(foo); // This guard is enabled.
// }
//
// void BarOne()
// {
// func_guard(bar); // This guard is disabled.
// }
//
// Right now (Nov 2009), the categories are mainly expected to match the files they're declared in one-to-one or
// one-to-many; i.e. In foo.cpp, you are expected to declare one or more guards to be used in that file only.
// However, there's a provision for categories that would span more that one file. The programmer would
// declare a category using func_guard_enable_cat(foo) or func_guard_disable_cat(foo) in one source file, and
// would be able to use that same category in another file using func_guard_import_cat(foo).
// This could be useful in case you have a few tightly coupled classes across a few files for which one would
// want to turn the tracing on or off by changing a single declaration instead of many.
//
// To be noted: in SHIPPING mode, the debug guards are simply compiled out. In all other cases, the guards will
// create a small object on the stack. The disabled ones simply won't output to the debug console.

#define func_guard_import_cat(cat) \
extern NppDebug::FuncGuard::State __func_guard_category_##cat
#define func_guard_enable_cat(cat) \
NppDebug::FuncGuard::State __func_guard_category_##cat = NppDebug::FuncGuard::Enabled
#define func_guard_disable_cat(cat) \
NppDebug::FuncGuard::State __func_guard_category_##cat = NppDebug::FuncGuard::Disabled
#define func_guard(cat) \
NppDebug::FuncGuard __npp_func_guard__( TEXT(__FUNCSIG__), \
TEXT(__FUNCTION__), \
TEXT(__FILE__), \
__LINE__, \
__func_guard_category_##cat, \
TEXT( #cat ))

// guard_debugf() acts just like debugf() described above, with the exception that it will indent the comment
// to match the current indentation of the function guards, if enabled. Otherwise, it will act just as a normal
// debugf().
//
// For example, given this:
//
// void FooOne()
// {
// func_guard(foo);
// int val = 42;
// guard_debugf("Hello World! My favorite number is %d\n", val);
// }
// void FooTwo()
// {
// func_guard(foo);
// // ...
// FooOne();
// }
//
// one would get the following output:
//
// file.cpp(42):
// Entering[ void __cdecl FooTwo(void) ]
// file.cpp(21):
// Entering[ void __cdecl FooOne(void) ]
// Hello World! My favorite number is 42
// Leaving[ FooOne ]
// Leaving[ FooTwo ]

#define guard_debugf(format, ...) \
/* JOCE: modify to make that a single call to OutputF (should make guard_debugf part of the function guard */ \
__npp_func_guard__.outputIndent(); \
NppDebug::outputF(format, __VA_ARGS__)

#else // if !SHIPPING

#define debugf(format, ...) void(0)
#define line_debugf(format, ...) void(0)
#define debugf(format, ...) void(0)
#define line_debugf(format, ...) void(0)

#define func_guard_declare_cat(cat) void(0)
#define func_guard_enable_cat(cat) void(0)
#define func_guard_disable_cat(cat) void(0)

#define func_guard_declare_cat(cat) void(0)
#define func_guard_enable_cat(cat) void(0)
#define func_guard_disable_cat(cat) void(0)
#define func_guard(cat) void(0)

#define func_guard(cat) void(0)
#define guard_debugf(format, ...) void(0)

#define guard_debugf(format, ...) void(0)
#endif // SHIPPING

#endif // NPP_DEBUG_H

0 comments on commit 9b0cc77

Please sign in to comment.