#ifndef PHSTBDBG_H
#define PHSTBDBG_H


/*****************************************************************************/
/* Copyright (c) 2009 NXP B.V.                                               */
/*                                                                           */
/* This library is free software; you can redistribute it and/or             */
/* modify it under the terms of the GNU Lesser General Public                */
/* License as published by the Free Software Foundation, using               */
/* version 2.1 of the License.                                               */
/*                                                                           */
/* This library is distributed in the hope that it will be useful,           */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU          */
/* Lesser General Public License for more details.                           */
/*                                                                           */
/* You should have received a copy of the GNU Lesser General Public          */
/* License along with this library; if not, write to the Free Software       */
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA   */
/*                                                                           */
/*****************************************************************************/
/**
    @file   phStbDbg.h
    @brief  Debug/trace/assert facility.

    This is a cutdown version of tmDbg with some extensions.

@b  Component:  phStbDbg.

*//*

Rev Date        Author      Comments
--------------------------------------------------------------------------------
 20 20070314    batelaan    Add DBG_UNREGISTER_MODULE in all modes.
 21 20070404    batelaan    Add missing DBG_ATTACH/DETACH macros for non-trace modes.
 22 20070926    batelaan    Portability fixes.
 23 20071002    batelaan    Portability enhancements
23.1.1 20071017 barnish     reduce qac warnings
 24 20071016    batelaan    WinCE port; undo v23.1.1 change
24.1.1 20071024 barnish     Make default debug unit DBG_ROOT instead of NULL (for QAC)
 25 20071023    batelaan    Usermode WinCE port
 26 20071025    batelaan    Merge
 27 20071120    F.Raiyat    Qmore-ing
 28 20071218    Hutchinson  WinCE porting
 29 20080206    batelaan    Update file copyright/license text
 30 20080815    batelaan    Make DBG_INIT in kmode a no-op.
 31 20081106    batelaan    Add DBG_KEY_* macros.
 32 20081210    batelaan    Add DBG_PRINT_CHECK to be also available if TMDBG_PRINTS_ARE_ENABLED is false.
 33 20090120    batelaan    Update file copyright/license text
--------------------------------------------------------------------------------
    For consistency and standardisation retain the Section Separators.
*/

/* On TriMedia we use the standard tmDbg library, otherwise we use our own reduced
   functionality macros defined inside this file. */
#ifdef __TCS__
#include <tmDbg.h>
#else

#include <phStbCommon.h>
#include <tmFlags.h>

#if TMFL_MODE_KERNEL && TMFL_OS_IS_LINUX
  #include <linux/module.h>
#endif

#ifdef __cplusplus
extern "C"
{
#endif

/** Linux device name used by this module for controlling DBG settings. */
#define PH_STBDBG_DEVNAME "phdbg"

/* These are the flags that are used for the units
 * need to be defined in a separate header file and based on
 * DBG_CUSTOM_START. */
#define DBG_DEFAULT             0x0001u
#define DBG_STATE               0x0002u
#define DBG_EVENTIN             0x0004u
#define DBG_EVENTOUT            0x0008u
#define DBG_INTERFACE_ENTER     0x0010u
#define DBG_INTERFACE_LEAVE     0x0020u
#define DBG_INTERNAL_ENTER      0x0040u
#define DBG_INTERNAL_LEAVE      0x0080u
/* Intentionally placed here, to let level 1 start at a good location
   (while 1 is taken by default). */
#define DBG_LEVEL_1             0x0100u
#define DBG_LEVEL_2             0x0200u
#define DBG_LEVEL_3             0x0400u
#define DBG_LEVEL_4             0x0800u
#define DBG_LEVEL_5             0x1000u
#define DBG_EXTERNAL_CALL       0x2000u
#define DBG_EXTERNAL_RETURN     0x4000u
#define DBG_WARNING             0x8000u
#define DBG_CUSTOM_START    0x00010000u
#define DBG_LEVEL_1_AND_BELOW   0x0100u
#define DBG_LEVEL_2_AND_BELOW   0x0300u
#define DBG_LEVEL_3_AND_BELOW   0x0700u
#define DBG_LEVEL_4_AND_BELOW   0x0f00u
#define DBG_LEVEL_5_AND_BELOW   0x1f00u
#define DBG_ALL_FLAGS       0xffffffffu
#define DBG_NO_FLAGS        0x00000000u

/*!
 *  Activate this macro to enable local debugging flags for each module.
 *  The debugging flags aren't shared with the phStbDbg driver in that case.
 *  Only needed if performance is bad because of debugging.
 *
 */
#define DBG_LOCAL_FLAGS_ENABLE 0

#if DBG_LOCAL_FLAGS_ENABLE
#define DBG_ROOT                (gphStbDbg_DbgUnit)
#else
#define DBG_ROOT                (phStbDbg_DbgUnit())
#endif

/******************************************************************************/
/* COMMON */
/******************************************************************************/

/******************************************************************************/
/* MODES */
/******************************************************************************/

#if (!defined(DBG_DISABLE_ALL) && \
    ((defined(DBG_ENABLE_ALL)) || \
    (defined(TMFL_REL_DEBUG) && (TMFL_REL == TMFL_REL_DEBUG)) ||\
    (defined(TMFL_REL_TRACE) && (TMFL_REL == TMFL_REL_TRACE))))
