Initial commit

master
nirenjan 2021-07-13 10:57:22 -07:00
commit 45762f497c
5 changed files with 394 additions and 0 deletions

37
.gitignore vendored 100644
View File

@ -0,0 +1,37 @@
# Compiled object files
*.o
# Generated objects (source, executables, tarballs, etc.)
# Vim swap files
.*.swp
# Autotools objects
.deps
.dirstamp
.libs
ar-lib
autom4te.cache
m4
compile
config.*
configure
depcomp
install-sh
libtool
ltmain.sh
missing
Makefile
Makefile.in
*.la
*.lo
*.m4
stamp-h1
tap-driver.sh
test-driver
*.log
*.trs
*.pc
# Build directory
/build/

21
LICENSE 100644
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 Nirenjan Krishnan
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

6
README.md 100644
View File

@ -0,0 +1,6 @@
Pinelog - a lightweight logging API
===================================
Pinelog is a lightweight logging API for C programs that's designed to be
included in your program source code. Parameters for Pinelog are configured at
build time by means of preprocessor flags.

179
pinelog.c 100644
View File

@ -0,0 +1,179 @@
/*
* Pinelog lightweight logging library
*
* Copyright (C) 2021 Nirenjan Krishnan (nirenjan@nirenjan.org)
*
* SPDX-License-Identifier: MIT
*/
#include <stdio.h>
#include <stdarg.h>
#include <time.h>
#include <errno.h>
#include "pinelog.h"
/**********************************************************************
* Global variables
*********************************************************************/
/** Stream buffer */
static FILE *output_stream = NULL;
/** Default logging level */
static int log_level = LOG_LVL_ERROR;
/* Initialize defaults */
void log_init_defaults(void)
{
output_stream = stdout;
log_level = LOG_LVL_ERROR;
}
int log_set_output_stream(FILE *stream)
{
if (stream == NULL) {
return EINVAL;
}
/* If current output stream is not stdout or stderr, then close it */
if (output_stream != stdout && output_stream != stderr) {
fclose(output_stream);
}
setlinebuf(stream);
output_stream = stream;
return 0;
}
int log_set_output_file(const char *file)
{
FILE *stream;
if (file == NULL) {
return EINVAL;
}
errno = 0;
stream = fopen(file, "w");
if (stream == NULL) {
return errno;
}
return log_set_output_stream(stream);
}
int log_get_level(void)
{
return log_level;
}
int log_set_level(int level)
{
if (level < LOG_LVL_NONE || level > LOG_LVL_TRACE) {
return EINVAL;
}
log_level = level;
return 0;
}
/**********************************************************************
* Configure logging parameters
*********************************************************************/
#ifndef PINELOG_SHOW_DATE
#define PINELOG_SHOW_DATE 0
#endif
#ifndef PINELOG_SHOW_LEVEL
#define PINELOG_SHOW_LEVEL 0
#endif
#ifndef PINELOG_SHOW_BACKTRACE
#define PINELOG_SHOW_BACKTRACE 0
#endif
/**********************************************************************
* Configure level strings
*********************************************************************/
#ifndef PINELOG_FATAL
#define PINELOG_FATAL "FATAL"
#endif
#ifndef PINELOG_ERROR
#define PINELOG_ERROR "ERROR"
#endif
#ifndef PINELOG_WARNING
#define PINELOG_WARNING "WARNING"
#endif
#ifndef PINELOG_INFO
#define PINELOG_INFO "INFO"
#endif
#ifndef PINELOG_DEBUG
#define PINELOG_DEBUG "DEBUG"
#endif
#ifndef PINELOG_TRACE
#define PINELOG_TRACE "TRACE"
#endif
/**********************************************************************
* Log the message to the output stream
*********************************************************************/
void log_message(int level, const char *file, int line, const char *fmt, ...)
{
va_list ap;
/* Don't log anything if the level is not severe enough */
if (level > log_level || level < 0) {
return;
}
/* Cap the log level */
if (level > LOG_LVL_TRACE) {
level = LOG_LVL_TRACE;
}
/* Validate and set output stream */
if (output_stream == NULL) {
output_stream = stdout;
}
#if PINELOG_SHOW_DATE
do {
time_t t;
struct tm *tmp;
char date_string[20];
t = time(NULL);
tmp = localtime(&t);
strftime(date_string, sizeof(date_string), "%F %T ", tmp);
fputs(date_string, out_stream);
} while (0);
#endif
#if PINELOG_SHOW_LEVEL
do {
static const char *level_strings[] = {
PINELOG_FATAL,
PINELOG_ERROR,
PINELOG_WARNING,
PINELOG_INFO,
PINELOG_DEBUG,
PINELOG_TRACE,
};
fputs(level_strings[level], out_stream);
fputs(": ", out_stream);
} while (0)
#endif
#if PINELOG_SHOW_BACKTRACE
fprintf(out_stream, "%s:%d ", file, line);
#endif
va_start(ap, fmt);
vfprintf(output_stream, fmt, ap);
va_end(ap);
}

