It's got some useful stuff in it, but doesn't pass ccanlint here.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
--- /dev/null
+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.
--- /dev/null
+#include <ccan/log/log.h>
+
+/**
+ * log - pretty-print logging information
+ *
+ * log is a set of functions and helper macros intended to make it easy to
+ * pretty-print log entries.
+ *
+ * Example:
+ * #include <ccan/log/log.h>
+ *
+ * int main(int argc, char *argv[])
+ * {
+ * print_log(LOG_INFO, "This is an info message.\n");
+ * print_log(LOG_WARNING, "This is a warning message. It indicates that"
+ * " an operation encountered minor issues\n");
+ * print_log(LOG_ERROR, "This is an error message. It indicates that the\n"
+ * "program could not complete an operation, but\n"
+ * "that the error was not fatal. It might have\n"
+ * "an error code, like so: %x\n", 0xDEADBEEF);
+ * print_log(LOG_CRITICAL, "This is a critical message. It indicates\n"
+ * "that the program had an unrecoverable error.\n");
+ * set_log_mode(LOG_CONCISE);
+ * print_log(LOG_INFO, "The symbol tags and information can be concise, as well.\n");
+ * print_log(LOG_WARNING, "That was an info message. This is a warning message.\n");
+ * print_log(LOG_ERROR, "And this is an error message.\n");
+ * print_log(LOG_ERROR, "And this is a critical message.\n");
+ * set_log_file("example.log");
+ * print_log(LOG_INFO, "Logs can also be automatically printed to files.\n");
+ *
+ * Author: Henry Eshbaugh <henryeshbaugh@gmail.com>
+ * License: MIT
+ * Version: 1.0
+ */
+
+ int main(int argc, char *argv[])
+ {
+ if (argc != 2) return 1;
+ if (strcmp(argv[1], "depends") == 0) return 0;
+ return 1;
+ }
--- /dev/null
+#include <log.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdarg.h>
+#include <time.h>
+
+// escape codes for different colors on the terminal
+#define FG_RED "\033[31m"
+#define FG_YELLOW "\033[33m"
+#define FG_BLUE "\033[34m"
+#define FG_PURPLE "\033[35m"
+#define TEXT_BOLD "\033[1m"
+#define COLOR_END "\033[0m" // reset colors to default
+
+static FILE *_logging_files[16] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
+static int _log_current_mode, _current_log_file = 1;
+
+FILE *set_log_file(char *filename)
+{
+ if (_current_log_file+1 > 16) return NULL; // we only support 16 different files
+ _logging_files[_current_log_file++] = fopen(filename, "a+");
+ return _logging_files[_current_log_file];
+}
+
+void set_log_mode(int mode)
+{
+ _log_current_mode = mode;
+}
+
+void get_log_mode()
+{
+ return _log_current_mode;
+}
+
+// this function is headache-inducing.
+void _print_log(int loglevel, char *file, const char *func, char *clock, int line, char *msg, ...)
+{
+ _logging_files[0] = stdout;
+ va_list args;
+ va_start(args, msg);
+
+ // append the varargs to the buffer we want to print.
+ // this is so that our pipe chars don't get fucked later.
+ // also, make sure we don't get an invalid loglevel.
+ char buffer[strlen(msg) + 1024];
+ vsnprintf(buffer, strlen(msg)+1024, msg, args);
+ if (loglevel < 0 || loglevel > 3) loglevel = LOG_INVALID;
+
+ // set console color for printing the tag
+ switch (loglevel) {
+ case LOG_CRITICAL:
+ printf(TEXT_BOLD FG_RED);
+ break;
+ case LOG_ERROR:
+ printf(FG_RED);
+ break;
+ case LOG_WARNING:
+ printf(FG_YELLOW);
+ break;
+ case LOG_INFO:
+ printf(FG_BLUE);
+ break;
+ case LOG_INVALID:
+ printf(FG_PURPLE);
+ break;
+ }
+ // print the log tag
+ int i;
+ for (i=0; i < 16; i++)
+ if (_logging_files[i])
+ fprintf(_logging_files[i], "%s", log_tags[_log_current_mode][loglevel]);
+ else break;
+ printf(COLOR_END);
+
+ if (_log_current_mode == LOG_VERBOSE) {
+ for (i=0; i < 16; i++)
+ if (_logging_files[i])
+ fprintf(_logging_files[i],
+ "%s() (%s:%d) at %s |\t",
+ func, file, line, clock);
+ else break;
+ }
+
+ // print the first line
+ char *to_print = strtok(buffer, "\n");
+ for (i = 0; i < 16; i++)
+ if (_logging_files[i])
+ fprintf(_logging_files[i], "%s\n", to_print);
+ else break;
+
+ // for these next lines, add a pipe and tab once.
+ while (to_print = strtok(NULL, "\n")) {
+ for (i = 0; i < 16; i++)
+ if (_logging_files[i])
+ fprintf(_logging_files[i], "%s\n", to_print);
+ else break;
+ }
+}
--- /dev/null
+#ifndef CCAN_LOG_H
+#define CCAN_LOG_H
+
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdarg.h>
+#include <time.h>
+
+#define LOG_CRITICAL 0
+#define LOG_ERROR 1
+#define LOG_WARNING 2
+#define LOG_INFO 3
+#define LOG_INVALID 4
+
+static
+char *log_tags[2][5] = { { "[CRITICAL] ",
+ "[ERROR] ",
+ "[WARNING] ",
+ "[INFO] ",
+ "[INVALID LOG LEVEL] "},
+ { "[!] ",
+ "[*] ",
+ "[-] ",
+ "[+] ",
+ "[~] " }};
+
+#define LOG_VERBOSE 0
+#define LOG_CONCISE 1
+
+extern FILE *set_log_file(char *);
+extern int get_log_mode();
+extern void set_log_mode(int);
+
+#define print_log(level, ...) do { \
+ time_t _clk = time(NULL); \
+ _print_log(level, __FILE__, __func__, ctime(&_clk), __LINE__, __VA_ARGS__); \
+ } while (0)
+
+extern void _print_log(int, char *, const char *, char*, int, char *, ...);
+#endif // CCAN_LOG_H