/* If DBG_DISABLE_ALL is defined, all debug macros for the current
 * file are disabled (as if it were compiled for release). This is
 * a convenient way to disable the debug library for certain files.
 * If DBG_ENABLE_ALL is defined, all macros are enabled. This is a
 * convinient way to include debug statements even when not building
 * in debug mode. */
/***************************/
/* TRACE AND DEBUG SECTION */
/***************************/

#define TMDBG_PRINTS_ARE_ENABLED 1
#define TMDBG_ASSERTS_ARE_ENABLED 1

#elif (defined(DBG_ENABLE_ASSERTS)) || (TMFL_REL == TMFL_REL_ASSERT) || \
    ((TMFL_REL == TMFL_REL_RETAIL) && (!defined(NDEBUG)))

/* If DBG_ENABLE_ASSERTS is defined, only DBG_INIT, DBG_UNINIT, DBG_ASSERT,
 * DBG_ASSERT2, and DBG_DETECT_ERROR are defined. This is a good way to reduce
 * the amount of debug overhead, while maintaining the protection the assert
 * statements offer. */
/******************/
/* ASSERT SECTION */
/******************/

#define TMDBG_PRINTS_ARE_ENABLED 0
#define TMDBG_ASSERTS_ARE_ENABLED 1

#else

/* The release version of the header file. Most macros
 * translate to nothing, except the ones that are used in
 * an expression. */
/******************/
/* RETAIL SECTION */
/******************/

#define TMDBG_PRINTS_ARE_ENABLED 0
#define TMDBG_ASSERTS_ARE_ENABLED 0

#endif

#if (TMDBG_PRINTS_ARE_ENABLED || TMDBG_ASSERTS_ARE_ENABLED) && !(TMFL_MODE_KERNEL && TMFL_OS_IS_LINUX)
#define DBG_INIT()                              \
    tmDbg_Init();
extern Void tmDbg_Init(Void);

#else /* (TMDBG_PRINTS_ARE_ENABLED || TMDBG_ASSERTS_ARE_ENABLED) && !(TMFL_MODE_KERNEL && TMFL_OS_IS_LINUX) */
#define DBG_INIT()
#endif


#if TMDBG_PRINTS_ARE_ENABLED
#  if !TMFL_OS_IS_CE
typedef struct tmDbgUnit {
    /** Debug flags for this unit. Since this structure can set in memory-mapped
        memory, modifiable by other processes we declare it as volatile.
        That should reduce QAC warnings. */
    volatile UInt32 flgs;
    Char name[1];
} tmDbgUnit_t;
#  else // TMFL_OS_IS_CE
#define PH_STBDBG_UNITNAME_LENGTH   24
typedef struct tmDbgUnit {
    UInt32 flgs;
    UInt32 lookupIndex;                     //!< array index for quick response in Get/SetFlags
    Char name[ PH_STBDBG_UNITNAME_LENGTH ]; //!< reserve reasonable amount to make it easier to handle
} tmDbgUnit_t;
#  endif
typedef tmDbgUnit_t *ptmDbgUnit_t;
/** Returns the #DGB_ROOT instance. */
extern ptmDbgUnit_t phStbDbg_DbgUnit(void);

/** Returns true if debug unit has the flags set.
    If the uid is NULL then always return true. Also checks if any of the flags
    are set in the DBG_ROOT unit.
    If #TMDBG_PRINTS_ARE_ENABLED is 0, then this macro always evaluates to (0 == 1).
*/
#define DBG_PRINT_CHECK(uid, flags)  \
    (((uid) == NULL) || (((flags) & (((DBG_ROOT->flgs)) | ((uid)->flgs))) != 0U))

