/**
 * @file
 * @brief __syslog__: control system log
 * @copyright (C) 2012-2019, Samsung Electronics Co., Ltd.
**/

#pragma once

#ifdef __cplusplus
extern "C" {
#endif

#include <dso_defs.h>
#include <compiler.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>

enum {
    LOG_CRIT,
    LOG_ERR,
    LOG_WARNING,
    LOG_NOTICE,
    LOG_INFO,
    LOG_DEBUG,
};

#define LOG_PID     (1 << 0)

DSO_EXPORT
int ksyslog(int priority, const void *data, unsigned long size);

DSO_EXPORT
void syslog(int priority, const char *format, ...) __attribute__((__format__(__printf__, 2, 3)));

DSO_EXPORT
void vsyslog(int priority, const char *format, va_list ap) __attribute__((__format__(__printf__, 2, 0)));

DSO_EXPORT
void openlog(const char *ident, int option, int facility);

DSO_EXPORT
void closelog(void);

#define __SYSLOG_LOG_ERR__(FORMAT, ...)        __syslog__(LOG_ERR, FORMAT, ##__VA_ARGS__)
#define __VSYSLOG_LOG_ERR__(FORMAT, AP)        __vsyslog__(LOG_ERR, FORMAT, AP)

#define __SYSLOG_LOG_NOTICE__(FORMAT, ...)     __syslog__(LOG_NOTICE, FORMAT, ##__VA_ARGS__)
#define __VSYSLOG_LOG_NOTICE__(FORMAT, AP)     __vsyslog__(LOG_NOTICE, FORMAT, AP)

#define __SYSLOG_LOG_WARNING__(FORMAT, ...)    __syslog__(LOG_WARNING, FORMAT, ##__VA_ARGS__)
#define __VSYSLOG_LOG_WARNING__(FORMAT, AP)    __vsyslog__(LOG_WARNING, FORMAT, AP)

#ifdef CONFIG_SYSLOG_INFO
#  define __SYSLOG_LOG_INFO__(FORMAT, ...)      __syslog__(LOG_INFO, FORMAT, ##__VA_ARGS__)
#  define __VSYSLOG_LOG_INFO__(FORMAT, AP)      __vsyslog__(LOG_INFO, FORMAT, AP)
#else /* !CONFIG_SYSLOG_INFO */
#  define __SYSLOG_LOG_INFO__(FORMAT, ...)      __syslog_stub__(LOG_INFO, FORMAT, ##__VA_ARGS__)
#  define __VSYSLOG_LOG_INFO__(FORMAT, ...)     __vsyslog_stub__(LOG_INFO, FORMAT, ##__VA_ARGS__)
#endif /* CONFIG_SYSLOG_INFO */

#ifdef CONFIG_SYSLOG_DEBUG
#  define __SYSLOG_LOG_DEBUG__(FORMAT, ...)     __syslog__(LOG_DEBUG, FORMAT, ##__VA_ARGS__)
#  define __VSYSLOG_LOG_DEBUG__(FORMAT, AP)     __vsyslog__(LOG_DEBUG, FORMAT, AP)
#else /* !CONFIG_SYSLOG_DEBUG */
#  define __SYSLOG_LOG_DEBUG__(FORMAT, ...)     __syslog_stub__(LOG_DEBUG, FORMAT, ##__VA_ARGS__)
#  define __VSYSLOG_LOG_DEBUG__(FORMAT, ...)    __vsyslog_stub__(LOG_DEBUG, FORMAT, ##__VA_ARGS__)
#endif /* CONFIG_SYSLOG_DEBUG */

#ifdef CONFIG_SYSLOG_EXTRA
#  define __SYSLOG_ROUTINE__    __func__
#  define __SYSLOG_FILE__       __FILE__
#  define __SYSLOG_LINE__       __LINE__
#else
#  define __SYSLOG_ROUTINE__    NULL
#  define __SYSLOG_FILE__       NULL
#  define __SYSLOG_LINE__       (-1)
#endif

static _printflike_(2, 3) _always_inline_ _pure_ _unused_
void __syslog_stub__(int priority, const char *format, ...)
{
    (void)priority;
    (void)format;
}

static _printflike_(2, 0) _always_inline_ _pure_ _unused_
void __vsyslog_stub__(int priority, const char *format, va_list ap)
{
    (void)priority;
    (void)format;
    (void)ap;
}

DSO_EXPORT _printflike_(5, 6)
void __syslog__(const char *function, const char *file, int line,
        int priority, const char *format, ...);

DSO_EXPORT _printflike_(5, 0)
void __vsyslog__(const char *function, const char *file, int line,
        int priority, const char *format, va_list ap);

#define __syslog__(PRIORITY, FORMAT, ...) \
    __syslog__(__SYSLOG_ROUTINE__, __SYSLOG_FILE__, __SYSLOG_LINE__, PRIORITY, FORMAT, ##__VA_ARGS__)

#define __vsyslog__(PRIORITY, FORMAT, VA_LIST) \
    __vsyslog__(__SYSLOG_ROUTINE__, __SYSLOG_FILE__, __SYSLOG_LINE__, (FORMAT), VA_LIST)

#define syslog(PRIORITY, FORMAT, ...)             __SYSLOG_##PRIORITY##__((FORMAT), ##__VA_ARGS__)
#define vsyslog(PRIORITY, FORMAT, VA_LIST)        __VSYSLOG_##PRIORITY##__((FORMAT), VA_LIST)

#ifdef __cplusplus
} /* extern "C" */
#endif