151
pinelog.h 100644
View File

@ -0,0 +1,151 @@
/*
* Pinelog lightweight logging library
*
* Copyright (C) 2021 Nirenjan Krishnan (nirenjan@nirenjan.org)
*
* SPDX-License-Identifier: MIT
*/
/**
* @file logging.h
* @brief Logging utility library
*
* This file contains the prototypes for the pinelog logging library
* used by any programs that need to log messages.
*
* @author Nirenjan Krishnan (nirenjan@nirenjan.org)
*/
#ifndef LOGGING_H
#define LOGGING_H
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Logging levels
*
* The log levels indicate the lowest severity level that will actually be
* logged to the logging framework.
*/
enum {
/** No messages will be logged */
LOG_LVL_NONE = -1,
/** Only fatal messages will be logged */
LOG_LVL_FATAL,
/** Error messages. This is the default log level */
LOG_LVL_ERROR,
/** Warning messages */
LOG_LVL_WARNING,
/** Informational messages */
LOG_LVL_INFO,
/** Debug messages */
LOG_LVL_DEBUG,
/** Trace messages */
LOG_LVL_TRACE,
};
/**
* @brief Initialize the logging library and set the defaults
*/
void log_init_defaults(void);
/**
* @brief Set the output stream. Must be a FILE pointer.
*
* @param[in] stream Pointer to the output stream
*
* @returns 0 on success, EINVAL if the pointer is not valid.
*/
int log_set_output_stream(FILE *stream);
/**
* @brief Set the output file.
*
* @param[in] file Filename to write to
*
* @returns 0 on success, EINVAL if the filename pointer is not valid, other
* error if the file could not be opened for writing.
*/
int log_set_output_file(const char *file);
/**
* @brief Set the logging level
*
* @param[in] level Level to filter
*
* @returns 0 on success, EINVAL if the level is not valid
*/
int log_set_level(int level);
/**
* @brief Get the logging level
*
* @returns the configured logging level
*/
int log_get_level(void);
/**
* @brief Log a message to the logger
*
* This is the actual function that logs the message. The application should
* never need to call this directly, but instead, should always use the
* \code LOG_* macros.
*
* @param[in] level Level to log the message at
* @param[in] fmt Format string
*
* @returns None
*/
void log_message(int level, const char *file, int line, const char *fmt, ...);
#define LOG_FATAL(fmt, ...) do { \
if (LOG_LVL_FATAL <= log_get_level()) { \
log_message(LOG_LVL_FATAL, __FILE__, __LINE__, fmt, ##__VA_ARGS__); \
} \
exit(1); \
} while (0)
#define LOG_ERROR(fmt, ...) do { \
if (LOG_LVL_ERROR <= log_get_level()) { \
log_message(LOG_LVL_ERROR, __FILE__, __LINE__, fmt, ##__VA_ARGS__); \
} \
} while (0)
#define LOG_WARN(fmt, ...) do { \
if (LOG_LVL_WARNING <= log_get_level()) { \
log_message(LOG_LVL_WARNING, __FILE__, __LINE__, fmt, ##__VA_ARGS__); \
} \
} while(0)
#define LOG_INFO(fmt, ...) do { \
if (LOG_LVL_INFO <= log_get_level()) { \
log_message(LOG_LVL_INFO, __FILE__, __LINE__, fmt, ##__VA_ARGS__); \
} \
} while(0)
#define LOG_DEBUG(fmt, ...) do { \
if (LOG_LVL_DEBUG <= log_get_level()) { \
log_message(LOG_LVL_DEBUG, __FILE__, __LINE__, fmt, ##__VA_ARGS__); \
} \
} while(0)
#define LOG_TRACE(fmt, ...) do { \
if (LOG_LVL_TRACE <= log_get_level()) { \
log_message(LOG_LVL_TRACE, __FILE__, __LINE__, fmt, ##__VA_ARGS__); \
} \
} while(0)
#ifdef __cplusplus
}
#endif
#endif // !defined LOGGING_H