#if TMFL_MODE_KERNEL && TMFL_OS_IS_LINUX
  #define __DBG_EXPORT(uid) EXPORT_SYMBOL(uid)
#else
  #define __DBG_EXPORT(uid)
#endif

#define DBG_UNIT(uid)           DBG_UNIT_PARAM(uid); __DBG_EXPORT(uid)
#define DBG_UNIT_STATIC(uid)    static DBG_UNIT_PARAM(uid)
#define DBG_UNIT_EXTERN(uid)    extern DBG_UNIT_PARAM(uid)
#define DBG_UNIT_PARAM(uid)     ptmDbgUnit_t uid
#define DBG_UNIT_AS_PARAM(uid)  (uid)

DBG_UNIT_EXTERN(gphStbDbg_DbgUnit);

#define DBG_IS_UNKNOWN(uid) \
    ( (uid) == Null )

#define DBG_REGISTER_MODULE(uid, __name)                        \
    tmDbg_RegisterModule( &(uid), __name )
#define DBG_UNREGISTER_MODULE(uid) do{}while(0)

extern Void
tmDbg_RegisterModule(
    ptmDbgUnit_t          * ppUnit,     // O: The registered debug unit will be
                                        //    stored here.
    const Char*             pUnitName   // I: A pointer to the name or GUID.
    );


#define DBG_ATTACH_MODULE(uid, name, prereg)    \
    DBG_REGISTER_MODULE(uid, name)

#define DBG_ATTACH_COMPONENT(uid, type, name, prereg) \
    DBG_REGISTER_MODULE(uid, name)


#define DBG_DETACH_MODULE(uid) \
    do{ (uid) = NULL; }while(0)

#define DBG_DETACH_COMPONENT(uid) \
    do{ (uid) = NULL; }while(0)


extern Void tmDbg_Print(ptmDbgUnit_t uid, UInt32 flags, Char *fmt, ...);

#define DBG_PRINT(param)                        \
    do{ tmDbg_Print param; }while(0)

#define DBG_PRINT0(uid, flags, message)         \
    do{                                         \
        if ( DBG_PRINT_CHECK(uid, flags) )      \
        {                                       \
            tmDbg_Print( uid, flags, message ); \
        }                                       \
    }while(0)

#define DBG_PRINT1(uid, flags, message, p1)         \
    do{                                             \
        if ( DBG_PRINT_CHECK(uid, flags) )          \
        {                                           \
            tmDbg_Print( uid, flags, message, p1 ); \
        }                                           \
    }while(0)

#define DBG_PRINT2(uid, flags, message, p1, p2)                 \
    do{                                             \
        if ( DBG_PRINT_CHECK(uid, flags) )  \
        {                                   \
            tmDbg_Print( uid, flags, message, p1, p2 );          \
        }                                   \
    }while(0)

#define DBG_PRINT3(uid, flags, message, p1, p2, p3)             \
    do{                                             \
        if ( DBG_PRINT_CHECK(uid, flags) )  \
        {                                   \
            tmDbg_Print( uid, flags, message, p1, p2, p3 );          \
        }                                   \
    }while(0)

#define DBG_PRINT4(uid, flags, message, p1, p2, p3, p4)             \
    do{                                             \
        if ( DBG_PRINT_CHECK(uid, flags) )  \
        {                                   \
            tmDbg_Print( uid, flags, message, p1, p2, p3, p4 );      \
        }                                   \
    }while(0)

#define DBG_PRINT5(uid, flags, message, p1, p2, p3, p4, p5)         \
    do{                                             \
        if ( DBG_PRINT_CHECK(uid, flags) )  \
        {                                   \
            tmDbg_Print( uid, flags, message, p1, p2, p3, p4, p5 );      \
        }                                   \
    }while(0)

#define DBG_PRINT6(uid, flags, message, p1, p2, p3, p4, p5, p6)         \
    do{                                             \
        if ( DBG_PRINT_CHECK(uid, flags) )  \
        {                                   \
            tmDbg_Print( uid, flags, message, p1, p2, p3, p4, p5, p6 );  \
        }                                   \
    }while(0)

