--- /dev/null
+/*
+ * Copyright (c) 2013, TOYOTA MOTOR CORPORATION.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+/*========================================================================*/
+/**
+ * @file ico_log.h
+ *
+ * @brief debug log function
+ */
+/*========================================================================*/
+#ifndef __ICO_LOG_H__
+#define __ICO_LOG_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef ICO_LOG_STDOUT
+#define ICO_LOG_STDOUT 0
+ /**!< Log output to stdout(=1) or file(=0) */
+#endif /*ICO_APF_LOG_STDOUT*/
+
+#define ICO_LOG_DIR "/var/log/ico"
+ /**!< Directory name of Log destination */
+
+/* Maximum lines/files */
+#define ICO_LOG_MAXLINES 10000
+ /**!< Maximum output lines of log file */
+#define ICO_LOG_MAXFILES 6
+ /**!< Maximum number of the log file */
+
+/* Log output level */
+#define ICO_LOG_DEBUG 0x0080 /**!< Debug write */
+#define ICO_LOG_INFO 0x0040 /**!< Information */
+#define ICO_LOG_WARNING 0x0010 /**!< Warning */
+#define ICO_LOG_CRITICAL 0x0008 /**!< Critical */
+#define ICO_LOG_ERROR 0x0004 /**!< Error */
+
+/* Log output flush */
+#define ICO_LOG_FLUSH 0x4000 /**!< Log outout with log flush */
+#define ICO_LOG_NOFLUSH 0x2000 /**!< Log output without log flush */
+
+#define ICO_TRA(fmt,...) \
+{ \
+ ico_log_print(ICO_LOG_DEBUG, \
+ "%s> " fmt " (%s,%s:%d)\n", \
+ ico_get_str_cur_time("DBG"), \
+ ##__VA_ARGS__, \
+ __func__, \
+ __FILE__, \
+ __LINE__); \
+}
+
+#define ICO_DBG(fmt,...) \
+{ \
+ ico_log_print(ICO_LOG_DEBUG, \
+ "%s> " fmt " (%s,%s:%d)\n", \
+ ico_get_str_cur_time("DBG"), \
+ ##__VA_ARGS__, \
+ __func__, \
+ __FILE__, \
+ __LINE__); \
+}
+
+#define ICO_INF(fmt,...) \
+{ \
+ ico_log_print(ICO_LOG_INFO, \
+ "%s> " fmt " (%s,%s:%d)\n", \
+ ico_get_str_cur_time("INF"), \
+ ##__VA_ARGS__, \
+ __func__, \
+ __FILE__, \
+ __LINE__); \
+}
+
+#define ICO_WRN(fmt,...) \
+{ \
+ ico_log_print(ICO_LOG_WARNING, \
+ "%s> " fmt " (%s,%s:%d)\n", \
+ ico_get_str_cur_time("WRN"), \
+ ##__VA_ARGS__, \
+ __func__, \
+ __FILE__, \
+ __LINE__); \
+}
+
+#define ICO_CRI(fmt,...) \
+{ \
+ ico_log_print(ICO_LOG_CRITICAL, \
+ "%s> " fmt " (%s,%s:%d)\n", \
+ ico_get_str_cur_time("CRI"), \
+ ##__VA_ARGS__, \
+ __func__, \
+ __FILE__, \
+ __LINE__); \
+}
+
+#define ICO_ERR(fmt,...) \
+{ \
+ ico_log_print(ICO_LOG_ERROR, \
+ "%s> " fmt " (%s,%s:%d)\n", \
+ ico_get_str_cur_time("ERR"), \
+ ##__VA_ARGS__, \
+ __func__, \
+ __FILE__, \
+ __LINE__); \
+}
+
+
+void ico_log_print(int level, const char *fmt, ...);
+void ico_log_open(const char *prog);
+void ico_log_close(void);
+void ico_log_flush(void);
+char * ico_get_str_cur_time(const char *level);
+void ico_log_set_level(int level);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __ICO__LOG_H__
+/* vim:set expandtab ts=4 sw=4: */
--- /dev/null
+/*
+ * Copyright (c) 2013, TOYOTA MOTOR CORPORATION.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+/*------------------------------------------------------------------------*/
+/**
+ * @file ico_log.c
+ *
+ * @brief
+ */
+/*------------------------------------------------------------------------*/
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <time.h>
+#include "ico_log.h"
+
+/*============================================================================*/
+/* global API */
+/*============================================================================*/
+#if defined(__GNUC__) && __GNUC__ >= 4
+#define ICO_API __attribute__ ((visibility("default")))
+#else
+#define ICO_API
+#endif
+
+/*========================================================================*/
+/**
+ * static variable
+ */
+/*========================================================================*/
+
+static int time_zone = 99*60*60; /*!< local time difference(sec) */
+static int log_level = 0x7FFFFFFF; /*!< output level debug log */
+static bool flush_mode = true; /*!< flush mode flag */
+static bool initialized = false; /*!< initialized flag */
+static FILE *log_fd = NULL; /*!< file descriptor of output debug log*/
+static int log_lines = 0; /*!< output lines */
+static char log_prog[32] = {0,}; /*!< name of output source module */
+
+
+/*------------------------------------------------------------------------*/
+/**
+ * @brief printout log message
+ *
+ * @param [in] level log output level
+ * @param [in] fmt message format(same as printf)
+ * @param [in] ... arguments if need
+ */
+/*------------------------------------------------------------------------*/
+ICO_API void
+ico_log_print(int level, const char *fmt, ...)
+{
+ if (log_level < level) {
+ return;
+ }
+ va_list list;
+
+ if (NULL == log_fd) {
+ ico_log_open(NULL);
+ }
+#if ICO_APF_LOG_STDOUT == 0
+ else if (log_lines >= (ICO_LOG_MAXLINES-2)) {
+ if (log_lines >= ICO_LOG_MAXLINES) {
+ ico_log_close();
+ ico_log_open(log_prog);
+ }
+ else {
+ fflush(log_fd);
+ }
+ }
+#endif /*ICO_APF_LOG_STDOUT*/
+ if (NULL != log_fd) {
+ va_start(list, fmt);
+ vfprintf(log_fd, fmt, list);
+ va_end(list);
+ if (flush_mode) {
+ fflush(log_fd);
+ }
+ }
+ if (log_fd != stdout) {
+ log_lines ++;
+ }
+}
+
+/*------------------------------------------------------------------------*/
+/**
+ * @brief open log file
+ *
+ * @param [in] prog program name
+ */
+/*------------------------------------------------------------------------*/
+ICO_API void
+ico_log_open(const char *prog)
+{
+#if ICO_LOG_STDOUT == 0
+ int idx;
+ char sPath[128];
+ char sPath2[128];
+#endif /*ICO_LOG_STDOUT*/
+
+ if (NULL != log_fd) {
+ fflush(log_fd);
+ if (log_fd != stdout) {
+ fclose(log_fd);
+ }
+ }
+
+ log_lines = 0;
+
+ if ((! prog) || (*prog == 0)) {
+ log_fd = stdout;
+ log_prog[0] = 0;
+ return;
+ }
+ else {
+ strncpy(log_prog, prog, sizeof(log_prog)-1);
+ log_prog[sizeof(log_prog)-1] = 0;
+ }
+#if ICO_LOG_STDOUT > 0
+ log_fd = stdout;
+#else /*ICO_LOG_STDOUT*/
+ snprintf(sPath, sizeof(sPath)-1, "%s/%s.log%d",
+ ICO_LOG_DIR, log_prog, ICO_LOG_MAXFILES-1);
+ (void)remove(sPath);
+
+ for (idx = (ICO_LOG_MAXFILES-1); idx > 0; idx--) {
+ strcpy(sPath2, sPath);
+ if (idx > 1) {
+ snprintf(sPath, sizeof(sPath)-1, "%s/%s.log%d",
+ ICO_LOG_DIR, log_prog, idx-1);
+ }
+ else {
+ snprintf(sPath, sizeof(sPath)-1, "%s/%s.log",
+ ICO_LOG_DIR, log_prog);
+ }
+ (void)rename(sPath, sPath2);
+ }
+
+ log_fd = fopen(sPath, "w");
+ if (NULL == log_fd) {
+ log_fd = stdout;
+ }
+ else if ((initialized == false) &&
+ (log_fd != stdout) && (log_fd != stderr)) {
+ initialized = true;
+ fflush(stdout);
+ fflush(stderr);
+ stdout = log_fd;
+ stderr = log_fd;
+ }
+#endif /*ICO_LOG_STDOUT*/
+}
+
+/*------------------------------------------------------------------------*/
+/**
+ * @brief close log file
+ */
+/*------------------------------------------------------------------------*/
+ICO_API void
+ico_log_close(void)
+{
+#if ICO_LOG_STDOUT == 0
+ if (NULL != log_fd) {
+ fflush(log_fd);
+ if (log_fd != stdout) {
+ fclose(log_fd);
+ }
+ log_fd = (FILE *)NULL;
+ }
+#endif /*ICO_LOG_STDOUT*/
+}
+
+/*------------------------------------------------------------------------*/
+/**
+ * @brief flush log file
+ */
+/*------------------------------------------------------------------------*/
+ICO_API void
+ico_log_flush(void)
+{
+ if ((NULL != log_fd) && (false == flush_mode)) {
+ fflush(log_fd);
+ }
+}
+
+/*------------------------------------------------------------------------*/
+/**
+ * @brief get current time string
+ *
+ * @param [in] level log level string(header of log message)
+ * @return current time string
+ */
+/*------------------------------------------------------------------------*/
+ICO_API char *
+ico_get_str_cur_time(const char *level)
+{
+ struct timeval NowTime;
+ extern long timezone;
+ static char sBuf[28];
+
+ gettimeofday(&NowTime, (struct timezone *)0);
+ if (time_zone > (24*60*60)) {
+ tzset();
+ time_zone = timezone;
+ }
+ NowTime.tv_sec -= time_zone;
+
+ sprintf(sBuf, "%02d:%02d:%02d.%03d[%s]@%d",
+ (int)((NowTime.tv_sec/3600) % 24),
+ (int)((NowTime.tv_sec/60) % 60),
+ (int)(NowTime.tv_sec % 60),
+ (int)NowTime.tv_usec/1000, level, getpid());
+
+ return sBuf;
+}
+
+/*------------------------------------------------------------------------*/
+/**
+ * @brief set log output level
+ *
+ * @param [in] level log output level
+ */
+/*------------------------------------------------------------------------*/
+ICO_API void
+ico_log_set_level(int level)
+{
+ log_level = level & (~(ICO_LOG_FLUSH|ICO_LOG_NOFLUSH));
+
+ if (log_level & (ICO_LOG_FLUSH|ICO_LOG_NOFLUSH)) {
+ if (log_level & ICO_LOG_FLUSH) {
+ flush_mode = true;
+ }
+ else {
+ flush_mode = false;
+ }
+ }
+}
+/* vim:set expandtab ts=4 sw=4: */