mirror of https://github.com/nirenjan/pinelog.git
				
				
				
			Initial commit
						commit
						45762f497c
					
				|  | @ -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/ | ||||
|  | @ -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. | ||||
|  | @ -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. | ||||
|  | @ -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); | ||||
| } | ||||
|  | @ -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
 | ||||
		Loading…
	
		Reference in New Issue