#define DBG_PRINT7(uid, flags, message, p1, p2, p3, p4, p5, p6, p7)     \
    do{                                             \
        if ( DBG_PRINT_CHECK(uid, flags) )  \
        {                                   \
            tmDbg_Print( uid, flags, message, p1, p2, p3, p4, p5, p6, p7 );  \
        }                                   \
    }while(0)

#define DBG_PRINT8(uid, flags, message, p1, p2, p3, p4, p5, p6, p7, p8)     \
    do{                                             \
        if ( DBG_PRINT_CHECK(uid, flags) )  \
        {                                   \
            tmDbg_Print( uid, flags, message, p1, p2, p3, p4, p5, p6, p7, p8 );\
        }                                   \
    }while(0)

#define DBG_PRINT9(uid, flags, message, p1, p2, p3, p4, p5, p6, p7, p8, p9) \
    do{                                             \
        if ( DBG_PRINT_CHECK(uid, flags) )  \
        {                                   \
            tmDbg_Print( uid, flags, message, p1, p2, p3, p4, p5, p6, p7, p8, p9 );\
        }                                   \
    }while(0)

/* QAC message 3356 mentions 'this condition is always false.
   We need to repeat the pragma for every macro that uses a submacro
   which causes the message! Doh!
*/
#ifdef QAC
#pragma PRQA_MACRO_MESSAGES_OFF "DBG_SET_FLAGS",3356
#pragma PRQA_MACRO_MESSAGES_OFF "tmDbg_SetFlags",3356
#pragma PRQA_MACRO_MESSAGES_OFF "DBG_GET_FLAGS",3356
#pragma PRQA_MACRO_MESSAGES_OFF "tmDbg_GetFlags",3356
#pragma PRQA_MACRO_MESSAGES_OFF "DBG_ENABLE_FLAGS",3356
#pragma PRQA_MACRO_MESSAGES_OFF "DBG_DISABLE_FLAGS",3356
#endif

#define DBG_SET_FLAGS(uid, flags) \
    tmDbg_SetFlags((uid), (flags))
#define DBG_GET_FLAGS(uid, flags)               \
    do{ flags = tmDbg_GetFlags((uid));} while(0)

#define DBG_ENABLE_FLAGS(uid, flags)        \
    do{tmDbg_SetFlags((uid), tmDbg_GetFlags((uid)) | (flags) );}while(0)

#define DBG_DISABLE_FLAGS(uid, flags)       \
    do{tmDbg_SetFlags((uid), tmDbg_GetFlags((uid)) & ~(flags) );}while(0)

#if TMFL_OS_IS_CE && !TMFL_MODE_KERNEL
    /* CE usermode implements these as functions. */
    void tmDbg_SetFlags( ptmDbgUnit_t uid, UInt32 flags );
    UInt32 tmDbg_GetFlags( ptmDbgUnit_t uid );
#else
#   define tmDbg_SetFlags(uid, flags) do { if ((uid) != NULL) { (uid)->flgs = (flags); }} while (0)
#   define tmDbg_GetFlags(uid) (((uid) == NULL) ? DBG_ALL_FLAGS : ((uid)->flgs))
#endif

#else
   /* debug prints are off */
#define DBG_PRINT_CHECK(uid, flags) (0 == 1)
#define DBG_UNIT(uid)
#define DBG_UNIT_EXTERN(uid)
#define DBG_UNIT_STATIC(uid)
#define DBG_UNIT_PARAM(uid)     Int uid
#define DBG_UNIT_AS_PARAM(uid)  0

#define DBG_IS_UNKNOWN(uid)     0

#define DBG_REGISTER_MODULE(uid, name) do{}while(0)
#define DBG_UNREGISTER_MODULE(uid) do{}while(0)
#define DBG_ATTACH_MODULE(uid, name, prereg) do{}while(0)
#define DBG_ATTACH_COMPONENT(uid, type, name, prereg) do{}while(0)
#define DBG_DETACH_MODULE(uid) do{}while(0)
#define DBG_DETACH_COMPONENT(uid) do{}while(0)

