Location Macros (PB_LOC_***)

The following preprocessor macros are used to manage location information (filenames and line numbers) for the logging calls. The various forms work together to provide consistency when prototyping functions, expanding arguments, and passing variables. Paul Bunyan uses them internally, and since other developers have found them quite valuable for writing wrapper or helper functions, they are published for external consumption as part of the public API. They are not required for such work but using them tightens code and prevents future maintenance issues.


The PB_LOC_*** macros are used when calling functions that take in location information. They all use the PB_THIS_FILE macros to enable filename string pooling and are defined as follows:

#define PB_LOC    PB_THIS_FILE,    __LINE__
#define PB_LOCA    PB_THIS_FILEA,    __LINE__
#define PB_LOCW    PB_THIS_FILEW,    __LINE__


The PB_LOC_ARGS_*** macros are used in function prototypes and are defined as follows:

#define PB_LOC_ARGS    PCTSTR pszFile,    ULONG ulLine
#define PB_LOC_ARGSA    PCSTR pszFile,    ULONG ulLine
#define PB_LOC_ARGSW    PCWSTR pszFile,    ULONG ulLine


The PB_LOC_VARS macro is only used in the very special case of calling a function prototyped with one of the PB_LOC_ARGS*** macros from a function prototyped with same. Using the PB_LOC_VARS macro in function calls maintains consistency with variable names and calling orders and helps avoid getting spanked if things change in some future version.

#define PB_LOC_VARS    pszFile,    ulLine


This example demonstrates a small helper function that logs from the location it was called from.

VOID Helper(PB_LOC_ARGS, ULONG ulMsgType, INT iArg1, PCTSTR pszArg2)
    if (SomeOtherFunction(iArg1, pszArg2) == FALSE)
        PBLog(PB_LOC_VARS, ulMsgType, _T("SomeOtherFunction(%d,%s) == FALSE"), iArg1, pszArg2);

The function can then be called as:

Helper(PB_ERROR, 7, “Seven”);


Helper(PB_LOC, _PB_ERROR, 7, “Seven”);

Note, the reason ulMsgType is passed in (in addition to the location arguments) instead of hardcoding it to _PB_ERROR or something is because there may be times when the caller knows the function may fail and doesn't care (like tests for the existence of environment variables or registry keys). This allows them to simply pass in _PB_NOSOUND instead of requiring them to pass in some blLoggingEnabled indicator or CPBLogger object etc. The same also applies where the caller wants to assert that failure of the function is actually a bug rather than simply an error (maybe it’s part of an installation verification routine) and would in this case prefer to pass in _PB_BUG instead of using a hardcoded _PB_ERROR.