/*
 * Copyright Likewise Software
 * All rights reserved.
 *
 * 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; either version 2.1 of the license, or (at
 * your option) any later version.
 *
 * 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 program.  If
 * not, see <http://www.gnu.org/licenses/>.
 *
 * LIKEWISE SOFTWARE MAKES THIS SOFTWARE AVAILABLE UNDER OTHER LICENSING
 * TERMS AS WELL.  IF YOU HAVE ENTERED INTO A SEPARATE LICENSE AGREEMENT
 * WITH LIKEWISE SOFTWARE, THEN YOU MAY ELECT TO USE THE SOFTWARE UNDER THE
 * TERMS OF THAT SOFTWARE LICENSE AGREEMENT INSTEAD OF THE TERMS OF THE GNU
 * LESSER GENERAL PUBLIC LICENSE, NOTWITHSTANDING THE ABOVE NOTICE.  IF YOU
 * HAVE QUESTIONS, OR WISH TO REQUEST A COPY OF THE ALTERNATE LICENSING
 * TERMS OFFERED BY LIKEWISE SOFTWARE, PLEASE CONTACT LIKEWISE SOFTWARE AT
 * license@likewisesoftware.com
 */

/*
 * Copyright (C) Likewise Software. All rights reserved.
 *
 * Module Name:
 *
 *        assert.h
 *
 * Abstract:
 *
 *        Macros for assertions
 *
 * Authors
 *
 *        Brian Koropoff (bkoropoff@likewise.com)
 */

#ifndef __LW_ASSERT_H__
#define __LW_ASSERT_H__

#include <lw/attrs.h>

LW_BEGIN_EXTERN_C

/**
 * @file lw/assert.h
 * @brief Assertion macros
 */

/**
 * @defgroup assert Assertions
 * @brief Assertions macros
 *
 * This module contains macros for assertions within code.
 */

/*@{*/

/**
 * @brief Assert that invariant holds (with message)
 *
 * Asserts that @a Expr is true.  If it is not, the application will log a message and abort.
 * This variant takes an additional message that will be included with the diagnostic.
 *
 * @param[in] Expr The expression to evaluate.
 * @param[in] Msg An optional message string to include with the diagnostic.
 * @hideinitializer
 */
#define LW_RTL_ASSERT_MSG(Expr, Msg) \
    do                               \
    {                                \
        if (!(Expr))                 \
        {                            \
            __LwRtlAssertFailed(     \
                __FILE__,            \
                __LINE__,            \
                __FUNCTION__,        \
                #Expr,               \
                Msg);                \
        }                            \
    } while (0)

/**
 * @brief Assert that invariant holds
 *
 * Asserts that @a Expr is true.  If it is not, the application will log a message and abort.
 *
 * @param[in] Expr The expression to evaluate.
 * @hideinitializer
 */
#define LW_RTL_ASSERT(Expr) LW_RTL_ASSERT_MSG(Expr, NULL)

/**
 * @brief Assert that compile-time invariant holds
 *
 * Asserts that @a Expr is true at compile time.  If it is not, compilation will fail.
 *
 * @param[in] Name A name for the assertion which is a valid C identifier.
 * @param[in] Expr A C99 constant expression.
 * @hideinitializer
 */
#define LW_RTL_STATIC_ASSERT(Name, Expr) \
    typedef int __assert_##Name[(Expr)?1:-1]

#ifndef DOXYGEN
void
__LwRtlAssertFailed(
    const char* pFile,
    unsigned int Line,
    const char* pFunction,
    const char* pExpr,
    const char* pMessage
    ) __attribute__((noreturn));
#endif

/*@}*/

LW_END_EXTERN_C

#endif /* __LW_ASSERT_H__ */