#define DBG_PRINT(param)
#define DBG_PRINT0(uid, flags, message) do{}while(0)
#define DBG_PRINT1(uid, flags, message, p1) do{}while(0)
#define DBG_PRINT2(uid, flags, message, p1, p2) do{}while(0)
#define DBG_PRINT3(uid, flags, message, p1, p2, p3) do{}while(0)
#define DBG_PRINT4(uid, flags, message, p1, p2, p3, p4) do{}while(0)
#define DBG_PRINT5(uid, flags, message, p1, p2, p3, p4, p5) do{}while(0)
#define DBG_PRINT6(uid, flags, message, p1, p2, p3, p4, p5, p6)  do{}while(0)
#define DBG_PRINT7(uid, flags, message, p1, p2, p3, p4, p5, p6, p7) do{}while(0)
#define DBG_PRINT8(uid, flags, message, p1, p2, p3, p4, p5, p6, p7, p8) do{}while(0)
#define DBG_PRINT9(uid, flags, message, p1, p2, p3, p4, p5, p6, p7, p8, p9) do{}while(0)

#define DBG_AGGREGATE_LINK(puid, chuid) do{}while(0)
#define DBG_SET_FLAGS(uid, flags) do{}while(0)
#define DBG_GET_FLAGS(uid, flags)   do{ flags = 0; }while(0)
#define DBG_ENABLE_FLAGS(uid, flags) do{}while(0)
#define DBG_DISABLE_FLAGS(uid, flags) do{}while(0)

#endif

#if TMDBG_ASSERTS_ARE_ENABLED


/* Note that message should include brackets,
    e.g.    DBG_ASSERT_ALWAYS(("Bad things happened"));
    or      DBG_ASSERT_ALWAYS(("More than %d bad things happened",numBadThings));
*/
#define DBG_ASSERT_ALWAYS(message)                                          \
        tmDbg_AssertError( "false", __FILE__, __LINE__,                     \
                           tmDbg_StrAssertFormat message)

#define DBG_ASSERT(assertion)                                               \
    do{                                                                     \
        if (!(assertion))                                                   \
        {                                                                   \
            tmDbg_AssertError( #assertion, __FILE__, __LINE__,              \
                               0);                                          \
        }                                                                   \
    }while(0)

#define DBG_ASSERT2(assertion, message)                                     \
    do{                                                                     \
        if (!(assertion))                                                   \
        {                                                                   \
            tmDbg_AssertError( #assertion, __FILE__, __LINE__,              \
                               tmDbg_StrAssertFormat message);              \
        }                                                                   \
    }while(0)

extern Void tmDbg_AssertError(
    const Char *assertion,
    const Char *file,
    UInt line,
    const Char *msg);
#ifdef QAC
#pragma PRQA_NO_RETURN tmDbg_AssertError
#endif

extern Char *tmDbg_StrAssertFormat(Char *fmt, ...);

#else  /* !TMDBG_ASSERTS_ARE_ENABLED */
#define DBG_ASSERT_ALWAYS(message)      do{}while(0)
#define DBG_ASSERT(assertion)           do{}while(0)
#define DBG_ASSERT2(assertion, message) do{}while(0)
#endif

/** Calls to DBG_CHK, DBG_ERR_CHK & DBG_ERR_DEPART do not include
    the debug unit ID or the warning level. These are set in the following defines.
    These should be undef'd and then redefined appropriately in your module */
/** default level */
#define DBG_MY_CHK_LEVEL   DBG_WARNING
/** default unit ID */
#define DBG_MY_UNIT        ((ptmDbgUnit_t)DBG_ROOT)

