root/usr/src/cmd/sendmail/include/sm/debug.h
/*
 * Copyright (c) 2000, 2001, 2003 Sendmail, Inc. and its suppliers.
 *      All rights reserved.
 *
 * By using this file, you agree to the terms and conditions set
 * forth in the LICENSE file which can be found at the top level of
 * the sendmail distribution.
 *
 *      $Id: debug.h,v 1.16 2003/01/10 00:26:06 ca Exp $
 */

/*
**  libsm debugging and tracing
**  See libsm/debug.html for documentation.
*/

#ifndef SM_DEBUG_H
# define SM_DEBUG_H

# include <sm/gen.h>
# include <sm/io.h>

/*
**  abstractions for printing trace messages
*/

extern SM_FILE_T *
sm_debug_file __P((void));

extern void
sm_debug_setfile __P(( SM_FILE_T *));

extern void PRINTFLIKE(1, 2)
sm_dprintf __P((char *_fmt, ...));

extern void
sm_dflush __P((void));

extern void
sm_debug_close __P((void));

/*
**  abstractions for setting and testing debug activation levels
*/

extern void
sm_debug_addsettings_x __P((const char *));

extern void
sm_debug_addsetting_x __P((const char *, int));

# define SM_DEBUG_UNKNOWN       ((SM_ATOMIC_UINT_T)(-1))

extern const char SmDebugMagic[];

typedef struct sm_debug SM_DEBUG_T;
struct sm_debug
{
        const char *sm_magic;   /* points to SmDebugMagic */

        /*
        **  debug_level is the activation level of this debug
        **  object.  Level 0 means no debug activity.
        **  It is initialized to SM_DEBUG_UNKNOWN, which indicates
        **  that the true value is unknown.  If debug_level ==
        **  SM_DEBUG_UNKNOWN, then the access functions will look up
        **  its true value in the internal table of debug settings.
        */

        SM_ATOMIC_UINT_T debug_level;

        /*
        **  debug_name is the name used to reference this SM_DEBUG
        **  structure via the sendmail -d option.
        */

        char *debug_name;

        /*
        **  debug_desc is a literal character string of the form
        **  "@(#)$Debug: <name> - <short description> $"
        */

        char *debug_desc;

        /*
        **  We keep a linked list of initialized SM_DEBUG structures
        **  so that when sm_debug_addsetting is called, we can reset
        **  them all back to the uninitialized state.
        */

        SM_DEBUG_T *debug_next;
};

# ifndef SM_DEBUG_CHECK
#  define SM_DEBUG_CHECK 1
# endif /* ! SM_DEBUG_CHECK */

# if SM_DEBUG_CHECK
/*
**  This macro is cleverly designed so that if the debug object is below
**  the specified level, then the only overhead is a single comparison
**  (except for the first time this macro is invoked).
*/

#  define sm_debug_active(debug, level) \
            ((debug)->debug_level >= (level) && \
             ((debug)->debug_level != SM_DEBUG_UNKNOWN || \
              sm_debug_loadactive(debug, level)))

#  define sm_debug_level(debug) \
            ((debug)->debug_level == SM_DEBUG_UNKNOWN \
             ? sm_debug_loadlevel(debug) : (debug)->debug_level)

#  define sm_debug_unknown(debug) ((debug)->debug_level == SM_DEBUG_UNKNOWN)
# else /* SM_DEBUG_CHECK */
#  define sm_debug_active(debug, level) 0
#  define sm_debug_level(debug)         0
#  define sm_debug_unknown(debug)       0
# endif /* SM_DEBUG_CHECK */

extern bool
sm_debug_loadactive __P((SM_DEBUG_T *, int));

extern int
sm_debug_loadlevel __P((SM_DEBUG_T *));

# define SM_DEBUG_INITIALIZER(name, desc) { \
                SmDebugMagic, \
                SM_DEBUG_UNKNOWN, \
                name, \
                desc, \
                NULL}

#endif /* ! SM_DEBUG_H */