/******************************************************************************/
/** Runs the given C_expression.
    If (expected != C_expression)
        Prints error message: Filename:line- expected, result, C_expression & msg.

    @param expected     @b IN  Expected (good) result of the expression.
    @param C_expression @b IN  Any valid C expression.
    @param msg          @b IN  An extra message string (with no arguments)

    @retval void
    @note               @See DBG_MY_CHK_LEVEL  @See DBG_MY_UNIT
*/
#define DBG_CHK(expected, C_expression, msg)   \
{\
    void * xXxX = (void *)(C_expression);\
    if ((void *)(expected) != xXxX)\
    {\
        DBG_PRINT6(DBG_MY_UNIT, DBG_MY_CHK_LEVEL, "ERROR: %s:%d- Expect=0x%X, Got=0x%X, From: %s --- %s\n",\
                   __FILE__, __LINE__, (unsigned int)(expected), (unsigned int)xXxX, #C_expression, (msg)); \
    }\
}

/******************************************************************************/
/** Runs the given C_expression which is typically of type tmErrorCode_t (or int).
    Puts the result in err, a variable which you MUST define (in scope) and typically
    of type tmErrorCode_t (or int).
    If (expected != C_expression)
        Prints error message: Filename:line- expected, result, C_expression & msg.

    @param expected     @b IN  Expected (good) result of the expression.
    @param C_expression @b IN  Any valid C expression.
    @param msg          @b IN  An extra message string (with no arguments)

    @retval void
    @note               @See DBG_MY_CHK_LEVEL  @See DBG_MY_UNIT
*/
#define DBG_ERR_CHK(expected, C_expression, msg)   \
    err = (tmErrorCode_t)(C_expression);  \
    if ((int)err != (int)(expected)) \
    {\
        DBG_PRINT6(DBG_MY_UNIT, DBG_MY_CHK_LEVEL, "ERROR: %s:%d- Expect=0x%X, Got=0x%X, From: %s --- %s\n",\
                  __FILE__, __LINE__, (unsigned int)(expected), (unsigned int)err, #C_expression, (msg)); \
    }


/******************************************************************************/
/** Runs the given C_expression which is typically of type tmErrorCode_t (or int).
    Puts the result in err, a variable which you MUST define (in scope) and typically
    of type tmErrorCode_t (or int).
    If (expected != C_expression)
        Prints error message: Filename:line- expected, result, C_expression & msg.
        And jumps to DEPARTURES (a label you MUST define in scope & typically towards
        the end of your function.

    @param expected     @b IN  Expected (good) result of the expression.
    @param C_expression @b IN  Any valid C expression.
    @param msg          @b IN  An extra message string (with no arguments)

    @retval void
    @note               @See DBG_MY_CHK_LEVEL  @See DBG_MY_UNIT
                        Don't forget DEPARTURES
*/
#define DBG_ERR_DEPART(expected, C_expression, msg)   \
    err = (tmErrorCode_t)(C_expression);  \
    if ((int)err != (int)(expected)) \
    {\
        DBG_PRINT6(DBG_MY_UNIT, DBG_MY_CHK_LEVEL, "ERROR & DEPART: %s:%d- Expect=0x%X, Got=0x%X, From: %s --- %s\n", \
                  __FILE__, __LINE__, (unsigned int)(expected), (unsigned int)err, #C_expression, (msg)); \
        goto DEPARTURES; \
    }

/******************************************************************************/
/** Set debug key to a new value.
    @param _key @b IN Key name. Can be a path,
    e.g. "a/b". Optionally may start with a "/" character.
    @param _value @b IN New string key value.
    String should be max DBG_KEY_MAX_LEN bytes, including terminating NUL.
    If the string is too long, it is silently truncated.
    A copy of the string is taken.
*/
#define DBG_KEY_SET(_key, _value)               \
    do { (void)tmDbg_KeySet((_key), (_value)); } while (0)
extern tmErrorCode_t tmDbg_KeySet(
    const char *key,
    const char *value);

/******************************************************************************/
/** Return the value of a debug key.
    @param _key @b IN Key name. Can be a path,
    e.g. "a/b". Optionally may start with a "/" character.
    @param _valueStorage @b OUT String key value.
    String can be max DBG_KEY_MAX_LEN bytes, including terminating NUL.
    @return String key value or NULL if no value (or NULL) has been
    set for the key.
*/
#define DBG_KEY_GET(_key, _valueStorage)               \
    tmDbg_KeyGet((_key), (_valueStorage))
extern tmErrorCode_t tmDbg_KeyGet(
    const char *key,
    char *valueStorage);

/******************************************************************************/
/** Return the next key and value of a debug key.
    @param _key @b INOUT Key name. Can be a path,
    e.g. "a/b". Optionally may start with a "/" character.
    Use an empty string to start an iteration from the root of the tree.
    String can be max DBG_KEY_MAX_LEN bytes, including terminating NUL.
    @param _valueStorage @b OUT String key value.
    String can be max DBG_KEY_MAX_LEN bytes, including terminating NUL.
    @return String key name, or NULL if starting key was not found,
    or there is no next key left.
*/
#define DBG_KEY_NEXT(_keyStorage, _valueStorage)   \
    tmDbg_KeyNext((_keyStorage), (_valueStorage))
extern tmErrorCode_t tmDbg_KeyNext(
    char *keyStorage,
    char *valueStorage);

/******************************************************************************/
/** Maximum number of bytes in a key or value,
    including the terminating null character.
    @see DBG_KEY_SET DBG_KEY_GET DBG_KEY_NEXT
*/
#define DBG_KEY_MAX_LEN 256

/******************************************************************************/
#if defined(__cplusplus)
}
#endif

#endif /* __linux__ */

#endif /* PHSTBDBG_H */
