aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore8
-rw-r--r--Makefile.am9
-rw-r--r--configure.ac2
-rw-r--r--examples/Makefile.am16
-rw-r--r--examples/decode-binary.c160
-rw-r--r--examples/print-binary.c43
-rw-r--r--examples/print-example.c29
-rw-r--r--examples/print-memory.c1
-rw-r--r--examples/print-options.c18
-rw-r--r--examples/print-simple.c4
-rw-r--r--examples/print-thread-safe.c2
-rw-r--r--examples/print-to-file.c59
-rw-r--r--examples/print-with-object.c47
-rwxr-xr-xgen-download-page.sh200
-rw-r--r--include/embedlog.h.in157
-rw-r--r--m4/gcov.m424
-rw-r--r--man/Makefile.am21
-rw-r--r--man/el_cleanup.374
-rw-r--r--man/el_destroy.31
-rw-r--r--man/el_flush.385
-rw-r--r--man/el_init.3150
-rw-r--r--man/el_new.31
-rw-r--r--man/el_ocleanup.31
-rw-r--r--man/el_oflush.31
-rw-r--r--man/el_oinit.31
-rw-r--r--man/el_ooption.31
-rw-r--r--man/el_operror.31
-rw-r--r--man/el_opmemory.31
-rw-r--r--man/el_opmemory_table.31
-rw-r--r--man/el_oprint.31
-rw-r--r--man/el_option.3818
-rw-r--r--man/el_oputs.31
-rw-r--r--man/el_overview.7358
-rw-r--r--man/el_ovprint.31
-rw-r--r--man/el_perror.31
-rw-r--r--man/el_pmemory.31
-rw-r--r--man/el_pmemory_table.31
-rw-r--r--man/el_print.3521
-rw-r--r--man/el_puts.31
-rw-r--r--man/el_vprint.31
-rw-r--r--readme.rst (renamed from readme.md)286
-rw-r--r--src/Makefile.am6
-rw-r--r--src/el-decode-number.c16
-rw-r--r--src/el-encode-number.c10
-rw-r--r--src/el-file.c191
-rw-r--r--src/el-flush.c16
-rw-r--r--src/el-lock.c14
-rw-r--r--src/el-options.c522
-rw-r--r--src/el-pbinary.c51
-rw-r--r--src/el-perror.c22
-rw-r--r--src/el-pmemory.c88
-rw-r--r--src/el-print.c39
-rw-r--r--src/el-private.h65
-rw-r--r--src/el-puts.c22
-rw-r--r--src/el-syslog.c81
-rw-r--r--src/el-ts.c16
-rw-r--r--src/el-tty.c16
-rw-r--r--src/el-utils.c12
-rwxr-xr-xtest-compilation.sh9
-rw-r--r--tst/Makefile.am8
-rw-r--r--tst/test-el-file.c273
-rw-r--r--tst/test-el-options.c182
-rw-r--r--tst/test-el-pmemory.c108
-rw-r--r--www/Makefile.am91
-rw-r--r--www/conf.py69
-rw-r--r--www/custom.css64
-rw-r--r--www/downloads.html48
-rw-r--r--www/el_overview.7.rst280
-rw-r--r--www/footer.in26
-rw-r--r--www/header.in26
-rw-r--r--www/in/el_cleanup.in41
-rw-r--r--www/in/el_color.err3
-rw-r--r--www/in/el_colors.desc6
-rw-r--r--www/in/el_custom_put.desc19
-rw-r--r--www/in/el_enable_colors.in33
-rw-r--r--www/in/el_enable_file_log.in71
-rw-r--r--www/in/el_enable_output.in47
-rw-r--r--www/in/el_enable_thread_safe.in32
-rw-r--r--www/in/el_finfo.desc3
-rw-r--r--www/in/el_flush.in55
-rw-r--r--www/in/el_fpath.desc3
-rw-r--r--www/in/el_fpath.err16
-rw-r--r--www/in/el_frotate_date.desc50
-rw-r--r--www/in/el_frotate_number.desc33
-rw-r--r--www/in/el_frotate_size.desc8
-rw-r--r--www/in/el_fsync_every.desc12
-rw-r--r--www/in/el_fsync_level.desc10
-rw-r--r--www/in/el_funcinfo.desc4
-rw-r--r--www/in/el_init.in99
-rw-r--r--www/in/el_level.desc15
-rw-r--r--www/in/el_level.err3
-rw-r--r--www/in/el_option.in548
-rw-r--r--www/in/el_out.desc45
-rw-r--r--www/in/el_out.err7
-rw-r--r--www/in/el_pbinary.in204
-rw-r--r--www/in/el_pmemory.in132
-rw-r--r--www/in/el_prefix.desc7
-rw-r--r--www/in/el_print.in187
-rw-r--r--www/in/el_print_extra_info.in43
-rw-r--r--www/in/el_print_level.desc3
-rw-r--r--www/in/el_set_custom_put.in41
-rw-r--r--www/in/el_set_file_sync.in40
-rw-r--r--www/in/el_set_log_level.in37
-rw-r--r--www/in/el_set_prefix.in36
-rw-r--r--www/in/el_set_timestamp.in67
-rw-r--r--www/in/el_set_tty_dev.in33
-rw-r--r--www/in/el_thread_safe.desc22
-rw-r--r--www/in/el_thread_safe.err6
-rw-r--r--www/in/el_ts.desc13
-rw-r--r--www/in/el_ts_fract.desc16
-rw-r--r--www/in/el_ts_tm.desc32
-rw-r--r--www/in/el_tty.desc7
-rw-r--r--www/in/el_tty.err3
-rw-r--r--www/in/ref-list.in52
-rw-r--r--www/index.in7
l---------www/index.md1
-rw-r--r--www/index.rst16
-rw-r--r--www/manuals/base/el_cleanup.3.rst6
-rw-r--r--www/manuals/base/el_destroy.3.rst6
-rw-r--r--www/manuals/base/el_flush.3.rst6
-rw-r--r--www/manuals/base/el_init.3.rst6
-rw-r--r--www/manuals/base/el_new.3.rst6
-rw-r--r--www/manuals/base/index.rst12
-rw-r--r--www/manuals/el_o/el_ocleanup.3.rst6
-rw-r--r--www/manuals/el_o/el_odestroy.3.rst6
-rw-r--r--www/manuals/el_o/el_odisable_output.3.rst6
-rw-r--r--www/manuals/el_o/el_oenable_colors.3.rst6
-rw-r--r--www/manuals/el_o/el_oenable_file_log.3.rst6
-rw-r--r--www/manuals/el_o/el_oenable_output.3.rst6
-rw-r--r--www/manuals/el_o/el_oenable_thread_safe.3.rst6
-rw-r--r--www/manuals/el_o/el_oflush.3.rst6
-rw-r--r--www/manuals/el_o/el_oinit.3.rst6
-rw-r--r--www/manuals/el_o/el_ooption.3.rst6
-rw-r--r--www/manuals/el_o/el_opbinary.3.rst6
-rw-r--r--www/manuals/el_o/el_operror.3.rst6
-rw-r--r--www/manuals/el_o/el_opmemory.3.rst6
-rw-r--r--www/manuals/el_o/el_opmemory_table.3.rst6
-rw-r--r--www/manuals/el_o/el_oprint.3.rst6
-rw-r--r--www/manuals/el_o/el_oprint_extra_info.3.rst6
-rw-r--r--www/manuals/el_o/el_oputb.3.rst6
-rw-r--r--www/manuals/el_o/el_oputs.3.rst6
-rw-r--r--www/manuals/el_o/el_oset_custom_put.3.rst6
-rw-r--r--www/manuals/el_o/el_oset_file_sync.3.rst6
-rw-r--r--www/manuals/el_o/el_oset_log_level.3.rst6
-rw-r--r--www/manuals/el_o/el_oset_prefix.3.rst6
-rw-r--r--www/manuals/el_o/el_oset_timestamp.3.rst6
-rw-r--r--www/manuals/el_o/el_oset_tty_dev.3.rst6
-rw-r--r--www/manuals/el_o/el_ovprint.3.rst6
-rw-r--r--www/manuals/el_o/index.rst37
-rw-r--r--www/manuals/index.rst14
-rw-r--r--www/manuals/options/el_disable_output.3.rst6
-rw-r--r--www/manuals/options/el_enable_colors.3.rst6
-rw-r--r--www/manuals/options/el_enable_file_log.3.rst6
-rw-r--r--www/manuals/options/el_enable_output.3.rst6
-rw-r--r--www/manuals/options/el_enable_thread_safe.3.rst6
-rw-r--r--www/manuals/options/el_option.3.rst6
-rw-r--r--www/manuals/options/el_print_extra_info.3.rst6
-rw-r--r--www/manuals/options/el_set_custom_put.3.rst6
-rw-r--r--www/manuals/options/el_set_file_sync.3.rst6
-rw-r--r--www/manuals/options/el_set_log_level.3.rst6
-rw-r--r--www/manuals/options/el_set_prefix.3.rst6
-rw-r--r--www/manuals/options/el_set_timestamp.3.rst6
-rw-r--r--www/manuals/options/el_set_tty_dev.3.rst6
-rw-r--r--www/manuals/options/index.rst23
-rw-r--r--www/manuals/print/el_pbinary.3.rst6
-rw-r--r--www/manuals/print/el_perror.3.rst6
-rw-r--r--www/manuals/print/el_pmemory.3.rst6
-rw-r--r--www/manuals/print/el_pmemory_table.3.rst6
-rw-r--r--www/manuals/print/el_print.3.rst6
-rw-r--r--www/manuals/print/el_putb.3.rst6
-rw-r--r--www/manuals/print/el_puts.3.rst6
-rw-r--r--www/manuals/print/el_vprint.3.rst6
-rw-r--r--www/manuals/print/index.rst18
-rwxr-xr-xwww/post-process.sh4
l---------www/readme.rst1
-rw-r--r--www/static/custom.css10
176 files changed, 4974 insertions, 3099 deletions
diff --git a/.gitignore b/.gitignore
index 30ea675..cf27acb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,11 +22,6 @@ configure
depcomp
embedlog-*
embedlog-*
-examples/print_memory
-examples/print_options
-examples/print_simple
-examples/print_to_file
-examples/print_tty
install-sh
libtool
ltmain.sh
@@ -45,9 +40,6 @@ test.log
test.trs
tst/coverage.info
tst/coveragereport/
-www/downloads.html
-www/manuals
-www/out
coverage.info
coveragereport/
pvs-studio.log
diff --git a/Makefile.am b/Makefile.am
index e84582a..8cd7cd4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,13 +1,12 @@
include Makefile.am.coverage
ACLOCAL_AMFLAGS=-I m4
-SUBDIRS = include src tst man examples www
-EXTRA_DIST = man2html.sh gen-download-page.sh readme.md tap-driver.sh
+SUBDIRS = include src tst www examples
+EXTRA_DIST = gen-download-page.sh readme.rst tap-driver.sh
www:
- ./gen-download-page.sh
- ./man2html.sh
- make www -C www
+ ./gen-download-page.sh > www/downloads.rst
+ make -C www html
analyze:
make analyze -C src
diff --git a/configure.ac b/configure.ac
index 1c67ab3..e15692e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -526,7 +526,7 @@ AC_ARG_ENABLE([analyzer],
AM_CONDITIONAL([ENABLE_ANALYZER], [test "x$enable_analyzer" = "xyes"])
AC_CONFIG_FILES([Makefile src/Makefile include/Makefile tst/Makefile \
- man/Makefile examples/Makefile www/Makefile])
+ examples/Makefile www/Makefile])
AC_OUTPUT
diff --git a/examples/Makefile.am b/examples/Makefile.am
index 38c5963..31a0466 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -7,28 +7,42 @@ EXTRA_PROGRAMS = print_to_file \
print_options \
print_simple \
print_memory \
- print_tty
+ print_tty \
+ print_with_object
+
+if ENABLE_BINARY_LOGS
+EXTRA_PROGRAMS += print_binary decode_binary
+endif
print_to_file_SOURCES = print-to-file.c
print_thread_safe_SOURCES = print-thread-safe.c
print_options_SOURCES = print-options.c
print_simple_SOURCES = print-simple.c
print_memory_SOURCES = print-memory.c
+print_binary_SOURCES = print-binary.c
+decode_binary_SOURCES = decode-binary.c
print_tty_SOURCES = print-tty.c
+print_with_object_SOURCES = print-with-object.c
print_to_file_LDFLAGS = $(VLDFLAGS)
print_thread_safe_LDFLAGS = $(VLDFLAGS)
print_options_LDFLAGS = $(VLDFLAGS)
print_simple_LDFLAGS = $(VLDFLAGS)
print_memory_LDFLAGS = $(VLDFLAGS)
+print_binary_LDFLAGS = $(VLDFLAGS)
+decode_binary_LDFLAGS = $(VLDFLAGS)
print_tty_LDFLAGS = $(VLDFLAGS)
+print_with_object_LDFLAGS = $(VLDFLAGS)
print_to_file_LDADD = $(VLDADD)
print_thread_safe_LDADD = $(VLDADD)
print_options_LDADD = $(VLDADD)
print_simple_LDADD = $(VLDADD)
print_memory_LDADD = $(VLDADD)
+print_binary_LDADD = $(VLDADD)
+decode_binary_LDADD = $(VLDADD)
print_tty_LDADD = $(VLDADD)
+print_with_object_LDADD = $(VLDADD)
.PHONY: examples
examples: $(EXTRA_PROGRAMS)
diff --git a/examples/decode-binary.c b/examples/decode-binary.c
new file mode 100644
index 0000000..d8283fc
--- /dev/null
+++ b/examples/decode-binary.c
@@ -0,0 +1,160 @@
+/* ==========================================================================
+ Licensed under BSD 2clause license See LICENSE file for more information
+ Author: Michał Łyszczek <michal.lyszczek@bofc.pl>
+ ========================================================================== */
+
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+
+#include "embedlog.h"
+
+#define die_perror(x, ...) do { el_perror(ELF, x, __VA_ARGS__); exit(1); } while (0)
+
+static size_t decode_number
+(
+ const void *number, /* number to decode */
+ unsigned long long *out /* decoded number */
+)
+{
+ const unsigned char *n; /* just a 'number' as unsigned char */
+ size_t i; /* temporary index */
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+
+ i = 0;
+ *out = 0;
+ n = number;
+
+ do
+ {
+ /* multiple stuff is happening in this one-liner
+ *
+ * - first we take 7 bits of number
+ * - calculate weigth of current number
+ * - set current number into right position of out */
+ *out |= (n[i] & 0x7f) << (i * 7);
+
+ /* we do this until number lacks of continuation bit, which
+ * means we are done */
+ }
+ while (n[i++] & 0x80);
+
+ /* return number of bytes processed from 'number' */
+
+ return i;
+}
+
+#ifdef EMBEDLOG_DEMO_LIBRARY
+int el_demo_decode_binary_main(int argc, char *argv[])
+#else
+int main(int argc, char *argv[])
+#endif
+{
+ int fd;
+ unsigned char *log;
+ struct stat st;
+ ssize_t i;
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+ el_init();
+
+ if (argc != 2)
+ {
+ fprintf(stderr, "Usage: %s <binary-file>\n", argv[0]);
+ return 1;
+ }
+
+ if (stat(argv[1], &st) != 0)
+ die_perror("stat(%s)", argv[1]);
+
+ if ((fd = open(argv[1], O_RDONLY)) < 0)
+ die_perror("open(%s)", argv[1]);
+
+ if ((log = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) == NULL)
+ die_perror("mmap(NULL, %zu, PROT_READ, MAP_PRIVATE, %s)",
+ st.st_size, argv[1]);
+
+ /* Parse file, until all frames are read */
+ for (i = 0; i < st.st_size;)
+ {
+ char timestamp[128];
+ int tslen;
+ unsigned char flags;
+ unsigned long long seconds;
+ unsigned long long fract;
+ unsigned long long data_len;
+ struct tm *tm;
+ int level;
+
+ /* flag is always 1st byte of frame */
+ flags = log[i++];
+
+ timestamp[0] = '\0';
+
+ /* Get log level of message in frame */
+ level = flags >> EL_FLAG_LEVEL_SHIFT & EL_FLAG_LEVEL_MASK;
+
+ if (flags & EL_FLAG_TS)
+ {
+ /* Timestamp is present, read seconds from frame, right
+ * now length of seconds is unknown, decode_number() will
+ * return us number of bytes on which seconds were encoded */
+ i += decode_number(log + i, &seconds);
+
+ /* Create timstamp string from the read seconds */
+ tm = gmtime((time_t *)&seconds);
+ tslen = strftime(timestamp, 20, "%Y-%m-%d %H:%M:%S", tm);
+
+ if (flags >> EL_FLAG_TS_FRACT_SHIFT & EL_FLAG_TS_FRACT_MASK)
+ {
+ /* Fractions of seconds are present, read them too */
+ i += decode_number(log + i, &fract);
+
+ /* Append fraction of second into timestamp string,
+ * we will be appending a little differently depending
+ * in fraction unit. */
+
+ switch (flags >> EL_FLAG_TS_FRACT_SHIFT & EL_FLAG_TS_FRACT_MASK)
+ {
+ case 1: /* nanosecond precision */
+ tslen += sprintf(timestamp + tslen, ".%09lld", fract);
+ break;
+
+ case 2: /* microsecond precision */
+ tslen += sprintf(timestamp + tslen, ".%06lld", fract);
+ break;
+
+ case 3: /* millisecond precision */
+ tslen += sprintf(timestamp + tslen, ".%03lld", fract);
+ break;
+ }
+ }
+ }
+
+ /* Get length of data in the frame */
+ i += decode_number(log + i, &data_len);
+
+ /* If timestamp is set, print it with received log level */
+ if (timestamp[0] != '\0')
+ /* first 3 arguments are 0, since we don't want to print
+ * log level location, it's useless in this case, we we would
+ * only print this very location, not when log originally
+ * was printed */
+ el_print(0, 0, 0, level, "%s", timestamp);
+
+ /* Dump received data as hexdump */
+ el_pmemory(0, 0, 0, level, log + i, data_len);
+
+ /* Move to next frame */
+ i += data_len;
+ }
+
+ close(fd);
+ el_cleanup();
+ return 0;
+}
diff --git a/examples/print-binary.c b/examples/print-binary.c
new file mode 100644
index 0000000..704ef37
--- /dev/null
+++ b/examples/print-binary.c
@@ -0,0 +1,43 @@
+/* ==========================================================================
+ Licensed under BSD 2clause license See LICENSE file for more information
+ Author: Michał Łyszczek <michal.lyszczek@bofc.pl>
+ ========================================================================== */
+
+#include "embedlog.h"
+#include <string.h>
+
+#ifdef EMBEDLOG_DEMO_LIBRARY
+int el_demo_print_binary_main(void)
+#else
+int main(void)
+#endif
+{
+ const char *s;
+ el_init();
+
+ /* We can't print binary data to stderr, so we need to print file */
+ if (el_enable_file_log("/tmp/embedlog-print-binary.bin", 0, 0))
+ perror("Error opening file");
+
+ /* Print some data, we print string, but this can be absolutely
+ * anything, First message won't contain timestamp. Notice that
+ * these functions do not take LEVEL macro, but level enum.
+ * There is no point in logging log location in code when doing
+ * binary logs. */
+ s = "not so binary";
+ el_pbinary(EL_NOTICE, s, strlen(s));
+
+ /* Enable timestamps, but no fractions. */
+ el_set_timestamp(EL_TS_SHORT, EL_TS_TM_REALTIME, EL_TS_FRACT_OFF);
+ s = "ts in, fract out";
+ el_pbinary(EL_WARN, s, strlen(s));
+
+ /* Enable timestamps, with fractions. */
+ el_set_timestamp(EL_TS_SHORT, EL_TS_TM_REALTIME, EL_TS_FRACT_US);
+ s = "we are all in";
+ el_pbinary(EL_FATAL, s, strlen(s));
+
+ el_cleanup();
+
+ return 0;
+}
diff --git a/examples/print-example.c b/examples/print-example.c
new file mode 100644
index 0000000..74e22d0
--- /dev/null
+++ b/examples/print-example.c
@@ -0,0 +1,29 @@
+#include <embedlog.h>
+#include <errno.h>
+
+int main(void) {
+ const char *file = "/tmp/embedlog-test-file.log";
+
+ el_init();
+
+ el_print(ELN, "first print");
+
+ el_set_timestamp(EL_TS_LONG, EL_TS_TM_REALTIME, EL_TS_FRACT_US);
+ el_print(ELW, "warning with timestamp");
+
+ el_print_extra_info(1);
+ el_print(ELF, "fatal error, with code location");
+ el_print(ELI, "normal log with timestamp and code location");
+ el_print(ELD, "won't be printed, log level too low");
+ el_set_log_level(EL_DBG);
+ el_print(ELD, "but now it will be printed");
+
+ el_enable_file_log(file, 0, 0);
+ el_print(ELN, "from now on, logs will be printed to both file and stderr");
+
+ errno = ENAMETOOLONG;
+ el_perror(ELA, "simulated error, failed to open file: %s", file);
+
+ el_cleanup();
+ return 0;
+}
diff --git a/examples/print-memory.c b/examples/print-memory.c
index c1cf9c4..63ac590 100644
--- a/examples/print-memory.c
+++ b/examples/print-memory.c
@@ -21,6 +21,7 @@ int main(void)
el_init();
+ el_option(EL_PMEMORY_SPACE, 1);
el_pmemory(ELI, ascii, sizeof(ascii));
el_pmemory(ELI, s, sizeof(s));
diff --git a/examples/print-options.c b/examples/print-options.c
index dd245ea..01a7709 100644
--- a/examples/print-options.c
+++ b/examples/print-options.c
@@ -24,7 +24,23 @@ int main(void)
el_init();
- el_option(EL_PRINT_LEVEL, 0);
+ el_print(ELI, "most common options can be set with special functions");
+ el_set_timestamp(EL_TS_LONG, EL_TS_TM_REALTIME, EL_TS_FRACT_US);
+ el_print_extra_info(1);
+ el_print(ELI, "like, printing timestamp and log location in a file");
+ el_enable_colors(1);
+ el_print(ELI, "or enabling colors in output");
+ el_print(ELA, "to make it easy to spot error");
+ el_set_log_level(EL_DBG);
+ el_print(ELD, "These options are enough for vast majority of use cases. "
+ "But it more fine tuning is necessary, you can always use "
+ "el_option(3) function, to really fine tune your experience");
+ el_puts("log");
+
+ el_set_timestamp(EL_TS_OFF, 0, 0);
+ el_print_extra_info(0);
+ el_enable_colors(0);
+
el_print(ELI, "We can disable information about log level\b");
el_print(ELF, "message still will be filtered by log level");
el_print(ELA, "but there is no way to tell what level message is");
diff --git a/examples/print-simple.c b/examples/print-simple.c
index e5ffc6b..73cb564 100644
--- a/examples/print-simple.c
+++ b/examples/print-simple.c
@@ -11,7 +11,7 @@ int el_demo_print_simple_main(void)
int main(void)
#endif
{
- /* first we nned to initialize logger to known state, embedlog
+ /* first we need to initialize logger to known state, embedlog
* will print to stdout by default */
el_init();
@@ -24,7 +24,7 @@ int main(void)
/* we can change log level in runtime as we see fit, now enable
* debug prints */
- el_option(EL_LEVEL, EL_DBG);
+ el_set_log_level(EL_DBG);
el_print(ELD, "But now debug will be printed");
/* altough embedlog does not use dynamic allocation by itself,
diff --git a/examples/print-thread-safe.c b/examples/print-thread-safe.c
index 68f7417..effb24b 100644
--- a/examples/print-thread-safe.c
+++ b/examples/print-thread-safe.c
@@ -13,7 +13,7 @@ int main(void)
{
el_init();
- if (el_option(EL_THREAD_SAFE, 1) != 0)
+ if (el_enable_thread_safe(1))
{
el_perror(ELF, "Failed to enable thread safety");
el_cleanup();
diff --git a/examples/print-to-file.c b/examples/print-to-file.c
index 7789540..b79f343 100644
--- a/examples/print-to-file.c
+++ b/examples/print-to-file.c
@@ -12,55 +12,68 @@
#define WORKDIR "/tmp/embedlog-example"
#ifdef EMBEDLOG_DEMO_LIBRARY
-int el_demo_print_to_file_main(void)
+int el_demo_print_to_file_main(int argc, char *argv[])
#else
-int main(void)
+int main(int argc, char *argv[])
#endif
{
+ int date_rotate = 0;
+ int ret;
+
+
+ if (argc == 2)
+ date_rotate = 1;
+
el_init();
- el_option(EL_TS, EL_TS_LONG);
- el_option(EL_TS_TM, EL_TS_TM_REALTIME);
+ el_set_timestamp(EL_TS_LONG, EL_TS_TM_REALTIME, 0);
+ el_print_extra_info(1);
el_option(EL_FINFO, 1);
if (mkdir(WORKDIR, 0755) != 0 && errno != EEXIST)
{
- fprintf(stderr, "Couldn't create %s, error %s\n",
- WORKDIR, strerror(errno));
-
+ el_perror(ELF, "Couldn't create directory "WORKDIR);
goto error;
}
- if (el_option(EL_FPATH, WORKDIR"/log") != 0)
+ /* Enable printing to file, and set log rotation. embedlog will
+ * create maximum 5 files, and non of those files will be larger
+ * than 512. This is demo only, in real life you may want to set
+ * file size to 1M or so. */
+ if (date_rotate)
+ ret = el_enable_file_log(WORKDIR"/log", EL_ROT_DATE_MIN, 0);
+ else
+ ret = el_enable_file_log(WORKDIR"/log", 5, 512);
+
+ if (ret)
{
/* embedlog will try to open file now, this may fail for
- * various of reasons, if opening fails, we cannot log to
- * file - all el_print to files will return error */
- fprintf(stderr, "Couldn't open file for logging %s\n",
- strerror(errno));
+ * various of reasons */
+ if (errno == EINVAL || errno == ENAMETOOLONG)
+ {
+ /* EINVAL and ENAMETOOLONG are the only non-recovarable
+ * errors, if these are returned you can be sure embedlog
+ * will never successully write to a file. All other errors
+ * can be recovered from, and embedlog will start printing
+ * to file once that condition is fixed. This may be
+ * wrong permission, or not existing directory */
+ el_perror(ELF, "Failed to open file for logging");
+ goto error;
+ }
- goto error;
+ el_perror(ELW, "failed to open log file, we will keep trying");
}
- /* instruct logger to print into both file and standard error */
- el_option(EL_OUT, EL_OUT_FILE | EL_OUT_STDERR);
-
el_print(ELI, "This message will appear both in standard error");
el_print(ELI, "and in file %s", WORKDIR"/log");
el_print(ELI, "in this file there might be another logs like this "
"from consecutive execution if this code, as embedlog "
"does not truncate logs but append to file");
-
- /* enable file rotation and set file size to small enough value
- * to present how rotation works, in real life, rotate size
- * should be much higher to prevent unnecessary rotation */
- el_option(EL_FROTATE_NUMBER, 5);
- el_option(EL_FROTATE_SIZE, 512);
- el_print(ELI, "Now we enabled log rotation");
el_print(ELI, "If log cannot fit in current file");
el_print(ELI, "it will be stored in new file");
el_print(ELI, "and if library creates EL_FROTATE_NUMBER files");
el_print(ELI, "oldest file will be deleted and new file will be created");
el_print(ELI, "run this program multiple times and see how it works");
+ el_print(ELI, "File without number, always points to newest log file");
el_cleanup();
return 0;
diff --git a/examples/print-with-object.c b/examples/print-with-object.c
new file mode 100644
index 0000000..a86e5b6
--- /dev/null
+++ b/examples/print-with-object.c
@@ -0,0 +1,47 @@
+/* ==========================================================================
+ Licensed under BSD 2clause license See LICENSE file for more information
+ Author: Michał Łyszczek <michal.lyszczek@bofc.pl>
+ ========================================================================== */
+
+#include "embedlog.h"
+
+#define EL_OPTIONS_OBJECT g_log
+
+#ifdef EMBEDLOG_DEMO_LIBRARY
+int el_demo_print_simple_main(void)
+#else
+int main(void)
+#endif
+{
+ /* Declaration on stack, this should only be used on RTOS, where
+ * stable ABI is not a concern, but allocating on stack is desireable */
+ /* struct el g_log; */
+ /* Heap allocating will provide stable ABI in systems with dynamic
+ * linking, your program will not have to be recompilled each time
+ * embedlog changes */
+ struct el *g_log;
+
+ /* Stack initialization of embedlog object */
+ /* el_oinit(&g_log); */
+ /* Heap allocation of embedlog object */
+ g_log = el_new();
+
+ /* Now we can print almost just as easy as with default functions.
+ * We just have to use slightly different function name and LEVEL
+ * macro */
+ el_oprint(OELI, "Info message");
+ el_oprint(OELF, "Fatal message with additional argument %d", 42);
+ el_oprint(OELD, "Debug message that won't be printed due to log level");
+
+ /* we can change log level in runtime as we see fit, now enable
+ * debug prints */
+ el_oset_log_level(g_log, EL_DBG);
+ el_oprint(OELD, "But now debug will be printed");
+
+ /* Cleaning up stack allocated object */
+ /* el_ocleanup(&g_log); */
+ /* Cleaning up heap allocated object */
+ el_destroy(g_log);
+
+ return 0;
+}
diff --git a/gen-download-page.sh b/gen-download-page.sh
index c870612..641c535 100755
--- a/gen-download-page.sh
+++ b/gen-download-page.sh
@@ -18,159 +18,73 @@ get_files_from_remote()
links="$(curl "${remote}/" -A "${project}-generator" 2>/dev/null \
| grep "${project}-[0-9]*\.[0-9]*\.[0-9]*\." | sort -r)"
-exec 6>&1
-exec 1<>"${out}"
-
-echo > "${out}"
-echo "<h1 class=\"first\">downloads</h1>"
-echo "<p>"
-echo "Below you can find source files and binary packages for various systems."
-echo "<b>(s)</b> right of package name is a gpg signature. You can download"
-echo "<a href=\"${gpg}\">gpg file</a> or"
-echo "<a href=\"${asc}\">armored asc file</a> to verify files. You can also"
-echo "look for key on public keyservers, fingerprint is<br><br>"
-echo "&nbsp;&nbsp;&nbsp;&nbsp;63D0 C3DB 42AF 3B4F CF6E 7880 E84A 7E61 C785 0C62<br><br>"
-echo "You can download key directly from keyserver with<br><br>"
-echo "&nbsp;&nbsp;&nbsp;&nbsp;gpg --recv-keys 63D0C3DB42AF3B4FCF6E7880E84A7E61C7850C62<br><br>"
-echo "Then you can verify downloaded image with command<br><br>"
-echo "&nbsp;&nbsp;&nbsp;&nbsp;gpg --verify &lt;sig-file&gt; &lt;package-file&gt;"
-echo "</p><p>"
-echo "All files (including md5, sha256 and sha512 for all files) can also"
-echo "be downloaded from: <a href=\"${remote}/\">${remote}</a><br>"
-echo "</p>"
-echo "<h1>git</h1>"
-echo "<p>"
-echo "git clone git@git.bofc.pl:${project}<br>"
-echo "git clone git://git.bofc.pl/${project}<br>"
-echo "git clone http://git.bofc.pl/${project}<br>"
-echo "</p>"
-
-echo "<h1>tarballs (source code)</h1>"
-echo "<pre>"
+
+cat << EOF
+=========
+downloads
+=========
+Below you can find released source files. (s) right of package name is a gpg
+signature. You can download gpg file or armored asc file to verify files.
+You can also look for key on public keyservers, fingerprint is::
+
+ 63D0 C3DB 42AF 3B4F CF6E 7880 E84A 7E61 C785 0C62
+
+You can download key directly from keyserver with::
+
+ gpg --recv-keys 63D0C3DB42AF3B4FCF6E7880E84A7E61C7850C62
+
+Then you can verify downloaded image with command::
+
+ gpg --verify <sig-file> <package-file>
+
+All files (including md5, sha256 and sha512 for all files) can also be
+downloaded from: https://distfiles.bofc.pl/embedlog
+
+git
+---
+::
+
+ git clone git@git.bofc.pl:embedlog
+ git clone git://git.bofc.pl/embedlog
+ git clone http://git.bofc.pl/embedlog
+
+tarballs (source code)
+----------------------
+.. parsed-literal::
+
+EOF
files="$(get_files_from_remote "${remote}/" | \
grep "${project}-[0-9]*\.[0-9]*\.[0-9][\.-]\(r[0-9]\)\?")"
versions="$(echo "${files}" | tr ' ' '\n' | rev | \
cut -f1 -d- | rev | cut -f1-3 -d. | sort -Vur)"
-for v in ${versions}
-do
- printf "%-10s%s(%s|%s) %s(%s|%s) %s(%s|%s)\n" "${v}" \
- "<a href=\"${remote}/${project}-${v}.tar.gz\">tar.gz</a>" \
- "<a href=\"${remote}/${project}-${v}.tar.gz.sig\">s</a>" \
- "<a href=\"${remote}/${project}-${v}.tar.gz.sha1\">sha1</a>" \
- "<a href=\"${remote}/${project}-${v}.tar.bz2\">tar.bz2</a>" \
- "<a href=\"${remote}/${project}-${v}.tar.bz2.sig\">s</a>" \
- "<a href=\"${remote}/${project}-${v}.tar.bz2.sha1\">sha1</a>" \
- "<a href=\"${remote}/${project}-${v}.tar.xz\">tar.xz</a>" \
- "<a href=\"${remote}/${project}-${v}.tar.xz.sig\">s</a>" \
- "<a href=\"${remote}/${project}-${v}.tar.xz.sha1\">sha1</a>"
-done
-
-echo "</pre>"
+for v in ${versions}; do
+ tgz=${remote}/${project}-${v}.tar.gz
+ tgz_s=${remote}/${project}-${v}.tar.gz.sig
+ tgz_h=${remote}/${project}-${v}.tar.gz.sha1
+ tbz=${remote}/${project}-${v}.tar.bz2
+ tbz_s=${remote}/${project}-${v}.tar.bz2.sig
+ tbz_h=${remote}/${project}-${v}.tar.bz2.sha1
+ txz=${remote}/${project}-${v}.tar.xz
+ txz_s=${remote}/${project}-${v}.tar.xz.sig
+ txz_h=${remote}/${project}-${v}.tar.xz.sha1
+
+ printf " %-10s%s\\ (%s\\|\\ %s) %s\\ (%s\\ \\|\\ %s) %s\\ (%s\\|\\ %s)\n" "${v}" \
+ "\`tar.gz <$tgz>\`__" \
+ "\`s <$tgz_s>\`__" \
+ "\`sha1 <$tgz_h>\`__" \
+ "\`tar.bz2 <$tbz>\`__" \
+ "\`s <$tbz_s>\`__" \
+ "\`sha1 <$tbz_h>\`__" \
+ "\`tar.xz <$txz>\`__" \
+ "\`s <$txz_s>\`__" \
+ "\`sha1 <$txz_h>\`__"
-distros="$(get_files_from_remote "${remote}/" | \
- grep -v "${project}-[0-9]*\.[0-9]*\.[0-9][\.-]\(r[0-9]\)\?" | \
- grep -v "${project}-9999.tar." | \
- sort -t'-' -k1,1 -k2,2Vr)"
-
-for d in ${distros}
-do
- dname="$(echo ${d} | cut -f1 -d-)"
- dvers="$(echo ${d} | cut -f2 -d-)"
- archs="$(get_files_from_remote "${remote}/${d}/")"
-
- echo "<h1>${dname} ${dvers}</h1>"
-
- for a in ${archs}
- do
- files="$(get_files_from_remote "${remote}/${d}/${a}/")"
- echo "<h2>${a}</h2>"
-
- case "${dname}" in
-
- debian|ubuntu)
- versions="$(echo ${files} | tr ' ' '\n' | \
- cut -f2 -d_ | cut -f1-3 -d. | sort -Vur)"
- ;;
-
- centos|rhel|opensuse|fedora)
- versions="$(echo ${files} | tr ' ' '\n' | rev | \
- cut -f2 -d- | rev | cut -f1-3 -d. | sort -Vur)"
- ;;
-
- slackware)
- versions="$(echo ${files} | tr ' ' '\n' | rev | \
- cut -f3 -d- | rev | cut -f1-3 -d. | sort -Vur)"
- ;;
- esac
-
- echo "<pre>"
- for v in ${versions}
- do
- case "${dname}" in
-
- debian)
- ABI="$(echo "${v}" | cut -f1 -d.)"
- printf "%-10s%s(%s|%s) %s(%s) %s(%s) %s(%s) %s(%s) %s(%s)\n" "${v}" \
- "<a href=\"${remote}/${d}/${a}/lib${project}${ABI}_${v}_${a}.deb\">deb</a>" \
- "<a href=\"${remote}/${d}/${a}/lib${project}${ABI}_${v}_${a}.deb.sig\">s</a>" \
- "<a href=\"${remote}/${d}/${a}/lib${project}${ABI}_${v}_${a}.deb.sha1\">sha1</a>" \
- "<a href=\"${remote}/${d}/${a}/lib${project}${ABI}-dbgsym_${v}_${a}.deb\">dbgsym</a>" \
- "<a href=\"${remote}/${d}/${a}/lib${project}${ABI}-dbgsym_${v}_${a}.deb.sig\">s</a>" \
- "<a href=\"${remote}/${d}/${a}/lib${project}-dev_${v}_${a}.deb\">dev</a>" \
- "<a href=\"${remote}/${d}/${a}/lib${project}-dev_${v}_${a}.deb.sig\">s</a>" \
- "<a href=\"${remote}/${d}/${a}/lib${project}_${v}.dsc\">dsc</a>" \
- "<a href=\"${remote}/${d}/${a}/lib${project}_${v}.dsc.sig\">s</a>" \
- "<a href=\"${remote}/${d}/${a}/lib${project}_${v}_${a}.build\">build</a>" \
- "<a href=\"${remote}/${d}/${a}/lib${project}_${v}_${a}.build.sig\">s</a>" \
- "<a href=\"${remote}/${d}/${a}/lib${project}_${v}_${a}.buildinfo\">buildinfo</a>" \
- "<a href=\"${remote}/${d}/${a}/lib${project}_${v}_${a}.buildinfo.sig\">s</a>"
- ;;
-
- ubuntu)
- ABI="$(echo "${v}" | cut -f1 -d.)"
- printf "%-10s%s(%s|%s) %s(%s) %s(%s) %s(%s) %s(%s) %s(%s)\n" "${v}" \
- "<a href=\"${remote}/${d}/${a}/lib${project}${ABI}_${v}_${a}.deb\">deb</a>" \
- "<a href=\"${remote}/${d}/${a}/lib${project}${ABI}_${v}_${a}.deb.sig\">s</a>" \
- "<a href=\"${remote}/${d}/${a}/lib${project}${ABI}_${v}_${a}.deb.sha1\">sha1</a>" \
- "<a href=\"${remote}/${d}/${a}/lib${project}${ABI}-dbgsym_${v}_${a}.ddeb\">dbgsym</a>" \
- "<a href=\"${remote}/${d}/${a}/lib${project}${ABI}-dbgsym_${v}_${a}.ddeb.sig\">s</a>" \
- "<a href=\"${remote}/${d}/${a}/lib${project}-dev_${v}_${a}.deb\">dev</a>" \
- "<a href=\"${remote}/${d}/${a}/lib${project}-dev_${v}_${a}.deb.sig\">s</a>" \
- "<a href=\"${remote}/${d}/${a}/lib${project}_${v}.dsc\">dsc</a>" \
- "<a href=\"${remote}/${d}/${a}/lib${project}_${v}.dsc.sig\">s</a>" \
- "<a href=\"${remote}/${d}/${a}/lib${project}_${v}_${a}.build\">build</a>" \
- "<a href=\"${remote}/${d}/${a}/lib${project}_${v}_${a}.build.sig\">s</a>" \
- "<a href=\"${remote}/${d}/${a}/lib${project}_${v}_${a}.buildinfo\">buildinfo</a>" \
- "<a href=\"${remote}/${d}/${a}/lib${project}_${v}_${a}.buildinfo.sig\">s</a>"
- ;;
-
- rhel|centos|opensuse|fedora)
- printf "%-10s%s(%s|%s) %s(%s) %s(%s)\n" "${v}" \
- "<a href=\"${remote}/${d}/${a}/${project}-${v}-1.${a}.rpm\">rpm</a>" \
- "<a href=\"${remote}/${d}/${a}/${project}-${v}-1.${a}.rpm.sig\">s</a>" \
- "<a href=\"${remote}/${d}/${a}/${project}-${v}-1.${a}.rpm.sha1\">sha1</a>" \
- "<a href=\"${remote}/${d}/${a}/${project}-debuginfo-${v}-1.${a}.rpm\">dbginfo</a>" \
- "<a href=\"${remote}/${d}/${a}/${project}-debuginfo-${v}-1.${a}.rpm.sig\">s</a>" \
- "<a href=\"${remote}/${d}/${a}/${project}-devel-${v}-1.${a}.rpm\">devel</a>" \
- "<a href=\"${remote}/${d}/${a}/${project}-devel-${v}-1.${a}.rpm.sig\">s</a>"
- ;;
-
- slackware)
- printf "%-10s%s(%s|%s)\n" "${v}" \
- "<a href=\"${remote}/${d}/${a}/${project}-${v}-${a}-1.tgz\">tgz</a>" \
- "<a href=\"${remote}/${d}/${a}/${project}-${v}-${a}-1.tgz.sig\">s</a>" \
- "<a href=\"${remote}/${d}/${a}/${project}-${v}-${a}-1.tgz.sha1\">sha1</a>"
- ;;
- esac
- done
- echo "</pre>"
- done
done
-exec 1>&6 6>&-
failed=0
+exit 0
for l in $(lynx -listonly -nonumbers -dump "${out}" | grep "https://distfiles")
do
diff --git a/include/embedlog.h.in b/include/embedlog.h.in
index a321e14..e1a7023 100644
--- a/include/embedlog.h.in
+++ b/include/embedlog.h.in
@@ -15,6 +15,10 @@
# include <pthread.h>
#endif
+#if HAVE_TERMIOS_H
+# include <termios.h>
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -69,6 +73,15 @@ extern "C" {
# define EL_FUNC_NAME NULL
#endif
+/* Define PRINTFLIKE macro for warnings on misused el_print function */
+#if !defined(PRINTFLIKE)
+# if defined(__GNUC__)
+# define PRINTFLIKE(n,m) __attribute__((format(printf,n,m)))
+# else
+# define PRINTFLIKE(n,m)
+# endif /* __GNUC__ */
+#endif /* PRINTFLIKE */
+
/* enum values, new enums can be added, but values of already
* existing enums *must* stay unchanged, to keep ABI stable! */
@@ -118,17 +131,19 @@ enum el_option
EL_FROTATE_NUMBER = 14,
EL_FROTATE_SIZE = 15,
EL_FROTATE_SYMLINK= 19,
+ EL_FROTATE_DATE = 21,
EL_FSYNC_EVERY = 16,
EL_FSYNC_LEVEL = 17,
EL_FILE_SYNC_EVERY= 16, /* deprecated */
EL_FILE_SYNC_LEVEL= 17, /* deprecated */
EL_THREAD_SAFE = 18,
+ EL_PMEMORY_SPACE = 20,
/* internal use only, should represent number of options, if
* you add option, increment this by one (or by the number of
* options you add). */
- EL_OPT_ERROR = 20
+ EL_OPT_ERROR = 22
};
enum el_option_timestamp
@@ -170,6 +185,41 @@ enum el_option_timestamp_fractions
EL_TS_FRACT_ERROR = 4
};
+enum el_option_rotate
+{
+ /* Date related rotation. Strangely enough, these are negative
+ * so that el_enable_file_log can distinguish between size
+ * rotation and date rotation. */
+ EL_ROT_DATE_SEC = -6,
+ EL_ROT_DATE_MIN = -5,
+ EL_ROT_DATE_HOUR = -4,
+ EL_ROT_DATE_DAY = -3,
+ EL_ROT_DATE_MON = -2,
+ EL_ROT_DATE_YEAR = -1,
+
+ EL_ROT_OFF = 0,
+
+ /* Rotate by file size */
+ EL_ROT_FSIZE = 1,
+};
+
+#define EL_IS_ROT_DATE(el) ((el)->frotate_type <= EL_ROT_DATE_YEAR && \
+ (el)->frotate_type >= EL_ROT_DATE_SEC)
+
+/* Definition of binary format for flags */
+#define EL_FLAG_TS (0x01)
+
+#define EL_FLAG_TS_FRACT_NONE (0x00)
+#define EL_FLAG_TS_FRACT_NSEC (0x01)
+#define EL_FLAG_TS_FRACT_USEC (0x02)
+#define EL_FLAG_TS_FRACT_MSEC (0x03)
+#define EL_FLAG_TS_FRACT_MASK (0x03)
+#define EL_FLAG_TS_FRACT_SHIFT (1)
+
+#define EL_FLAG_LEVEL_MASK (0x07)
+#define EL_FLAG_LEVEL_SHIFT (3)
+
+
typedef int (*el_custom_put)(const char *s, size_t slen, void *user);
/* Main embedlog object that holds printing options and other data.
@@ -198,11 +248,14 @@ struct el
unsigned int funcinfo:1;
unsigned int level:3;
unsigned int level_current_msg:3;
+ unsigned int pmemory_space:2;
#if @ENABLE_OUT_FILE@
unsigned int fsync_level:3;
unsigned int frotate_symlink:1;
unsigned int frotate_number_count:3;
+ signed char frotate_type;
+ unsigned short frotate_datewatch;
unsigned short frotate_number;
unsigned short fcurrent_rotate;
unsigned long frotate_size;
@@ -233,12 +286,14 @@ struct el
#endif
};
+#ifndef DISABLE_ALL_EMBEDLOG
+
int el_init(void);
int el_cleanup(void);
int el_option(int option, ...);
int el_puts(const char *string);
int el_print(const char *file, size_t line, const char *func,
- enum el_level level, const char *fmt, ...);
+ enum el_level level, const char *fmt, ...) PRINTFLIKE(5, 6);
int el_vprint(const char *file, size_t line, const char *func,
enum el_level level, const char *fmt, va_list ap);
int el_pmemory(const char *file, size_t line, const char *func,
@@ -246,7 +301,7 @@ int el_pmemory(const char *file, size_t line, const char *func,
int el_pmemory_table(const char *file, size_t line, const char *func,
enum el_level level, const void *memory, size_t mlen);
int el_perror(const char *file, size_t line, const char *func,
- enum el_level level, const char *fmt, ...);
+ enum el_level level, const char *fmt, ...) PRINTFLIKE(5, 6);
int el_putb(const void *memory, size_t mlen);
int el_pbinary(enum el_level level, const void *memory, size_t mlen);
const struct el *el_get_el(void);
@@ -260,7 +315,8 @@ int el_ocleanup(struct el *el);
int el_ooption(struct el *el, int option, ...);
int el_oputs(struct el *el, const char *string);
int el_oprint(const char *file, size_t line, const char *func,
- enum el_level level, struct el *el, const char *fnt, ...);
+ enum el_level level, struct el *el, const char *fnt, ...)
+ PRINTFLIKE(6, 7);
int el_ovprint(const char *file, size_t line, const char *func,
enum el_level level, struct el *el, const char *fmt,
va_list ap);
@@ -271,12 +327,103 @@ int el_opmemory_table(const char *file, size_t line, const char *func,
enum el_level level, struct el *el, const void *memory,
size_t mlen);
int el_operror(const char *file, size_t line, const char *func,
- enum el_level level, struct el *el, const char *fmt, ...);
+ enum el_level level, struct el *el, const char *fmt, ...)
+ PRINTFLIKE(6, 7);
int el_oputb(struct el *el, const void *memory, size_t mlen);
int el_opbinary(enum el_level level, struct el *el,
const void *memory, size_t mlen);
int el_oflush(struct el *el);
+/* Shortcut for most frequently used options */
+
+int el_set_log_level(enum el_level level);
+int el_enable_output(enum el_output output);
+int el_disable_output(enum el_output output);
+int el_set_prefix(const char *prefix);
+int el_set_timestamp(enum el_option_timestamp timestamp,
+ enum el_option_timestamp_timer timer,
+ enum el_option_timestamp_fractions fraction);
+int el_enable_colors(int enable);
+int el_print_extra_info(int print);
+int el_set_custom_put(el_custom_put clbk, void *user);
+int el_enable_file_log(const char *path, int rotate_number, long rotate_size);
+int el_set_file_sync(long sync_every, enum el_level level);
+int el_set_tty_dev(const char *dev, unsigned speed);
+int el_enable_thread_safe(int enable);
+
+int el_oset_log_level(struct el *el, enum el_level level);
+int el_oenable_output(struct el *el, enum el_output output);
+int el_odisable_output(struct el *el, enum el_output output);
+int el_oset_prefix(struct el *el, const char *prefix);
+int el_oset_timestamp(struct el *el, enum el_option_timestamp timestamp,
+ enum el_option_timestamp_timer timer,
+ enum el_option_timestamp_fractions fraction);
+int el_oenable_colors(struct el *el, int enable);
+int el_oprint_extra_info(struct el *el, int print);
+int el_oset_custom_put(struct el *el, el_custom_put clbk, void *user);
+int el_oenable_file_log(struct el *el, const char *path,
+ int rotate_number, long rotate_size);
+int el_oset_file_sync(struct el *el, long sync_every, enum el_level level);
+int el_oset_tty_dev(struct el *el, const char *dev, unsigned speed);
+int el_oenable_thread_safe(struct el *el, int enable);
+
+#else /* DISABLE_ALL_EMBEDLOG */
+static inline int el_nothing_int(void) { return 0; }
+static inline void *el_nothing_ptr(void) { return (void *)0; }
+
+#define el_init(...) el_nothing_int()
+#define el_cleanup(...) el_nothing_int()
+#define el_option(...) el_nothing_int()
+#define el_puts(...) el_nothing_int()
+#define el_print(...) el_nothing_int()
+#define el_vprint(...) el_nothing_int()
+#define el_pmemory(...) el_nothing_int()
+#define el_pmemory_table(...) el_nothing_int()
+#define el_perror(...) el_nothing_int()
+#define el_putb(...) el_nothing_int()
+#define el_pbinary(...) el_nothing_int()
+#define el_get_el(...) el_nothing_ptr()
+#define el_flush(...) el_nothing_int()
+#define el_new(...) el_nothing_ptr()
+#define el_destroy(...) el_nothing_int()
+#define el_oinit(...) el_nothing_int()
+#define el_ocleanup(...) el_nothing_int()
+#define el_ooption(...) el_nothing_int()
+#define el_oputs(...) el_nothing_int()
+#define el_oprint(...) el_nothing_int()
+#define el_ovprint(...) el_nothing_int()
+#define el_opmemory(...) el_nothing_int()
+#define el_opmemory_table(...) el_nothing_int()
+#define el_operror(...) el_nothing_int()
+#define el_oputb(...) el_nothing_int()
+#define el_opbinary(...) el_nothing_int()
+#define el_oflush(...) el_nothing_int()
+#define el_set_log_level(...) el_nothing_int()
+#define el_enable_output(...) el_nothing_int()
+#define el_disable_output(...) el_nothing_int()
+#define el_set_prefix(...) el_nothing_int()
+#define el_set_timestamp(...) el_nothing_int()
+#define el_enable_colors(...) el_nothing_int()
+#define el_print_extra_info(...) el_nothing_int()
+#define el_set_custom_put(...) el_nothing_int()
+#define el_enable_file_log(...) el_nothing_int()
+#define el_set_file_sync(...) el_nothing_int()
+#define el_set_tty_dev(...) el_nothing_int()
+#define el_enable_thread_safe(...) el_nothing_int()
+#define el_oset_log_level(...) el_nothing_int()
+#define el_oenable_output(...) el_nothing_int()
+#define el_odisable_output(...) el_nothing_int()
+#define el_oset_prefix(...) el_nothing_int()
+#define el_oset_timestamp(...) el_nothing_int()
+#define el_oenable_colors(...) el_nothing_int()
+#define el_oprint_extra_info(...) el_nothing_int()
+#define el_oset_custom_put(...) el_nothing_int()
+#define el_oenable_file_log(...) el_nothing_int()
+#define el_oset_file_sync(...) el_nothing_int()
+#define el_oset_tty_dev(...) el_nothing_int()
+#define el_oenable_thread_safe(...) el_nothing_int()
+
+#endif /* DISABLE_ALL_EMBEDLOG */
#ifdef __cplusplus
}
#endif
diff --git a/m4/gcov.m4 b/m4/gcov.m4
index 3a6bd7e..58699bd 100644
--- a/m4/gcov.m4
+++ b/m4/gcov.m4
@@ -47,33 +47,9 @@ AC_DEFUN([AC_TDD_GCOV],
AC_MSG_ERROR([ccache must be disabled when --enable-gcov option is used. You can disable ccache by setting environment variable CCACHE_DISABLE=1.])
fi
- lcov_version_list="1.6 1.7 1.8 1.9 1.11"
AC_CHECK_PROG(LCOV, lcov, lcov)
AC_CHECK_PROG(GENHTML, genhtml, genhtml)
- if test "$LCOV"; then
- AC_CACHE_CHECK([for lcov version], glib_cv_lcov_version, [
- glib_cv_lcov_version=invalid
- lcov_version=`$LCOV -v 2>/dev/null | $SED -e 's/^.* //'`
- for lcov_check_version in $lcov_version_list; do
- if test "$lcov_version" = "$lcov_check_version"; then
- glib_cv_lcov_version="$lcov_check_version (ok)"
- fi
- done
- ])
- else
- lcov_msg="To enable code coverage reporting you must have one of the following lcov versions installed: $lcov_version_list"
- AC_MSG_ERROR([$lcov_msg])
- fi
-
- case $glib_cv_lcov_version in
- ""|invalid[)]
- lcov_msg="You must have one of the following versions of lcov: $lcov_version_list (found: $lcov_version)."
- AC_MSG_ERROR([$lcov_msg])
- LCOV="exit 0;"
- ;;
- esac
-
if test -z "$GENHTML"; then
AC_MSG_ERROR([Could not find genhtml from the lcov package])
fi
diff --git a/man/Makefile.am b/man/Makefile.am
deleted file mode 100644
index 54a2186..0000000
--- a/man/Makefile.am
+++ /dev/null
@@ -1,21 +0,0 @@
-man_MANS = el_cleanup.3 \
- el_init.3 \
- el_ocleanup.3 \
- el_oinit.3 \
- el_ooption.3 \
- el_operror.3 \
- el_opmemory.3 \
- el_oprint.3 \
- el_option.3 \
- el_oputs.3 \
- el_overview.7 \
- el_ovprint.3 \
- el_perror.3 \
- el_pmemory.3 \
- el_print.3 \
- el_puts.3 \
- el_vprint.3 \
- el_flush.3 \
- el_oflush.3
-
-EXTRA_DIST = $(man_MANS)
diff --git a/man/el_cleanup.3 b/man/el_cleanup.3
deleted file mode 100644
index a7bb313..0000000
--- a/man/el_cleanup.3
+++ /dev/null
@@ -1,74 +0,0 @@
-.TH "el_cleanup" "3" "10 June 2019 (v9999)" "bofc.pl"
-.SH NAME
-.PP
-.B el_cleanup
-- cleans all resources allocated by
-.BR el_init (3)
-and
-.BR el_option (3)
-calls.
-.SH SYNOPSIS
-.PP
-.BI "#include <embedlog.h>"
-.PP
-.BI "int el_cleanup(void)"
-.br
-.BI "int el_ocleanup(struct el *" el ")"
-.br
-.BI "int el_destroy(struct el *" el ")"
-.SH DESCRIPTION
-.PP
-.BR el_cleanup (3)
-flushes all remaining buffers and frees any resources allocated through the
-life of the library.
-After clean up, library calls cannot be used without initialization.
-.PP
-.BR el_ocleanup (3)
-works just the same, but accepts custom
-.I el
-object as argument.
-.PP
-.BR el_destroy (3)
-works just the same, but must be used when
-.I el
-object has been created with
-.BR el_new (3)
-function.
-.SH RETURN VALUE
-.PP
-Functions return 0 upon successful cleanup or -1 on errors.
-When -1 was returned no resources were freed, and library functions still can be
-used.
-.SH ERRORS
-.PP
-.BR el_cleanup (3)
-function cannot fail.
-.BR el_ocleanup (3)
-and
-.BR el_destroy (3)
-may return:
-.TP
-.B EINVAL
-Passed el object is not valid
-.SH SEE ALSO
-.PP
-.BR el_overview (7),
-.BR el_flush (3),
-.BR el_init (3),
-.BR el_new (3),
-.BR el_oflush (3),
-.BR el_oinit (3),
-.BR el_ooption (3),
-.BR el_operror (3),
-.BR el_opmemory (3),
-.BR el_opmemory_table (3),
-.BR el_oprint (3),
-.BR el_option (3),
-.BR el_oputs (3),
-.BR el_ovprint (3),
-.BR el_perror (3),
-.BR el_pmemory (3),
-.BR el_pmemory_table (3),
-.BR el_print (3),
-.BR el_puts (3),
-.BR el_vprint (3).
diff --git a/man/el_destroy.3 b/man/el_destroy.3
deleted file mode 100644
index f5c1d77..0000000
--- a/man/el_destroy.3
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/el_cleanup.3
diff --git a/man/el_flush.3 b/man/el_flush.3
deleted file mode 100644
index c7d8a84..0000000
--- a/man/el_flush.3
+++ /dev/null
@@ -1,85 +0,0 @@
-.TH "el_flush" "3" "10 June 2019 (v9999)" "bofc.pl"
-.SH NAME
-.PP
-.BR el_flush ,\ el_oflush
-- flush logs from all buffers to underlying devices.
-.SH SYNOPSIS
-.PP
-.BI "#include <embedlog.h>"
-.PP
-.BI "int el_flush(void)"
-.br
-.BI "int el_oflush(struct el *" el ")"
-.SH DESCRIPTION
-.PP
-.B embedlog
-(and underlying drivers, operating systems, libraries etc) to improve
-performance, may buffer message before commiting changes to actual device.
-And it's ok, there is really no need to waste resources every time you want to
-log 50 bytes of debug print on commiting message physically to the drive - or
-send via network.
-It's much more common to buffer messages in RAM until certain ammount of bytes
-are ready to send - and then send a bunch of data in one quick burst.
-But that behaviour is not always desired, like in situation in which we know we
-won't be printing logs for long time.
-For such situation explicit flush may in order.
-.PP
-.BR el_flush (3)
-flushes logs from all buffers to underlying device.
-For example, when logs are printed to file, logs are written through buffered
-.B stdio
-functions, which may result in some logs never being actually put into block
-device in case of abnormal application crash - that of course depends on
-settings like
-.BR EL_FSYNC_EVERY .
-This function will do everything what is in its power to make sure logs landed
-on underlying device.
-This applies to files, but also to logs with network output.
-.PP
-.BR el_oflush (3)
-works just the same, but accepts custom
-.I el
-object as argument.
-.SH RETURN VALUE
-.PP
-Functions return 0 upon successful flush or -1 on errors.
-When -1 was returned there is no guarantee that data has landed on underlying
-device.
-.SH ERRORS
-.PP
-.BR el_flush (3)
-and
-.BR el_oflush (3)
-may return errors from functions like:
-.BR fflush (),\ fileno (),\ fsync (),\ fseek (),\ ftell (),\ fopen ()
-and/or
-.BR fclose ().
-.PP
-.BR el_oflush (3)
-may additionally return:
-.TP
-.B EINVAL
-Passed el object is not valid
-.SH SEE ALSO
-.PP
-.BR el_overview (7),
-.BR el_cleanup (3),
-.BR el_destroy (3),
-.BR el_init (3),
-.BR el_new (3),
-.BR el_ocleanup (3),
-.BR el_oinit (3),
-.BR el_ooption (3),
-.BR el_operror (3),
-.BR el_opmemory (3),
-.BR el_opmemory_table (3),
-.BR el_oprint (3),
-.BR el_option (3),
-.BR el_oputs (3),
-.BR el_ovprint (3),
-.BR el_perror (3),
-.BR el_pmemory (3),
-.BR el_pmemory_table (3),
-.BR el_print (3),
-.BR el_puts (3),
-.BR el_vprint (3).
diff --git a/man/el_init.3 b/man/el_init.3
deleted file mode 100644
index faf7fd8..0000000
--- a/man/el_init.3
+++ /dev/null
@@ -1,150 +0,0 @@
-.TH "el_init" "3" "10 June 2019 (v9999)" "bofc.pl"
-.SH NAME
-.PP
-.B el_init
-- initializes library and el for printing.
-.SH SYNOPSIS
-.PP
-.B "#include <embedlog.h>"
-.PP
-.BI "int el_init(void)"
-.br
-.BI "int el_oinit(struct el *" el ")"
-.br
-.BI "struct el * el_new(void)"
-.SH DESCRIPTION
-.PP
-There are two types of functions in
-.BR embedlog.
-Functions that use global static structure inside library, these functions don't
-accept
-.I el
-argument with options.
-.PP
-Another type are functions that accept additional
-.I el
-argument. These functions are prefixed with
-.BR el_o .
-.PP
-.BR el_init (3)
-initializes static global option structure. This option structure is used by all
-functions that don't accept
-.I el
-object parameter.
-If you want to use only one instance of
-.BR embedlog ,
-this is the function you want to use.
-.PP
-.BR el_oinit (3)
-initializes only
-.I el
-struct passed to it.
-Functions that accepts
-.I el
-object may be used.
-If you want to have multiple embedlog instances (ie. one for program logs,
-and one for queries) that stores logs differently - this is the function you
-want to use.
-Object initialized with this function must be deinitialized with
-.BR el_ocleanup (3)
-function.
-.PP
-.BR el_new (3)
-Works in the same way as
-.BR el_oinit (3)
-but function returns newly heap-allocated pointer to
-.I el
-struct.
-Object created with this function must be destroyed with
-.BR el_destroy (3)
-function.
-.SH NOTES
-.PP
-Keep in mind that using
-.BR el_oinit (3)
-function is suscible to ABI breakage.
-If stable ABI is important to you, use
-.BR el_new (3)
-function.
-Please check
-.BR el_overview (3)
-for more information about this.
-.SH RETURN VALUE
-.PP
-.BR el_init (3)
-cannot fail and always returns 0.
-.BR el_oinit (3)
-function will return 0 upon success and -1 on errors.
-.BR el_new (3)
-returns valid pointer on success and
-.B NULL
-when error occurs.
-.SH ERRORS
-.PP
-.BR el_oinit (3)
-can return:
-.TP
-.B EINVAL
-.I el
-object is invalid (null).
-.PP
-.BR el_new (3)
-can return:
-.TP
-.B ENOMEM
-Not enough memory in the system to perform necessary memory allocations.
-.SH EXAMPLE
-.PP
-Note: error handling has been ommited for clarity sake
-.PP
-.nf
- #include <embedlog.h>
-
- int main(void)
- {
- struct el el, *elp;
-
- /* initialize default and two custom el objects */
- el_init();
- el_oinit(&el);
- elp = el_new();
-
- /* make el to print to file and stderr */
- el_ooption(&el, EL_OUT, EL_OUT_FILE | EL_OUT_STDERR);
- el_ooption(&el, EL_FPATH, "/tmp/test.log");
-
- /* print messages */
- el_print(ELI, "will print to stderr");
- el_oprint(ELI, &el, "will print to file /tmp/test.log and stderr");
- el_oprint(ELN, elp, "print to stderr");
-
- /* cleanup after any initialization code (like fopen) */
- el_destroy(elp);
- el_ocleanup(&el);
- el_cleanup();
-
- return 0;
- }
-.fi
-.SH SEE ALSO
-.PP
-.BR el_overview (7),
-.BR el_cleanup (3),
-.BR el_destroy (3),
-.BR el_flush (3),
-.BR el_ocleanup (3),
-.BR el_oflush (3),
-.BR el_ooption (3),
-.BR el_operror (3),
-.BR el_opmemory (3),
-.BR el_opmemory_table (3),
-.BR el_oprint (3),
-.BR el_option (3),
-.BR el_oputs (3),
-.BR el_ovprint (3),
-.BR el_perror (3),
-.BR el_pmemory (3),
-.BR el_pmemory_table (3),
-.BR el_print (3),
-.BR el_puts (3),
-.BR el_vprint (3).
diff --git a/man/el_new.3 b/man/el_new.3
deleted file mode 100644
index 3dbf2b6..0000000
--- a/man/el_new.3
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/el_init.3
diff --git a/man/el_ocleanup.3 b/man/el_ocleanup.3
deleted file mode 100644
index f5c1d77..0000000
--- a/man/el_ocleanup.3
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/el_cleanup.3
diff --git a/man/el_oflush.3 b/man/el_oflush.3
deleted file mode 100644
index 0f1a0a9..0000000
--- a/man/el_oflush.3
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/el_flush.3
diff --git a/man/el_oinit.3 b/man/el_oinit.3
deleted file mode 100644
index 3dbf2b6..0000000
--- a/man/el_oinit.3
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/el_init.3
diff --git a/man/el_ooption.3 b/man/el_ooption.3
deleted file mode 100644
index a82cd78..0000000
--- a/man/el_ooption.3
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/el_option.3
diff --git a/man/el_operror.3 b/man/el_operror.3
deleted file mode 100644
index 8a9800f..0000000
--- a/man/el_operror.3
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/el_print.3
diff --git a/man/el_opmemory.3 b/man/el_opmemory.3
deleted file mode 100644
index 8a9800f..0000000
--- a/man/el_opmemory.3
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/el_print.3
diff --git a/man/el_opmemory_table.3 b/man/el_opmemory_table.3
deleted file mode 100644
index 8a9800f..0000000
--- a/man/el_opmemory_table.3
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/el_print.3
diff --git a/man/el_oprint.3 b/man/el_oprint.3
deleted file mode 100644
index 8a9800f..0000000
--- a/man/el_oprint.3
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/el_print.3
diff --git a/man/el_option.3 b/man/el_option.3
deleted file mode 100644
index a5ac711..0000000
--- a/man/el_option.3
+++ /dev/null
@@ -1,818 +0,0 @@
-.TH "el_option" "3" "10 June 2019 (v9999)" "bofc.pl"
-.SH NAME
-.PP
-.B el_option
-- sets optional configuration of the logger
-.SH SYNOPSIS
-.PP
-.B #include <embedlog.h>
-.PP
-.BI "int el_option(enum el_option " option ", " ... ")"
-.br
-.B const struct el *el_get_el(void)
-.br
-.BI "int el_ooption(struct el *" el ", \
-enum el_option " option ", " ... ")"
-.SH DESCRIPTION
-.PP
-.BR el_option (3)
-allows user to configure logger's internal el object, to tune logging to users
-needs.
-.PP
-.BR el_get_el (3)
-allows user to get pointer to global embedlog object - that is used by all
-embedlog functions that don't accept
-.I el
-object - to directly read its fields.
-.SH OPTIONS
-.PP
-Below is a list of
-.I option
-that can be configured.
-Value inside parenthesis determines argument types of variadic arguments
-.I ...
-.PP
-.BI "EL_LEVEL (" enum " " el_level " level)"
-.RB "[default: " EL_INFO "]"
-.RS
-. B EL_LEVEL
-sets what the current logging level shall be.
-Altough it accepts
-. B enum el_level
-type, this can be whatever number from range <0, 7>.
-The higher the level, the lower priority of the message.
-All messages that have lower priority (higher number) then currently set
-. I level
-will not be printed.
-There are 8 predefined levels, sorted by priority (highest first):
-. PP
-. RS
-. B EL_FATAL,
-. br
-. B EL_ALERT,
-. br
-. B EL_CRIT,
-. br
-. B EL_ERROR,
-. br
-. B EL_WARN,
-. br
-. B EL_NOTICE,
-. br
-. B EL_INFO,
-. br
-. B EL_DBG
-. RE
-. PP
-. B ERRORS
-. RS
-. B EINVAL
-. RS
-specified
-. I level
-is invalid (bigger than EL_DBG).
-. RE
-. RE
-.RE
-.PP
-.BI "EL_OUT (" enum " " el_output " outputs)"
-.RB "[default: " EL_OUT_STDERR "]"
-.RS
-. B EL_OUT
-simply sets to what
-.IR outputs .
-logs will be printed to with any of the printing
-function.
-User can enable as many outputs as he desires - it can be all inputs or even
-none (if one wants to surpress logging for some time).
-To enable multiple outputs join values with
-. B or
-operator (
-. B |
-).
-. PP
-Currently following
-.I outputs
-can be enabled.
-. PP
-. B EL_OUT_STDERR
-. RS
-Messages will be printed to standard error output
-. RE
-. PP
-. B EL_OUT_STDOUT
-. RS
-Messages will be printed to standard output
-. RE
-. PP
-. B EL_OUT_SYSLOG
-. RS
-Messages will be sent to syslog facility. This requires system with implemented
-POSIX.1-2001 and any syslog daemon
-. RE
-. PP
-. B EL_OUT_FILE
-. RS
-Messages will be printed to file.
-To work user should set output file with
-. BR EL_FPATH .
-Log rotation can be configured with
-. B EL_FROTATE_NUMBER
-and
-. B EL_FROTATE_SIZE
-options.
-. RE
-. PP
-. B EL_OUT_NET
-. RS
-Messages shall be printed to external server.
-This requires BSD Sockets to be enabled on the clients system, and listening
-server.
-(TODO Not implemented yet)
-. RE
-. PP
-. B EL_OUT_TTY
-. RS
-Prints messages directly to configured serial console.
-Apart from setting this, user should also configure device and speed with
-. BR EL_TTY_DEV .
-. RE
-. PP
-. B EL_OUT_ALL
-. RS
-Enables all supported outputs at once
-. RE
-. PP
-. B EL_OUT_NONE
-. RS
-Disables every output - logs won't be printed at all
-. RE
-. PP
-. B EL_OUT_CUSTOM
-. RS
-Enables custom function to be called on log print.
-Pointer to custom function needs to be set with
-. B EL_CUSTOM_PUTS
-option.
-. RE
-. PP
-Many of the outputs can be configured for special needs, and some of them need
-mandatory configuration.
-For information about output configuration see proper option description
-. PP
-. B ERRORS
-. RS
-. B EINVAL
-. RS
-Specified
-. I output
-is invalid
-. RE
-. RE
-. PP
-. RS
-. B ENODEV
-. RS
-Specified
-.I output
-is not implemented on current system (support was not compiled into library)
-. RE
-. RE
-.RE
-.PP
-.BI "EL_PRINT_NL (" int " nl)"
-.RB "[default: " 1 "]"
-.RS
-When enables, new line marker will be added to each print.
-If you disable it, you will be able to create very long lines
-with consecutive print calls.
-.RE
-.PP
-.BI "EL_PREFIX (" const " " char " " * "prefix)"
-.RB "[default: " unset " (won't be printed)]"
-.RS
-You can configure logger to add
-. I prefix
-to every message you print.
-. I prefix
-will be printed between log level info "i/" and you message.
-No spaces are added.
-If you set your
-. I prefix
-to simple
-. BR PREFIX ,
-printed message will be
-. BR "i/PREFIXmy log message" ,
-so you might want to add space there.
-If
-. I prefix
-is bigger than
-. B EL_PREFIX_LEN
-prefix will be truncated.
-To disable prefixing, simply set
-. I prefix
-to
-. BR NULL .
-.RE
-.PP
-.BI "EL_COLORS (" int " colors)"
-.RB "[default: " 0 "]"
-.RS
-If this is set to 1, output will be enriched with ANSI colors depending on the
-message severity.
-This option needs terminal supporting colors.
-You can store messages with colors to file, and then read them with colors on
-color-enabled terminal.
-If this is set to 0, no colors will be added.
-. PP
-. B ERRORS
-. RS
-. B EINVAL
-. RS
-Input argument is different than 1 or 0
-. RE
-. RE
-.RE
-.PP
-.BI "EL_TS (" enum " " el_option_timestamp " timestamp)"
-.RB "[default: " EL_TS_OFF "]"
-.RS
-Allows timestamp to be added to each log message. Possible values for
-.I timestamp
-are:
-. PP
-. B EL_TS_OFF
-. RS
-Timestamp will not be added to messages
-. RE
-. PP
-. B EL_TS_SHORT
-. RS
-Short timestamp will be added to log in format
-. B [1503661223.537631]
-. RE
-. PP
-. B EL_TS_LONG
-. RS
-Long timestamp will be added to log in format
-. B [2017-08-25 11:40:23.537651]
-. RE
-. PP
-. B ERRORS
-. RS
-. B EINVAL
-. RS
-Input argument is invalid
-. RE
-. PP
-. B ENOSYS
-. RS
-Timestamp support was not compiled in and setting this option is disabled.
-. RE
-. RE
-.RE
-.PP
-.BI "EL_TS_TM (" enum " " el_option_timestamp_timer " timer)"
-.RB "[default: " EL_TS_TM_TIME "]"
-.RS
-Sets the timer source for the timestamp print.
-. PP
-. B EL_TS_TM_CLOCK
-. RS
-Library will use value from
-. BR clock ()
-function.
-With this clock precission varies from 10^-3[s] to 10^-9[s].
-On POSIX systems, this clock has precision of 10^-6[s].
-This timer has a lot drawbacks, time value is unspecified at the beggining of
-the program, timer is not incremented when thread is sleeping, timer will
-overlap eventually (on 32bit systems with POSIX it takes around 72 minutes for
-the clock to overlap).
-On the other hand this is the most precise clock for pure c89 systems without
-POSIX.
-. RE
-. PP
-. B EL_TS_TM_TIME
-. RS
-Time is taken from
-. BR time ()
-function.
-This returns current wall clock of the system, it's precision is very low
-(1[s]), but it's pure c89 and it is good for logging low frequent messages.
-This clock is susceptible to unexpected time change (from NTP or by root
-itself).
-. RE
-. PP
-. B EL_TS_TM_REALTIME
-. RS
-Time is taken from
-. BR clock_gettime ()
-using
-. B CLOCK_REALTIME
-clock.
-This required system with POSIX.1-2001.
-This time returns current system wall clock, but it's precision is much higher
-than
-. B EL_TS_TM_TIME
-clock (depending on system it can vary from 10^-3[s] up to even 10^-9[s]).
-Just like it is with
-. B EL_TS_TM_TIME
-this timestamp can jump forward of backward if it is changed in the system.
-. RE
-. PP
-. B EL_TS_TM_MONOTONIC
-. RS
-This clock is similar to
-. B EL_TS_TM_REALTIME
-but it shows time from unspecified time and is not affected by time change
-(it can still be altered with
-. BR adjtime ()
-or NTP)
-. RE
-. PP
-. B ERRORS
-. RS
-. B EINVAL
-. RS
-Input argument is invalid
-. RE
-. PP
-. B ENODEV
-. RS
-Specified timer source was not compiled in and is not available
-. RE
-. RE
-.RE
-.PP
-.BI "EL_TS_FRACT (" enum " " el_option_timestamp_fraction " fraction)
-.RB "[default: " EL_TS_FRACT_OFF "]"
-.RS
-This option controls how to display fractions of seconds.
-If high resolution is not needed or not supported, it's best to set this to
-lowest resolution possible.
-Table will show exacly what this is about.
-Example uses long timestamp, interesting part is after date after dot '.'.
-.PP
-.nf
- +-----------------+-------------------------------+
- | value | resulting timestamp string |
- +-----------------+-------------------------------+
- | EL_TS_FRACT_OFF | 2018-04-17 22:02:57 |
- | EL_TS_FRACT_MS | 2018-04-17 22:02:57.070 |
- | EL_TS_FRACT_US | 2018-04-17 22:02:57.070518 |
- | EL_TS_FRACT_NS | 2018-04-17 22:02:57.070518782 |
- +-----------------+-------------------------------+
-.fi
-.RE
-.PP
-.BI "EL_PRINT_LEVEL (" int " print)"
-.RB "[default: " 1 "]"
-.RS
-If this is set to 1, each log will have log level information prefix in format
-"l/" where 'l' is first character of level message is printed with, for example:
-. PP
-. RS
-c/this is critical message
-. br
-n/this is just a notice
-. br
-d/debug print
-. RE
-.PP
-If value is set to 0, level information will not be added, and above messages
-would like like this
-.PP
-. RS
-this is critical message
-. br
-this is just an notice
-. br
-debug print
-. RE
-. PP
-. B ERRORS
-. RS
-. B EINVAL
-. RS
-Input argument is different than 1 or 0
-. RE
-. RE
-.RE
-.PP
-.BI "EL_FINFO (" int " finfo)"
-.RB "[default: " 0 "]"
-.RS
-If set to 1, adds information about log location to each message in format
-[some_file.c:123]. Setting this to 0, will result in no file information at all
-. PP
-. B ERRORS
-. RS
-. B EINVAL
-. RS
-Input argument is different than 1 or 0
-. RE
-. RE
-.RE
-.PP
-.BI "EL_FUNCINFO (" int " funcinfo)"
-.RB "[default: " 0 "]"
-.RS
-If set to 1, adds information about function from which message has been
-printed in format [funcname()] or if
-. B EL_FINFO
-is enabled [some_file.c:123:funcname()].
-Setting this to 0 will result in no function information.
-. PP
-. B ERRORS
-. RS
-. B EINVAL
-. RS
-Input argument is different than 1 or 0
-. RE
-. RE
-.RE
-.PP
-.B EL_CUSTOM_PUT (
-.IB "int (*" el_custom_put ")(const char *s, size_t slen, void *user)" ,
-.IB void\ *user
-.B )
-.RB "[default: " unset "]"
-.RS
-Sets function pointer for custom message print.
-Function will receive complete messsage (after processsing) to print, just as it
-would be printed to ie. stderr or another facility. Both binary and string data
-can be received this way.
-. PP
-. I s
-points to a data buffer, it can be null terminated string, or arbitrary binary
-data - depending on which functions has been called.
-. PP
-. I slen
-contains size of
-. I s
-buffer.
-If
-. I s
-is null terminated string, then
-. I slen
-contains length of string including null terminator character.
-For binary data, it contains size of binary buffer.
-. PP
-. I user
-pointer can be used to pass own logger object where data shall be sent.
-For example it may contain pointer to
-. B el
-struct, if you don't use global el struct.
-. PP
-Function cannot fail. If NULL is passed, custom function won't be called.
-It is still mandatory to enable custom printing with
-. BR el_option (3)\ -\ EL_OUT .
-.RE
-.PP
-.BI "EL_FPATH (" const " " char " " * "path)"
-.RB "[default: " unset "]"
-.RS
-Sets the
-.I path
-for the logs. Logs will be stored in this file. If file
-rotation is enabled, a numer will be postfixed to each file. See
-. B EL_FROTATE_NUMBER
-in this page for more details.
-. PP
-. B ERRORS
-. RS
-. B EINVAL
-. RS
-Input parameter is NULL
-. RE
-. PP
-. B ENAMETOOLONG
-. RS
-File name is too long
-. RE
-. PP
-Function can also fail and set
-. I errno
-for any of the errors specified for the routing
-. BR fopen ()
-. RE
-.PP
-If function fails with
-.B EINVAL
-or
-.BR ENAMETOOLONG ,
-file is not opened and any calls that logs to file will
-result in failure.
-Any other error is in reality just a warning, meaning file could not have been
-opened now, but embedlog will try to reopen in each time it logs to file.
-.RE
-.PP
-.BI "EL_FROTATE_NUMBER (" int " number)"
-.RB "[default: " 0 "]"
-.RS
-If set to 0, file rotation will be disabled and logs will be printed into
-specified file without size limit.
-The only size limit is the one presented by the filesystem and architecture.
-. PP
-If this value is bigger than 0, file rotation will be enabled. All files will
-have suffixes added to name set in EL_FPATH. For example,
-. IR program.log.0 .
-Files are enumareted from
-. I .0
-to
-. IR .n ,
-where
-. I n
-is set rotate number.
-File with suffix
-. I .0
-is the oldest one, and the higher the number, the newer the file is.
-If logger reaches maximum number of files, oldest one with suffix
-. I .0
-will be deleted and suffixes of the files will be decremented by 1 (ie.
-. I log.1
-will be renamed to
-. IR log.0 ,
-. I log.2
-will be renamed to
-. I log.1
-and so on).
-. PP
-User can also pass 1 here, but if file reaches its size limit, it will be
-deleted and printing will continue from the empty file
-. PP
-When
-. I number
-is bigger than 10, padded zeroes will be added to rotated logs like
-. IR log.02\ ,\ log.004\ or\ log.076 .
-Actual number of padded zeroes depends in
-. I number
-passed.
-For bigger than 10 it will be 1 zero, for bigger than 100 it will be 0
-zeroes and so on.
-This is done to ease up sorting when one would want to concat all files
-with one simple
-. BR cat\ * .
-. PP
-. B ERRORS
-. RS
-. B EINVAL
-. RS
-Input parameter is less than 0 or bigger than
-. BR USHRT_MAX (65535).
-. RE
-. RE
-.RE
-.PP
-.BI "EL_FROTATE_SYMLINK (" int " enable)"
-.RB "[default: " 1 "]"
-.RS
-When
-. B EL_FROTATE_NUMBER
-is bigger than 0, this option is enabled and program runs on UNIX,
-. B embedlog
-will create symlink file in the same directory as rest of the logs with base
-name of
-. I path
-that is passed to
-. BR EL_FPATH .
-So if "/var/log/program/program.log" path is passed, after some time more
-or less this file structure will be generated
-. PP
-. nf
- /var/log/program/program.log.0
- /var/log/program/program.log.1
- /var/log/program/program.log.2
- /var/log/program/program.log.3
- /var/log/program/program.log -> program.log.3
-. fi
-. PP
-Symlink will always point to file directly in the same directory.
-Symlink file will always point to most recent log file. This option
-is enabled by default.
-. PP
-. B ERRORS
-. RS
-. B EINVAL
-. RS
-Input parameter is not 0 or 1
-. RE
-. RE
-.RE
-.PP
-.BI "EL_FROTATE_SIZE (" unsigned\ long " size)"
-.RB "[default: " 0 "]"
-.RS
-This defines
-.I size
-at which files will be rotated.
-If message being printed would overflow rotate size, current file will be closed
-and new one will be created, and current message will be stored in that new
-file.
-It is guaranteed that file will not be bigger than value set in this option.
-If log printed into file is bigger than configure rotate size, message will be
-truncated, to prevent file bigger than configure rotate size.
-It's very rare situation as it doesn't make a lot of sense to set rotate size to
-such small value.
-. PP
-. B ERRORS
-. RS
-. B EINVAL
-. RS
-Value is less than 1
-. RE
-. RE
-.RE
-.PP
-.BI "EL_FSYNC_EVERY (" unsigned\ long " size)"
-.RB "[default: " 32768 "]"
-.RS
-Simply writing data to file descriptor is not enough, metadata also has to be
-synced or you are facing data loose on unexpected power loose.
-Yes, data will be on block device, but entry to it in file system will not be
-updated, thus system will think file did not change.
-To prevent that one must sync data and metadata periodically.
-Data will be synced every
-.I size
-of bytes written.
-It basically translates to 'how much data am I ready to loose?'.
-Set this too high and you may loose a significant ammout of data on power lose.
-Set this too low and your performance goes out of the window.
-. PP
-. B ERRORS
-. RS
-. B EINVAL
-. RS
-Value is less than 0
-. RE
-. RE
-.RE
-.PP
-.BI "EL_FSYNC_LEVEL (" enum " " el_level " level)"
-.RB "[default: " EL_FATAL "]"
-.RS
-If level of printed message is
-. I level
-or less (that is higher priority), it will be synced to disk every single time
-regardless of
-. B EL_FSYNC_EVERY
-option.
-Messages with level
-. B EL_FATAL
-(that is also default value for level sync) are synced always regardless of any
-options set.
-Messages printed with functions that don't take log level, will be treated as
-messages with
-. B EL_DBG
-level.
-If
-. I level
-is set to
-. B EL_DBG
-every message printed with any function will be immediately synced to drive
-(careful with that, this will impact performance a great deal if you print a lot
-of debug messages).
-. PP
-. B ERRORS
-. RS
-. B EINVAL
-. RS
-specified
-. I level
-is invalid (bigger than EL_DBG).
-. RE
-. RE
-.RE
-.PP
-.BI "EL_TTY_DEV (" const\ char\ * "dev, " speed_t " speed)"
-.RB "[default: " unset "]"
-.RS
-Tells
-.I embedlog
-to use
-.I dev
-serial device configured to
-.IR speed .
-Serial device will also be configured to transmit in 8 bits of data, without
-parity and one stop bit (8N1).
-Logger uses only transmit pin (TX) and will translate all
-.B LF
-into
-.BR CR-LF .
-If
-.I speed
-is configured to
-.BR B0,
-serial port settings will not be altered, library will simply open port and
-will happily work on current serial settings.
-. PP
-. B ERRORS
-. RS
-Function can return errors from
-. BR open ,
-. BR tcgetattr ,
-. B cfsetispeed
-and
-. BR tcsetattr .
-. RE
-.RE
-.PP
-.BI "EL_THREAD_SAFE (" int " safe)"
-.RB "[default: " 0 "]"
-.RS
-By default,
-. B embedlog
-is not thread safe.
-While it may be relatively safe to use it in multi-thread environment
-when you are logging to
-. B stdio
-or
-. BR stderr ,
-this surely isn't the case for more complex outputs like printing to file.
-Also, without
-. B EL_THREAD_SAFE
-calling
-. BR el_pmemory (3)
-may result in interlacing prints.
-. PP
-So, when using embedlog in multi-threaded environment, it is advised to enable
-. B EL_THREAD_SAFE
-by passing 1 as
-. I safe
-argument.
-. B embedlog
-will then
-. BR pthread_mutex_lock ()
-whenever threads access
-. I el
-object.
-. PP
-. B EL_THREAD_SAFE
-call must be performed when no other threads are accessing
-. I el
-object, since at this point it is not possible to lock the mutex.
-Common usage is to enable thread safety at the beggining - right after
-. BR el_init (3),
-and leave it to be destroyed by
-. BR el_cleanup (3).
-. PP
-It is safe to call this option multiple time with same argument.
-.B embedlog
-will not allow for multiple initialization nor destruction of mutex.
-When options is called for the second time with same argument (like 1),
-nothing will happen and funciton will return 0.
-. PP
-. B ERRORS
-. RS
-Function can return errors from
-. BR pthread_mutex_init (),
-and
-. BR pthread_mutex_destroy ().
-. PP
-. B EINVAL
-. RS
-. I safe
-is different than 1 or 0
-. RE
-. RE
-.RE
-.SH RETURN VALUE
-.PP
-On success 0 is returned. -1 is returned when any error occured.
-.SH ERRORS
-.TP
-.B EINVAL
-Passed
-.I option
-is invalid.
-.TP
-.B ENOSYS
-Passed
-.I option
-is not supported on this system (support was not compiled)
-.PP
-Also check for error description of specific option that failed for more
-informations
-.SH SEE ALSO
-.PP
-.BR el_overview (7),
-.BR el_cleanup (3),
-.BR el_destroy (3),
-.BR el_flush (3),
-.BR el_init (3),
-.BR el_new (3),
-.BR el_ocleanup (3),
-.BR el_oflush (3),
-.BR el_oinit (3),
-.BR el_operror (3),
-.BR el_opmemory (3),
-.BR el_opmemory_table (3),
-.BR el_oprint (3),
-.BR el_oputs (3),
-.BR el_ovprint (3),
-.BR el_perror (3),
-.BR el_pmemory (3),
-.BR el_pmemory_table (3),
-.BR el_print (3),
-.BR el_puts (3),
-.BR el_vprint (3).
diff --git a/man/el_oputs.3 b/man/el_oputs.3
deleted file mode 100644
index 8a9800f..0000000
--- a/man/el_oputs.3
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/el_print.3
diff --git a/man/el_overview.7 b/man/el_overview.7
deleted file mode 100644
index cf02472..0000000
--- a/man/el_overview.7
+++ /dev/null
@@ -1,358 +0,0 @@
-.TH "el_overview" "7" "10 June 2019 (v9999)" "bofc.pl"
-.SH NAME
-.PP
-.B el_overview
-- quick overview of
-.B embedlog
-logging library
-.SH SYNOPSIS
-.PP
-.B embedlog
-- is a highly portable
-.B c89
-complaint logger (with additional features for users with
-.B c99
-compilers and/or
-.B POSIX
-systems).
-This library is designed mainly for embedded devices, but can also be
-used in high level OSes like
-.BR Linux .
-.SH DESCRIPTION
-.PP
-Logger incorporates features like:
-.PP
-.RS
-- printing to different outputs (simultaneously) like:
-.RS
-- stderr
-.br
-- syslog (very limited, works on *nuttx* for now)
-.br
-- directly to serial device (like /dev/ttyS0)
-.br
-- file (with optional rotating and syncing to prevent data loss)
-.br
-- automatic file reopening on unexpected events (file deletion, SD remount)
-.br
-- custom routine, can be anything, embedlog just calls your function with
-string to print
-.RE
-- timestamping using following clocks:
-.RS
-- clock_t
-.br
-- time_t
-.br
-- CLOCK_REALTIME (requires POSIX)
-.br
-- CLOCK_MONOTONIC (requires POSIX)
-.br
-- configurable precision of fraction of seconds (mili, micro, nano)
-.RE
-- printing file and line information
-.br
-- 8 predefined log levels (total rip off from syslog(2) levels)
-.br
-- colorful output (for easy error spotting)
-.br
-- print memory block in wireshark-like output
-.br
-- fully binary logs with binary data (like CAN frames) to save space
-.RE
-.RE
-.PP
-Library implements following functions:
-.PP
-.BI "int el_init(void)"
-.br
-.BI "int el_cleanup(void)"
-.br
-.BI "int el_option(enum el_option " option ", ...)"
-.br
-.BI "int el_puts(const char *" string ")"
-.br
-.BI "int el_putb(const void *" memory ", size_t " mlen ")"
-.br
-.BI "int el_print(const char *" file ", size_t " line ", const char *" func ", \
-enum el_level " level ", const char *" fmt ", " ... ")"
-.br
-.BI "int el_vprint(const char *" file ", size_t " line ", const char *" func ", \
-enum el_level " level ", const char *" fmt ", va_list " ap ")"
-.br
-.BI "int el_perror(const char *" file ", size_t " line ", \
-const char *" func ", enum el_level " level ", const char *" fmt ", " ... ")"
-.br
-.BI "int el_pmemory(const char *" file ", size_t " line ", \
-const char *" func ", enum el_level " level ", const void *" memory ", \
-size_t " mlen ")
-.br
-.BI "int el_pmemory_table(const char *" file ", size_t " line ", \
-const char *" func ", enum el_level " level ", const void *" memory ", \
-size_t " mlen ")
-.br
-.BI "int el_pbinary(enum el_level " level ", const void *" memory ", \
-size_t " mlen ")
-.br
-.BI "int el_flush(void)"
-.br
-.B const struct el *el_get_el(void)
-.PP
-Each functions has its equivalent function that accepts
-.I el
-object as argument.
-This is helpful if we want to have more than one, separated loggers in a single
-program.
-Please see
-.BR el_option (3)
-for more information.
-.PP
-.BI "int el_oinit(struct el *" el ")"
-.br
-.BI "int el_ocleanup(struct el *" el ")"
-.br
-.B struct el * el_new(void)
-.br
-.BI "int el_destroy(struct el *" el ")"
-.br
-.BI "int el_ooption(struct el *" el ", enum el_option " option ", \
-\&...)"
-.br
-.BI "int el_oputs(struct el *" el ", const char *" string ")"
-.br
-.BI "int el_oputb(struct el *" el ", const void *" memory ", \
-size_t " mlen ")"
-.br
-.BI "int el_oprint(const char *" file ", size_t " line ", \
-const char *" func ", enum el_level " level ", struct el *" el ", \
-const char *" fmt ", " ... ")"
-.br
-.BI "int el_ovprint(const char *" file ", size_t " line ", \
-const char *" func ", enum el_level " level ", struct el *" el ", \
-const char *" fmt ", va_list " ap ")"
-.br
-.BI "int el_operror(const char *" file ", size_t " line ", \
-const char *" func ", enum el_level " level ", struct el *" el ", \
-const char *" fmt ", " ... ")"
-.br
-.BI "int el_opmemory(const char *" file ", size_t " line ", \
-const char *" func ", enum el_level " level ", struct el *" el ", \
-const void *" memory ", size_t " mlen ")"
-.br
-.BI "int el_opmemory_table(const char *" file ", size_t " line ", \
-const char *" func ", enum el_level " level ", struct el *" el ", \
-const void *" memory ", size_t " mlen ")"
-.br
-.BI "int el_opbinary(enum el_level " level ", struct el *" el ", \
-const void *" memory ", size_t " mlen ")"
-.br
-.BI "int el_oflush(struct el *" el ")"
-.PP
-For more information about a function open manual page with functions name from
-section 3 (ie. for el_oputs, you'd open
-.BR el_oputs (3))
-.PP
-Every function that accepts 3 parameters
-.IR level ,
-.I file
-and
-.I line
-as its first arguments, can accept short macro that injects proper values into
-function.
-Awailable macros are:
-.PP
-.RS
-.BR ELF " Fatal errors, usually precedes application crash"
-.br
-.BR ELA " Alert, vey major error that should be fixed as soon as possible"
-.br
-.BR ELC " Critical"
-.br
-.BR ELE " Error"
-.br
-.BR ELW " Warning"
-.br
-.BR ELN " Normal log, but of high importance"
-.br
-.BR ELI " Information message, shouldn't spam too much here"
-.br
-.BR ELD " Debug messages, can spam as much as you'd like"
-.RE
-.PP
-So instead of calling
-.PP
-.nf
- el_print(__FILE__, __LINE__, EL_FUNC_NAME, EL_NOTICE, "Notice message");
-.fi
-.PP
-You can simply call it like
-.PP
-.nf
- el_print(ELN, "Notice message");
-.fi
-.PP
-There are also equivalent macros for use with functions that also provides
-.I el
-object, so the can be used with
-.B el_o
-function family.
-To make these work, you need to provide
-.B EL_OPTIONS_OBJECT
-macro.
-Check
-.BR el_print (3)
-for more info about that.
-.PP
-.RS
-.BR OELF " Fatal errors, usually precedes application crash"
-.br
-.BR OELA " Alert, vey major error that should be fixed as soon as possible"
-.br
-.BR OELC " Critical"
-.br
-.BR OELE " Error"
-.br
-.BR OELW " Warning"
-.br
-.BR OELN " Normal log, but of high importance"
-.br
-.BR OELI " Information message, shouldn't spam too much here"
-.br
-.BR OELD " Debug messages, can spam as much as you'd like"
-.RE
-.PP
-So instead of calling
-.PP
-.nf
- el_oprint(__FILE__, __LINE__, EL_FUNC_NAME, EL_NOTICE, &g_log_object, "Notice message");
-.fi
-or
-.nf
- el_oprint(ELN, &g_log_object, "Notice message");
-.fi
-.PP
-You can simply call it like
-.PP
-.nf
- el_oprint(OELN, "Notice message");
-.fi
-.SH "STABLE ABI CONSIDERATION"
-.PP
-Since
-.B embedlog
-is versatile and can work on both hardcore embedded systems (nuttx, freertos,
-bare metals) and on big CPUs that can run Linux, library must provide a way
-for user to use stack-allocated objects and stable ABI.
-Unfortunately there is no way to provide both at the same time, so
-.B embedlog
-provides two solutions so everybody is happy.
-.PP
-Note that library versioning follows
-.B STABLE ABI
-way of using library.
-So if feature is added that adds new field to
-.BR "struct el",
-then this will not be treated as ABI breakage, because if you are using
-.BR el_new (3)
-or
-.BR el_init (3)
-functions, ABI will not be broken.
-Only when using
-.BR el_oinit (3)
-ABI will be broken.
-.SS "STABLE ABI"
-.PP
-When stable ABI is required, user must initialize
-.B embedlog
-either with
-.BR el_init (3)
-or
-.BR el_new (3)
-function.
-User also must not access internal fields directly and all operations on
-.I el
-object must be done through the API functions.
-.BR el_new (3)
-will malloc necessary memory for the user which must be freed with
-.BR el_destroy (3)
-function.
-Under no circumstances use
-.B sizeof
-on the object nor struct.
-Operation will succeed, but may return invalid results when library is updated.
-To put it in as few word as possible - you don't know anything about internals
-of
-.BR "struct el" .
-.SS "STACK ALLOCATED OBJECT"
-.PP
-When you use library in hardcore embedded environment, where there is not
-dynamic linking involved, you are save to ignore any ABI changes, since
-you always build your programs alongside the library.
-But thanks to that you can avoid
-.BR malloc ()
-call and allocate everything on the stack.
-To allocate object on stack you must use
-.BR el_oinit (3)
-function, and deinitialize object with
-.BR el_ocleanup (3).
-.PP
-If you are using
-.BR el_oinit (3)
-on systems with dynamic library support you are suscible to ABI breakage and
-undefined behaviour when only new features are added, or even when bugfix
-introduces new field to
-.BR "struct el" .
-Heck, even recompilation with different flags can break ABI here.
-Do not use this approach if your system have dynamic library support unless
-you can rebuild all programs against new version of library.
-.PP
-.B You've been warned!
-.SH EXAMPLE
-.PP
-Initial setup is very trivial.
-One should call init function and it will print to stderr by default.
-Output can also be customized with proper el object, see
-.BR el_option (3)
-for more details.
-.PP
-.nf
- #include <embedlog.h>
-
- int main(void)
- {
- /* initialize library, default output is stderr */
- el_init();
-
- /* print message with info severity */
- el_print(ELI, "answer is %d", 42);
-
- /* clean after ourselfs */
- el_cleanup();
-
- return 0;
- }
-.fi
-.SH SEE ALSO
-.PP
-.BR el_cleanup (3),
-.BR el_destroy (3),
-.BR el_flush (3),
-.BR el_init (3),
-.BR el_new (3),
-.BR el_ocleanup (3),
-.BR el_oflush (3),
-.BR el_oinit (3),
-.BR el_ooption (3),
-.BR el_operror (3),
-.BR el_opmemory (3),
-.BR el_opmemory_table (3),
-.BR el_oprint (3),
-.BR el_option (3),
-.BR el_oputs (3),
-.BR el_ovprint (3),
-.BR el_perror (3),
-.BR el_pmemory (3),
-.BR el_pmemory_table (3),
-.BR el_print (3),
-.BR el_puts (3),
-.BR el_vprint (3).
diff --git a/man/el_ovprint.3 b/man/el_ovprint.3
deleted file mode 100644
index 8a9800f..0000000
--- a/man/el_ovprint.3
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/el_print.3
diff --git a/man/el_perror.3 b/man/el_perror.3
deleted file mode 100644
index 8a9800f..0000000
--- a/man/el_perror.3
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/el_print.3
diff --git a/man/el_pmemory.3 b/man/el_pmemory.3
deleted file mode 100644
index 8a9800f..0000000
--- a/man/el_pmemory.3
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/el_print.3
diff --git a/man/el_pmemory_table.3 b/man/el_pmemory_table.3
deleted file mode 100644
index 8a9800f..0000000
--- a/man/el_pmemory_table.3
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/el_print.3
diff --git a/man/el_print.3 b/man/el_print.3
deleted file mode 100644
index 23d9079..0000000
--- a/man/el_print.3
+++ /dev/null
@@ -1,521 +0,0 @@
-.TH "el_print" "3" "10 June 2019 (v9999)" "bofc.pl"
-.SH NAME
-.PP
-.BR el_print ,
-.BR el_vprint ,
-.BR el_puts ,
-.BR el_pmemory,
-.BR el_pmemory_table,
-.B el_perror
-- prints message to previously configured outputs.
-.SH SYNOPSIS
-.PP
-.B "#include <embedlog.h>"
-.PP
-.BI "int el_puts(const char *" message ")"
-.br
-.BI "int el_putb(const void *" memory ", size_t " mlen ")"
-.br
-.BI "int el_print(const char *" file ", size_t " line ", const char *" func ", \
-enum el_level " level ", const char *" fmt ", " ... ")"
-.br
-.BI "int el_vprint(const char *" file ", size_t " line ", const char *" func ", \
-enum el_level " level ", const char *" fmt ", va_list " ap ")"
-.br
-.BI "int el_perror(const char *" file ", size_t " line ", \
-const char *" func ", enum el_level " level ", const char *" fmt ", " ... ")"
-.br
-.BI "int el_pmemory(const char *" file ", size_t " line ", \
-const char *" func ", enum el_level " level ", const void *" memory ", \
-size_t " mlen ")
-.br
-.BI "int el_pmemory_table(const char *" file ", size_t " line ", \
-const char *" func ", enum el_level " level ", const void *" memory ", \
-size_t " mlen ")
-.br
-.BI "int el_pbinary(enum el_level " level ", const void *" memory", \
-size_t " mlen ")
-.PP
-.BI "int el_oputs(struct el *" el ", const char *" message ")"
-.br
-.BI "int el_oputb(struct el *" el ", const void *" memory ", \
-size_t " mlen ")"
-.br
-.BI "int el_oprint(const char *" file ", size_t " line ", \
-const char *" func ", enum el_level " level ", struct el *" el ", \
-const char *" fmt ", " ... ")"
-.br
-.BI "int el_ovprint(const char *" file ", size_t " line ", \
-const char *" func ", enum el_level " level ", struct el *" el ", \
-const char *" fmt ", va_list " ap ")"
-.br
-.BI "int el_operror(const char *" file ", size_t " line ", \
-const char *" func ", enum el_level " level ", struct el *" el ", \
-const char *" fmt ", " ... ")"
-.br
-.BI "int el_opmemory(const char *" file ", size_t " line ", \
-const char *" func ", enum el_level " level ", struct el *" el ", \
-const void *" memory ", size_t " mlen ")"
-.br
-.BI "int el_opmemory_table(const char *" file ", size_t " line ", \
-const char *" func ", enum el_level " level ", struct el *" el ", \
-const void *" memory ", size_t " mlen ")"
-.br
-.BI "int el_opbinary(enum el_level " level ", struct el *" el ", \
-const void *" memory ", size_t " mlen ")"
-.PP
-.BI "#define ELF " __FILE__ ", " __LINE__ ", " EL_FUNC_NAME ", " EL_FATAL
-.br
-.BI "#define ELA " __FILE__ ", " __LINE__ ", " EL_FUNC_NAME ", " EL_ALERT
-.br
-.BI "#define ELC " __FILE__ ", " __LINE__ ", " EL_FUNC_NAME ", " EL_CRIT
-.br
-.BI "#define ELE " __FILE__ ", " __LINE__ ", " EL_FUNC_NAME ", " EL_ERROR
-.br
-.BI "#define ELW " __FILE__ ", " __LINE__ ", " EL_FUNC_NAME ", " EL_WARN
-.br
-.BI "#define ELN " __FILE__ ", " __LINE__ ", " EL_FUNC_NAME ", " EL_NOTICE
-.br
-.BI "#define ELI " __FILE__ ", " __LINE__ ", " EL_FUNC_NAME ", " EL_INFO
-.br
-.BI "#define ELD " __FILE__ ", " __LINE__ ", " EL_FUNC_NAME ", " EL_DBG
-.PP
-.BI "#define OELF " __FILE__ ", " __LINE__ ", " EL_FUNC_NAME ", " EL_FATAL ", " EL_OPTIONS_OBJECT
-.br
-.BI "#define OELA " __FILE__ ", " __LINE__ ", " EL_FUNC_NAME ", " EL_ALERT ", " EL_OPTIONS_OBJECT
-.br
-.BI "#define OELC " __FILE__ ", " __LINE__ ", " EL_FUNC_NAME ", " EL_CRIT ", " EL_OPTIONS_OBJECT
-.br
-.BI "#define OELE " __FILE__ ", " __LINE__ ", " EL_FUNC_NAME ", " EL_ERROR ", " EL_OPTIONS_OBJECT
-.br
-.BI "#define OELW " __FILE__ ", " __LINE__ ", " EL_FUNC_NAME ", " EL_WARN ", " EL_OPTIONS_OBJECT
-.br
-.BI "#define OELN " __FILE__ ", " __LINE__ ", " EL_FUNC_NAME ", " EL_NOTICE ", " EL_OPTIONS_OBJECT
-.br
-.BI "#define OELI " __FILE__ ", " __LINE__ ", " EL_FUNC_NAME ", " EL_INFO ", " EL_OPTIONS_OBJECT
-.br
-.BI "#define OELD " __FILE__ ", " __LINE__ ", " EL_FUNC_NAME ", " EL_DBG ", " EL_OPTIONS_OBJECT
-.PP
-.BI "#define EL_DEBUG(" ... ") el_print(ELD, __VA_ARGS__)
-.PP
-Feature Test Macro
-.PP
-.BR "#define EL_DEBUG" ()
-.RS
-__ISOC99_SOURCE
-.RE
-.SH DESCRIPTION
-.PP
-Functions print log into configured outputs.
-.PP
-.BR el_puts (3)
-function prints
-.I message
-that is simple string,
-.I message
-is not altered in anyway - that means no automatic log levels, location of the
-log nor timestamp is printed - even if they are enabled.
-Logs printed with this functions are not filtered by log level, and will always
-be printed. Prints can still be suppressed by disabling output.
-.PP
-.BR el_putb (3)
-function works same as
-.BR el_puts (3)
-but binary data can be passed.
-That binary data will not be printed in ASCII like it it with
-.BR el_pmemory (3).
-If
-.I memory
-contains
-.B NULL
-characters, they will be stored to file.
-If
-.I memory
-is for example
-.B char buf[] = { 0xb0, 0xfc, 0x13, 0x37 }
-then exactly these bytes will be stored into file.
-.PP
-.BR el_print (3)
-function behaves similar to standard
-.BR printf ()
-function from the standard library, but it adds (if enabled) additional
-information, such as
-.I file
-name,
-.I line
-number or
-.I func
-name
-from where log has been printed, log
-.IR level ,
-and timestamp of the message.
-.I fmt
-and variadic variables
-.I ...
-have the same role as it is described in
-.BR printf ()
-manual page.
-.PP
-.BR el_vprint (3)
-function behaves just like
-.BR el_print (3)
-but it accepts argument pointer
-.I ap
-instead of variadic variables.
-Check
-.BR vprintf ()
-for more information.
-.PP
-.BR el_perror (3)
-works the same way as
-.BR el_print (3)
-but will also print information about current errno that was set.
-If
-.I fmt
-is
-.BR NULL ,
-only information about errno will be printed.
-It is similar to
-.BR perror ()
-function.
-It is guaranteed that
-.BR el_perror (3)
-functions will not modify
-.B errno
-value.
-.PP
-.BR el_pmemory (3)
-is designed to print memory location in a nice hex+ascii format.
-Function accepts pointer to
-.I memory
-and
-.I mlen
-number of bytes caller wants to print.
-If
-.I mlen
-is 0, function won't print anything and will return
-.B EINVAL
-error.
-Function doesn't care what is under passed address, memory block may contain
-strings with null characters '\\0', integers, floats or even
-.B struct
-objects.
-.PP
-Example output can look like this.
-We print all ascii table, to present printing of printable and non-printable
-values.
-.PP
-.nf
- 0x0000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f ................
- 0x0010 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f ................
- 0x0020 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f !"#$%&'()*+,-./
- 0x0030 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 0123456789:;<=>?
- 0x0040 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f @ABCDEFGHIJKLMNO
- 0x0050 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f PQRSTUVWXYZ[\]^_
- 0x0060 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f `abcdefghijklmno
- 0x0070 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f pqrstuvwxyz{|}~.
-.fi
-.PP
-.BR el_pmemory_table (3)
-works just like
-.BR el_pmemory (3)
-but also prints table-like header and footer.
-.PP
-.nf
- ------ ----------------------------------------------- ----------------
- offset hex ascii
- ------ ----------------------------------------------- ----------------
- 0x0000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f ................
- 0x0010 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f ................
- 0x0020 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f !"#$%&'()*+,-./
- 0x0030 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 0123456789:;<=>?
- 0x0040 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f @ABCDEFGHIJKLMNO
- 0x0050 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f PQRSTUVWXYZ[\]^_
- 0x0060 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f `abcdefghijklmno
- 0x0070 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f pqrstuvwxyz{|}~.
- ------ ----------------------------------------------- ----------------
-.fi
-.PP
-.BR el_pbinary (3)
-is used to log binary data into block device.
-Both metadata and data itself are treated as binary data.
-Such files cannot be read with text tools like
-.BR less ,
-but rather needs special program that will parse the file.
-This may be usefull when you need, for example to log every message on CAN bus.
-If there are a lot of messages, it may be better to store them in binary format
-as this may save *a lot* of space.
-.PP
-.BR el_pbinary (3)
-uses specific format to store metadata to save as much space as possible.
-All numerical values in metadata are variadic in size. Order of fields are as
-follows:
-.PP
-.nf
- +-------+------------+--------------+-------------+------+
- | flags | ts_seconds | ts_fractions | data_length | data |
- +-------+------------+--------------+-------------+------+
-.fi
-.PP
-The only mandatory fields are
-.BR flags ", " data_length " and " data .
-.B flags
-determin what fields are present.
-.B flags
-field is always 1 byte in size and its format is
-.PP
-.nf
- +------+-------+-----------------------------------------------------------+
- | bits | value | description |
- +------+-------+-----------------------------------------------------------+
- | 0 | 0 | both ts_seconds and ts_fraction will not appear |
- | +-------+-----------------------------------------------------------+
- | | 1 | at least ts_seconds will appear, ts_fraction appearance |
- | | | depends on 1..2 bits values |
- +------+-------+-----------------------------------------------------------+
- | 1..2 | 0 | ts_fractions will not appear |
- | +-------+-----------------------------------------------------------+
- | | 1 | ts_fractions will hold milliseconds value |
- | +-------+-----------------------------------------------------------+
- | | 2 | ts_fractions will hold microseconds value |
- | +-------+-----------------------------------------------------------+
- | | 3 | ts_fractions will hold nanoseconds value |
- +------+-------+-----------------------------------------------------------+
- | 3..5 | 0..7 | severity of the log, 0 is the highest and 7 is the lowest |
- +------+-------+-----------------------------------------------------------+
- | 6..7 | 0..3 | reserved |
- +------+-------+-----------------------------------------------------------+
-.fi
-.PP
-.BR ts_seconds ", " ts_fractions " and " data_length
-are numerical values with dynamic size.
-Each byte of a numerical value can hold number up to 127 and oldest bit is used
-as continuation bit, if that bit is set, program should treat next byte as next
-part of the same numerical value.
-Below is table with example decimal values and it's encoded counterpart.
-.PP
-.nf
- +---------------+--------------------------+
- | decimal value | encoded hex value |
- +---------------+--------------------------+
- | 0 | 0x00 |
- | 1 | 0x01 |
- | 2 | 0x02 |
- | 127 | 0x7f |
- | 128 | 0x80 0x01 |
- | 129 | 0x81 0x01 |
- | 255 | 0xff 0x01 |
- | 256 | 0x80 0x02 |
- | 257 | 0x81 0x02 |
- | 16383 | 0xff 0x7f |
- | 16384 | 0x80 0x80 0x01 |
- | 16385 | 0x81 0x80 0x01 |
- | 438478374 | 0xa6 0xcc 0x8a 0xd1 0x01 |
- | 2147483647 | 0xff 0xff 0xff 0xff 0x07 |
- | 4294967295 | 0xff 0xff 0xff 0xff 0x0f |
- +---------------+--------------------------+
-.fi
-.PP
-Encoded number are always
-.BR little-endian ,
-that is first byte is always the least significant byte.
-.PP
-.B data
-is be whatever you want of any size.
-.BR el_pbinary (3)
-uses only timestamp and log level, rest of the options in
-.I el
-are simply ignores.
-.PP
-.BR el_print (3),
-.BR el_vprint (3),
-.BR el_perror (3),
-.BR el_pmemory_table (3)
-and
-.BR el_pmemory (3)
-are filtered based on their
-.IR level .
-.PP
-All of above functions have their counterpart that also accepts custom
-.I el
-object.
-This is useful if we want for example, print logs into one file, and program
-queries into another.
-It can also be used to print every level into different file.
-.PP
-When user defines
-.B EL_OPTIONS_OBJECT
-macros with
-.B OEL*
-can be used to save yourself the trouble to type
-.B &opt_obj
-each time.
-This macro should be defined to what normally would be passed to
-.B el_oprint
-functions familly.
-It usually is used with
-.B extern
-keyword like
-.PP
-.nf
- extern struct el log_foobar;
- #define EL_OPTIONS_OBJECT &log_foobar
-.fi
-.PP
-It is real pain in the ass to provide information about file in every print
-function. For that matter very simple macros have been provided.
-.PP
-.RS
-.BR ELF " Fatal errors, usually precedes application crash"
-.br
-.BR ELA " Alert, vey major error that should be fixed as soon as possible"
-.br
-.BR ELC " Critical"
-.br
-.BR ELE " Error"
-.br
-.BR ELW " Warning"
-.br
-.BR ELN " Normal log, but of high importance"
-.br
-.BR ELI " Information message, shouldn't spam too much here"
-.br
-.BR ELD " Debug messages, can spam as much as you'd like"
-.RE
-.PP
-These macros comprese first 3 parameters
-.IR file ,
-.I line
-and
-.I level
-into single, short parameter.
-For example instead calling this
-.PP
-.nf
- el_print(__FILE__, __LINE__, EL_FUNC_NAME, EL_NOTICE, "notice message number %d", num);
-.fi
-.PP
-you can simply call
-.PP
-.nf
- el_print(ELN, "notice message number %d", num);
-.fi
-.PP
-This solution works both for
-.B c89
-and
-.B c99
-standards.
-All side effects (like from calling function or incrementing variable in print
-function call) will take effect always regardless of set logging level.
-Also strings used in functions will be compiled and put into binary - always.
-If user defines
-.B NOFINFO
-in his project, all
-.B __FILE__
-,
-.B __LINE__
-and
-.B EL_FUNC_NAME
-will be unconditionally set to
-.B NULL
-and
-.B 0
-and no file information will be printed - even if it was enabled with
-.BR el_option (3).
-.PP
-If user has access to
-.B c99
-compiler, one can use
-.B EL_DEBUG
-for debuging messages only.
-Later when application is compiled with NDEBUG, all side effects as well as
-strings used will be stripped out from final binary - so no vital information
-will be leaked in such way.
-This is not possible on
-.B c89
-compiller due to absence of variadic variables in
-preprocesor macros.
-.PP
-.B EL_FUNC_NAME
-will work only on
-.B c99
-compilers, where
-.B __func__
-is defined, on
-.B c89
-compilers function name won't be printed, and setting
-.B EL_FUNCINFO
-won't help it.
-.SH RETURN VALUE
-.PP
-All functions return 0 when whole message has been successfuly printed to all
-configured outputs.
-If message couldn't be printed, it was printed only partially, or was not send
-to at least one configured output -1 is returned.
-Note that only one error is returned even if there was multiple errors.
-.SH ERRORS
-.PP
-All functions may return one of these on error
-.TP
-.B EINVAL
-Any of the input parameters is invalid.
-.TP
-.B EBADF
-Loggig to file is enabled and filename was not set with
-.B EL_FPATH
-option
-.TP
-.B EBADF
-Logging to file is enabled, file was opened sucessfuly, but log cannot be stored
-into file.
-This usually happen that file was unlinked from the file system and
-.B embedlog
-couldn't create new file again (no access to directory or directory doesn't
-exist at all).
-Log is lost, but
-.B embedlog
-will try to recreate log file everytime
-.BR el_print (3)
-is called.
-.TP
-.B ENODEV
-All possible outputs are disabled
-.PP
-.BR el_print (3),
-.BR el_vprint (3),
-.BR el_perror (3),
-.BR el_pmemory_table (3)
-and
-.BR el_pmemory (3)
-may also return:
-.TP
-.B ERANGE
-Message will not be logged as message log level is lower than configured one.
-.TP
-.B ENOBUFS
-Message is bigger than
-.B EL_LOG_MAX
-and will be truncated.
-.PP
-When logging to file is enabled, all functions may also return errors
-from
-.BR fwrite ()
-and if file rotation is enabled also from
-.BR fopen ()
-.SH SEE ALSO
-.PP
-.BR el_overview (7),
-.BR el_cleanup (3),
-.BR el_destroy (3),
-.BR el_flush (3),
-.BR el_init (3),
-.BR el_new (3),
-.BR el_ocleanup (3),
-.BR el_oflush (3),
-.BR el_oinit (3),
-.BR el_ooption (3),
-.BR el_operror (3),
-.BR el_opmemory (3),
-.BR el_opmemory_table (3),
-.BR el_option (3).
diff --git a/man/el_puts.3 b/man/el_puts.3
deleted file mode 100644
index 8a9800f..0000000
--- a/man/el_puts.3
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/el_print.3
diff --git a/man/el_vprint.3 b/man/el_vprint.3
deleted file mode 100644
index 8a9800f..0000000
--- a/man/el_vprint.3
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/el_print.3
diff --git a/readme.md b/readme.rst
index 7fc6249..49aae25 100644
--- a/readme.md
+++ b/readme.rst
@@ -1,7 +1,54 @@
-[kursg-meta]: # (order: 1)
+========
+embedlog
+========
+Quick intro
+-----------
+
+.. code-block:: c
+
+ #include <embedlog.h>
+
+ int main(void) {
+ el_init();
+
+ /* Turn on timestamp and information from which log originates */
+ el_set_timestamp(EL_TS_LONG, EL_TS_TM_REALTIME, EL_TS_FRACT_US);
+ el_print_extra_info(1);
+
+ /* Enable log to file, create max 10 files, each of 1MB of max size */
+ el_enable_file_log("/tmp/embedlog-test-file.log", 10, 1024 * 1024);
+ el_print(ELN, "from now on, logs will be printed to both file and stderr");
+ el_print(ELF, "log with fatal severity");
+
+ el_cleanup();
+ return 0;
+ }
+
+Above program will print::
+
+ [2024-02-29 14:05:51.929980][print-example.c:12:main()] n/from now on, logs will be printed to both file and stderr
+ [2024-02-29 14:05:51.930005][print-example.c:13:main()] f/log with fatal severity
+
+Dump memory locations in readable formats
+
+.. code-block:: c
+
+ const char *ascii = get_ascii_table();
+ el_pmemory(ELN, ascii, strlen(ascii));
+
+Output::
+
+ i/0x0000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f ........ ........
+ i/0x0010 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f ........ ........
+ i/0x0020 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f !"#$%&' ()*+,-./
+ i/0x0030 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 01234567 89:;<=>?
+ i/0x0040 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f @ABCDEFG HIJKLMNO
+ i/0x0050 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f PQRSTUVW XYZ[\]^_
+ i/0x0060 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f `abcdefg hijklmno
+ i/0x0070 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f pqrstuvw xyz{|}~.
About
-=====
+-----
Logger written in **C89** targeting embedded systems. It's main goals are to be
small and fast. Many features can be disabled during compilation to generate
@@ -11,20 +58,29 @@ systems, it is general **c/c++** logger that can be used in any application.
Implemented features are (most of them optionally configured in runtime):
* printing to different outputs (simultaneously) like:
- * syslog (very limited, works on *nuttx* for now)
- * directly to serial device (like /dev/ttyS0)
- * standard error (stderr)
- * standard output (stdout)
- * file (with optional log rotate, and syncing to prevent data loss)
- * automatic file reopening on unexpected events (file deletion, SD remount)
- * custom routine - can be anything **embedlog** just calls custom function
- with string to print
+
+ * syslog (very limited, works on *nuttx* for now)
+ * directly to serial device (like /dev/ttyS0)
+ * standard error (stderr)
+ * standard output (stdout)
+ * file (with optional log rotate, and syncing to prevent data loss)
+ * automatic file reopening on unexpected events (file deletion, SD remount)
+ * custom routine - can be anything **embedlog** just calls custom function
+ with string to print
+
* appending timestamp to every message
- * clock_t
- * time_t
- * CLOCK_REALTIME (requires POSIX)
- * CLOCK_MONOTONIC (requires POSIX)
- * configurable precision of fraction of seconds (mili, micro, nano)
+
+ * clock_t
+ * time_t
+ * CLOCK_REALTIME (requires POSIX)
+ * CLOCK_MONOTONIC (requires POSIX)
+ * configurable precision of fraction of seconds (mili, micro, nano)
+
+* file log rotation based on:
+
+ * file size - limit number of files and their sizes
+ * date - new file is created every day (or hour, or other choosen timeslice)
+
* print location of printed log (file and line)
* print function name of printed log (required at least c99)
* 8 predefinied log levels (total rip off from syslog(2))
@@ -32,114 +88,80 @@ Implemented features are (most of them optionally configured in runtime):
* print memory block in wireshark-like output
* fully binary logs with binary data (like CAN frames) to save space
* full thread safety using *pthread*
+* stripping binary from all strings and **embedlog** code in final release image
Almost all of these features can be disabled to save some precious bytes of
memory.
Functions description
-=====================
+---------------------
+Overview of the library (functions, use cases etc.) can be found at
+:ref:`el_overview(7) <el_overview.7:overview>` This is very good starting
+point to get to know library better.
For detailed description of every function check out
-[man pages](https://embedlog.bofc.pl/manuals.html)
+project documentation at `manual pages <manuals/index.html#manual-pages>`_
Examples
-========
-
-Check [examples](https://git.bofc.pl/embedlog/tree/examples) directory to get
+--------
+Check `examples <https://git.bofc.pl/embedlog/tree/examples>`_ directory to get
the idea of how to use **embedlog**. Examples can also be compiled to see how
they work.
-Dependencies
-============
+Short examples are also in the documentation.
+Dependencies
+------------
Library is written in **C89** but some features require implemented **POSIX** to
work. Also there are some additional features for users with **C99** compiler.
-To run unit tests, you also need [librb](https://librb.bofc.pl)
-
-Test results
-============
-
-Project has been tested on following systems/architectures
-
-operating system tests
-----------------------
-
-* arm-cortex-m4-nuttx-7.24 (manual)
-* parisc-polarhome-hpux-11.11
-* power4-polarhome-aix-7.1
-* i686-builder-freebsd-11.1
-* i686-builder-netbsd-8.0
-* i686-builder-openbsd-6.2
-* x86_64-builder-solaris-11.3
-* i686-builder-linux-gnu-4.9
-* i686-builder-linux-musl-4.9
-* i686-builder-linux-uclibc-4.9
-* x86_64-builder-linux-gnu-4.9
-* x86_64-builder-linux-musl-4.9
-* x86_64-builder-linux-uclibc-4.9
-* x86_64-bofc-debian-9
-* x86_64-bofc-centos-7
-* x86_64-bofc-fedora-28
-* x86_64-bofc-opensuse-15
-* x86_64-bofc-rhel-7
-* x86_64-bofc-slackware-14.2
-* x86_64-bofc-ubuntu-18.04
-
-machine tests
--------------
-
-* aarch64-builder-linux-gnu
-* armv5te926-builder-linux-gnueabihf
-* armv6j1136-builder-linux-gnueabihf
-* armv7a15-builder-linux-gnueabihf
-* armv7a9-builder-linux-gnueabihf
-* mips-builder-linux-gnu
-
-sanitizers
-----------
+To run unit tests, you also need `librb <https://librb.bofc.pl>`_
-* -fsanitize=address
-* -fsanitize=leak
-* -fsanitize=undefined
+Robustness
+----------
+Code is about 800 lines of code of which 300 are just to set and validate
+passed options. -Wall and -Wextra are standard, and code is code is passed
+through sanitizers and static code analyzers before release.
+Code is also very heavily tested::
+
+ # total tests.......:61620
+ # passed tests......:61620
+ # failed tests......: 0
+ # total checks......:66181
+ # passed checks.....:66181
+ # failed checks.....: 0
+
+ Overall coverage rate:
+ lines...........: 89.5% (739 of 826 lines)
+ functions.......: 90.6% (77 of 85 functions)
Compiling and installing
-========================
-
+------------------------
Compiling library
------------------
+^^^^^^^^^^^^^^^^^
-Project uses standard automake so to build you need to:
+Project uses standard automake so to build you need to:::
-~~~
-$ autoreconf -i
-$ ./configure
-$ make
-# make install
-~~~
+ $ autoreconf -i
+ $ ./configure
+ $ make
+ # make install
Running tests
--------------
-
-To run test simply run
+^^^^^^^^^^^^^
+To run test simply run::
-~~~
-$ make check
-~~~
+ $ make check
Compiling examples
-------------------
-
-Compile examples with
+^^^^^^^^^^^^^^^^^^
+Compile examples with::
-~~~
-$ cd examples
-$ make
-~~~
+ $ cd examples
+ $ make
Build time options
-==================
-
+------------------
Many features can be disabled to save space and ram. While this may not be
neccessary to change on big operating systems such as **linux** or **freebsd**,
it may come in handy when compiling for very small embedded systems. All options
@@ -150,55 +172,47 @@ mean it will be hard enabled in runtime, this will just give you an option to
enable these settings later in runtime.
--enable-out-stderr (default: enable)
--------------------------------------
-
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When set, library will be able to print logs to standard error output (stderr)
and standard output (stdout). Nothing fancy.
--enable-out-file (default: enable)
------------------------------------
-
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Allows to configure logger to print logs to file. Optional file rotation can be
enabled. Number of rotation files and maximum size of rotation log file can be
defined in runtime
--enable-out-custom (default: enable)
--------------------------------------
-
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Allows to pas own function which will receive fully constructed message to print
as **const char \***. Usefull when there is no output facility that suits your
needs.
--enable-timestamp (default: enable)
-------------------------------------
-
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When enabled, logger will be able to add timestamp to every message. Timestamp
can be in short or long format and timer source can be configured. Check out
-[man page](https://embedlog.bofc.pl/manuals/el_option.3.html) to read more
-about it.
+:ref:`el_set_timestamp(3) <manuals/options/el_set_timestamp.3:el_set_timestamp>`
+to read more about it.
--enable-fractions (default: enable)
-------------------------------------
-
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When enabled, logger will be able to add fractions of seconds to each message.
Fractions are added after reguler timestamp in format ".mmm" where mmm is
fractions of seconds in milliseconds. This can be tuned to use micro or even
nanoseconds - if system has such resolution.
--enable-realtime, --enable-monotonic (default: enable)
--------------------------------------------------------
-
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Allows to use better precision timers - **CLOCK_REALTIME** and
**CLOCK_MONOTONIC** but requires **POSIX**
--enable-clock (default: enable)
---------------------------------
-
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Allows logger to use clock(3) as time source
--enable-binary-logs (default: disable)
----------------------------------------
-
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This will allow you to log binary data (like data read from CAN). Such logs
cannot be read with ordinary *cat* or *less* and will ned custom-made log
decoder, but such logs will use much less space on block devices. This of
@@ -206,42 +220,36 @@ course can be used with file rotation. This doesn't work with *stderr* or
*syslog* output as it would make no sense to send binary data there
--enable-prefix (default: enable)
----------------------------------
-
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This will allow user to add custom string prefix to each message printed.
Very usefull when multiple programs logs to single source (like *syslog* or
*stderr*, it's easier to distinguish who sent that log. It's also usefull
when you want to merge logs from multiple files into on big file of logs.
--enable-finfo (default: enable)
---------------------------------
-
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When enabled, information about line and file name from where log originated
will be added to each message.
--enable-funcinfo (default: disable)
-------------------------------------
-
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When enabled, information about function name from where log originated
will be added to each message. This uses *__func__* so you need compiler
that supports that. It was added in *c99* standard.
--enable-colors (default: enable)
----------------------------------
-
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If enabled, output logs can be colored depending on their level. Good for
quick error spotting.
--enable-colors-extended (default: disable)
--------------------------------------------
-
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When enable, *embedlog* will use more colors for some log levels. Without that
some log levels will have same output color. Not all terminals/tools supports
extended colors.
--enable-reentrant (default: enable)
-------------------------------------
-
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Uses reentrant functions where possible. Not available on every platform, but
if enabled, provides thread-safety on line level - that means, lines won't
overlap with another thread. This is true only when output is *stderr* or
@@ -249,39 +257,35 @@ overlap with another thread. This is true only when output is *stderr* or
the help of **EL_THREAD_SAFE** and **--enable-pthread**.
--enable-pthread (default: enable)
-----------------------------------
-
- When enabled, you will be able to configure **embedlog** to use
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+When enabled, you will be able to configure **embedlog** to use
**EL_THREAD_SAFE**, which will provide full thread safety in all circumstances.
This is critical if output is other than *stderr* or *stdout* - like *file*,
as there is internal state in *el* object that is kept between calls.
--enable-portable-snprintf (default: disable)
----------------------------------------------
-
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When enabled, library will use internal implementation of **snprintf** even if
**snprintf** is provided by the operating system.
Contact
-=======
-
+-------
Michał Łyszczek <michal.lyszczek@bofc.pl>
License
-=======
-
+-------
Library is licensed under BSD 2-clause license. See
-[LICENSE](https://git.bofc.pl/embedlog/tree/LICENSE) file for details
+`LICENSE <https://git.bofc.pl/embedlog/tree/LICENSE>`_ file for details
See also
-========
-
-* [c89 snprintf function family](https://www.ijs.si/software/snprintf) by
+--------
+* `c89 snprintf function family <https://www.ijs.si/software/snprintf>`_ by
Mark Martinec
-* [mtest](https://mtest.bofc.pl) unit test framework **embedlog** uses
-* [librb](https://librb.bofc.pl) ring buffer used in unit tests
-* [git repository](https://git.bofc.pl/embedlog) to browse code online
-* [polarhome](http://www.polarhome.com) nearly free shell accounts for virtually
+* `mtest <https://mtest.bofc.pl>`_ unit test framework **embedlog** uses
+* `librb <https://librb.bofc.pl>`_ ring buffer used in unit tests
+* `git repository <http://git.bofc.pl/embedlog>`_ to browse code online
+* `continous integration <http://ci.embedlog.bofc.pl>`_ for project
+* `polarhome <http://www.polarhome.com>`_ nearly free shell accounts for virtually
any unix there is.
-* [pvs studio](https://www.viva64.com/en/pvs-studio) static code analyzer with
+* `pvs studio <https://www.viva64.com/en/pvs-studio>`_ static code analyzer with
free licenses for open source projects
diff --git a/src/Makefile.am b/src/Makefile.am
index 3a03616..2dd0e7b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -32,7 +32,7 @@ libembedlog_la_SOURCES = $(embedlog_sources)
libembedlog_la_SOURCES += el-private.h \
el-utils.h \
valid.h
-LIBRARY_VERSION=9999:0:0
+LIBRARY_VERSION=6:0:6
# .------' | `---.
# current:revision:age
# | | `- increment if interfaces have been added
@@ -41,9 +41,9 @@ LIBRARY_VERSION=9999:0:0
# | `- increment if source code has changed
# | set to zero if current is incremented
# `- increment if interfaces have been added, removed or changed
-libembedlog_la_LDFLAGS = -version-info $(LIBRARY_VERSION)
+libembedlog_la_LDFLAGS = $(COVERAGE_CFLAGS) -version-info $(LIBRARY_VERSION)
-libembedlog_la_CFLAGS = -I$(top_builddir)/include
+libembedlog_la_CFLAGS = $(COVERAGE_CFLAGS) -I$(top_builddir)/include
# static code analyzer
diff --git a/src/el-decode-number.c b/src/el-decode-number.c
index 260ae1d..8283698 100644
--- a/src/el-decode-number.c
+++ b/src/el-decode-number.c
@@ -2,38 +2,28 @@
Licensed under BSD 2clause license See LICENSE file for more information
Author: Michał Łyszczek <michal.lyszczek@bofc.pl>
==========================================================================
- _ __ __ ____ _ __
(_)____ _____ / /__ __ ____/ /___ / __/(_)/ /___ _____
/ // __ \ / ___// // / / // __ // _ \ / /_ / // // _ \ / ___/
/ // / / // /__ / // /_/ // /_/ // __/ / __// // // __/(__ )
/_//_/ /_/ \___//_/ \__,_/ \__,_/ \___/ /_/ /_//_/ \___//____/
-
========================================================================== */
-
-
#include "el-private.h"
#include <limits.h>
/* ==========================================================================
- __ __ _ ____
____ __ __ / /_ / /(_)_____ / __/__ __ ____ _____ _____
/ __ \ / / / // __ \ / // // ___/ / /_ / / / // __ \ / ___// ___/
/ /_/ // /_/ // /_/ // // // /__ / __// /_/ // / / // /__ (__ )
/ .___/ \__,_//_.___//_//_/ \___/ /_/ \__,_//_/ /_/ \___//____/
/_/
- ========================================================================== */
-
-
-/* ==========================================================================
+ ==========================================================================
Decodes encoded 'number' and stores value into 'out'. Check description
of el_encode_number for more information.
returns number of bytes processed from 'number'
========================================================================== */
-
-
size_t el_decode_number
(
const void *number, /* number to decode */
@@ -67,8 +57,8 @@ size_t el_decode_number
*out |= (unsigned long)(n[i] & 0x7f) << (i * 7);
#endif
- /* we do this until number lacks of continuation bit, which
- * means we are done */
+ /* we do this until number lacks of continuation bit,
+ * which means we are done */
}
while (n[i++] & 0x80);
diff --git a/src/el-encode-number.c b/src/el-encode-number.c
index bfe6b5f..34d619d 100644
--- a/src/el-encode-number.c
+++ b/src/el-encode-number.c
@@ -23,10 +23,7 @@
/ /_/ // /_/ // /_/ // // // /__ / __// /_/ // / / // /__ (__ )
/ .___/ \__,_//_.___//_//_/ \___/ /_/ \__,_//_/ /_/ \___//____/
/_/
- ========================================================================== */
-
-
-/* ==========================================================================
+ ==========================================================================
This will code 'number' to into as small buffer as possible. Each byte
of encoded value can hold 7 bits of data and 1 bit (oldest) of
continuation information. If continuation bit is set, that means next
@@ -37,8 +34,6 @@
returns number of bytes stored into 'out' buffer.
========================================================================== */
-
-
size_t el_encode_number
(
#ifdef LLONG_MAX
@@ -59,8 +54,7 @@ size_t el_encode_number
do
{
/* put only youngest 7 bits into out -
- * that's a max number single byte can
- * hold */
+ * that's a max number single byte can hold */
o[n] = number & 0x7f;
/* remove those 7 bits from number, they
diff --git a/src/el-file.c b/src/el-file.c
index 7d3419f..5958712 100644
--- a/src/el-file.c
+++ b/src/el-file.c
@@ -26,15 +26,11 @@
COW-OPERATION
==========================================================================
- _ __ __ ____ _ __
(_)____ _____ / /__ __ ____/ /___ / __/(_)/ /___ _____
/ // __ \ / ___// // / / // __ // _ \ / /_ / // // _ \ / ___/
/ // / / // /__ / // /_/ // /_/ // __/ / __// // // __/(__ )
/_//_/ /_/ \___//_/ \__,_/ \__,_/ \___/ /_/ /_//_/ \___//____/
-
========================================================================== */
-
-
#include "el-private.h"
#include "el-utils.h"
@@ -56,41 +52,31 @@
/* ==========================================================================
- __ __ __
____ _ / /____ / /_ ____ _ / / _ __ ____ _ _____ _____
/ __ `// // __ \ / __ \ / __ `// / | | / // __ `// ___// ___/
/ /_/ // // /_/ // /_/ // /_/ // / | |/ // /_/ // / (__ )
\__, //_/ \____//_.___/ \__,_//_/ |___/ \__,_//_/ /____/
/____/
========================================================================== */
-
-
#ifdef RUN_TESTS
/* there is no easy way to check if file has been fsynced to disk
* or not, so we introduce this helper variable to know if we
- * executed syncing code or not
- */
+ * executed syncing code or not */
int file_synced;
#endif
/* ==========================================================================
- __ __ __ _
____/ /___ _____ / /____ _ _____ ____ _ / /_ (_)____ ____ _____
/ __ // _ \ / ___// // __ `// ___// __ `// __// // __ \ / __ \ / ___/
/ /_/ // __// /__ / // /_/ // / / /_/ // /_ / // /_/ // / / /(__ )
\__,_/ \___/ \___//_/ \__,_//_/ \__,_/ \__//_/ \____//_/ /_//____/
-
========================================================================== */
-
-
#ifndef PATH_MAX
-/*
- * for systems that don't define PATH_MAX we use our MAX_PATH macro that is
- * defined in config.h during ./configure process
- */
+/* for systems that don't define PATH_MAX we use our MAX_PATH macro that is
+ * defined in config.h during ./configure process */
#define PATH_MAX MAX_PATH
@@ -98,13 +84,52 @@ int file_synced;
/* ==========================================================================
- _ __ ____
____ _____ (_)_ __ ____ _ / /_ ___ / __/__ __ ____ _____ _____
/ __ \ / ___// /| | / // __ `// __// _ \ / /_ / / / // __ \ / ___// ___/
/ /_/ // / / / | |/ // /_/ // /_ / __/ / __// /_/ // / / // /__ (__ )
/ .___//_/ /_/ |___/ \__,_/ \__/ \___/ /_/ \__,_//_/ /_/ \___//____/
/_/
+ ==========================================================================
+ Gets date string for current timeslice for current time.
+
+ So for, timeslice minute, it will save "YYYY-mm-dd--HH-MM" in out.
+ Caller has to make sure $out is at least 21 bytes long.
========================================================================== */
+static void el_date_rotate_str
+(
+ struct el *el, /* el object to work on */
+ char *out /* string for rotate postfix will be stored here */
+)
+{
+ const char *dfmt; /* pointer to string format for strftime */
+ time_t now; /* current time since epoch */
+ struct tm *tmp; /* usable pointer from gmtime */
+ struct tm tm; /* when reentrant is enabled, it's passed to gmtime */
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+
+ switch (el->frotate_type)
+ {
+ case EL_ROT_DATE_YEAR: dfmt = "%Y"; break;
+ case EL_ROT_DATE_MON: dfmt = "%Y-%m"; break;
+ case EL_ROT_DATE_DAY: dfmt = "%Y-%m-%d"; break;
+ case EL_ROT_DATE_HOUR: dfmt = "%Y-%m-%d--%H"; break;
+ case EL_ROT_DATE_MIN: dfmt = "%Y-%m-%d--%H-%M"; break;
+ case EL_ROT_DATE_SEC: dfmt = "%Y-%m-%d--%H-%M-%S"; break;
+ }
+
+ now = time(NULL);
+#if ENABLE_REENTRANT
+ tmp = gmtime_r(&now, &tm);
+#else
+ tmp = gmtime(&now);
+#endif
+
+ /* Construct date format from current UTC time, we are
+ * working on static variables, so we know it won't fail
+ * or overflow timstr buffer */
+ strftime(out, 21, dfmt, tmp);
+}
/* ==========================================================================
@@ -115,8 +140,6 @@ int file_synced;
0 file does not exist
1 file exists
========================================================================== */
-
-
static int el_file_exists
(
const char *path /* file to check */
@@ -168,8 +191,6 @@ static int el_file_exists
Symlink is optional and if it is not created no data is lost and
returning error would confuse caller.
========================================================================== */
-
-
static void el_symlink_to_newest_log
(
struct el *el /* embedlog object to work on */
@@ -192,8 +213,6 @@ static void el_symlink_to_newest_log
suffixed) function will remove oldest log file and new file will be
created
========================================================================== */
-
-
static int el_file_rotate
(
struct el *el
@@ -281,21 +300,15 @@ skip_rotate:
/* ==========================================================================
- __ __ _ ____
____ __ __ / /_ / /(_)_____ / __/__ __ ____ _____ _____
/ __ \ / / / // __ \ / // // ___/ / /_ / / / // __ \ / ___// ___/
/ /_/ // /_/ // /_/ // // // /__ / __// /_/ // / / // /__ (__ )
/ .___/ \__,_//_.___//_//_/ \___/ /_/ \__,_//_/ /_/ \___//____/
/_/
- ========================================================================== */
-
-
-/* ==========================================================================
+ ==========================================================================
opens log file specified in el and sets file position, so we can
track it.
========================================================================== */
-
-
int el_file_open
(
struct el *el /* el object with file information */
@@ -305,18 +318,34 @@ int el_file_open
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
- /* we need current_log filename for ourself - we modify its
- * last digit when we rotate file. In theory this could be
- * done in struct declaration, but PATH_MAX is such a waste
- * of memory and programs usually do not get even close to
- * that ammount. Allocate enough memory for fname and max
- * of 5 digits for rotate + null character */
- pathlen = strlen(el->fname) + 6;
+ /* we need current_log filename for ourself - we modify it when
+ * we rotate file. In theory this could be done in struct
+ * declaration, but PATH_MAX is such a waste of memory and
+ * programs usually do not get even close to that amount. So we
+ * just add what is necessary. */
+
+ /* pathlen must be with null termination character, as this
+ * variable is passed to snprintf() */
+ pathlen = strlen(el->fname) + 1;
- /* realloc needs to be done each time open() is called, in
- * case log file is being changed via EL_FPATH option. */
- el->fcurrent_log = realloc(el->fcurrent_log, pathlen);
- VALID(ENOMEM, el->fcurrent_log != NULL)
+ if (el->frotate_type == EL_ROT_FSIZE)
+ /* Allocate enough memory for fname and max of 5 digits for
+ * rotate + 1 for separator dot */
+ pathlen += 5 + 1;
+ else if (EL_IS_ROT_DATE(el))
+ /* if we are doing date base rotation, maximum additional
+ * file length will be strlen(YYYY-mm-dd--HH-MM-SS) = 20 */
+ pathlen += 20 + 1;
+
+ if (el->fcurrent_log == NULL || pathlen > strlen(el->fcurrent_log))
+ {
+ /* If new pathlen is larger than length of current log file,
+ * than we need to allocate more memory. If we never opened
+ * file before, fcurrent_log will be NULL, in which case
+ * we also must allocate memory */
+ el->fcurrent_log = realloc(el->fcurrent_log, pathlen);
+ VALID(ENOMEM, el->fcurrent_log != NULL)
+ }
if (el->file)
{
@@ -328,7 +357,10 @@ int el_file_open
el->file = NULL;
}
- if (el->frotate_number)
+ /* We are opening new file, so we don't have current log file. */
+ el->fcurrent_log[0] = '\0';
+
+ if (el->frotate_type == EL_ROT_FSIZE && el->frotate_number)
{
FILE *f; /* opened file */
int i; /* simple interator for loop */
@@ -471,7 +503,36 @@ int el_file_open
}
}
- /* rotation is disabled, simply open file with append flag */
+ if (EL_IS_ROT_DATE(el))
+ {
+ /* We are rotating by date. This it not as complex case
+ * as with rotate by size, we just open file with current
+ * date (based on rotate timescale */
+
+ char timstr[20 + 1];
+ size_t pathl; /* length of path after snprintf */
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+
+ el_date_rotate_str(el, timstr);
+
+ /* Construct file name with selected date rotation in format
+ * user-filename.$date */
+ pathl = snprintf(el->fcurrent_log, pathlen, "%s.%s", el->fname, timstr);
+ if (pathl > PATH_MAX)
+ {
+ /* path is too long, we cannot safely create file
+ * with suffix, return error as opening such
+ * truncated file name could result in some data
+ * lose on the disk. */
+ el->fcurrent_log[0] = '\0';
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+ }
+
+ /* rotation is disabled or we deal with date rotation, simply
+ * open file with append flag */
if (strlen(el->fname) > pathlen)
{
@@ -481,7 +542,10 @@ int el_file_open
return -1;
}
- strcpy(el->fcurrent_log, el->fname);
+ /* fcurrent log might have been already set (in date rotation),
+ * so set fcurrent_log only when it was not already set */
+ if (el->fcurrent_log[0] == '\0')
+ strcpy(el->fcurrent_log, el->fname);
/* in case we couldn't open file, don't set clear
* el->fcurrent_log - we will try to reopen this file each time
@@ -500,8 +564,6 @@ int el_file_open
Does whatever it takes to make sure that logs are flushed from any
buffers to physical disk. It's not always possible, but boy, do we try.
========================================================================== */
-
-
int el_file_flush
(
struct el *el /* printing options */
@@ -521,8 +583,7 @@ int el_file_flush
* metadata, parent directory might not get flushed and there
* will not be entry for our file - meaning file will be lost
* too, but such situations are ultra rare and there isn't
- * really much we can do about it here but praying.
- */
+ * really much we can do about it here but praying. */
#if HAVE_FSYNC && HAVE_FILENO
@@ -603,7 +664,7 @@ int el_file_putb
if (el_file_open(el) != 0)
return -1;
- if (el->frotate_number)
+ if (el->frotate_type == EL_ROT_FSIZE && el->frotate_number)
{
/* we get here only when frotate is enabled. check if
* writing to current file would result in exceding
@@ -622,6 +683,32 @@ int el_file_putb
mlen = el->frotate_size;
}
+ if (EL_IS_ROT_DATE(el))
+ {
+ /* If we are date rotating, check it time has come
+ * to rotate the file. And by rotate I simply mean
+ * open new file with new date. */
+
+ char timstr[20 + 1];
+ const char *file_timstr;
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+
+ /* get current rotate time that should be */
+ el_date_rotate_str(el, timstr);
+ /* point file_timestr to beginning of date rotate suffix.
+ * for file log.2024-01-01, it will point to 2024-01-01 */
+ file_timstr = el->fname + strlen(el->fname) + 1;
+
+ /* If timstr (current, now, value) is different than
+ * file_timstr (currently opened file), it means that
+ * second, minut, hour, day... has changed, and we need to
+ * open new file */
+ if (strcmp(timstr, file_timstr))
+ if (el_file_open(el))
+ return -1;
+ }
+
if (fwrite(mem, mlen, 1, el->file) != 1) return -1;
el->fpos += mlen;
el->fwritten_after_sync += mlen;
@@ -640,8 +727,6 @@ int el_file_putb
/* ==========================================================================
Puts string 's' into file if needed rotates file
========================================================================== */
-
-
int el_file_puts
(
struct el *el, /* printing options */
@@ -660,8 +745,6 @@ int el_file_puts
/* ==========================================================================
free resources allocated by this module
========================================================================== */
-
-
void el_file_cleanup
(
struct el *el /* file options */
diff --git a/src/el-flush.c b/src/el-flush.c
index f8b0e6f..933164f 100644
--- a/src/el-flush.c
+++ b/src/el-flush.c
@@ -13,15 +13,11 @@
( )
.( o ).
==========================================================================
- _ __ __ ____ _ __
(_)____ _____ / /__ __ ____/ /___ / __/(_)/ /___ _____
/ // __ \ / ___// // / / // __ // _ \ / /_ / // // _ \ / ___/
/ // / / // /__ / // /_/ // /_/ // __/ / __// // // __/(__ )
/_//_/ /_/ \___//_/ \__,_/ \__,_/ \___/ /_/ /_//_/ \___//____/
-
========================================================================== */
-
-
#include "el-private.h"
#include <errno.h>
@@ -29,22 +25,16 @@
/* ==========================================================================
- __ __ _ ____
____ __ __ / /_ / /(_)_____ / __/__ __ ____ _____ _____
/ __ \ / / / // __ \ / // // ___/ / /_ / / / // __ \ / ___// ___/
/ /_/ // /_/ // /_/ // // // /__ / __// /_/ // / / // /__ (__ )
/ .___/ \__,_//_.___//_//_/ \___/ /_/ \__,_//_/ /_/ \___//____/
/_/
- ========================================================================== */
-
-
-/* ==========================================================================
+ ==========================================================================
Does whatever it takes to make sure data is flushed from buffers and is
received by underlying devices (which may be block device or remote
server).
========================================================================== */
-
-
/* public api */ int el_flush
(
void
@@ -57,8 +47,6 @@
/* ==========================================================================
Same as el_flush() but takes el object as argument
========================================================================== */
-
-
/* public api */ int el_oflush
(
struct el *el /* options defining printing style */
@@ -67,13 +55,13 @@
int rv; /* return value from function */
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
VALID(EINVAL, el);
el_lock(el);
VALIDC(ENODEV, el->outputs != 0, el_unlock(el));
rv = 0;
-
#if ENABLE_OUT_STDERR
if (el->outputs & EL_OUT_STDERR) rv |= fflush(stderr);
#endif
diff --git a/src/el-lock.c b/src/el-lock.c
index 276594a..eea8cf5 100644
--- a/src/el-lock.c
+++ b/src/el-lock.c
@@ -11,36 +11,26 @@
||----w |
|| ||
==========================================================================
- _ __ __ ____ _ __
(_)____ _____ / /__ __ ____/ /___ / __/(_)/ /___ _____
/ // __ \ / ___// // / / // __ // _ \ / /_ / // // _ \ / ___/
/ // / / // /__ / // /_/ // /_/ // __/ / __// // // __/(__ )
/_//_/ /_/ \___//_/ \__,_/ \__,_/ \___/ /_/ /_//_/ \___//____/
-
========================================================================== */
-
-
#include "el-private.h"
#include <pthread.h>
/* ==========================================================================
- __ __ _ ____
____ __ __ / /_ / /(_)_____ / __/__ __ ____ _____ _____
/ __ \ / / / // __ \ / // // ___/ / /_ / / / // __ \ / ___// ___/
/ /_/ // /_/ // /_/ // // // /__ / __// /_/ // / / // /__ (__ )
/ .___/ \__,_//_.___//_//_/ \___/ /_/ \__,_//_/ /_/ \___//____/
/_/
- ========================================================================== */
-
-
-/* ==========================================================================
+ ==========================================================================
Locks mutex on specified "el" object. If mutex is not initialized, that
is thread safety is turned off, nothing happens.
========================================================================== */
-
-
void el_lock
(
struct el *el /* el object to lock */
@@ -54,8 +44,6 @@ void el_lock
Unlock mutex on specified "el" object. If mutex is not initialized, that
is thread safety is turned off, nothing happens.
========================================================================== */
-
-
void el_unlock
(
struct el *el /* el object to unlock */
diff --git a/src/el-options.c b/src/el-options.c
index dd802de..422299f 100644
--- a/src/el-options.c
+++ b/src/el-options.c
@@ -2,7 +2,6 @@
Licensed under BSD 2clause license. See LICENSE file for more information
Author: Michał Łyszczek <michal.lyszczek@bofc.pl>
==========================================================================
-
-------------------------------------------------------------
/ This is option module, here we parse and manage all options \
| regarding logging. Also this is home for global default |
@@ -23,15 +22,11 @@
| / | / ~-. `-. _ _ _
|_____| |_____| ~ - . _ _ _ _ _>
==========================================================================
- _ __ __ ____ _ __
(_)____ _____ / /__ __ ____/ /___ / __/(_)/ /___ _____
/ // __ \ / ___// // / / // __ // _ \ / /_ / // // _ \ / ___/
/ // / / // /__ / // /_/ // /_/ // __/ / __// // // __/(__ )
/_//_/ /_/ \___//_/ \__,_/ \__,_/ \___/ /_/ /_//_/ \___//____/
-
========================================================================== */
-
-
#include "el-private.h"
#include <errno.h>
@@ -40,24 +35,19 @@
/* ==========================================================================
- __ __ __ _
____/ /___ _____ / /____ _ _____ ____ _ / /_ (_)____ ____ _____
/ __ // _ \ / ___// // __ `// ___// __ `// __// // __ \ / __ \ / ___/
/ /_/ // __// /__ / // /_/ // / / /_/ // /_ / // /_/ // / / /(__ )
\__,_/ \___/ \___//_/ \__,_//_/ \__,_/ \__//_/ \____//_/ /_//____/
-
========================================================================== */
-
+#define OK_OR_RETURN(x) do { int ret; if((ret = x)) return ret; } while (0)
/* global el object, used with all functions that does not take "el"
- * as argument
- */
+ * as argument */
struct el g_el;
-/* mask of outputs that have been compiled and are supported by current
- * build
- */
+/* mask of outputs that have been compiled and are supported by current build */
static const int VALID_OUTS = 0
@@ -92,16 +82,12 @@ static const int VALID_OUTS = 0
/* ==========================================================================
- _ __ ____
____ _____ (_)_ __ ____ _ / /_ ___ / __/__ __ ____ _____ _____
/ __ \ / ___// /| | / // __ `// __// _ \ / /_ / / / // __ \ / ___// ___/
/ /_/ // / / / | |/ // /_/ // /_ / __/ / __// /_/ // / / // /__ (__ )
/ .___//_/ /_/ |___/ \__,_/ \__/ \___/ /_/ \__,_//_/ /_/ \___//____/
/_/
- ========================================================================== */
-
-
-/* ==========================================================================
+ ==========================================================================
sets 'option' with 'ap' values in 'el' object.
errno
@@ -109,8 +95,6 @@ static const int VALID_OUTS = 0
EINVAL value for specific option is invalid
ENOSYS option was disabled during compilation
========================================================================== */
-
-
static int el_vooption
(
struct el *el, /* el object to set option to */
@@ -130,14 +114,10 @@ static int el_vooption
switch (option)
{
/* ==================================================================
- __ __
/ /___ _ __ ___ / /
/ // -_)| |/ // -_)/ /
/_/ \__/ |___/ \__//_/
-
================================================================== */
-
-
case EL_LEVEL:
value_int = va_arg(ap, int);
VALID(EINVAL, value_int <= 7);
@@ -148,14 +128,11 @@ static int el_vooption
/* ==================================================================
- ___ __ __
/ _/___ __ __ ___ ____ / /___ _ __ ___ / /
/ _/(_-</ // // _ \/ __/ / // -_)| |/ // -_)/ /
/_/ /___/\_, //_//_/\__/ /_/ \__/ |___/ \__//_/
/___/
================================================================== */
-
-
# if ENABLE_OUT_FILE
case EL_FSYNC_LEVEL:
@@ -170,14 +147,10 @@ static int el_vooption
/* ==================================================================
- __
___ __ __ / /_
/ _ \/ // // __/
\___/\_,_/ \__/
-
================================================================== */
-
-
case EL_OUT:
value_int = va_arg(ap, int);
value_int = value_int == EL_OUT_ALL ? VALID_OUTS : value_int;
@@ -190,14 +163,11 @@ static int el_vooption
/* ==================================================================
- _ __ __ __
___ ____ (_)___ / /_ / /___ _ __ ___ / /
/ _ \ / __// // _ \/ __/ / // -_)| |/ // -_)/ /
/ .__//_/ /_//_//_/\__/ /_/ \__/ |___/ \__//_/
/_/
================================================================== */
-
-
case EL_PRINT_LEVEL:
value_int = va_arg(ap, int);
VALID(EINVAL, (value_int & ~1) == 0);
@@ -209,14 +179,11 @@ static int el_vooption
/* ==================================================================
- _ __ __
___ ____ (_)___ / /_ ___ / /
/ _ \ / __// // _ \/ __/ / _ \ / /
/ .__//_/ /_//_//_/\__/ /_//_//_/
/_/
================================================================== */
-
-
case EL_PRINT_NL:
value_int = va_arg(ap, int);
VALID(EINVAL, (value_int & ~1) == 0);
@@ -228,14 +195,11 @@ static int el_vooption
/* ==================================================================
- ___ _
___ ____ ___ / _/(_)__ __
/ _ \ / __// -_)/ _// / \ \ /
/ .__//_/ \__//_/ /_/ /_\_\
/_/
================================================================== */
-
-
# if ENABLE_PREFIX
case EL_PREFIX:
@@ -249,14 +213,10 @@ static int el_vooption
/* ==================================================================
- __
____ ___ / /___ ____ ___
/ __// _ \ / // _ \ / __/(_-<
\__/ \___//_/ \___//_/ /___/
-
================================================================== */
-
-
# if ENABLE_COLORS
case EL_COLORS:
@@ -274,14 +234,10 @@ static int el_vooption
/* ==================================================================
- __
/ /_ ___
/ __/(_-<
\__//___/
-
================================================================== */
-
-
# if ENABLE_TIMESTAMP
case EL_TS:
@@ -295,14 +251,10 @@ static int el_vooption
/* ==================================================================
- __ ___ __
/ /_ ___ / _/____ ___ _ ____ / /_
/ __/(_-< / _// __// _ `// __// __/
\__//___/ /_/ /_/ \_,_/ \__/ \__/
-
================================================================== */
-
-
# if ENABLE_FRACTIONS
case EL_TS_FRACT:
@@ -318,14 +270,10 @@ static int el_vooption
/* ==================================================================
- __ __
/ /_ ___ / /_ __ _
/ __/(_-< / __// ' \
\__//___/ \__//_/_/_/
-
================================================================== */
-
-
case EL_TS_TM:
value_int = va_arg(ap, int);
VALID(EINVAL, 0 <= value_int && value_int < EL_TS_TM_ERROR);
@@ -352,14 +300,10 @@ static int el_vooption
/* ==================================================================
- ___ _ ___
/ _/(_)___ / _/___
/ _// // _ \ / _// _ \
/_/ /_//_//_//_/ \___/
-
================================================================== */
-
-
# if ENABLE_FINFO
case EL_FINFO:
@@ -375,14 +319,10 @@ static int el_vooption
/* ==================================================================
- ___ _ ___
/ _/__ __ ___ ____ (_)___ / _/___
/ _// // // _ \/ __// // _ \ / _// _ \
/_/ \_,_//_//_/\__//_//_//_//_/ \___/
-
================================================================== */
-
-
# if ENABLE_FUNCINFO
case EL_FUNCINFO:
@@ -409,14 +349,11 @@ static int el_vooption
/* ==================================================================
- ___ __ __
/ _/___ ___ _ / /_ / /
/ _// _ \/ _ `// __// _ \
/_/ / .__/\_,_/ \__//_//_/
/_/
================================================================== */
-
-
# if ENABLE_OUT_FILE
case EL_FPATH:
@@ -430,25 +367,31 @@ static int el_vooption
/* ==================================================================
- ___ __ __ __
/ _/____ ___ / /_ ___ _ / /_ ___ ___ __ __ __ _ / / ___ ____
/ _// __// _ \/ __// _ `// __// -_) / _ \/ // // ' \ / _ \/ -_)/ __/
/_/ /_/ \___/\__/ \_,_/ \__/ \__/ /_//_/\_,_//_/_/_//_.__/\__//_/
-
================================================================== */
-
-
case EL_FROTATE_NUMBER:
{
- int previous_frotate; /* previous value of frotate number */
+ int need_reopen; /* should we repoen file after this operation? */
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
value_int = va_arg(ap, int);
VALID(EINVAL, 0 <= value_int && value_int <= USHRT_MAX);
+
+ /* reopening of the file is needed if */
+ need_reopen =
+ /* current rotate type is not already based on size */
+ el->frotate_type != EL_ROT_FSIZE ||
+ /* or if we change rotate number from 0 to N */
+ (el->frotate_number == 0 && value_int);
+
el_lock(el);
- previous_frotate = el->frotate_number;
el->frotate_number = (unsigned short)value_int;
+ /* If user sets frotate number to 0, it means he does not want
+ * any rotate to happen, so set currnet rotate type to OFF */
+ el->frotate_type = el->frotate_number ? EL_ROT_FSIZE : EL_ROT_OFF;
ret = 0;
if (value_int > 0)
@@ -464,7 +407,7 @@ static int el_vooption
* and even data loss, we reopen file as opening with log
* rotation is a bit different. el_file_open() function
* will close file before reopening */
- if (previous_frotate == 0 && el->file) ret = el_file_open(el);
+ if (need_reopen && el->file) ret = el_file_open(el);
el_unlock(el);
return ret;
@@ -472,32 +415,61 @@ static int el_vooption
/* ==================================================================
- ___ __ __ _
/ _/____ ___ / /_ ___ _ / /_ ___ ___ (_)___ ___
/ _// __// _ \/ __// _ `// __// -_) (_-< / //_ // -_)
/_/ /_/ \___/\__/ \_,_/ \__/ \__/ /___//_/ /__/\__/
-
================================================================== */
-
-
case EL_FROTATE_SIZE:
value_ulong = va_arg(ap, unsigned long);
VALID(EINVAL, value_ulong >= 1);
el_lock(el);
el->frotate_size = value_ulong;
+ el->frotate_type = EL_ROT_FSIZE;
el_unlock(el);
return 0;
/* ==================================================================
- ___ __ __ __ _ __
+ / _/____ ___ / /_ ___ _ / /_ ___ ___/ /___ _ / /_ ___
+ / _// __// _ \/ __// _ `// __// -_) / _ // _ `// __// -_)
+ /_/ /_/ \___/\__/ \_,_/ \__/ \__/ \_,_/ \_,_/ \__/ \__/
+ ================================================================== */
+ case EL_FROTATE_DATE:
+ {
+ int need_reopen; /* should we repoen file after this operation? */
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+
+ value_int = va_arg(ap, int);
+ VALID(EINVAL, value_int <= EL_ROT_DATE_YEAR);
+ VALID(EINVAL, value_int >= EL_ROT_DATE_SEC);
+
+ /* If current rotate type is not already based on date,
+ * we will have to reopen the file */
+ need_reopen = !EL_IS_ROT_DATE(el);
+
+ ret = 0;
+ el_lock(el);
+ el->frotate_type = value_int;
+
+ /* if user turned on file rotation when file is already
+ * opened without rotation then to prevent weird situations
+ * and even data loss, we reopen file as opening with log
+ * rotation is a bit different. el_file_open() function
+ * will close file before reopening */
+ if (need_reopen && el->file) ret = el_file_open(el);
+
+ el_unlock(el);
+ return ret;
+ }
+
+
+ /* ==================================================================
/ _/____ ___ / /_ ___ _ / /_ ___ ___ __ __ __ _ / /(_)___ / /__
/ _// __// _ \/ __// _ `// __// -_) (_-</ // // ' \ / // // _ \ / '_/
_/ /_/ \___/\__/ \_,_/ \__/ \__/ /___/\_, //_/_/_//_//_//_//_//_/\_\
/___/
================================================================== */
-
-
case EL_FROTATE_SYMLINK:
value_int = va_arg(ap, int);
VALID(EINVAL, (value_int & ~1) == 0);
@@ -509,14 +481,11 @@ static int el_vooption
/* ==================================================================
- ___
/ _/___ __ __ ___ ____ ___ _ __ ___ ____ __ __
/ _/(_-</ // // _ \/ __/ / -_)| |/ // -_)/ __// // /
/_/ /___/\_, //_//_/\__/ \__/ |___/ \__//_/ \_, /
/___/ /___/
================================================================== */
-
-
case EL_FSYNC_EVERY:
value_ulong = va_arg(ap, unsigned long);
VALID(EINVAL, value_ulong >= 0);
@@ -530,14 +499,11 @@ static int el_vooption
/* ==================================================================
- __ __ __
/ /_ / /_ __ __ ___/ /___ _ __
/ __// __// // / / _ // -_)| |/ /
\__/ \__/ \_, / \_,_/ \__/ |___/
/___/
================================================================== */
-
-
# if ENABLE_OUT_TTY
case EL_TTY_DEV:
@@ -561,14 +527,11 @@ static int el_vooption
/* ==================================================================
- __ __
____ __ __ ___ / /_ ___ __ _ ___ __ __ / /_ ___
/ __// // /(_-</ __// _ \ / ' \ / _ \/ // // __/(_-<
\__/ \_,_//___/\__/ \___//_/_/_/ / .__/\_,_/ \__//___/
/_/
================================================================== */
-
-
# if ENABLE_OUT_CUSTOM
case EL_CUSTOM_PUTS:
@@ -582,11 +545,9 @@ static int el_vooption
/* ==================================================================
- __ __ __ ___
/ /_ / / ____ ___ ___ _ ___/ / ___ ___ _ / _/___
/ __// _ \ / __// -_)/ _ `// _ / (_-</ _ `// _// -_)
\__//_//_//_/ \__/ \_,_/ \_,_/ /___/\_,_//_/ \__/
-
==================================================================
param
int [0,1]
@@ -597,8 +558,6 @@ static int el_vooption
destroy mutex. This case must be called when no
other threads are accessing any of "el" fields.
================================================================== */
-
-
# if ENABLE_PTHREAD
case EL_THREAD_SAFE:
@@ -637,15 +596,34 @@ static int el_vooption
# endif /* ENABLE_PTHREAD */
+ /* ==================================================================
+ / _ \ / ' \/ -_)/ ' \/ _ \ / __// // / (_-< / _ \/ _ `// __// -_)
+ / .__//_/_/_/\__//_/_/_/\___//_/ \_, / /___// .__/\_,_/ \__/ \__/
+ /_/ /___/ /_/
+ ==================================================================
+ param
+ int [0,3]
+
+ description
+ Configure spacing between 8 consecutive memory bytes
+ ================================================================== */
+ case EL_PMEMORY_SPACE:
+ value_int = va_arg(ap, int);
+
+ VALID(EINVAL, value_int >= 0);
+ VALID(EINVAL, value_int <= 3);
+
+ el_lock(el);
+ el->pmemory_space = value_int;
+ el_unlock(el);
+ return 0;
+
+
/* ==================================================================
- __ ___ __ __
___/ /___ / _/___ _ __ __ / // /_
/ _ // -_)/ _// _ `// // // // __/
\_,_/ \__//_/ \_,_/ \_,_//_/ \__/
-
================================================================== */
-
-
default:
/* if we get here, user used option that was disabled
* during compilation time and is not implemented
@@ -664,20 +642,14 @@ static int el_vooption
/* ==========================================================================
- __ __ _ ____
____ __ __ / /_ / /(_)_____ / __/__ __ ____ _____ _____
/ __ \ / / / // __ \ / // // ___/ / /_ / / / // __ \ / ___// ___/
/ /_/ // /_/ // /_/ // // // /__ / __// /_/ // / / // /__ (__ )
/ .___/ \__,_//_.___//_//_/ \___/ /_/ \__,_//_/ /_/ \___//____/
/_/
- ========================================================================== */
-
-
-/* ==========================================================================
+ ==========================================================================
initializes global el object to default state
========================================================================== */
-
-
/* public api */ int el_init
(
void
@@ -693,8 +665,6 @@ static int el_vooption
errno
EINVAL el is invalid (null)
========================================================================== */
-
-
/* public api */ int el_oinit
(
struct el *el /* el object */
@@ -734,8 +704,6 @@ static int el_vooption
errno
ENOMEM not enough memory in the system to allocate data
========================================================================== */
-
-
/* public api */ struct el *el_new
(
void
@@ -758,8 +726,6 @@ static int el_vooption
nature of pthread, this functions must be called only when no other
threads operate on "el" object.
========================================================================== */
-
-
/* public api */ int el_cleanup
(
void
@@ -777,8 +743,6 @@ static int el_vooption
errno
EINVAL el is invalid (null)
========================================================================== */
-
-
/* public api */ int el_ocleanup
(
struct el *el /* el object */
@@ -806,8 +770,6 @@ static int el_vooption
Same as el_ocleanup but can be used only with object created on heap
with el_new().
========================================================================== */
-
-
/* public api */ int el_destroy
(
struct el *el /* el object */
@@ -823,8 +785,6 @@ static int el_vooption
checks wheter log print is allowed if not. Print is not allowed when log
level is no high enough or no output has been configured.
========================================================================== */
-
-
int el_log_allowed
(
struct el *el, /* el object */
@@ -838,8 +798,6 @@ int el_log_allowed
/* ==========================================================================
same as el_ooption but for default g_el object
========================================================================== */
-
-
/* public api */ int el_option
(
int option, /* option to set */
@@ -861,8 +819,6 @@ int el_log_allowed
/* ==========================================================================
same as el_voel but accepts variadic arguments
========================================================================== */
-
-
/* public api */ int el_ooption
(
struct el *el, /* el object to set option to */
@@ -887,8 +843,6 @@ int el_log_allowed
Returns const pointer to global el struct used by all el_ functions
that don't take el object.
========================================================================== */
-
-
/* public api */ const struct el *el_get_el
(
void
@@ -896,3 +850,325 @@ int el_log_allowed
{
return (const struct el *)&g_el;
}
+
+
+/* ==========================================================================
+ ========================================================================== */
+/* public api */ int el_oset_log_level
+(
+ struct el *el, /* el object to set option to */
+ enum el_level level
+)
+{
+ return el_ooption(el, EL_LEVEL, level);
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+/* public api */ int el_set_log_level
+(
+ enum el_level level
+)
+{
+ return el_oset_log_level(&g_el, level);
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+/* public api */ int el_oenable_output
+(
+ struct el *el, /* el object to set option to */
+ enum el_output output
+)
+{
+ return el_ooption(el, EL_OUT, el->outputs | output);
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+/* public api */ int el_enable_output
+(
+ enum el_output output
+)
+{
+ return el_oenable_output(&g_el, output);
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+/* public api */ int el_odisable_output
+(
+ struct el *el, /* el object to set option to */
+ enum el_output output
+)
+{
+ return el_ooption(el, EL_OUT, el->outputs & ~output);
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+/* public api */ int el_disable_output
+(
+ enum el_output output
+)
+{
+ return el_odisable_output(&g_el, output);
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+/* public api */ int el_oset_prefix
+(
+ struct el *el, /* el object to set option to */
+ const char *prefix
+)
+{
+ return el_ooption(el, EL_PREFIX, prefix);
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+/* public api */ int el_set_prefix
+(
+ const char *prefix
+)
+{
+ return el_oset_prefix(&g_el, prefix);
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+/* public api */ int el_oset_timestamp
+(
+ struct el *el, /* el object to set option to */
+ enum el_option_timestamp timestamp,
+ enum el_option_timestamp_timer timer,
+ enum el_option_timestamp_fractions fraction
+)
+{
+ OK_OR_RETURN(el_ooption(el, EL_TS, timestamp));
+ OK_OR_RETURN(el_ooption(el, EL_TS_TM, timer));
+ OK_OR_RETURN(el_ooption(el, EL_TS_FRACT, fraction));
+
+ return 0;
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+/* public api */ int el_set_timestamp
+(
+ enum el_option_timestamp timestamp,
+ enum el_option_timestamp_timer timer,
+ enum el_option_timestamp_fractions fraction
+)
+{
+ return el_oset_timestamp(&g_el, timestamp, timer, fraction);
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+/* public api */ int el_oenable_colors
+(
+ struct el *el, /* el object to set option to */
+ int enable
+)
+{
+ return el_ooption(el, EL_COLORS, enable);
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+/* public api */ int el_enable_colors
+(
+ int enable
+)
+{
+ return el_oenable_colors(&g_el, enable);
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+/* public api */ int el_oprint_extra_info
+(
+ struct el *el, /* el object to set option to */
+ int print
+)
+{
+ OK_OR_RETURN(el_ooption(el, EL_FINFO, print));
+ OK_OR_RETURN(el_ooption(el, EL_FUNCINFO, print));
+ OK_OR_RETURN(el_ooption(el, EL_PRINT_LEVEL, print));
+
+ return 0;
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+/* public api */ int el_print_extra_info
+(
+ int print
+)
+{
+ return el_oprint_extra_info(&g_el, print);
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+/* public api */ int el_oset_custom_put
+(
+ struct el *el, /* el object to set option to */
+ el_custom_put clbk,
+ void *user
+)
+{
+ el_ooption(el, EL_CUSTOM_PUT, clbk, user);
+ if (clbk)
+ return el_oenable_output(el, EL_OUT_CUSTOM);
+ else
+ return el_odisable_output(el, EL_OUT_CUSTOM);
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+/* public api */ int el_set_custom_put
+(
+ el_custom_put clbk,
+ void *user
+)
+{
+ return el_oset_custom_put(&g_el, clbk, user);
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+/* public api */ int el_oenable_file_log
+(
+ struct el *el, /* el object to set option to */
+ const char *path,
+ int rotate_number,
+ long rotate_size
+
+)
+{
+ if (rotate_number >= 0)
+ OK_OR_RETURN(el_ooption(el, EL_FROTATE_NUMBER, rotate_number));
+ else
+ /* If rotate number is negative, then this means user passed
+ * EL_ROT_DATE enum and wants to date rotate */
+ OK_OR_RETURN(el_ooption(el, EL_FROTATE_DATE, rotate_number));
+
+ if (rotate_number > 0)
+ OK_OR_RETURN(el_ooption(el, EL_FROTATE_SIZE, rotate_size));
+
+ OK_OR_RETURN(el_enable_output(EL_OUT_FILE));
+ OK_OR_RETURN(el_ooption(el, EL_FPATH, path));
+
+ return 0;
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+/* public api */ int el_enable_file_log
+(
+ const char *path,
+ int rotate_number,
+ long rotate_size
+)
+{
+ return el_oenable_file_log(&g_el, path, rotate_number, rotate_size);
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+int el_oset_file_sync
+(
+ struct el *el,
+ long sync_every,
+ enum el_level sync_level
+)
+{
+ OK_OR_RETURN(el_ooption(el, EL_FSYNC_EVERY, sync_every));
+ OK_OR_RETURN(el_ooption(el, EL_FSYNC_LEVEL, sync_level));
+
+ return 0;
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+int el_set_file_sync
+(
+ long sync_every,
+ enum el_level sync_level
+)
+{
+ return el_oset_file_sync(&g_el, sync_every, sync_level);
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+/* public api */ int el_oset_tty_dev
+(
+ struct el *el, /* el object to set option to */
+ const char *dev,
+ unsigned speed
+)
+{
+ OK_OR_RETURN(el_ooption(el, EL_TTY_DEV, dev, speed));
+ OK_OR_RETURN(el_enable_output(EL_OUT_TTY));
+
+ return 0;
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+/* public api */ int el_set_tty_dev
+(
+ const char *dev,
+ unsigned speed
+)
+{
+ return el_oset_tty_dev(&g_el, dev, speed);
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+/* public api */ int el_oenable_thread_safe
+(
+ struct el *el, /* el object to set option to */
+ int enable
+)
+{
+ return el_ooption(el, EL_THREAD_SAFE, enable);
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+/* public api */ int el_enable_thread_safe
+(
+ int enable
+)
+{
+ return el_oenable_thread_safe(&g_el, enable);
+}
diff --git a/src/el-pbinary.c b/src/el-pbinary.c
index ae46fd1..3810e0f 100644
--- a/src/el-pbinary.c
+++ b/src/el-pbinary.c
@@ -21,15 +21,11 @@
__/\ / _/ \/ __,-' ) ,' _|'
(((__/(((_.' ((___..-'((__,'
==========================================================================
- _ __ __ ____ _ __
(_)____ _____ / /__ __ ____/ /___ / __/(_)/ /___ _____
/ // __ \ / ___// // / / // __ // _ \ / /_ / // // _ \ / ___/
/ // / / // /__ / // /_/ // /_/ // __/ / __// // // __/(__ )
/_//_/ /_/ \___//_/ \__,_/ \__,_/ \___/ /_/ /_//_/ \___//____/
-
========================================================================== */
-
-
#include "el-private.h"
#include <errno.h>
@@ -38,39 +34,12 @@
/* ==========================================================================
- __ __ __ _
- ____/ /___ _____ / /____ _ _____ ____ _ / /_ (_)____ ____ _____
- / __ // _ \ / ___// // __ `// ___// __ `// __// // __ \ / __ \ / ___/
- / /_/ // __// /__ / // /_/ // / / /_/ // /_ / // /_/ // / / /(__ )
- \__,_/ \___/ \___//_/ \__,_//_/ \__,_/ \__//_/ \____//_/ /_//____/
-
- ========================================================================== */
-
-
-#define FLAG_TS (0x01)
-
-#define FLAG_TS_FRACT_NONE (0x00)
-#define FLAG_TS_FRACT_NSEC (0x01)
-#define FLAG_TS_FRACT_USEC (0x02)
-#define FLAG_TS_FRACT_MSEC (0x03)
-#define FLAG_TS_FRACT_MASK (0x03)
-#define FLAG_TS_FRACT_SHIFT (1)
-
-#define FLAG_LEVEL_MASK (0x07)
-#define FLAG_LEVEL_SHIFT (3)
-
-
-/* ==========================================================================
- _ __ ____
____ _____ (_)_ __ ____ _ / /_ ___ / __/__ __ ____ _____ _____
/ __ \ / ___// /| | / // __ `// __// _ \ / /_ / / / // __ \ / ___// ___/
/ /_/ // / / / | |/ // /_/ // /_ / __/ / __// /_/ // / / // /__ (__ )
/ .___//_/ /_/ |___/ \__,_/ \__/ \___/ /_/ \__,_//_/ /_/ \___//____/
/_/
- ========================================================================== */
-
-
-/* ==========================================================================
+ ==========================================================================
Puts flags with log information to buf. Flags is single byte with fields
bit 0 timestamp enabled/disabled
@@ -78,8 +47,6 @@
bit 3-5 severity of the log
bit 6-7 reserved
========================================================================== */
-
-
static size_t el_flags
(
enum el_level level,
@@ -92,33 +59,29 @@ static size_t el_flags
#if ENABLE_TIMESTAMP
if (el->timestamp != EL_TS_OFF)
{
- *buf |= FLAG_TS;
+ *buf |= EL_FLAG_TS;
# if ENABLE_FRACTIONS
/* fraction of seconds can be printed only when timestamp
* is on */
- *buf |= el->timestamp_fractions << FLAG_TS_FRACT_SHIFT;
+ *buf |= el->timestamp_fractions << EL_FLAG_TS_FRACT_SHIFT;
# endif
}
#endif
- *buf |= level << FLAG_LEVEL_SHIFT;
+ *buf |= level << EL_FLAG_LEVEL_SHIFT;
return 1;
}
/* ==========================================================================
- __ __ _ ____
____ __ __ / /_ / /(_)_____ / __/__ __ ____ _____ _____
/ __ \ / / / // __ \ / // // ___/ / /_ / / / // __ \ / ___// ___/
/ /_/ // /_/ // /_/ // // // /__ / __// /_/ // / / // /__ (__ )
/ .___/ \__,_//_.___//_//_/ \___/ /_/ \__,_//_/ /_/ \___//____/
/_/
- ========================================================================== */
-
-
-/* ==========================================================================
+ ==========================================================================
Stores data pointed by "memory" of size "mlen" into destination
specified by "el". All metadata amd "memory" itself will be stored in
binary format.
@@ -156,8 +119,6 @@ static size_t el_flags
| 6..7 | 0..3 | reserved |
+------+-------+-------------------------------------------------+
========================================================================== */
-
-
/* public api */ int el_opbinary
(
enum el_level level, /* log severity level */
@@ -229,8 +190,6 @@ static size_t el_flags
/* ==========================================================================
Same as el_opbinary but uses global el object
========================================================================== */
-
-
/* public api */ int el_pbinary
(
enum el_level level, /* log severity level */
diff --git a/src/el-perror.c b/src/el-perror.c
index a9ee759..1ffd7c8 100644
--- a/src/el-perror.c
+++ b/src/el-perror.c
@@ -11,15 +11,11 @@
(__) )\
||--|| *
==========================================================================
- _ __ __ ____ _ __
(_)____ _____ / /__ __ ____/ /___ / __/(_)/ /___ _____
/ // __ \ / ___// // / / // __ // _ \ / /_ / // // _ \ / ___/
/ // / / // /__ / // /_/ // /_/ // __/ / __// // // __/(__ )
/_//_/ /_/ \___//_/ \__,_/ \__,_/ \___/ /_/ /_//_/ \___//____/
-
========================================================================== */
-
-
#include "el-private.h"
#include <errno.h>
@@ -28,21 +24,15 @@
/* ==========================================================================
- _ __ ____
____ _____ (_)_ __ ____ _ / /_ ___ / __/__ __ ____ _____ _____
/ __ \ / ___// /| | / // __ `// __// _ \ / /_ / / / // __ \ / ___// ___/
/ /_/ // / / / | |/ // /_/ // /_ / __/ / __// /_/ // / / // /__ (__ )
/ .___//_/ /_/ |___/ \__,_/ \__/ \___/ /_/ \__,_//_/ /_/ \___//____/
/_/
- ========================================================================== */
-
-
-/* ==========================================================================
+ ==========================================================================
calls el_print with 'fmt' and '...' parameters, but additionaly prints
information about errno. Functionaly it is similar to perror function
========================================================================== */
-
-
static int el_ovperror
(
const char *file, /* file name where log is printed */
@@ -81,21 +71,15 @@ static int el_ovperror
/* ==========================================================================
- __ __ _ ____
____ __ __ / /_ / /(_)_____ / __/__ __ ____ _____ _____
/ __ \ / / / // __ \ / // // ___/ / /_ / / / // __ \ / ___// ___/
/ /_/ // /_/ // /_/ // // // /__ / __// /_/ // / / // /__ (__ )
/ .___/ \__,_//_.___//_//_/ \___/ /_/ \__,_//_/ /_/ \___//____/
/_/
- ========================================================================== */
-
-
-/* ==========================================================================
+ ==========================================================================
calls el_print with 'fmt' and '...' parameters, but additionaly prints
information about errno. Functionaly it is similar to perror function
========================================================================== */
-
-
/* public api */ int el_perror
(
const char *file, /* file name where log is printed */
@@ -122,8 +106,6 @@ static int el_ovperror
/* ==========================================================================
el_perror function with custom el
========================================================================== */
-
-
/* public api */ int el_operror
(
const char *file, /* file name where log is printed */
diff --git a/src/el-pmemory.c b/src/el-pmemory.c
index 979d3c7..4ecbd2f 100644
--- a/src/el-pmemory.c
+++ b/src/el-pmemory.c
@@ -25,15 +25,11 @@
//__\\ \__ Ack! ///.----..< \ _ -~
// \\ ///-._ _ _ _ _ _ _{^ - - - - ~
==========================================================================
- _ __ __ ____ _ __
(_)____ _____ / /__ __ ____/ /___ / __/(_)/ /___ _____
/ // __ \ / ___// // / / // __ // _ \ / /_ / // // _ \ / ___/
/ // / / // /__ / // /_/ // /_/ // __/ / __// // // __/(__ )
/_//_/ /_/ \___//_/ \__,_/ \__,_/ \___/ /_/ /_//_/ \___//____/
-
========================================================================== */
-
-
#include "el-private.h"
#include <ctype.h>
@@ -41,22 +37,20 @@
/* ==========================================================================
- _ __ ____
____ _____ (_)_ __ ____ _ / /_ ___ / __/__ __ ____ _____ _____
/ __ \ / ___// /| | / // __ `// __// _ \ / /_ / / / // __ \ / ___// ___/
/ /_/ // / / / | |/ // /_/ // /_ / __/ / __// /_/ // / / // /__ (__ )
/ .___//_/ /_/ |___/ \__,_/ \__/ \___/ /_/ \__,_//_/ /_/ \___//____/
/_/
- ========================================================================== */
-
-
-/* ==========================================================================
+ ==========================================================================
prints single memory line, example line can look like this:
0x0020: 6e 20 70 72 69 6e 74 61 62 6c 65 09 63 68 61 72 n printable.char
- ========================================================================== */
+ Or like this, if pmemory spacing is set to 1
+ 0x0020: 6e 20 70 72 69 6e 74 61 62 6c 65 09 63 68 61 72 n printa ble.char
+ ========================================================================== */
static int el_print_line
(
const char *file, /* file name where log is printed */
@@ -73,10 +67,16 @@ static int el_print_line
* representation in hex and char */
char hex_data[EL_MEM_HEX_LEN + 1] = {0};
char char_data[EL_MEM_CHAR_LEN + 1] = {0};
+ char spacing[] = " ";
/* calculate buf offset value */
const unsigned int offset = EL_MEM_LINE_SIZE * line_number;
+ /* pointers to current hex and char data */
+ char *current_hex_pos = hex_data;
+ char *current_char_pos = char_data;
+
+ unsigned char current_byte;
size_t bn; /* byte number */
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
@@ -84,24 +84,31 @@ static int el_print_line
/* fill data buffers with representation of bytes */
for (bn = 0; bn < line_size; ++bn)
{
- unsigned char current_byte;
- char *current_hex_pos;
- char *current_char_pos;
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-
current_byte = *buf++;
- current_hex_pos = hex_data + bn * EL_MEM_SINGLE_HEX_LEN;
- current_char_pos = char_data + bn;
+
+ if (el->pmemory_space && bn == 8)
+ {
+ /* If this is 9th byte, then we already printed 8 bytes,
+ * id pmemory_space is set, we add additional spaces */
+ sprintf(current_hex_pos, "%*s", el->pmemory_space, spacing);
+ sprintf(current_char_pos, "%*s", el->pmemory_space, spacing);
+ current_hex_pos += el->pmemory_space;
+ current_char_pos += el->pmemory_space;
+ }
sprintf(current_hex_pos, "%02x ", current_byte);
if (isprint(current_byte) == 0) current_byte = '.';
*current_char_pos = current_byte;
+
+ /* Move pointers for current position of hex and char buffers */
+ current_hex_pos += EL_MEM_SINGLE_HEX_LEN;
+ current_char_pos++;
}
/* print constructed line */
return el_oprint_nb(file, num, func, level, el, "0x%04x %-*s %s",
- offset, EL_MEM_HEX_LEN, hex_data, char_data);
+ offset, EL_MEM_HEX_LEN - (3 - el->pmemory_space),
+ hex_data, char_data);
}
@@ -131,9 +138,11 @@ static int el_print_line
------ ----------------------------------------------- ----------------
0xNNNN HH HH HH HH HH HH HH HH HH HH HH HH HH HH HH HH CCCCCCCCCCCCCCCC
------ ----------------------------------------------- ----------------
- ========================================================================== */
+ If pmemory space is set to 1, like will be like this:
+ 0xNNNN HH HH HH HH HH HH HH HH HH HH HH HH HH HH HH HH CCCCCCCC CCCCCCCC
+ ========================================================================== */
static int el_pmem
(
const char *file, /* file name where log is printed */
@@ -157,6 +166,7 @@ static int el_pmem
size_t line_number; /* current line number being printed */
int rv; /* return value of print functions */
+ int table_shrink; /* how many extra '-' to add depending on spacing */
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
@@ -179,22 +189,32 @@ static int el_pmem
* ------ ----------------------------------------------- ----------------
*/
+ /* separators in table print for hex and ascii are compile time statics,
+ * with spacing this includes additional 3 characters, and so if spacing
+ * is off, separator will be 3 characters longer than expected, like
+ *
+ * --------
+ * fa fc
+ *
+ * When we don't print spacing, these 3 extra '-' should be removed.
+ * Calculate how many bytes we have to remove to have nice alignment */
+ table_shrink = 3 - el->pmemory_space;
if (table)
{
rv = 0;
rv |= el_oprint_nb(file, num, func, level, el, "%.*s %.*s %.*s",
EL_MEM_OFFSET_LEN - 2, separator,
- EL_MEM_HEX_LEN - 1, separator,
- EL_MEM_CHAR_LEN, separator);
+ EL_MEM_HEX_LEN - 1 - table_shrink, separator,
+ EL_MEM_CHAR_LEN - table_shrink, separator);
rv |= el_oprint_nb(file, num, func, level, el, "%-*s%-*s%s",
EL_MEM_OFFSET_LEN, "offset",
- EL_MEM_HEX_LEN + 1, "hex", "ascii");
+ EL_MEM_HEX_LEN + 1 - table_shrink, "hex", "ascii");
rv |= el_oprint_nb(file, num, func, level, el, "%.*s %.*s %.*s",
EL_MEM_OFFSET_LEN - 2, separator,
- EL_MEM_HEX_LEN - 1, separator,
- EL_MEM_CHAR_LEN, separator);
+ EL_MEM_HEX_LEN - 1 - table_shrink, separator,
+ EL_MEM_CHAR_LEN - table_shrink, separator);
}
/* print all lines that contains EL_MEM_LINE_SIZE bytes,
@@ -224,8 +244,8 @@ static int el_pmem
if (table)
rv |= el_oprint_nb(file, num, func, level, el, "%.*s %.*s %.*s",
EL_MEM_OFFSET_LEN - 2, separator,
- EL_MEM_HEX_LEN - 1, separator,
- EL_MEM_CHAR_LEN, separator);
+ EL_MEM_HEX_LEN - 1 - table_shrink, separator,
+ EL_MEM_CHAR_LEN - table_shrink, separator);
el_unlock(el);
return rv;
@@ -233,20 +253,14 @@ static int el_pmem
/* ==========================================================================
- __ __ _ ____
____ __ __ / /_ / /(_)_____ / __/__ __ ____ _____ _____
/ __ \ / / / // __ \ / // // ___/ / /_ / / / // __ \ / ___// ___/
/ /_/ // /_/ // /_/ // // // /__ / __// /_/ // / / // /__ (__ )
/ .___/ \__,_//_.___//_//_/ \___/ /_/ \__,_//_/ /_/ \___//____/
/_/
- ========================================================================== */
-
-
-/* ==========================================================================
+ ==========================================================================
same as el_pmem and prints table
========================================================================== */
-
-
/* public api */ int el_opmemory_table
(
const char *file, /* file name where log is printed */
@@ -265,8 +279,6 @@ static int el_pmem
/* ==========================================================================
same as el_opmemory_table but uses default option object
========================================================================== */
-
-
/* public api */ int el_pmemory_table
(
const char *file, /* file name where log is printed */
@@ -283,8 +295,6 @@ static int el_pmem
/* ==========================================================================
Same as el_pmem and prints no table
========================================================================== */
-
-
/* public api */ int el_opmemory
(
const char *file, /* file name where log is printed */
@@ -303,8 +313,6 @@ static int el_pmem
/* ==========================================================================
same as el_opmemory but uses default option object
========================================================================== */
-
-
/* public api */ int el_pmemory
(
const char *file, /* file name where log is printed */
diff --git a/src/el-print.c b/src/el-print.c
index cf91585..eb91872 100644
--- a/src/el-print.c
+++ b/src/el-print.c
@@ -31,15 +31,11 @@
^^^//\\_^^//\\_^ ^(\_\_\_\)
^^^ ^^ ^^^ ^
==========================================================================
- _ __ __ ____ _ __
(_)____ _____ / /__ __ ____/ /___ / __/(_)/ /___ _____
/ // __ \ / ___// // / / // __ // _ \ / /_ / // // _ \ / ___/
/ // / / // /__ / // /_/ // /_/ // __/ / __// // // __/(__ )
/_//_/ /_/ \___//_/ \__,_/ \__,_/ \___/ /_/ /_//_/ \___//____/
-
========================================================================== */
-
-
#include "el-private.h"
#include "el-utils.h"
@@ -51,18 +47,13 @@
/* ==========================================================================
- __ __ __ _
____/ /___ _____ / /____ _ _____ ____ _ / /_ (_)____ ____ _____
/ __ // _ \ / ___// // __ `// ___// __ `// __// // __ \ / __ \ / ___/
/ /_/ // __// /__ / // /_/ // / / /_/ // /_ / // /_/ // / / /(__ )
\__,_/ \___/ \___//_/ \__,_//_/ \__,_/ \__//_/ \____//_/ /_//____/
-
========================================================================== */
-
-
static const char char_level[8] = { 'f', 'a', 'c', 'e', 'w', 'n', 'i', 'd' };
-
#if ENABLE_COLORS
/* colors indexes are synced with log level */
@@ -110,16 +101,12 @@ static const char *color[] =
/* ==========================================================================
- _ __ ____
____ _____ (_)_ __ ____ _ / /_ ___ / __/__ __ ____ _____ _____
/ __ \ / ___// /| | / // __ `// __// _ \ / /_ / / / // __ \ / ___// ___/
/ /_/ // / / / | |/ // /_/ // /_ / __/ / __// /_/ // / / // /__ (__ )
/ .___//_/ /_/ |___/ \__,_/ \__/ \___/ /_/ \__,_//_/ /_/ \___//____/
/_/
- ========================================================================== */
-
-
-/* ==========================================================================
+ ==========================================================================
adds color information to 'buf' based on 'level'. Returns number of
bytes stored in buf. If colors are disabled, function will return 0 and
nothing will be stored int 'buf'.
@@ -127,8 +114,6 @@ static const char *color[] =
color can be one of log levels passed directly, or int value 8, which
will reset colors.
========================================================================== */
-
-
static size_t el_color
(
struct el *el, /* el defining printing style */
@@ -159,8 +144,6 @@ static size_t el_color
'buf' is returned. If file info is disabled during compilation or in
runtime, value 0 is returned
========================================================================== */
-
-
static size_t el_finfo
(
struct el *el, /* el defining printing style */
@@ -207,8 +190,6 @@ static size_t el_finfo
/* ==========================================================================
Stores function name with appended "()" into 'buf'.
========================================================================== */
-
-
static size_t el_funcinfo
(
struct el *el, /* el defining printing style */
@@ -259,20 +240,14 @@ static size_t el_funcinfo
/* ==========================================================================
- __ __ _ ____
____ __ __ / /_ / /(_)_____ / __/__ __ ____ _____ _____
/ __ \ / / / // __ \ / // // ___/ / /_ / / / // __ \ / ___// ___/
/ /_/ // /_/ // /_/ // // // /__ / __// /_/ // / / // /__ (__ )
/ .___/ \__,_//_.___//_//_/ \___/ /_/ \__,_//_/ /_/ \___//____/
/_/
- ========================================================================== */
-
-
-/* ==========================================================================
+ ==========================================================================
simply calls el_printv with '...' converted to 'va_list'
========================================================================== */
-
-
/* public api */ int el_print
(
const char *file, /* file name where log is printed */
@@ -299,8 +274,6 @@ static size_t el_funcinfo
/* ==========================================================================
el_print but with custom el
========================================================================== */
-
-
/* public api */ int el_oprint
(
const char *file, /* file name to print in log */
@@ -328,8 +301,6 @@ static size_t el_funcinfo
/* ==========================================================================
el_print but with custom el and does not lock mutex.
========================================================================== */
-
-
int el_oprint_nb
(
const char *file, /* file name to print in log */
@@ -356,8 +327,6 @@ int el_oprint_nb
/* ==========================================================================
el_print but accepts variadic argument list object instead of '...'
========================================================================== */
-
-
/* public api */ int el_vprint
(
const char *file, /* file name where log is printed */
@@ -375,8 +344,6 @@ int el_oprint_nb
/* ==========================================================================
Same as el_ovprint_nb() but can lock mutex.
========================================================================== */
-
-
/* public api */ int el_ovprint
(
const char *file, /* file name to print in log */
@@ -414,8 +381,6 @@ int el_oprint_nb
ERANGE printing is disabled
ENOBUFS message was too long and has been truncated
========================================================================== */
-
-
int el_ovprint_nb
(
const char *file, /* file name to print in log */
diff --git a/src/el-private.h b/src/el-private.h
index 240ba2f..dbf919a 100644
--- a/src/el-private.h
+++ b/src/el-private.h
@@ -2,7 +2,6 @@
Licensed under BSD 2clause license See LICENSE file for more information
Author: Michał Łyszczek <michal.lyszczek@bofc.pl>
========================================================================== */
-
#ifndef EL_PRIVATE_H
#define EL_PRIVATE_H 1
@@ -25,15 +24,11 @@ int vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap);
/* ==========================================================================
- _ __ __ ____ _ __
(_)____ _____ / /__ __ ____/ /___ / __/(_)/ /___ _____
/ // __ \ / ___// // / / // __ // _ \ / /_ / // // _ \ / ___/
/ // / / // /__ / // /_/ // /_/ // __/ / __// // // __/(__ )
/_//_/ /_/ \___//_/ \__,_/ \__,_/ \___/ /_/ /_//_/ \___//____/
-
========================================================================== */
-
-
#include "embedlog.h"
#include "valid.h"
@@ -45,31 +40,24 @@ int vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap);
/* ==========================================================================
- __ __ __
____ _ / /____ / /_ ____ _ / / _ __ ____ _ _____ _____
/ __ `// // __ \ / __ \ / __ `// / | | / // __ `// ___// ___/
/ /_/ // // /_/ // /_/ // /_/ // / | |/ // /_/ // / (__ )
\__, //_/ \____//_.___/ \__,_//_/ |___/ \__,_//_/ /____/
/____/
========================================================================== */
-
-
extern struct el g_el;
/* ==========================================================================
- __ __
_____ ____ ____ _____ / /_ ____ _ ____ / /_ _____
/ ___// __ \ / __ \ / ___// __// __ `// __ \ / __// ___/
/ /__ / /_/ // / / /(__ )/ /_ / /_/ // / / // /_ (__ )
\___/ \____//_/ /_//____/ \__/ \__,_//_/ /_/ \__//____/
-
========================================================================== */
-
/* ==== defines for el_pmemory function ===================================== */
-
/* ==========================================================================
single line of el_pmemory will be similar to this
@@ -80,39 +68,32 @@ extern struct el g_el;
/* ==========================================================================
this defines length of "0xNNNN " part.
========================================================================== */
-
-
#define EL_MEM_OFFSET_LEN 8
/* ==========================================================================
length of the "HH " part
========================================================================== */
-
-
#define EL_MEM_SINGLE_HEX_LEN 3
/* ==========================================================================
length of all "HH ". EL_MEM_LINE_SIZE is externally defined during
- compilation to tune the output
+ compilation to tune the output. We add +3 for possible spacing after
+ 8 printed bytes.
========================================================================== */
-
-
-#define EL_MEM_HEX_LEN (EL_MEM_SINGLE_HEX_LEN * (EL_MEM_LINE_SIZE))
+#define EL_MEM_HEX_LEN (EL_MEM_SINGLE_HEX_LEN * (EL_MEM_LINE_SIZE) + 3)
/* ==========================================================================
- length of all "C" characters
+ length of all "C" characters. We add +3 for possible spacing after
+ 8 printed bytes.
========================================================================== */
-
-
-#define EL_MEM_CHAR_LEN (EL_MEM_LINE_SIZE)
+#define EL_MEM_CHAR_LEN (EL_MEM_LINE_SIZE + 3)
/* ==== defines for el_print function ======================================= */
-
/* ==========================================================================
length of long timestamp in a single log. Timestamp format is
@@ -120,8 +101,6 @@ extern struct el g_el;
which is 21 bytes long
========================================================================== */
-
-
#define EL_PRE_TS_LONG_LEN 21
@@ -133,8 +112,6 @@ extern struct el g_el;
which is 12 bytes long. This is maximum value for short timestamp, as it
can be shorter.
========================================================================== */
-
-
#define EL_PRE_TS_SHORT_LEN 12
@@ -147,16 +124,12 @@ extern struct el g_el;
[yyyy-mm-dd hh:mm:ss.fffffffff]
========================================================================== */
-
-
#define EL_PRE_TS_FRACT_LEN 10
/* ==========================================================================
Calculate what is the minimum needed length to hold longest timestamp
========================================================================== */
-
-
#if ENABLE_TIMESTAMP
# define EL_PRE_TS_MAX (EL_PRE_TS_LONG_LEN + EL_PRE_TS_FRACT_LEN)
#else
@@ -168,8 +141,6 @@ extern struct el g_el;
Maximum length of line number. ie, if set to 1, range 0-9 is allowed,
rendering [source-file.c:5] valid while [source-file.c:13] invalid.
========================================================================== */
-
-
#define EL_PRE_FINFO_LINE_MAX_LEN 7
@@ -178,8 +149,6 @@ extern struct el g_el;
EL_PRE_FINFO_LINE_MAX_LEN. So if EL_PRE_FINFO_LINE_MAX_LEN is 2, best to
define it to 99, when 5 -> 99999.
========================================================================== */
-
-
#define EL_PRE_FINFO_LINE_MAX_NUM 9999999l
@@ -193,8 +162,6 @@ extern struct el g_el;
during compilation to suite users needs, 3 is for special characters
"[:]". EL_PRE_FINFO_LINE_MAX_LEN can be redefined to any value.
========================================================================== */
-
-
#if ENABLE_FINFO
# define EL_PRE_FINFO_LEN ((EL_FLEN_MAX) + 3 + EL_PRE_FINFO_LINE_MAX_LEN)
#else
@@ -216,8 +183,6 @@ extern struct el g_el;
EL_FUNCLEN_MAX is defined during compilation.
========================================================================== */
-
-
#if ENABLE_FUNCINFO
# define EL_PRE_FUNCINFO_LEN ((EL_FUNCLEN_MAX) + 2 + 1 + 1)
#else
@@ -231,8 +196,6 @@ extern struct el g_el;
a situation where another preamble (like timestamp) is printed before
level, and we need to delimiter them with space
========================================================================== */
-
-
#define EL_PRE_LEVEL_LEN 3
@@ -241,8 +204,6 @@ extern struct el g_el;
[2017-05-24 14:43:10.123456][source-file.c:12345:function()] e/prefix
========================================================================== */
-
-
#if ENABLE_PREFIX
# define EL_PREFIX_LEN EL_PREFIX_MAX
#else
@@ -258,8 +219,6 @@ extern struct el g_el;
start coloring output, and 4 characters are neede to reset terminal
color to default
========================================================================== */
-
-
#if ENABLE_COLORS
# define EL_COLORS_LEN (5 + 4)
#else
@@ -272,16 +231,12 @@ extern struct el g_el;
defines length of final output not format. So "%s" can take even 100
bytes. EL_LOG_MAX is defined externally during compilation.
========================================================================== */
-
-
#define EL_BUF_MAX (EL_PRE_LEN + (EL_LOG_MAX) + EL_COLORS_LEN)
/* ==========================================================================
Defines if timestamp should be stored into buffer as string or binary
========================================================================== */
-
-
#define TS_STRING (0)
#define TS_BINARY (1)
@@ -295,22 +250,16 @@ extern struct el g_el;
another check). This is basically an bitwise OR of all fields in enum
el_output
========================================================================== */
-
-
#define ALL_OUTS (EL_OUT_STDERR | EL_OUT_STDOUT | EL_OUT_SYSLOG | \
EL_OUT_FILE | EL_OUT_NET | EL_OUT_TTY | EL_OUT_CUSTOM)
/* ==========================================================================
- ____ __ _
/ __/__ __ ____ _____ / /_ (_)____ ____ _____
/ /_ / / / // __ \ / ___// __// // __ \ / __ \ / ___/
/ __// /_/ // / / // /__ / /_ / // /_/ // / / /(__ )
/_/ \__,_//_/ /_/ \___/ \__//_/ \____//_/ /_//____/
-
========================================================================== */
-
-
#if ENABLE_OUT_FILE
int el_file_open(struct el *el);
int el_file_puts(struct el *el, const char *s);
@@ -319,7 +268,7 @@ void el_file_cleanup(struct el *el);
int el_file_flush(struct el *el);
#endif
-
+
int el_oputb_nb(struct el *el, const void *mem, size_t mlen);
int el_oputs_nb(struct el *el, const char *s);
int el_ovprint_nb(const char *file, size_t num, const char *func,
diff --git a/src/el-puts.c b/src/el-puts.c
index 0a6b9bb..2c2467e 100644
--- a/src/el-puts.c
+++ b/src/el-puts.c
@@ -18,15 +18,11 @@
| | | |
|m| |m|
==========================================================================
- _ __ __ ____ _ __
(_)____ _____ / /__ __ ____/ /___ / __/(_)/ /___ _____
/ // __ \ / ___// // / / // __ // _ \ / /_ / // // _ \ / ___/
/ // / / // /__ / // /_/ // /_/ // __/ / __// // // __/(__ )
/_//_/ /_/ \___//_/ \__,_/ \__,_/ \___/ /_/ /_//_/ \___//____/
-
========================================================================== */
-
-
#include "el-private.h"
#include <errno.h>
@@ -35,21 +31,15 @@
/* ==========================================================================
- __ __ _ ____
____ __ __ / /_ / /(_)_____ / __/__ __ ____ _____ _____
/ __ \ / / / // __ \ / // // ___/ / /_ / / / // __ \ / ___// ___/
/ /_/ // /_/ // /_/ // // // /__ / __// /_/ // / / // /__ (__ )
/ .___/ \__,_//_.___//_//_/ \___/ /_/ \__,_//_/ /_/ \___//____/
/_/
- ========================================================================== */
-
-
-/* ==========================================================================
+ ==========================================================================
puts string 's' to all enabled output facilities specified by default
el object
========================================================================== */
-
-
/* public api */ int el_puts
(
const char *s /* string to put into output */
@@ -62,8 +52,6 @@
/* ==========================================================================
Just like el_oputs_nb() but can lock mutex.
========================================================================== */
-
-
/* public api */ int el_oputs
(
struct el *el, /* el defining printing style */
@@ -86,8 +74,6 @@
puts string 's' to all enabled output facilities specified by el. Does
not do any locking, thus _nb (non blocking).
========================================================================== */
-
-
int el_oputs_nb
(
struct el *el, /* el defining printing style */
@@ -147,8 +133,6 @@ int el_oputs_nb
puts memory 'mem' to all supported output facilities specified by
default el object. Not all outputs support printing binary data
========================================================================== */
-
-
/* public api */ int el_putb
(
const void *mem, /* memory location to 'print' */
@@ -162,8 +146,6 @@ int el_oputs_nb
/* ==========================================================================
Just like el_oputb_nb() but also can perform pthread locking.
========================================================================== */
-
-
/* public api */ int el_oputb
(
struct el *el, /* el defining printing style */
@@ -188,8 +170,6 @@ int el_oputs_nb
This functions does not do any locking - thus _nb (non blocking).
========================================================================== */
-
-
int el_oputb_nb
(
struct el *el, /* el defining printing style */
diff --git a/src/el-syslog.c b/src/el-syslog.c
index 8b24f69..22fff29 100644
--- a/src/el-syslog.c
+++ b/src/el-syslog.c
@@ -1,19 +1,13 @@
/* ==========================================================================
Licensed under BSD 2clause license See LICENSE file for more information
Author: Michał Łyszczek <michal.lyszczek@bofc.pl>
- ========================================================================== */
-
-
-/* ==========================================================================
- _ __ __ ____ _ __
+ ==========================================================================
(_)____ _____ / /__ __ ____/ /___ / __/(_)/ /___ _____
/ // __ \ / ___// // / / // __ // _ \ / /_ / // // _ \ / ___/
/ // / / // /__ / // /_/ // /_/ // __/ / __// // // __/(__ )
/_//_/ /_/ \___//_/ \__,_/ \__,_/ \___/ /_/ /_//_/ \___//____/
========================================================================== */
-
-
#include "el-private.h"
#include <errno.h>
@@ -27,26 +21,14 @@
/* ==========================================================================
- __ __ _
- ____ __ __ / /_ / /(_)_____
- / __ \ / / / // __ \ / // // ___/
- / /_/ // /_/ // /_/ // // // /__
- / .___/ \__,_//_.___//_//_/ \___/
- /_/
- ____ __ _
- / __/__ __ ____ _____ / /_ (_)____ ____ _____
- / /_ / / / // __ \ / ___// __// // __ \ / __ \ / ___/
- / __// /_/ // / / // /__ / /_ / // /_/ // / / /(__ )
- /_/ \__,_//_/ /_/ \___/ \__//_/ \____//_/ /_//____/
-
- ========================================================================== */
-
-
-/* ==========================================================================
+ ____ __ __ / /_ / /(_)_____ / __/__ __ ____ _____ _____
+ / __ \ / / / // __ \ / // // ___/ / /_ / / / // __ \ / ___// ___/
+ / /_/ // /_/ // /_/ // // // /__ / __// /_/ // / / // /__ (__ )
+ / .___/ \__,_//_.___//_//_/ \___/ /_/ \__,_//_/ /_/ \___//____/
+ /_/
+ ==========================================================================
Open tty device and configure it for output only
========================================================================== */
-
-
int el_tty_open
(
struct el *el, /* store serial file descriptor here */
@@ -69,34 +51,23 @@ int el_tty_open
return -1;
#if HAVE_TERMIOS_H
- /*
- * if termios is not available, simply open device without reconfiguring
- * it. Some embedded OSes might configure tty during compilation and
- * have termios disabled to save memory.
- */
+ /* if termios is not available, simply open device without reconfiguring
+ * it. Some embedded OSes might configure tty during compilation and
+ * have termios disabled to save memory. */
if (speed == B0)
- {
- /*
- * normally with B0 we should terminate transmission, it is used
- * with modem lines, but since we do not use modem lines, and in
- * logger terminating connection does not make any sense, we use
- * this to tell embedlog *not* to change any settings but only open
- * serial
- */
-
+ /* normally with B0 we should terminate transmission, it is used
+ * with modem lines, but since we do not use modem lines, and in
+ * logger terminating connection does not make any sense, we use
+ * this to tell embedlog *not* to change any settings but only open
+ * serial */
return 0;
- }
if (tcgetattr(el->serial_fd, &tty) != 0)
- {
goto error;
- }
if (cfsetispeed(&tty, speed) != 0)
- {
goto error;
- }
tty.c_cflag &= ~CSIZE; /* apply size mask */
tty.c_cflag |= CS8; /* 8bit transmission */
@@ -108,9 +79,7 @@ int el_tty_open
tty.c_oflag |= OPOST | ONLCR; /* enable output post-processing by OS */
if (tcsetattr(el->serial_fd, TCSANOW, &tty) != 0)
- {
goto error;
- }
return 0;
@@ -132,31 +101,27 @@ error:
/* ==========================================================================
Yup, you guessed right - it closes serial.
========================================================================== */
-
-
int el_tty_close
(
- struct el *el /* el object with serial descriptor */
+ struct el *el /* el object with serial descriptor */
)
{
- VALID(EINVAL, el->serial_fd != -1);
+ VALID(EINVAL, el->serial_fd != -1);
- close(el->serial_fd);
- el->serial_fd = -1;
- return 0;
+ close(el->serial_fd);
+ el->serial_fd = -1;
+ return 0;
}
/* ==========================================================================
Simply sends string pointed by s to serial port configured in el
========================================================================== */
-
-
int el_tty_puts
(
- struct el *el, /* el object with serial descriptor */
- const char *s /* string to send */
+ struct el *el, /* el object with serial descriptor */
+ const char *s /* string to send */
)
{
- return write(el->serial_fd, s, strlen(s));
+ return write(el->serial_fd, s, strlen(s));
}
diff --git a/src/el-ts.c b/src/el-ts.c
index 6bee5dd..6041415 100644
--- a/src/el-ts.c
+++ b/src/el-ts.c
@@ -29,15 +29,11 @@
\XXXXXXXXXXXXXXXXXXXXXXXXXX/
""VXXXXXXXXXXXXXXXXXXV""
==========================================================================
- _ __ __ ____ _ __
(_)____ _____ / /__ __ ____/ /___ / __/(_)/ /___ _____
/ // __ \ / ___// // / / // __ // _ \ / /_ / // // _ \ / ___/
/ // / / // /__ / // /_/ // /_/ // __/ / __// // // __/(__ )
/_//_/ /_/ \___//_/ \__,_/ \__,_/ \___/ /_/ /_//_/ \___//____/
-
========================================================================== */
-
-
#include "el-private.h"
#include <time.h>
@@ -46,8 +42,6 @@
/* ==========================================================================
returns seconds and nanoseconds calculated from clock() function
========================================================================== */
-
-
#if ENABLE_TIMESTAMP
#if ENABLE_CLOCK
@@ -75,8 +69,6 @@ static void el_ts_clock
/* ==========================================================================
returns seconds and nanoseconds calculated from time() function.
========================================================================== */
-
-
#if ENABLE_TIMESTAMP
static void el_ts_time
@@ -91,11 +83,10 @@ static void el_ts_time
#endif /* ENABLE_TIMESTAMP */
+
/* ==========================================================================
returns seconds and nanoseconds calculated from clock_gettime function
========================================================================== */
-
-
#if ENABLE_TIMESTAMP
#if ENABLE_REALTIME || ENABLE_MONOTONIC
@@ -125,8 +116,6 @@ static void el_ts_clock_gettime
number of bytes copied to 'buf'. If timestamp has been disabled during
compilation time or in runtime during settings, function will return 0.
========================================================================== */
-
-
size_t el_timestamp
(
struct el *el, /* el defining printing style */
@@ -185,8 +174,7 @@ size_t el_timestamp
if (binary)
{
- /* put encoded seconds timestamp in buf
- */
+ /* put encoded seconds timestamp in buf */
# ifdef LLONG_MAX
tl = el_encode_number((unsigned long long)s, (unsigned char *)buf);
diff --git a/src/el-tty.c b/src/el-tty.c
index 42f335b..89a4c41 100644
--- a/src/el-tty.c
+++ b/src/el-tty.c
@@ -17,15 +17,11 @@
`YY~~~~YY'
|| ||
==========================================================================
- _ __ __ ____ _ __
(_)____ _____ / /__ __ ____/ /___ / __/(_)/ /___ _____
/ // __ \ / ___// // / / // __ // _ \ / /_ / // // _ \ / ___/
/ // / / // /__ / // /_/ // /_/ // __/ / __// // // __/(__ )
/_//_/ /_/ \___//_/ \__,_/ \__,_/ \___/ /_/ /_//_/ \___//____/
-
========================================================================== */
-
-
#include "el-private.h"
#include <errno.h>
@@ -40,20 +36,14 @@
/* ==========================================================================
- __ __ _ ____
____ __ __ / /_ / /(_)_____ / __/__ __ ____ _____ _____
/ __ \ / / / // __ \ / // // ___/ / /_ / / / // __ \ / ___// ___/
/ /_/ // /_/ // /_/ // // // /__ / __// /_/ // / / // /__ (__ )
/ .___/ \__,_//_.___//_//_/ \___/ /_/ \__,_//_/ /_/ \___//____/
/_/
- ========================================================================== */
-
-
-/* ==========================================================================
+ ==========================================================================
Open tty device and configure it for output only
========================================================================== */
-
-
int el_tty_open
(
struct el *el, /* store serial file descriptor here */
@@ -120,8 +110,6 @@ error:
/* ==========================================================================
Yup, you guessed right - it closes serial.
========================================================================== */
-
-
int el_tty_close
(
struct el *el /* el object with serial descriptor */
@@ -138,8 +126,6 @@ int el_tty_close
/* ==========================================================================
Simply sends string pointed by s to serial port configured in el
========================================================================== */
-
-
int el_tty_puts
(
struct el *el, /* el object with serial descriptor */
diff --git a/src/el-utils.c b/src/el-utils.c
index c473c1f..da78d49 100644
--- a/src/el-utils.c
+++ b/src/el-utils.c
@@ -12,15 +12,11 @@
(oo) ||----w |
(__) || || \/\
==========================================================================
- _ __ __ ____ _ __
(_)____ _____ / /__ __ ____/ /___ / __/(_)/ /___ _____
/ // __ \ / ___// // / / // __ // _ \ / /_ / // // _ \ / ___/
/ // / / // /__ / // /_/ // /_/ // __/ / __// // // __/(__ )
/_//_/ /_/ \___//_/ \__,_/ \__,_/ \___/ /_/ /_//_/ \___//____/
-
========================================================================== */
-
-
#if HAVE_CONFIG_H
# include "config.h"
#endif
@@ -28,16 +24,12 @@
/* ==========================================================================
- __ __ _ ____
____ __ __ / /_ / /(_)_____ / __/__ __ ____ _____ _____
/ __ \ / / / // __ \ / // // ___/ / /_ / / / // __ \ / ___// ___/
/ /_/ // /_/ // /_/ // // // /__ / __// /_/ // / / // /__ (__ )
/ .___/ \__,_//_.___//_//_/ \___/ /_/ \__,_//_/ /_/ \___//____/
/_/
- ========================================================================== */
-
-
-/* ==========================================================================
+ ==========================================================================
returns pointer to where basename of 's' starts
Examples:
@@ -49,8 +41,6 @@
"" ""
NULL segmentation fault
========================================================================== */
-
-
const char *el_basename
(
const char *s /* string to basename */
diff --git a/test-compilation.sh b/test-compilation.sh
index 800b745..e53bf85 100755
--- a/test-compilation.sh
+++ b/test-compilation.sh
@@ -17,7 +17,7 @@ prepare()
project_dir="${3}"
# clone
- if ! git clone git://git.bofc.pl/"${project}" "${project}-${slot}"
+ if ! git clone "${project}-base" "${project}-${slot}"
then
echo "couldn't clone, sorry"
exit 1
@@ -160,6 +160,13 @@ do
slots+="${i} "
done
+# we will clone $job-number times, no need to bash the server with so much
+# clone jobs, clone once and then we will use that local repo to clone from
+if ! git clone git://git.bofc.pl/"${project}" "${project}-base"; then
+ echo "couldn't clone, sorry"
+ exit 1
+fi
+
# run preparation
parallel --output-as-files --bar --results "${workdir}" \
--halt-on-error now,fail=1 --jobs ${num_jobs} \
diff --git a/tst/Makefile.am b/tst/Makefile.am
index 6acfd06..865bb91 100644
--- a/tst/Makefile.am
+++ b/tst/Makefile.am
@@ -1,5 +1,5 @@
include Makefile.am.coverage
-check_PROGRAMS = test
+check_PROGRAMS = test test_wrapper
test_SOURCES = main.c \
test-el-options.c \
@@ -18,6 +18,10 @@ test_CFLAGS = -I$(top_builddir)/include \
test_LDFLAGS = $(COVERAGE_LDFLAGS)
test_LDADD = -lrb $(top_builddir)/src/.libs/libembedlog.a
-TESTS = $(check_PROGRAMS)
+test_wrapper: test
+ echo 'LD_PRELOAD=/usr/lib64/libfaketime.so FAKETIME_NO_CACHE=1 TZ=UTC ./test' > $@
+ chmod +x $@
+
+TESTS = test_wrapper
LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \
$(top_srcdir)/tap-driver.sh
diff --git a/tst/test-el-file.c b/tst/test-el-file.c
index 0dbada8..b9b7170 100644
--- a/tst/test-el-file.c
+++ b/tst/test-el-file.c
@@ -83,15 +83,14 @@ static int file_check
{
char fc[128];
int fd;
- ssize_t r;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+ memset(fc, 0x00, sizeof(fc));
fd = open(f, O_RDONLY);
- r = read(fd, fc, sizeof(fc));
+ read(fd, fc, sizeof(fc));
close(fd);
- fc[r] = '\0';
if(strcmp(s, fc) != 0) return -1;
return 0;
@@ -163,17 +162,11 @@ static void test_cleanup(void)
unlink(WORKDIR"/log");
unlink(WORKDIR"/log-another");
- for (i = 0; i != 5; ++i)
- {
- char path1[PATH_MAX] = WORKDIR"/log.";
- char path2[PATH_MAX] = WORKDIR"/log-another.";
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+ /* We may have different files, with different dates. Go lazy
+ * route and remove them with system call */
- path1[strlen(path1)] = '0' + i;
- path2[strlen(path2)] = '0' + i;
- unlink(path1);
- unlink(path2);
- }
+ /* WORKDIR is statically set, and we don't remove recursive */
+ system("rm -f "WORKDIR"/*");
el_cleanup();
}
@@ -2002,6 +1995,249 @@ static void file_print_threaded(void)
#endif /* ENABLE_PTHREAD */
+/* ==========================================================================
+ ========================================================================== */
+static void options_f_enable_file_log(void)
+{
+ mt_fok(el_enable_file_log(WORKDIR"/log", 4, 4326));
+ mt_fail(g_el.frotate_type == EL_ROT_FSIZE);
+ mt_fail(g_el.frotate_number == 4);
+ mt_fail(g_el.frotate_size == 4326);
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+static void options_f_enable_file_log_no_rotate(void)
+{
+ long old_rotate = g_el.frotate_size;
+ mt_fok(el_enable_file_log(WORKDIR"/log", 0, 0));
+ mt_fail(g_el.frotate_type == EL_ROT_OFF);
+ mt_fail(g_el.frotate_number == 0);
+ mt_fail(g_el.frotate_size == old_rotate);
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+static void options_f_enable_file_log_rotate_no_size(void)
+{
+ mt_ferr(el_enable_file_log(WORKDIR"/log", 2, 0), EINVAL);
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+static void options_f_enable_file_log_date_rotate(void)
+{
+ mt_fok(el_enable_file_log(WORKDIR"/log", EL_ROT_DATE_SEC, 0));
+ mt_fail(g_el.frotate_type == EL_ROT_DATE_SEC);
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+static void file_date_rotate_seconds(void)
+{
+ setenv("FAKETIME", "2000-01-01 00:00:00", 1);
+ el_option(EL_FROTATE_DATE, EL_ROT_DATE_SEC);
+ el_puts(s1);
+
+ setenv("FAKETIME", "2000-01-01 00:00:01", 1);
+ el_puts(s1);
+ el_puts(s1);
+
+ setenv("FAKETIME", "2000-01-01 00:00:02", 1);
+ el_puts(s1);
+ el_puts(s1);
+ el_puts(s1);
+
+ setenv("FAKETIME", "2000-01-01 00:01:02", 1);
+ el_puts(s1);
+ el_puts(s1);
+
+ setenv("FAKETIME", "2001-01-01 00:00:02", 1);
+ el_puts(s1);
+
+ mt_fok(file_check(WORKDIR"/log.2000-01-01--00-00-00", s1));
+ mt_fok(file_check(WORKDIR"/log.2000-01-01--00-00-01", s1 s1));
+ mt_fok(file_check(WORKDIR"/log.2000-01-01--00-00-02", s1 s1 s1));
+ mt_fok(file_check(WORKDIR"/log.2000-01-01--00-01-02", s1 s1));
+ mt_fok(file_check(WORKDIR"/log.2001-01-01--00-00-02", s1));
+
+ unsetenv("FAKETIME");
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+static void file_date_rotate_minute(void)
+{
+ setenv("FAKETIME", "2000-01-01 00:00:00", 1);
+ el_option(EL_FROTATE_DATE, EL_ROT_DATE_MIN);
+ el_puts(s1);
+ setenv("FAKETIME", "2000-01-01 00:00:01", 1);
+ el_puts(s1);
+ el_puts(s1);
+ setenv("FAKETIME", "2000-01-01 00:00:02", 1);
+ el_puts(s1);
+ el_puts(s1);
+
+ setenv("FAKETIME", "2000-01-01 00:01:02", 1);
+ el_puts(s1);
+ el_puts(s1);
+ setenv("FAKETIME", "2000-01-01 00:01:02", 1);
+ el_puts(s1);
+ setenv("FAKETIME", "2000-01-01 00:01:32", 1);
+ el_puts(s1);
+
+ setenv("FAKETIME", "2000-01-02 00:01:32", 1);
+ el_puts(s1);
+ el_puts(s1);
+
+ mt_fok(file_check(WORKDIR"/log.2000-01-01--00-00", s1 s1 s1 s1 s1));
+ mt_fok(file_check(WORKDIR"/log.2000-01-01--00-01", s1 s1 s1 s1));
+ mt_fok(file_check(WORKDIR"/log.2000-01-02--00-01", s1 s1));
+
+ unsetenv("FAKETIME");
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+static void file_date_rotate_hour(void)
+{
+ setenv("FAKETIME", "2000-01-01 00:00:00", 1);
+ el_option(EL_FROTATE_DATE, EL_ROT_DATE_HOUR);
+ el_puts(s1);
+ setenv("FAKETIME", "2000-01-01 00:00:01", 1);
+ el_puts(s1);
+ el_puts(s1);
+ setenv("FAKETIME", "2000-01-01 00:01:02", 1);
+ el_puts(s1);
+ el_puts(s1);
+
+ setenv("FAKETIME", "2000-01-01 03:01:02", 1);
+ el_puts(s1);
+ el_puts(s1);
+ setenv("FAKETIME", "2000-01-01 03:01:02", 1);
+ el_puts(s1);
+ setenv("FAKETIME", "2000-01-01 03:01:32", 1);
+ el_puts(s1);
+
+ setenv("FAKETIME", "2000-01-02 03:01:32", 1);
+ el_puts(s1);
+ el_puts(s1);
+
+ mt_fok(file_check(WORKDIR"/log.2000-01-01--00", s1 s1 s1 s1 s1));
+ mt_fok(file_check(WORKDIR"/log.2000-01-01--03", s1 s1 s1 s1));
+ mt_fok(file_check(WORKDIR"/log.2000-01-02--03", s1 s1));
+
+ unsetenv("FAKETIME");
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+static void file_date_rotate_day(void)
+{
+ setenv("FAKETIME", "2000-01-01 00:00:00", 1);
+ el_option(EL_FROTATE_DATE, EL_ROT_DATE_DAY);
+ el_puts(s1);
+ setenv("FAKETIME", "2000-01-01 00:00:01", 1);
+ el_puts(s1);
+ el_puts(s1);
+ setenv("FAKETIME", "2000-01-01 00:01:02", 1);
+ el_puts(s1);
+ el_puts(s1);
+
+ setenv("FAKETIME", "2000-01-04 03:01:02", 1);
+ el_puts(s1);
+ el_puts(s1);
+ setenv("FAKETIME", "2000-01-04 03:01:02", 1);
+ el_puts(s1);
+ setenv("FAKETIME", "2000-01-04 03:01:32", 1);
+ el_puts(s1);
+
+ setenv("FAKETIME", "2000-02-04 03:01:32", 1);
+ el_puts(s1);
+ el_puts(s1);
+
+ mt_fok(file_check(WORKDIR"/log.2000-01-01", s1 s1 s1 s1 s1));
+ mt_fok(file_check(WORKDIR"/log.2000-01-04", s1 s1 s1 s1));
+ mt_fok(file_check(WORKDIR"/log.2000-02-04", s1 s1));
+
+ unsetenv("FAKETIME");
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+static void file_date_rotate_month(void)
+{
+ setenv("FAKETIME", "2000-01-01 00:00:00", 1);
+ el_option(EL_FROTATE_DATE, EL_ROT_DATE_MON);
+ el_puts(s1);
+ setenv("FAKETIME", "2000-01-01 10:00:01", 1);
+ el_puts(s1);
+ el_puts(s1);
+ setenv("FAKETIME", "2000-01-02 00:01:02", 1);
+ el_puts(s1);
+ el_puts(s1);
+
+ setenv("FAKETIME", "2000-10-04 03:01:02", 1);
+ el_puts(s1);
+ el_puts(s1);
+ setenv("FAKETIME", "2000-10-04 03:01:02", 1);
+ el_puts(s1);
+ setenv("FAKETIME", "2000-10-04 03:01:32", 1);
+ el_puts(s1);
+
+ setenv("FAKETIME", "2001-10-04 03:01:32", 1);
+ el_puts(s1);
+ el_puts(s1);
+
+ mt_fok(file_check(WORKDIR"/log.2000-01", s1 s1 s1 s1 s1));
+ mt_fok(file_check(WORKDIR"/log.2000-10", s1 s1 s1 s1));
+ mt_fok(file_check(WORKDIR"/log.2001-10", s1 s1));
+
+ unsetenv("FAKETIME");
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+static void file_date_rotate_year(void)
+{
+ setenv("FAKETIME", "2000-01-01 00:00:00", 1);
+ el_option(EL_FROTATE_DATE, EL_ROT_DATE_YEAR);
+ el_puts(s1);
+ setenv("FAKETIME", "2000-01-01 10:00:01", 1);
+ el_puts(s1);
+ el_puts(s1);
+ setenv("FAKETIME", "2000-01-02 00:01:02", 1);
+ el_puts(s1);
+ el_puts(s1);
+
+ setenv("FAKETIME", "2003-10-04 03:01:02", 1);
+ el_puts(s1);
+ el_puts(s1);
+ setenv("FAKETIME", "2003-10-04 03:01:02", 1);
+ el_puts(s1);
+ setenv("FAKETIME", "2003-10-04 03:01:32", 1);
+ el_puts(s1);
+
+ setenv("FAKETIME", "2004-10-04 03:01:32", 1);
+ el_puts(s1);
+ el_puts(s1);
+
+ mt_fok(file_check(WORKDIR"/log.2000", s1 s1 s1 s1 s1));
+ mt_fok(file_check(WORKDIR"/log.2003", s1 s1 s1 s1));
+ mt_fok(file_check(WORKDIR"/log.2004", s1 s1));
+
+ unsetenv("FAKETIME");
+}
+
/* ==========================================================================
__ __
@@ -2070,6 +2306,7 @@ void el_file_test_group(void)
mt_run(file_and_directory_reapear);
mt_run(file_filename_too_long);
mt_run(file_path_too_long);
+
mt_run(file_rotate_1_no_rotate);
mt_run(file_rotate_1_exact_print);
mt_run(file_rotate_1_overflow_but_no_rotate);
@@ -2108,6 +2345,16 @@ void el_file_test_group(void)
mt_run(file_rotate_filename_too_long);
mt_run(file_rotate_path_too_long);
mt_run(file_rotate_fail);
+ mt_run(options_f_enable_file_log);
+ mt_run(options_f_enable_file_log_no_rotate);
+ mt_run(options_f_enable_file_log_rotate_no_size);
+ mt_run(options_f_enable_file_log_date_rotate);
+ mt_run(file_date_rotate_seconds);
+ mt_run(file_date_rotate_minute);
+ mt_run(file_date_rotate_hour);
+ mt_run(file_date_rotate_day);
+ mt_run(file_date_rotate_month);
+ mt_run(file_date_rotate_year);
#ifdef RUN_TESTS
mt_run(file_sync_always);
mt_run(file_sync_periodic);
diff --git a/tst/test-el-options.c b/tst/test-el-options.c
index ec67700..46ef182 100644
--- a/tst/test-el-options.c
+++ b/tst/test-el-options.c
@@ -19,6 +19,7 @@
#include "mtest.h"
#include "test-group-list.h"
#include "config.h"
+#include "embedlog.h"
/* ==========================================================================
@@ -569,6 +570,176 @@ static void options_set_funcinfo(void)
/* ==========================================================================
========================================================================== */
+static void options_f_set_log_level(void)
+{
+ mt_fok(el_set_log_level(EL_WARN));
+ mt_fail(g_el.level == EL_WARN);
+ mt_fok(el_set_log_level(EL_FATAL));
+ mt_fail(g_el.level == EL_FATAL);
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+static void options_f_enable_output(void)
+{
+ int expected_outputs;
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+
+ expected_outputs = EL_OUT_STDERR;
+
+ mt_fok(el_enable_output(EL_OUT_STDOUT));
+ expected_outputs |= EL_OUT_STDOUT;
+ mt_fail(g_el.outputs == expected_outputs);
+
+ /* Set same output again, nothing should change */
+ mt_fok(el_enable_output(EL_OUT_STDOUT));
+ mt_fail(g_el.outputs == expected_outputs);
+
+ mt_fok(el_enable_output(EL_OUT_TTY | EL_OUT_CUSTOM));
+ expected_outputs |= EL_OUT_TTY | EL_OUT_CUSTOM;
+ mt_fail(g_el.outputs == expected_outputs);
+
+ /* Set same output again, nothing should change */
+ mt_fok(el_enable_output(EL_OUT_TTY | EL_OUT_CUSTOM));
+ mt_fail(g_el.outputs == expected_outputs);
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+static void options_f_disable_output(void)
+{
+ int expected_outputs;
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+ expected_outputs = EL_OUT_STDERR | EL_OUT_STDOUT | EL_OUT_FILE | EL_OUT_TTY;
+ mt_fok(el_enable_output(expected_outputs));
+ mt_fail(g_el.outputs == expected_outputs);
+
+ mt_fok(el_disable_output(EL_OUT_STDERR));
+ expected_outputs &= ~EL_OUT_STDERR;
+ mt_fail(g_el.outputs == expected_outputs);
+
+ mt_fok(el_disable_output(EL_OUT_FILE | EL_OUT_STDOUT));
+ expected_outputs &= ~(EL_OUT_FILE | EL_OUT_STDOUT);
+ mt_fail(g_el.outputs == expected_outputs);
+
+ /* Disable same output again, nothing should change */
+ mt_fok(el_disable_output(EL_OUT_STDERR));
+ mt_fail(g_el.outputs == expected_outputs);
+
+ mt_fok(el_disable_output(EL_OUT_FILE | EL_OUT_STDOUT));
+ mt_fail(g_el.outputs == expected_outputs);
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+static void options_f_set_prefix(void)
+{
+ mt_fok(el_set_prefix("prefixon"));
+ mt_fail(strcmp(g_el.prefix, "prefixon") == 0);
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+static void options_f_set_timestamp(void)
+{
+ mt_fok(el_set_timestamp(EL_TS_SHORT, EL_TS_TM_CLOCK, EL_TS_FRACT_US));
+ mt_fail(g_el.timestamp == EL_TS_SHORT);
+ mt_fail(g_el.timestamp_timer == EL_TS_TM_CLOCK);
+ mt_fail(g_el.timestamp_fractions == EL_TS_FRACT_US);
+
+ mt_fok(el_set_timestamp(EL_TS_LONG, EL_TS_TM_TIME, EL_TS_FRACT_OFF));
+ mt_fail(g_el.timestamp == EL_TS_LONG);
+ mt_fail(g_el.timestamp_timer == EL_TS_TM_TIME);
+ mt_fail(g_el.timestamp_fractions == EL_TS_FRACT_OFF);
+
+ mt_fok(el_set_timestamp(EL_TS_OFF, EL_TS_TM_TIME, EL_TS_FRACT_OFF));
+ mt_fail(g_el.timestamp == EL_TS_OFF);
+ mt_fail(g_el.timestamp_timer == EL_TS_TM_TIME);
+ mt_fail(g_el.timestamp_fractions == EL_TS_FRACT_OFF);
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+static void options_f_enable_colors(void)
+{
+ mt_fok(el_enable_colors(1));
+ mt_fail(g_el.colors == 1);
+ mt_fok(el_enable_colors(0));
+ mt_fail(g_el.colors == 0);
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+static void options_f_oprint_extra_info(void)
+{
+ mt_fok(el_print_extra_info(1));
+ mt_fail(g_el.finfo == 1);
+ mt_fail(g_el.funcinfo == 1);
+ mt_fail(g_el.print_log_level == 1);
+
+ mt_fok(el_print_extra_info(0));
+ mt_fail(g_el.finfo == 0);
+ mt_fail(g_el.funcinfo == 0);
+ mt_fail(g_el.print_log_level == 0);
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+int custom_put(const char *s, size_t slen, void *user)
+{ (void)s; (void)slen; (void)user; return 0; }
+
+static void options_f_custom_put(void)
+{
+ void *user = (void *)0xdeadbeef;
+
+ mt_fok(el_set_custom_put(custom_put, user));
+ mt_fail(g_el.custom_put == custom_put);
+ mt_fail(g_el.custom_put_user == (void *)0xdeadbeef);
+
+ mt_fok(el_set_custom_put(NULL, NULL));
+ mt_fail(g_el.custom_put == NULL);
+ mt_fail(g_el.custom_put_user == NULL);
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+static void options_f_sync_every(void)
+{
+ mt_fok(el_set_file_sync(1337, EL_WARN));
+ mt_fail(g_el.fsync_every == 1337);
+ mt_fail(g_el.fsync_level == EL_WARN);
+
+ mt_fok(el_set_file_sync(INT_MAX, EL_FATAL));
+ mt_fail(g_el.fsync_every == INT_MAX);
+ mt_fail(g_el.fsync_level == EL_FATAL);
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+static void options_f_enable_thread_safe(void)
+{
+#if ENABLE_PTHREAD
+ mt_fok(el_enable_thread_safe(1));
+ mt_fail(g_el.lock_initialized == 1);
+ mt_fok(el_enable_thread_safe(0));
+ mt_fail(g_el.lock_initialized == 0);
+#endif
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
static void options_get_global_el(void)
@@ -614,4 +785,15 @@ void el_options_test_group(void)
mt_run(options_global_el_after_el_cleanup);
mt_run(options_set_funcinfo);
mt_run(options_get_global_el);
+
+ mt_run(options_f_set_log_level);
+ mt_run(options_f_enable_output);
+ mt_run(options_f_disable_output);
+ mt_run(options_f_set_prefix);
+ mt_run(options_f_set_timestamp);
+ mt_run(options_f_enable_colors);
+ mt_run(options_f_oprint_extra_info);
+ mt_run(options_f_custom_put);
+ mt_run(options_f_sync_every);
+ mt_run(options_f_enable_thread_safe);
}
diff --git a/tst/test-el-pmemory.c b/tst/test-el-pmemory.c
index 42b9fbe..0c7427c 100644
--- a/tst/test-el-pmemory.c
+++ b/tst/test-el-pmemory.c
@@ -239,6 +239,108 @@ static void pmemory_print_ascii_table_with_table(void)
========================================================================== */
+static void pmemory_test_spacing_1(void)
+{
+ el_option(EL_PMEMORY_SPACE, 1);
+ el_pmemory(ELI, ascii, 32 + 10);
+ mt_fok(strcmp(logbuf,
+"0x0000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f ........ ........\n"
+"0x0010 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f ........ ........\n"
+"0x0020 20 21 22 23 24 25 26 27 28 29 !\"#$%&' ()\n"));
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+
+
+static void pmemory_test_spacing_2(void)
+{
+ el_option(EL_PMEMORY_SPACE, 2);
+ el_pmemory(ELI, ascii, 32 + 10);
+ mt_fok(strcmp(logbuf,
+"0x0000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f ........ ........\n"
+"0x0010 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f ........ ........\n"
+"0x0020 20 21 22 23 24 25 26 27 28 29 !\"#$%&' ()\n"));
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+
+
+static void pmemory_test_spacing_3(void)
+{
+ el_option(EL_PMEMORY_SPACE, 3);
+ el_pmemory(ELI, ascii, 32 + 10);
+ mt_fok(strcmp(logbuf,
+"0x0000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f ........ ........\n"
+"0x0010 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f ........ ........\n"
+"0x0020 20 21 22 23 24 25 26 27 28 29 !\"#$%&' ()\n"));
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+
+
+static void pmemory_test_spacing_table_1(void)
+{
+ el_option(EL_PMEMORY_SPACE, 1);
+ el_pmemory_table(ELI, ascii, 32 + 10);
+ mt_fok(strcmp(logbuf,
+"------ ------------------------------------------------ -----------------\n"
+"offset hex ascii\n"
+"------ ------------------------------------------------ -----------------\n"
+"0x0000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f ........ ........\n"
+"0x0010 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f ........ ........\n"
+"0x0020 20 21 22 23 24 25 26 27 28 29 !\"#$%&' ()\n"
+"------ ------------------------------------------------ -----------------\n"));
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+
+
+static void pmemory_test_spacing_table_2(void)
+{
+ el_option(EL_PMEMORY_SPACE, 2);
+ el_pmemory_table(ELI, ascii, 32 + 10);
+ mt_fok(strcmp(logbuf,
+"------ ------------------------------------------------- ------------------\n"
+"offset hex ascii\n"
+"------ ------------------------------------------------- ------------------\n"
+"0x0000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f ........ ........\n"
+"0x0010 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f ........ ........\n"
+"0x0020 20 21 22 23 24 25 26 27 28 29 !\"#$%&' ()\n"
+"------ ------------------------------------------------- ------------------\n"));
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+
+
+static void pmemory_test_spacing_table_3(void)
+{
+ el_option(EL_PMEMORY_SPACE, 3);
+ el_pmemory_table(ELI, ascii, 32 + 10);
+ mt_fok(strcmp(logbuf,
+"------ -------------------------------------------------- -------------------\n"
+"offset hex ascii\n"
+"------ -------------------------------------------------- -------------------\n"
+"0x0000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f ........ ........\n"
+"0x0010 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f ........ ........\n"
+"0x0020 20 21 22 23 24 25 26 27 28 29 !\"#$%&' ()\n"
+"------ -------------------------------------------------- -------------------\n"));
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+
+
static void pmemory_print_ascii_table_option(void)
{
struct el el;
@@ -464,4 +566,10 @@ void el_pmemory_test_group(void)
mt_run(pmemory_print_ascii_table_with_table);
mt_run(pmemory_null_memory);
mt_run(pmemory_zero_size);
+ mt_run(pmemory_test_spacing_table_1);
+ mt_run(pmemory_test_spacing_table_2);
+ mt_run(pmemory_test_spacing_table_3);
+ mt_run(pmemory_test_spacing_1);
+ mt_run(pmemory_test_spacing_2);
+ mt_run(pmemory_test_spacing_3);
}
diff --git a/www/Makefile.am b/www/Makefile.am
index d16edc3..2ca939d 100644
--- a/www/Makefile.am
+++ b/www/Makefile.am
@@ -1,10 +1,85 @@
-EXTRA_DIST = custom.css footer.in header.in index.in index.md
+# You can set these variables from the command line, and also
+# from the environment for the first two.
+SPHINXOPTS ?= -j auto
+SPHINXBUILD ?= sphinx-build
+SOURCEDIR = .
+BUILDDIR = _build
-www:
- kursg -o out
- ./post-process.sh
- chmod a+rX out -R
+# Put it first so that "make" without argument is like "make help".
+help:
+ @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
-make clean:
- $(RM) -r out
- $(RM) -r manuals
+.PHONY: help Makefile
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
+html : Makefile
+ $(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+man: Makefile
+ $(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+ @echo fix broken tables
+ sed -i 's/^center;$$/box center;/' $(BUILDDIR)/man/*
+
+# sphinx-build clean does not remove _build dir
+clean-local:
+ rm -rf _build
+
+man_MANS = \
+ _build/man/el_cleanup.3 \
+ _build/man/el_destroy.3 \
+ _build/man/el_disable_output.3 \
+ _build/man/el_enable_colors.3 \
+ _build/man/el_enable_file_log.3 \
+ _build/man/el_enable_output.3 \
+ _build/man/el_enable_thread_safe.3 \
+ _build/man/el_flush.3 \
+ _build/man/el_init.3 \
+ _build/man/el_new.3 \
+ _build/man/el_ocleanup.3 \
+ _build/man/el_odestroy.3 \
+ _build/man/el_odisable_output.3 \
+ _build/man/el_oenable_colors.3 \
+ _build/man/el_oenable_file_log.3 \
+ _build/man/el_oenable_output.3 \
+ _build/man/el_oenable_thread_safe.3 \
+ _build/man/el_oflush.3 \
+ _build/man/el_oinit.3 \
+ _build/man/el_ooption.3 \
+ _build/man/el_opbinary.3 \
+ _build/man/el_operror.3 \
+ _build/man/el_opmemory.3 \
+ _build/man/el_opmemory_table.3 \
+ _build/man/el_oprint.3 \
+ _build/man/el_oprint_extra_info.3 \
+ _build/man/el_option.3 \
+ _build/man/el_oputb.3 \
+ _build/man/el_oputs.3 \
+ _build/man/el_oset_custom_put.3 \
+ _build/man/el_oset_file_sync.3 \
+ _build/man/el_oset_log_level.3 \
+ _build/man/el_oset_prefix.3 \
+ _build/man/el_oset_timestamp.3 \
+ _build/man/el_oset_tty_dev.3 \
+ _build/man/el_overview.7 \
+ _build/man/el_ovprint.3 \
+ _build/man/el_pbinary.3 \
+ _build/man/el_perror.3 \
+ _build/man/el_pmemory.3 \
+ _build/man/el_pmemory_table.3 \
+ _build/man/el_print.3 \
+ _build/man/el_print_extra_info.3 \
+ _build/man/el_putb.3 \
+ _build/man/el_puts.3 \
+ _build/man/el_set_custom_put.3 \
+ _build/man/el_set_file_sync.3 \
+ _build/man/el_set_log_level.3 \
+ _build/man/el_set_prefix.3 \
+ _build/man/el_set_timestamp.3 \
+ _build/man/el_set_tty_dev.3 \
+ _build/man/el_vprint.3
+
+EXTRA_DIST = $(man_MANS)
+
+$(man_MANS) &:
+ @$(SPHINXBUILD) -M man "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
diff --git a/www/conf.py b/www/conf.py
new file mode 100644
index 0000000..015030f
--- /dev/null
+++ b/www/conf.py
@@ -0,0 +1,69 @@
+# Configuration file for the Sphinx documentation builder.
+#
+# For the full list of built-in configuration values, see the documentation:
+# https://www.sphinx-doc.org/en/master/usage/configuration.html
+
+import glob
+
+# -- Project information -----------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
+
+project = 'embedlog'
+copyright = '2024, Michał Łyszczek'
+author = 'Michał Łyszczek'
+release = 'v9999'
+
+# -- General configuration ---------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
+
+extensions = [
+ "sphinx.ext.autosectionlabel",
+]
+
+templates_path = ['templates']
+exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
+autosectionlabel_prefix_document = True
+
+# -- Options for HTML output -------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
+
+html_theme = 'alabaster'
+html_static_path = ['static']
+highlight_language = 'none'
+
+
+html_css_files = [
+ 'http://static.bofc.pl/fonts.css',
+ 'static/custom.css'
+]
+
+html_theme_options = {
+ 'github_user': 'mlyszczek',
+ 'github_repo': 'embedlog',
+ 'github_banner': True,
+ 'github_type': 'star',
+ 'page_width': '103ch',
+ 'code_font_family': 'JetBrainsMono',
+ 'caption_font_family': 'sans',
+ 'head_font_family': 'sans',
+ 'font_family': 'sans',
+}
+
+man_pages = []
+for file in glob.glob('manuals/*/*.[0-9].rst'):
+ f = file.split("/")[2]
+ man_pages.append((
+ file[:-4], # source file (no extension)
+ f[:-6].replace('/', '-'), # output file (under output dir)
+ '',
+ 'Michał Łyszczek <michal.lyszczek@boc.pl>',
+ f[-5], # section
+ ))
+
+man_pages.append((
+ "el_overview.7",
+ "el_overview",
+ '',
+ 'Michał Łyszczek <michal.lyszczek@boc.pl>',
+ 7
+))
diff --git a/www/custom.css b/www/custom.css
deleted file mode 100644
index f60c90e..0000000
--- a/www/custom.css
+++ /dev/null
@@ -1,64 +0,0 @@
-pre#logo
-{
- font-size: 3px;
- max-width: 100%;
-}
-
-pre#logo-footer
-{
- font-size: 1px;
- max-width: 100%;
-}
-
-div#footer a:hover, div#header a:hover
-{
- color: red;
- text-decoration: none;
-}
-
-div.codehilite:before
-{
- content: "// code";
-}
-
-img[alt=test-result-svg]
-{
- float: right;
-}
-
-p.info
-{
- margin-top: 2ch;
- margin-bottom: 2ch;
- margin-left: 0ch;
- margin-right: 0ch;
- float: left;
-}
-
-p.left
-{
- text-align: left;
- width: 33%
-}
-
-p.center
-{
- text-align: center;
- width: 33%
-}
-
-p.right
-{
- text-align: right;
- width: 34%
-}
-
-ul.man-toc
-{
- clear: both;
-}
-
-h1.first
-{
- margin-top: 2ch;
-}
diff --git a/www/downloads.html b/www/downloads.html
new file mode 100644
index 0000000..d8e6206
--- /dev/null
+++ b/www/downloads.html
@@ -0,0 +1,48 @@
+=========
+Downloads
+=========
+Below you can find released source files. (s) right of package name is a gpg
+signature. You can download gpg file or armored asc file to verify files.
+You can also look for key on public keyservers, fingerprint is
+
+ 63D0 C3DB 42AF 3B4F CF6E 7880 E84A 7E61 C785 0C62
+
+You can download key directly from keyserver with
+
+ gpg --recv-keys 63D0C3DB42AF3B4FCF6E7880E84A7E61C7850C62
+
+Then you can verify downloaded image with command
+
+ gpg --verify <sig-file> <package-file>
+
+All files (including md5, sha256 and sha512 for all files) can also be
+downloaded from: https://distfiles.bofc.pl/embedlog
+
+git
+---
+git clone git@git.bofc.pl:embedlog
+git clone git://git.bofc.pl/embedlog
+git clone http://git.bofc.pl/embedlog
+
+tarballs (source code)
+----------------------
+.. parsed-literal::
+
+ 0.6.0 `tar.gz <https://distfiles.bofc.pl/embedlog/embedlog-0.6.0.tar.gz>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.6.0.tar.gz.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.6.0.tar.gz.sha1>`_) `tar.bz2 <https://distfiles.bofc.pl/embedlog/embedlog-0.6.0.tar.bz2>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.6.0.tar.bz2.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.6.0.tar.bz2.sha1>`_) `tar.xz <https://distfiles.bofc.pl/embedlog/embedlog-0.6.0.tar.xz>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.6.0.tar.xz.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.6.0.tar.xz.sha1>`_)
+ 0.5.0 `tar.gz <https://distfiles.bofc.pl/embedlog/embedlog-0.5.0.tar.gz>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.5.0.tar.gz.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.5.0.tar.gz.sha1>`_) `tar.bz2 <https://distfiles.bofc.pl/embedlog/embedlog-0.5.0.tar.bz2>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.5.0.tar.bz2.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.5.0.tar.bz2.sha1>`_) `tar.xz <https://distfiles.bofc.pl/embedlog/embedlog-0.5.0.tar.xz>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.5.0.tar.xz.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.5.0.tar.xz.sha1>`_)
+ 0.4.1 `tar.gz <https://distfiles.bofc.pl/embedlog/embedlog-0.4.1.tar.gz>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.4.1.tar.gz.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.4.1.tar.gz.sha1>`_) `tar.bz2 <https://distfiles.bofc.pl/embedlog/embedlog-0.4.1.tar.bz2>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.4.1.tar.bz2.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.4.1.tar.bz2.sha1>`_) `tar.xz <https://distfiles.bofc.pl/embedlog/embedlog-0.4.1.tar.xz>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.4.1.tar.xz.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.4.1.tar.xz.sha1>`_)
+ 0.4.0 `tar.gz <https://distfiles.bofc.pl/embedlog/embedlog-0.4.0.tar.gz>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.4.0.tar.gz.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.4.0.tar.gz.sha1>`_) `tar.bz2 <https://distfiles.bofc.pl/embedlog/embedlog-0.4.0.tar.bz2>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.4.0.tar.bz2.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.4.0.tar.bz2.sha1>`_) `tar.xz <https://distfiles.bofc.pl/embedlog/embedlog-0.4.0.tar.xz>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.4.0.tar.xz.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.4.0.tar.xz.sha1>`_)
+ 0.3.4 `tar.gz <https://distfiles.bofc.pl/embedlog/embedlog-0.3.4.tar.gz>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.3.4.tar.gz.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.3.4.tar.gz.sha1>`_) `tar.bz2 <https://distfiles.bofc.pl/embedlog/embedlog-0.3.4.tar.bz2>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.3.4.tar.bz2.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.3.4.tar.bz2.sha1>`_) `tar.xz <https://distfiles.bofc.pl/embedlog/embedlog-0.3.4.tar.xz>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.3.4.tar.xz.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.3.4.tar.xz.sha1>`_)
+ 0.3.3 `tar.gz <https://distfiles.bofc.pl/embedlog/embedlog-0.3.3.tar.gz>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.3.3.tar.gz.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.3.3.tar.gz.sha1>`_) `tar.bz2 <https://distfiles.bofc.pl/embedlog/embedlog-0.3.3.tar.bz2>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.3.3.tar.bz2.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.3.3.tar.bz2.sha1>`_) `tar.xz <https://distfiles.bofc.pl/embedlog/embedlog-0.3.3.tar.xz>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.3.3.tar.xz.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.3.3.tar.xz.sha1>`_)
+ 0.3.2 `tar.gz <https://distfiles.bofc.pl/embedlog/embedlog-0.3.2.tar.gz>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.3.2.tar.gz.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.3.2.tar.gz.sha1>`_) `tar.bz2 <https://distfiles.bofc.pl/embedlog/embedlog-0.3.2.tar.bz2>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.3.2.tar.bz2.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.3.2.tar.bz2.sha1>`_) `tar.xz <https://distfiles.bofc.pl/embedlog/embedlog-0.3.2.tar.xz>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.3.2.tar.xz.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.3.2.tar.xz.sha1>`_)
+ 0.3.1 `tar.gz <https://distfiles.bofc.pl/embedlog/embedlog-0.3.1.tar.gz>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.3.1.tar.gz.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.3.1.tar.gz.sha1>`_) `tar.bz2 <https://distfiles.bofc.pl/embedlog/embedlog-0.3.1.tar.bz2>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.3.1.tar.bz2.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.3.1.tar.bz2.sha1>`_) `tar.xz <https://distfiles.bofc.pl/embedlog/embedlog-0.3.1.tar.xz>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.3.1.tar.xz.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.3.1.tar.xz.sha1>`_)
+ 0.3.0 `tar.gz <https://distfiles.bofc.pl/embedlog/embedlog-0.3.0.tar.gz>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.3.0.tar.gz.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.3.0.tar.gz.sha1>`_) `tar.bz2 <https://distfiles.bofc.pl/embedlog/embedlog-0.3.0.tar.bz2>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.3.0.tar.bz2.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.3.0.tar.bz2.sha1>`_) `tar.xz <https://distfiles.bofc.pl/embedlog/embedlog-0.3.0.tar.xz>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.3.0.tar.xz.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.3.0.tar.xz.sha1>`_)
+ 0.2.2 `tar.gz <https://distfiles.bofc.pl/embedlog/embedlog-0.2.2.tar.gz>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.2.2.tar.gz.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.2.2.tar.gz.sha1>`_) `tar.bz2 <https://distfiles.bofc.pl/embedlog/embedlog-0.2.2.tar.bz2>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.2.2.tar.bz2.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.2.2.tar.bz2.sha1>`_) `tar.xz <https://distfiles.bofc.pl/embedlog/embedlog-0.2.2.tar.xz>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.2.2.tar.xz.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.2.2.tar.xz.sha1>`_)
+ 0.2.1 `tar.gz <https://distfiles.bofc.pl/embedlog/embedlog-0.2.1.tar.gz>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.2.1.tar.gz.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.2.1.tar.gz.sha1>`_) `tar.bz2 <https://distfiles.bofc.pl/embedlog/embedlog-0.2.1.tar.bz2>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.2.1.tar.bz2.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.2.1.tar.bz2.sha1>`_) `tar.xz <https://distfiles.bofc.pl/embedlog/embedlog-0.2.1.tar.xz>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.2.1.tar.xz.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.2.1.tar.xz.sha1>`_)
+ 0.2.0 `tar.gz <https://distfiles.bofc.pl/embedlog/embedlog-0.2.0.tar.gz>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.2.0.tar.gz.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.2.0.tar.gz.sha1>`_) `tar.bz2 <https://distfiles.bofc.pl/embedlog/embedlog-0.2.0.tar.bz2>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.2.0.tar.bz2.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.2.0.tar.bz2.sha1>`_) `tar.xz <https://distfiles.bofc.pl/embedlog/embedlog-0.2.0.tar.xz>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.2.0.tar.xz.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.2.0.tar.xz.sha1>`_)
+ 0.1.1 `tar.gz <https://distfiles.bofc.pl/embedlog/embedlog-0.1.1.tar.gz>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.1.1.tar.gz.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.1.1.tar.gz.sha1>`_) `tar.bz2 <https://distfiles.bofc.pl/embedlog/embedlog-0.1.1.tar.bz2>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.1.1.tar.bz2.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.1.1.tar.bz2.sha1>`_) `tar.xz <https://distfiles.bofc.pl/embedlog/embedlog-0.1.1.tar.xz>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.1.1.tar.xz.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.1.1.tar.xz.sha1>`_)
+ 0.1.0 `tar.gz <https://distfiles.bofc.pl/embedlog/embedlog-0.1.0.tar.gz>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.1.0.tar.gz.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.1.0.tar.gz.sha1>`_) `tar.bz2 <https://distfiles.bofc.pl/embedlog/embedlog-0.1.0.tar.bz2>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.1.0.tar.bz2.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.1.0.tar.bz2.sha1>`_) `tar.xz <https://distfiles.bofc.pl/embedlog/embedlog-0.1.0.tar.xz>`_(`s <https://distfiles.bofc.pl/embedlog/embedlog-0.1.0.tar.xz.sig>`_|`sha1 <https://distfiles.bofc.pl/embedlog/embedlog-0.1.0.tar.xz.sha1>`_)
+</pre>
+les.bofc.pl/embedlog/embedlog-0.1.1.tar.gz">tar.gz</a>(<a href="https://distfiles.bofc.pl/embedlog/embedlog-0.1.1.tar.gz.sig">s</a>|<a href="https://distfiles.bofc.pl/embedlog/embedlog-0.1.1.tar.gz.sha1">sha1</a>) <a href="https://distfiles.bofc.pl/embedlog/embedlog-0.1.1.tar.bz2">tar.bz2</a>(<a href="https://distfiles.bofc.pl/embedlog/embedlog-0.1.1.tar.bz2.sig">s</a>|<a href="https://distfiles.bofc.pl/embedlog/embedlog-0.1.1.tar.bz2.sha1">sha1</a>) <a href="https://distfiles.bofc.pl/embedlog/embedlog-0.1.1.tar.xz">tar.xz</a>(<a href="https://distfiles.bofc.pl/embedlog/embedlog-0.1.1.tar.xz.sig">s</a>|<a href="https://distfiles.bofc.pl/embedlog/embedlog-0.1.1.tar.xz.sha1">sha1</a>)
+0.1.0 <a href="https://distfiles.bofc.pl/embedlog/embedlog-0.1.0.tar.gz">tar.gz</a>(<a href="https://distfiles.bofc.pl/embedlog/embedlog-0.1.0.tar.gz.sig">s</a>|<a href="https://distfiles.bofc.pl/embedlog/embedlog-0.1.0.tar.gz.sha1">sha1</a>) <a href="https://distfiles.bofc.pl/embedlog/embedlog-0.1.0.tar.bz2">tar.bz2</a>(<a href="https://distfiles.bofc.pl/embedlog/embedlog-0.1.0.tar.bz2.sig">s</a>|<a href="https://distfiles.bofc.pl/embedlog/embedlog-0.1.0.tar.bz2.sha1">sha1</a>) <a href="https://distfiles.bofc.pl/embedlog/embedlog-0.1.0.tar.xz">tar.xz</a>(<a href="https://distfiles.bofc.pl/embedlog/embedlog-0.1.0.tar.xz.sig">s</a>|<a href="https://distfiles.bofc.pl/embedlog/embedlog-0.1.0.tar.xz.sha1">sha1</a>)
+</pre>
diff --git a/www/el_overview.7.rst b/www/el_overview.7.rst
new file mode 100644
index 0000000..4dee4d4
--- /dev/null
+++ b/www/el_overview.7.rst
@@ -0,0 +1,280 @@
+.. include:: in/ref-list.in
+
+========
+overview
+========
+NAME
+----
+
+**el_overview** - quick overview of **embedlog** logging library
+
+SYNOPSIS
+--------
+
+**embedlog** - is a highly portable **c89** complaint logger (with
+additional features for users with **c99** compilers and/or **POSIX**
+systems). This library is designed mainly for embedded devices, but can
+also be used in high level OSes like **Linux**.
+
+DESCRIPTION
+-----------
+
+Logger incorporates features like:
+
+* printing to different outputs (simultaneously) like:
+
+ * stderr
+ * syslog (very limited, works on *nuttx* for now)
+ * directly to serial device (like ``/dev/ttyS0``)
+ * file (with optional rotating and syncing to prevent data loss)
+ * automatic file reopening on unexpected events (file deletion, SD remount)
+ * custom routine, can be anything, embedlog just calls your
+ function with string to print
+
+* timestamping using following clocks:
+
+ * ``clock_t``
+ * ``time_t``
+ * ``CLOCK_REALTIME`` (requires POSIX)
+ * ``CLOCK_MONOTONIC`` (requires POSIX)
+ * configurable precision of fraction of seconds (mili, micro, nano)
+
+* file log rotation based on:
+
+ * file size - limit number of files and their sizes
+ * date - new file is created every day (or hour, or other choosen timeslice)
+
+* printing file and line information
+* 8 predefined log levels (total rip off from **syslog** (2) levels)
+* colorful output (for easy error spotting)
+* print memory block in wireshark-like output
+* fully binary logs with binary data (like CAN frames) to save space
+
+Library implements following functions:
+
+Basic functions are:
+
+.. list-table::
+ :header-rows: 1
+
+ * - function
+ - description
+ * - |el_init|
+ - initialize embedlog, call before anything else
+ * - |el_cleanup|
+ - cleans up any resources allocated by el_init
+ * - |el_flush|
+ - flushes all buffers to respective underlying devices
+ * - |el_print|
+ - printf-like, prints log, with previously configured options
+ * - |el_perror|
+ - prints log, and errno string, saves you time to type strerror(errno)
+ * - |el_pmemory|
+ - dumps memory location in wireshark/hexdump like format
+
+There are multiple different print functions when standard is not enough:
+
+.. list-table::
+ :header-rows: 1
+
+ * - function
+ - description
+ * - |el_print|
+ - standard printf-like function
+ * - |el_perror|
+ - standard perror function, but it's also printf-like (perror(3) does not take fmt)
+ * - |el_pmemory|
+ - dumps memory in wireshark/hexdump like format
+ * - |el_pmemory_table|
+ - like el_pmemory, but also adds ascii table
+ * - |el_vprint|
+ - just like |el_print| but takes **va_arg** instead format
+ * - |el_pbinary|
+ - used to print fully binary logs (with binary metadata) to save space
+ * - |el_puts|
+ - like puts(3), these logs won't be processed and will be printed as-is
+ * - |el_putb|
+ - similar to |el_puts| but used for binary logging
+
+Printing can be altered to suit your needs:
+
+.. list-table::
+ :header-rows: 1
+
+ * - |el_enable_output|
+ - allows you to enable specified outputs
+ * - |el_enable_file_log|
+ - configures and enables logging to file with (or without) log rotation
+ * - |el_set_timestamp|
+ - configures how (and if) timestamps should be printed with each log
+ * - |el_print_extra_info|
+ - configures if extra info should be added to logs (file, line and
+ function or log origin)
+ * - |el_set_file_sync|
+ - configures how often **embedlog** should sync logs, to prevent data
+ loss on program crash or power loss.
+ * - |el_enable_colors|
+ - enable ANSI colors, different log level will have different color
+ * - |el_set_log_level|
+ - set maximum log level to print (like you can leave only warning and more
+ severe logs on production)
+ * - |el_set_prefix|
+ - add custom prefix, that will be added to each log, usefull when multiple
+ programs log to single output (like serial device)
+ * - |el_set_custom_put|
+ - can be used to implement own printing, embedlog will pass fully processed
+ string.
+ * - |el_enable_thread_safe|
+ - can be used if you want to print from multiple threads
+ * - |el_set_tty_dev|
+ - configure and enable tty (serial device) output
+ * - |el_disable_output|
+ - disable specified outputs
+ * - |el_option|
+ - if above functions are not enough, this can be used to really fine tune
+ embedlog behaviour.
+
+Each function has its equivalent function that accepts *el* object as
+argument. These functions have ``el_o`` prefix instead of ``el_``. This is
+helpful if we want to have more than one, separated loggers in a single
+program, or when using embedlog on RTOS. Few examples are:
+
+.. code-block:: c
+
+ int el_oinit(struct el *el)
+ int el_ocleanup(struct el *el)
+ struct el * el_new(void)
+ int el_destroy(struct el *el)
+ int el_oputs(struct el *el, const char *string)
+ int el_oprint(LEVEL, struct el *el, const char *fmt, ...)
+ int el_oflush(struct el *el)
+
+**LEVEL** in function declaration is a macro that expands to
+
+.. code-block:: c
+
+ __FILE__, __LINE__, __func__, LOG_LEVEL
+
+but it would be very cumbersome to type that each time, so these helper
+macros are defined. Awailable macros are:
+
+.. code-block:: none
+
+ ELF Fatal errors, usually precedes application crash
+ ELA Alert, vey major error that should be fixed as soon as possible
+ ELC Critical
+ ELE Error
+ ELW Warning
+ ELN Normal log, but of high importance
+ ELI Information message, shouldn't spam too much here
+ ELD Debug messages, can spam as much as you'd like
+
+So instead of calling
+
+.. code-block:: c
+
+ el_print(__FILE__, __LINE__, __func__, EL_NOTICE, "Notice message");
+
+You can simply call it like
+
+.. code-block:: c
+
+ el_print(ELN, "Notice message");
+
+There are also equivalent macros for use with functions that also
+provides *el* object, so the can be used with **el_o** function family.
+To make these work, you need to provide **EL_OPTIONS_OBJECT** macro.
+Check |el_print| for more info about that.
+
+So instead of calling
+
+.. code-block:: c
+
+ el_oprint(__FILE__, __LINE__, __func__, EL_NOTICE, &g_log_object, "Notice message");
+
+or
+
+.. code-block:: c
+
+ el_oprint(ELN, &g_log_object, "Notice message");
+
+You can simply call it like
+
+.. code-block:: c
+
+ /* One time macro declaration */
+ #define EL_OPTIONS_OBJECT &g_log_object
+
+ el_oprint(OELN, "Notice message");
+
+STABLE ABI CONSIDERATION
+------------------------
+
+Since **embedlog** is versatile and can work on both hardcore embedded
+systems (nuttx, freertos, bare metals) and on big CPUs that can run
+Linux, library must provide a way for user to use stack-allocated
+objects and stable ABI. Unfortunately there is no way to provide both at
+the same time, so **embedlog** provides two solutions so everybody is
+happy.
+
+Note that library versioning follows **STABLE ABI** way of using
+library. So if feature is added that adds new field to **struct el**,
+then this will not be treated as ABI breakage, because if you are using
+**el_new** (3) or **el_init** (3) functions, ABI will not be broken.
+Only when using **el_oinit** (3) ABI will be broken.
+
+STABLE ABI
+^^^^^^^^^^
+When stable ABI is required, user must initialize **embedlog** either
+with |el_init| or |el_new| function. User also must not
+access internal fields directly and all operations on *el* object must
+be done through the API functions. |el_new| will malloc necessary
+memory for the user which must be freed with |el_destroy|
+function. Under no circumstances use **sizeof** on the object nor
+struct. Operation will succeed, but may return invalid results when
+library is updated. To put it in as few word as possible - you don't
+know anything about internals of **struct el**.
+
+STACK ALLOCATED OBJECT
+^^^^^^^^^^^^^^^^^^^^^^
+When you use library in hardcore embedded environment, where there is
+not dynamic linking involved, you are save to ignore any ABI changes,
+since you always build your programs alongside the library. But thanks
+to that you can avoid **malloc** (3) call and allocate everything on the
+stack. To allocate object on stack you must use **el_oinit** (3)
+function, and deinitialize object with **el_ocleanup** (3).
+
+If you are using **el_oinit** (3) on systems with dynamic library
+support you are suscible to ABI breakage and undefined behaviour when
+only new features are added, or even when bugfix introduces new field to
+**struct el**. Heck, even recompilation with different flags can break
+ABI here. Do not use this approach if your system have dynamic library
+support unless you can rebuild all programs against new version of
+library.
+
+**You've been warned!**
+
+STRIPPING BIN FROM STRINGS
+--------------------------
+If you want to use **embedlog**, but during release strip all logs from
+final binary, you just have to globally define ``DISABLE_ALL_EMBEDLOG``
+
+``DISABLE_ALL_EMBEDLOG`` will change all embedlog functions into functions
+that return 0, so these can still be used in ``if()`` checks, or blocks,
+or anywhere else you would normally use **embedlog** functions. During
+compilation, compiler should optimize all calls, and linker should remove
+all embedlog code from final binary, saving space, and hiding all strings.
+
+This case is usefull during development and testing, when development may
+happen on fat MCU with a lot of memory, but final program should work on,
+smaller - and cheaper - MCU.
+
+EXAMPLE
+-------
+
+Initial setup is very trivial. One should call init function and it will
+print to stderr by default. Output can also be customized with proper el
+object, see **el_option** (3) for more details.
+
+.. literalinclude:: ../examples/print-simple.c
+ :language: c
diff --git a/www/footer.in b/www/footer.in
deleted file mode 100644
index bf90771..0000000
--- a/www/footer.in
+++ /dev/null
@@ -1,26 +0,0 @@
- <a href="http://en.bofc.pl"><pre id="logo-footer">
-  
-88888888  
-8::::::8 8888888888888888 8888888 
-8::::::8 8::::::::::::::::8 8:::::8 
-8::::::8 8::::::::::::::::::8 8:::::8 
- 8:::::8 8::::::8888888:::::8 8:::::8 
- 8:::::888888888 88888888888 8:::::8 8888888888888888888888 88888 888888888 8::::8 
- 8::::::::::::::88 88:::::::::::88 8:::::8 88:::::::::::::::8 8::::888:::::::::8 8::::8 
- 8::::::::::::::::8 8:::::::::::::::88:::::::888888 8:::::::::::::::::8 8:::::::::::::::::8 8::::8 
- 8:::::88888:::::::88:::::88888:::::88::::::::::::8 8:::::::888888:::::8 88::::::88888::::::8 8::::8 
- 8:::::8 8::::::88::::8 8::::88::::::::::::8 8::::::8 8888888 8:::::8 8:::::8 8::::8  
- 8:::::8 8:::::88::::8 8::::88:::::::888888 8:::::8 8:::::8 8:::::8 8::::8  
- 8:::::8 8:::::88::::8 8::::8 8:::::8 8:::::8 8:::::8 8:::::8 8::::8  
- 8:::::8 8:::::88::::8 8::::8 8:::::8 8::::::8 8888888 8:::::8 8::::::8 8::::8  
- 8:::::888888::::::88:::::88888:::::88:::::::8 8:::::::888888:::::8 8:::::88888:::::::88::::::8
- 8::::::::::::::::8 8:::::::::::::::88:::::::8 8:::::::::::::::::8 ...... 8::::::::::::::::8 8::::::8
- 8:::::::::::::::8 88:::::::::::88 8:::::::8 88:::::::::::::::8 .::::. 8::::::::::::::88 8::::::8
- 8888888888888888 88888888888 888888888 8888888888888888 ...... 8::::::88888888 88888888
- 8:::::8  
- 8:::::8  
- 8:::::::8  
- 8:::::::8  
- 8:::::::8  
- 888888888  
- </pre></a>
diff --git a/www/header.in b/www/header.in
deleted file mode 100644
index 8e8cb25..0000000
--- a/www/header.in
+++ /dev/null
@@ -1,26 +0,0 @@
-<a href="/"><pre id="logo">
- 88888888 88888888
- 8::::::8 8::::::88888888
- 8::::::8 8::::::88:::::8
- 8::::::8 8::::::88:::::8
- 8:::::8 8:::::8 8:::::8
- 888888888888 8888888 8888888 8:::::888888888 888888888888 888888888:::::8 8::::8 88888888888 888888888 88888
- 88::::::::::::88 88:::::::8 8:::::::88 8::::::::::::::88 88::::::::::::88 88::::::::::::::8 8::::8 88:::::::::::88 8:::::::::888::::8
- 8::::::88888:::::888::::::::::88::::::::::88::::::::::::::::8 8::::::88888:::::88 8::::::::::::::::8 8::::8 8:::::::::::::::8 8:::::::::::::::::8
-8::::::8 8:::::88::::::::::::::::::::::88:::::88888:::::::88::::::8 8:::::88:::::::88888:::::8 8::::8 8:::::88888:::::88::::::88888::::::88
-8:::::::88888::::::88:::::888::::::888:::::88:::::8 8::::::88:::::::88888::::::88::::::8 8:::::8 8::::8 8::::8 8::::88:::::8 8:::::8
-8:::::::::::::::::8 8::::8 8::::8 8::::88:::::8 8:::::88:::::::::::::::::8 8:::::8 8:::::8 8::::8 8::::8 8::::88:::::8 8:::::8
-8::::::88888888888 8::::8 8::::8 8::::88:::::8 8:::::88::::::88888888888 8:::::8 8:::::8 8::::8 8::::8 8::::88:::::8 8:::::8
-8:::::::8 8::::8 8::::8 8::::88:::::8 8:::::88:::::::8 8:::::8 8:::::8 8::::8 8::::8 8::::88::::::8 8:::::8
-8::::::::8 8::::8 8::::8 8::::88:::::888888::::::88::::::::8 8::::::88888::::::888::::::88:::::88888:::::88:::::::88888:::::8
- 8::::::::88888888 8::::8 8::::8 8::::88::::::::::::::::8 8::::::::88888888 8:::::::::::::::::88::::::88:::::::::::::::8 8::::::::::::::::8
- 88:::::::::::::8 8::::8 8::::8 8::::88:::::::::::::::8 88:::::::::::::8 8:::::::::888::::88::::::8 88:::::::::::88 88::::::::::::::8
- 88888888888888 888888 888888 8888888888888888888888 88888888888888 888888888 8888888888888 88888888888 88888888::::::8
- 8:::::8
- 888888 8:::::8
- 8:::::88 88:::::8
- 8::::::888:::::::8
- 88:::::::::::::8
- 888::::::888
- 888888
-</pre></a>
diff --git a/www/in/el_cleanup.in b/www/in/el_cleanup.in
new file mode 100644
index 0000000..01fbca1
--- /dev/null
+++ b/www/in/el_cleanup.in
@@ -0,0 +1,41 @@
+NAME
+-----
+**el_cleanup** - cleans all resources allocated by |el_init| and
+|el_option| calls.
+**el_destroy** - cleans all resurces allocated by |el_new|.
+
+SYNOPSIS
+--------
+.. code-block:: c
+
+ include <embedlog.h>
+
+ int el_cleanup(void)
+ int el_ocleanup(struct el *el)
+ int el_destroy(struct el *el)
+
+DESCRIPTION
+-----------
+|el_cleanup| flushes all remaining buffers and frees any
+resources allocated through the life of the library. After clean up,
+library calls cannot be used without initialization.
+
+|el_ocleanup| works just the same, but accepts custom *el* object
+as argument.
+
+|el_destroy| works just the same, but must be used when *el*
+object has been created with |el_new| function.
+
+RETURN VALUE
+------------
+Functions return 0 upon successful cleanup or -1 on errors. When -1 was
+returned no resources were freed, and library functions still can be
+used.
+
+ERRORS
+------
+|el_cleanup| function cannot fail. |el_ocleanup| and
+|el_destroy| may return:
+
+EINVAL
+ Passed el object is not valid
diff --git a/www/in/el_color.err b/www/in/el_color.err
new file mode 100644
index 0000000..4b61eb7
--- /dev/null
+++ b/www/in/el_color.err
@@ -0,0 +1,3 @@
+ERRORS
+ EINVAL
+ Input argument is different than 1 or 0
diff --git a/www/in/el_colors.desc b/www/in/el_colors.desc
new file mode 100644
index 0000000..04395a3
--- /dev/null
+++ b/www/in/el_colors.desc
@@ -0,0 +1,6 @@
+If this is set to 1, output will be enriched with ANSI colors
+depending on the message severity. This option needs terminal
+supporting colors. You can store messages with colors to file, and
+then read them with colors on color-enabled terminal. If this is set
+to 0, no colors will be added. If you read file with colors in editor
+like **vim**, you will see control characters all over file.
diff --git a/www/in/el_custom_put.desc b/www/in/el_custom_put.desc
new file mode 100644
index 0000000..8711f11
--- /dev/null
+++ b/www/in/el_custom_put.desc
@@ -0,0 +1,19 @@
+Sets function pointer for custom message print. Function will receive
+complete messsage (after processsing) to print, just as it would be
+printed to ie. stderr or another facility. Both binary and string
+data can be received this way.
+
+*s* points to a data buffer, it can be null terminated string, or
+arbitrary binary data - depending on which functions has been called.
+
+*slen* contains size of *s* buffer. If *s* is null terminated string,
+then *slen* contains length of string including null terminator
+character. For binary data, it contains size of binary buffer.
+
+*user* pointer can be used to pass own logger object where data shall
+be sent. For example it may contain pointer to **el** struct, if you
+don't use global el struct.
+
+Function cannot fail. If NULL is passed, custom function won't be
+called. It is still mandatory to enable custom printing with
+**el_option**\ (3) - **EL_OUT**.
diff --git a/www/in/el_enable_colors.in b/www/in/el_enable_colors.in
new file mode 100644
index 0000000..8c6291f
--- /dev/null
+++ b/www/in/el_enable_colors.in
@@ -0,0 +1,33 @@
+NAME
+----
+**el_enable_colors** - enable pretty colors, depending on level log was
+printed with
+
+SYNOPSIS
+--------
+.. code-block:: c
+
+ #include <embedlog.h>
+
+ int el_enable_colors(int enable);
+
+ int el_oenable_colors(struct el *el, int enable);
+
+DESCRIPTION
+-----------
+.. include:: /in/el_colors.desc
+
+EXAMPLES
+--------
+.. code-block:: c
+
+ el_enable_colors(1);
+ el_enable_colors(0);
+
+RETURN VALUE
+------------
+0 on succes, or -1 and set **errno** on failure.
+
+ERRORS
+------
+.. include:: /in/el_color.err
diff --git a/www/in/el_enable_file_log.in b/www/in/el_enable_file_log.in
new file mode 100644
index 0000000..98d01f1
--- /dev/null
+++ b/www/in/el_enable_file_log.in
@@ -0,0 +1,71 @@
+NAME
+----
+**el_enable_file_log** - configures and enables printing to file
+
+SYNOPSIS
+--------
+.. code-block:: c
+
+ #include <embedlog.h>
+
+ int el_enable_file_log(const char *path, int rotate_number,
+ long rotate_size);
+
+ int el_oenable_file_log(struct el *el, const char *path,
+ int rotate_number, long rotate_size);
+
+DESCRIPTION
+-----------
+This function will do multiple things. First it will configure log rotation.
+
+If you want to have limited number of files with limited size, you can
+specify log rotation in these values.
+
+.. include:: /in/el_frotate_number.desc
+
+.. include:: /in/el_frotate_size.desc
+
+If you want date log rotation, in place of *rotate_number* pass
+``enum el_option_rotate``.
+
+.. include:: /in/el_frotate_date.desc
+
+Next it will try to open file specified by *path*
+
+.. include:: /in/el_fpath.desc
+
+And at the end it will enable outputing to file.
+
+EXAMPLES
+--------
+.. code-block:: c
+
+ /* Enable logging to file without rotating, file will grow
+ * without any limits, until it devours whole disk space */
+ el_enable_file_log("/var/log/file.log", 0, 0)
+
+ /* Enable logging to file, but also enable log rotation.
+ * Program will take maximum 10 files each of 1MB in size.
+ * When you enable log rotation do this in separate directory,
+ * because program will create multiple file.log.N files in
+ * directory where file.log is specified.
+ *
+ * In this case, file.log will always be a symlink to newest file */
+ el_enable_file_log("/var/log/progname/file.log", 10, 1024 * 1024)
+
+ /* Enable date log rotation. Once per day new file will be created */
+ el_enable_file_log("/var/log/progname/file.log", EL_ROT_DATE_DAY, 0)
+
+RETURN VALUE
+------------
+0 on succes, or -1 and set **errno** on failure.
+
+ERRORS
+------
+EINVAL
+ Input parameter is invalid
+ENAMETOOLONG
+ File name is too long
+
+Function can also fail and set errno for any of the errors specified for the
+routing fopen(3)
diff --git a/www/in/el_enable_output.in b/www/in/el_enable_output.in
new file mode 100644
index 0000000..4a6dd1c
--- /dev/null
+++ b/www/in/el_enable_output.in
@@ -0,0 +1,47 @@
+NAME
+----
+**el_enable_output** - enable one or more outputs.
+**el_disable_output** - disable one or more outputs.
+
+SYNOPSIS
+--------
+.. code-block:: c
+
+ #include <embedlog.h>
+
+ int el_enable_output(enum el_output output)
+ int el_disable_output(enum el_output output)
+
+ int el_oenable_output(struct el *el, enum el_output output);
+ int el_odisable_output(struct el *el, enum el_output output);
+
+DESCRIPTION
+-----------
+.. include:: /in/el_out.desc
+
+With this function you can enable or disable outputs without
+altering any previously set outputs.
+
+EXAMPLES
+--------
+.. code-block:: c
+
+ /* Enable stdout outout (default stderr, is still enabled) */
+ el_enable_output(EL_OUT, EL_OUT_STDOUT);
+
+ /* Add file and network logging retaining stdout and stderr */
+ el_enable_output(EL_OUT, EL_OUT_NET | EL_OUT_FILE);
+
+ /* Remove only stderr from the outputs, all other will be rtained */
+ el_disable_output(EL_OUT, EL_OUT_STDERR);
+
+ /* Now disable net and file, leaving only stdout as result */
+ el_disable_output(EL_OUT, EL_OUT_NET | EL_OUT_FILE);
+
+RETURN VALUE
+------------
+0 on succes, or -1 and set **errno** on failure.
+
+ERRORS
+------
+.. include:: /in/el_out.err
diff --git a/www/in/el_enable_thread_safe.in b/www/in/el_enable_thread_safe.in
new file mode 100644
index 0000000..c857c39
--- /dev/null
+++ b/www/in/el_enable_thread_safe.in
@@ -0,0 +1,32 @@
+NAME
+----
+**el_enable_thread_safe** - enable thread safety checks
+
+SYNOPSIS
+--------
+.. code-block:: c
+
+ #include <embedlog.h>
+
+ int el_enable_thread_safe(int enable);
+
+ int el_oenable_thread_safe(struct el *el, int enable);
+
+DESCRIPTION
+-----------
+.. include:: /in/el_thread_safe.desc
+
+EXAMPLES
+--------
+.. code-block:: c
+
+ el_enable_thread_safe(1);
+ el_enable_thread_safe(0);
+
+RETURN VALUE
+------------
+0 on succes, or -1 and set **errno** on failure.
+
+ERRORS
+------
+.. include:: /in/el_thread_safe.err
diff --git a/www/in/el_finfo.desc b/www/in/el_finfo.desc
new file mode 100644
index 0000000..3fd323d
--- /dev/null
+++ b/www/in/el_finfo.desc
@@ -0,0 +1,3 @@
+EL_FINFO adds information about log location to each message in
+format [some_file.c:123]. Setting this to 0, will result in no file
+information at all
diff --git a/www/in/el_flush.in b/www/in/el_flush.in
new file mode 100644
index 0000000..07de36d
--- /dev/null
+++ b/www/in/el_flush.in
@@ -0,0 +1,55 @@
+NAME
+----
+**el_flush**, **el_oflush** - flush logs from all buffers to underlying
+devices.
+
+SYNOPSIS
+--------
+.. code-block:: c
+
+ include <embedlog.h>
+
+ int el_flush(void)
+
+ int el_oflush(struct el *el)
+
+DESCRIPTION
+-----------
+**embedlog** (and underlying drivers, operating systems, libraries etc)
+to improve performance, may buffer message before commiting changes to
+actual device. And it's ok, there is really no need to waste resources
+every time you want to log 50 bytes of debug print on commiting message
+physically to the drive - or send via network. It's much more common to
+buffer messages in RAM until certain amount of bytes are ready to send
+- and then send a bunch of data in one quick burst. But that behaviour
+is not always desired, like in situation in which we know we won't be
+printing logs for long time. For such situation explicit flush may in
+order.
+
+|el_flush| flushes logs from all buffers to underlying device.
+For example, when logs are printed to file, logs are written through
+buffered **stdio** functions, which may result in some logs never being
+actually put into block device in case of abnormal application crash.
+This function will do everything what is in its power to make sure logs
+landed on underlying device. This applies to files, but also to logs
+with network output.
+
+|el_oflush| works just the same, but accepts custom *el* object
+as argument.
+
+RETURN VALUE
+------------
+Functions return 0 upon successful flush or -1 on errors. When -1 was
+returned there is no guarantee that data has landed on underlying
+device.
+
+ERRORS
+------
+|el_flush| and |el_oflush| may return errors from
+functions like: **fflush**, **fileno**, **fsync**,
+**fseek**, **ftell**, **fopen** and/or **fclose**.
+
+|el_oflush| may additionally return:
+
+**EINVAL**
+ Passed el object is not valid
diff --git a/www/in/el_fpath.desc b/www/in/el_fpath.desc
new file mode 100644
index 0000000..c0bac77
--- /dev/null
+++ b/www/in/el_fpath.desc
@@ -0,0 +1,3 @@
+Sets the *path* for the logs. Logs will be stored in this file. If
+file rotation is enabled, a numer will be postfixed to each file. See
+**EL_FROTATE_NUMBER** or **EL_FROTATE_DATE** details.
diff --git a/www/in/el_fpath.err b/www/in/el_fpath.err
new file mode 100644
index 0000000..69e3f23
--- /dev/null
+++ b/www/in/el_fpath.err
@@ -0,0 +1,16 @@
+ERRORS
+ EINVAL
+ Input parameter is NULL
+
+ ENAMETOOLONG
+ File name is too long
+
+ Function can also fail and set *errno* for any of the errors
+ specified for the routing **fopen**\ (3)
+
+If function fails with **EINVAL** or **ENAMETOOLONG**, file is not
+opened and any calls that logs to file will result in failure. Any
+other error is in reality just a warning, meaning file could not have
+been opened now, but embedlog will try to reopen in each time it logs
+to file. **EINVAL** and **ENAMETOOLONG** are unrecovery errors, and
+embedlog will never store any log in that situation.
diff --git a/www/in/el_frotate_date.desc b/www/in/el_frotate_date.desc
new file mode 100644
index 0000000..e0fb67a
--- /dev/null
+++ b/www/in/el_frotate_date.desc
@@ -0,0 +1,50 @@
+**EL_FROTATE_DATE** enables log rotation based on date. When log is printed,
+**embedlog** checks if *timeslice* has passed. If so, a new file with
+new date will be opened.
+
+There is no file limit size in this mode. If you set rotation to happen once
+per day, log ``logfile.2024-03-01`` may be only 100kB, but next day
+``logfile.2024-03-02`` may be 1GB in size. Program does not remove files in
+this mode
+
+If not log has heppend within configured timeslice, no empty files will be
+created, program wil just jump to newest date.
+
+For example, if *timeslice* is set to **EL_ROT_DATE_MIN**, new file will
+be created each time minute advances and new log is printed in that new minute.
+
+There are 6 possible timeslices.
+
++----------------------+------------------------------------+
+| timeslice | example rotated output |
++======================+====================================+
+| ``EL_ROT_DATE_SEC`` | | ``logname.2024-03-01--15-04-23`` |
+| | | ``logname.2024-03-01--15-04-24`` |
+| | | ``logname.2024-03-01--15-04-25`` |
+| | | ``logname.2024-03-01--15-04-36`` |
++----------------------+------------------------------------+
+| ``EL_ROT_DATE_MIN`` | | ``logname.2024-03-01--15-04`` |
+| | | ``logname.2024-03-01--15-05`` |
+| | | ``logname.2024-03-01--15-06`` |
+| | | ``logname.2024-03-01--15-08`` |
++----------------------+------------------------------------+
+| ``EL_ROT_DATE_HOUR`` | | ``logname.2024-03-01--15`` |
+| | | ``logname.2024-03-01--16`` |
+| | | ``logname.2024-03-01--18`` |
+| | | ``logname.2024-03-02--01`` |
++----------------------+------------------------------------+
+| ``EL_ROT_DATE_DAY`` | | ``logname.2024-03-01`` |
+| | | ``logname.2024-03-02`` |
+| | | ``logname.2024-03-03`` |
+| | | ``logname.2024-03-08`` |
++----------------------+------------------------------------+
+| ``EL_ROT_DATE_MON`` | | ``logname.2024-03`` |
+| | | ``logname.2024-04`` |
+| | | ``logname.2024-10`` |
+| | | ``logname.2024-12`` |
++----------------------+------------------------------------+
+| ``EL_ROT_DATE_YEAR`` | | ``logname.2024`` |
+| | | ``logname.2025`` |
+| | | ``logname.2026`` |
+| | | ``logname.2028`` |
++----------------------+------------------------------------+
diff --git a/www/in/el_frotate_number.desc b/www/in/el_frotate_number.desc
new file mode 100644
index 0000000..5721546
--- /dev/null
+++ b/www/in/el_frotate_number.desc
@@ -0,0 +1,33 @@
+If **FROTATE_NUMBER** is set to 0, file rotation will be disabled and logs
+will be printed into specified file without size limit. The only size limit
+is the one presented by the filesystem and architecture.
+
+If this value is bigger than 0, file rotation will be enabled. All
+files will have suffixes added to name set in EL_FPATH. For example,
+*program.log.0*. Files are enumareted from *.0* to *.n*, where *n* is
+set rotate number. File with suffix *.0* is the oldest one, and the
+higher the number, the newer the file is. If logger reaches maximum
+number of files, oldest one with suffix *.0* will be deleted and
+suffixes of the files will be decremented by 1 (ie. *log.1* will be
+renamed to *log.0*, *log.2* will be renamed to *log.1* and so on).
+
+User can also pass 1 here, but if file reaches its size limit, it
+will be deleted and printing will continue from the empty file
+
+When *number* is bigger than 10, padded zeroes will be added to
+rotated logs like *log.02*, *log.004*\ or *log.076*. Actual number of
+padded zeroes depends in *number* passed. For bigger than 10 it will
+be 1 zero, for bigger than 100 it will be 0 zeroes and so on. This is
+done to ease up sorting when one would want to concat all files with
+one simple **cat \***.
+
+Example file listing after multiple rotations may look like this::
+
+ $ ls -l /tmp/embedlog-example
+ total 20K
+ lrwxrwxrwx 1 lm- family 5 mar 1 19:50 log -> log.4
+ -rw-r----- 1 lm- family 496 mar 1 19:50 log.0
+ -rw-r----- 1 lm- family 470 mar 1 19:50 log.1
+ -rw-r----- 1 lm- family 496 mar 1 19:50 log.2
+ -rw-r----- 1 lm- family 470 mar 1 19:50 log.3
+ -rw-r----- 1 lm- family 496 mar 1 19:50 log.4
diff --git a/www/in/el_frotate_size.desc b/www/in/el_frotate_size.desc
new file mode 100644
index 0000000..bf55f04
--- /dev/null
+++ b/www/in/el_frotate_size.desc
@@ -0,0 +1,8 @@
+**FROTATE_SIZE** defines file size at which files will be rotated. If
+message being printed would overflow rotate size, current file will be
+closed and new one will be created, and current message will be stored in
+that new file. It is guaranteed that file will not be bigger than value set
+in this option. If log printed into file is bigger than configure rotate
+size, message will be truncated, to prevent file bigger than configure
+rotate size. It's very rare situation as it doesn't make a lot of sense to
+set rotate size to such small value.
diff --git a/www/in/el_fsync_every.desc b/www/in/el_fsync_every.desc
new file mode 100644
index 0000000..f04fd47
--- /dev/null
+++ b/www/in/el_fsync_every.desc
@@ -0,0 +1,12 @@
+**EL_FSYNC_EVERY** defines how often logs shall be synced to disk.
+Simply writing data to file descriptor is not enough, metadata also
+has to be synced or you are facing data loose on unexpected power
+loose. Yes, data will be on block device, but entry to it in file
+system will not be updated, thus system will think file did not
+change. To prevent that one must sync data and metadata periodically.
+Data will be synced every *size* of bytes written. It basically
+translates to 'how much data am I ready to loose?'. Set too high
+and you may loose a significant ammout of data on power lose. Set
+this too low and your performance goes out of the window. Setting
+this to 0 will result in all logs being flush ever time they are
+printed.
diff --git a/www/in/el_fsync_level.desc b/www/in/el_fsync_level.desc
new file mode 100644
index 0000000..c8db3bf
--- /dev/null
+++ b/www/in/el_fsync_level.desc
@@ -0,0 +1,10 @@
+**EL_FSYNC_LEVEL** defines which log levels are always synced.
+If level of printed message is *level* or less (that is higher
+priority), it will be synced to disk every single time regardless of
+**EL_FSYNC_EVERY** option. Messages with level **EL_FATAL** (that is
+also default value for level sync) are synced always regardless of
+any options set. Messages printed with functions that don't take log
+level, will be treated as messages with **EL_DBG** level. If *level*
+is set to **EL_DBG** every message printed with any function will be
+immediately synced to drive (careful with that, this will impact
+performance a great deal if you print a lot of debug messages).
diff --git a/www/in/el_funcinfo.desc b/www/in/el_funcinfo.desc
new file mode 100644
index 0000000..0946e6b
--- /dev/null
+++ b/www/in/el_funcinfo.desc
@@ -0,0 +1,4 @@
+EL_FUNCINFO adds information about function from which message has
+been printed in format [funcname()] or if **EL_FINFO** is enabled
+[some_file.c:123:funcname()]. Setting this to 0 will result in no
+function information.
diff --git a/www/in/el_init.in b/www/in/el_init.in
new file mode 100644
index 0000000..ae266c6
--- /dev/null
+++ b/www/in/el_init.in
@@ -0,0 +1,99 @@
+NAME
+----
+**el_init** - initializes library and el for printing.
+
+SYNOPSIS
+--------
+
+.. code-block:: c
+
+ include <embedlog.h>
+
+ int el_init(void)
+ int el_oinit(struct el *el)
+ struct el * el_new(void)
+
+DESCRIPTION
+===========
+
+There are two types of functions in **embedlog.** Functions that use
+global static structure inside library, these functions don't accept
+*el* argument with options, and just use that internal variable.
+
+Another type are functions that accept external *el* object. These
+functions are prefixed with **el_o**.
+
+|el_init| initializes static global option structure. This option
+structure is used by all functions that don't accept *el* object
+parameter. If you want to use only one instance of **embedlog**, this is
+the function you want to use.
+
+|el_oinit| initializes only *el* struct passed to it. Functions
+that accepts *el* object may be used. If you want to have multiple
+embedlog instances (ie. one for program logs, and one for queries) that
+stores logs differently - this is the function you want to use. Multiple
+embedlog objects will be also necessary on RTOSes with flat memory space.
+Object initialized with this function must be deinitialized with
+|el_ocleanup| function.
+
+|el_new| Works in the same way as |el_oinit| but function
+returns newly heap-allocated pointer to *el* struct. Object created with
+this function must be destroyed with |el_destroy| function.
+
+NOTES
+-----
+Keep in mind that using |el_oinit| function is suscible to ABI
+breakage. If stable ABI is important to you, use |el_new|
+function. Please check |el_overview| for more information about
+this.
+
+RETURN VALUE
+------------
+|el_init| cannot fail and always returns 0. |el_oinit|
+function will return 0 upon success and -1 on errors. |el_new|
+returns valid pointer on success and **NULL** when error occurs.
+
+ERRORS
+------
+|el_oinit| can return:
+
+EINVAL
+ *el* object is invalid (null).
+
+|el_new| can return:
+
+ENOMEM
+ Not enough memory in the system to perform necessary memory allocations.
+
+EXAMPLE
+-------
+
+.. code-block:: c
+
+ #include <embedlog.h>
+
+ int main(void)
+ {
+ struct el el, *elp;
+
+ /* initialize default object and two custom el objects */
+ el_init();
+ el_oinit(&el);
+ elp = el_new();
+
+ /* make el to print to file and stderr, elp will print to
+ * default output - that is stderr only. */
+ el_enable_file_log("/tmp/test.log", 0, 0);
+
+ /* print messages */
+ el_print(ELI, "will print to stderr");
+ el_oprint(ELI, &el, "will print to file /tmp/test.log and stderr");
+ el_oprint(ELN, elp, "print to stderr");
+
+ /* cleanup after any initialization code (like fopen) */
+ el_destroy(elp);
+ el_ocleanup(&el);
+ el_cleanup();
+
+ return 0;
+ }
diff --git a/www/in/el_level.desc b/www/in/el_level.desc
new file mode 100644
index 0000000..1748c1d
--- /dev/null
+++ b/www/in/el_level.desc
@@ -0,0 +1,15 @@
+Set what the current logging level shall be. Altough it
+accepts **enum el_level** type, this can be whatever number from
+range <0, 7>. The higher the level, the lower priority of the
+message. All messages that have lower priority (higher number) then
+currently set *level* will not be printed. There are 8 predefined
+levels, sorted by priority (highest first):
+
+| EL_FATAL
+| EL_ALERT
+| EL_CRIT
+| EL_ERROR
+| EL_WARN
+| EL_NOTICE
+| EL_INFO
+| EL_DBG
diff --git a/www/in/el_level.err b/www/in/el_level.err
new file mode 100644
index 0000000..49b57f5
--- /dev/null
+++ b/www/in/el_level.err
@@ -0,0 +1,3 @@
+ERRORS
+ EINVAL
+ specified *level* is invalid (bigger than EL_DBG).
diff --git a/www/in/el_option.in b/www/in/el_option.in
new file mode 100644
index 0000000..24fd147
--- /dev/null
+++ b/www/in/el_option.in
@@ -0,0 +1,548 @@
+NAME
+----
+**el_option** - sets optional configuration of the logger
+
+SYNOPSIS
+--------
+.. code-block:: c
+
+ #include <embedlog.h>
+
+ int el_option(int option, ...);
+
+ int el_ooption(struct el *el, int option, ...);
+
+DESCRIPTION
+-----------
+
+|el_option| allows user to configure logger's internal el object,
+to tune logging to users needs. This is quite raw function to fine tune
+every aspect of embedlog. For normal usage it may be more beneficial and
+simpler to use some function that use most common options. Often setting
+multiple options in one call. These functions are not necessary better
+or faster. They are just different way of setting **embedlog** options.
+
+Below is list of these functions and options they set.
+
+.. parsed-literal::
+
+ +--------------------------+-------------------+----------------------------------+
+ | function | modified ioctl | short description |
+ +==========================+===================+==================================+
+ | |el_set_log_level| | EL_LEVEL | set new log level |
+ +--------------------------+-------------------+----------------------------------+
+ | |el_enable_output| | EL_OUT | enable output(s) |
+ | |el_disable_output| | | disable output(s) |
+ +--------------------------+-------------------+----------------------------------+
+ | |el_set_prefix| | EL_PREFIX | set new prefix for logs |
+ +--------------------------+-------------------+----------------------------------+
+ | |el_set_timestamp| | EL_TS | Enable timestamps, set time |
+ | | EL_TS_TM | source, and optionally turn on |
+ | | EL_TS_FRACT | fraction of seconds in logging |
+ +--------------------------+-------------------+----------------------------------+
+ | |el_enable_colors| | EL_COLORS | enable pretty colors in output |
+ +--------------------------+-------------------+----------------------------------+
+ | |el_print_extra_info| | EL_FINFO | Adds to log information about |
+ | | EL_FUNCINFO | filename, line and function name |
+ | | EL_PRINT_LEVEL | where log originated from |
+ +--------------------------+-------------------+----------------------------------+
+ | |el_set_custom_put| | EL_CUSTOM_PUT | Set custom function for printing |
+ +--------------------------+-------------------+----------------------------------+
+ | |el_enable_file_log| | EL_FROTATE_NUMBER | Enables logging to file, and |
+ | | EL_FPATH | optionally sets file rotate |
+ | | EL_FROTATE_SIZE | configuration |
+ | | EL_FROTATE_DATE | |
+ | | EL_OUT_FILE | |
+ +--------------------------+-------------------+----------------------------------+
+ | |el_set_file_sync| | EL_FSYNC_EVERY | Configures conditions to |
+ | | EL_FSYNC_LEVEL + forcefully sync logs to disk |
+ +--------------------------+-------------------+----------------------------------+
+ | |el_set_tty_dev| | EL_TTY_DEV | Enables printing to tty device |
+ | | EL_OUT | |
+ +--------------------------+-------------------+----------------------------------+
+ | |el_enable_thread_safe| | EL_THREAD_SAFE | Enables thread safety features |
+ +--------------------------+-------------------+----------------------------------+
+
+OPTIONS
+--------
+Below is a list of *option* that can be configured. Value inside
+parenthesis determines argument types of variadic arguments *...*
+
+.. list-table::
+ :header-rows: 1
+
+ * - option
+ - arguments
+ - default value
+ * - :ref:`EL_LEVEL <manuals/options/el_option.3:el_level>`
+ - ``enum el_level level``
+ - ``EL_INFO``
+ * - :ref:`EL_OUT <manuals/options/el_option.3:el_out>`
+ - ``enum el_output outputs``
+ - ``EL_OUT_STDERR``
+ * - :ref:`EL_PRINT_NL <manuals/options/el_option.3:el_print_nl>`
+ - ``int nl``
+ - ``1``
+ * - :ref:`EL_PREFIX <manuals/options/el_option.3:el_prefix>`
+ - ``const char *prefix``
+ - ``none``
+ * - :ref:`EL_COLORS <manuals/options/el_option.3:el_colors>`
+ - ``int colors``
+ - ``0``
+ * - :ref:`EL_TS <manuals/options/el_option.3:el_ts>`
+ - ``enum el_option_timestamp timestamp``
+ - ``EL_TS_OFF``
+ * - :ref:`EL_TS_TM <manuals/options/el_option.3:el_ts_tm>`
+ - ``enum el_option_timestamp_timer timer``
+ - ``EL_TS_TM_TIME``
+ * - :ref:`EL_TS_FRACT <manuals/options/el_option.3:el_ts_fract>`
+ - ``enum el_option_timestamp_fraction fraction``
+ - ``EL_TS_FRACT_OFF``
+ * - :ref:`EL_PRINT_LEVEL <manuals/options/el_option.3:el_print_level>`
+ - ``int print``
+ - ``1``
+ * - :ref:`EL_PMEMORY_SPACE <manuals/options/el_option.3:el_pmemory_space>`
+ - ``int spacing``
+ - ``0``
+ * - :ref:`EL_FINFO <manuals/options/el_option.3:el_finfo>`
+ - ``int finfo``
+ - ``0``
+ * - :ref:`EL_FUNCINFO <manuals/options/el_option.3:el_funcinfo>`
+ - ``int funcinfo``
+ - ``0``
+ * - :ref:`EL_CUSTOM_PUT <manuals/options/el_option.3:el_custom_put>`
+ - ``el_custom_put, void *user``
+ - ``NULL``
+ * - :ref:`EL_FPATH <manuals/options/el_option.3:el_fpath>`
+ - ``const char *path``
+ - ``unset``
+ * - :ref:`EL_FROTATE_NUMBER <manuals/options/el_option.3:el_frotate_number>`
+ - ``long number``
+ - ``0``
+ * - :ref:`EL_FROTATE_SYMLINK <manuals/options/el_option.3:el_frotate_symlink>`
+ - ``int enable``
+ - ``1``
+ * - :ref:`EL_FROTATE_SIZE <manuals/options/el_option.3:el_frotate_size>`
+ - ``long size``
+ - ``0``
+ * - :ref:`EL_FROTATE_DATE <manuals/options/el_option.3:el_frotate_date>`
+ - ``el_option_rotate timeslice``
+ - ``EL_ROT_OFF``
+ * - :ref:`EL_FSYNC_EVERY <manuals/options/el_option.3:el_fsync_every>`
+ - ``long size``
+ - ``32768``
+ * - :ref:`EL_FSYNC_LEVEL <manuals/options/el_option.3:el_fsync_level>`
+ - ``enum el_level level``
+ - ``EL_FATAL``
+ * - :ref:`EL_TTY_DEV <manuals/options/el_option.3:el_tty_dev>`
+ - ``const char *dev, speed_t speed``
+ - ``unset``
+ * - :ref:`EL_THREAD_SAFE <manuals/options/el_option.3:el_thread_safe>`
+ - ``int safe``
+ - ``0``
+
+--------------------------------------------------------------------------------
+
+EL_LEVEL
+^^^^^^^^
+``EL_LEVEL (enum el_level level)`` [default: **EL_INFO**]
+
+.. include:: /in/el_level.desc
+
+.. code-block:: c
+
+ /* print only alert and fatal logs */
+ el_option(EL_LEVEL, EL_ALERT);
+ /* print only error, critical, alert and fatal */
+ el_option(EL_LEVEL, EL_ERROR);
+ /* print all, including debug logs */
+ el_option(EL_LEVEL, EL_DBG);
+
+.. include:: /in/el_level.err
+
+--------------------------------------------------------------------------------
+
+EL_OUT
+^^^^^^
+``EL_OUT (enum el_output outputs)`` [default: **EL_OUT_STDERR**]
+
+.. include:: /in/el_out.desc
+
+.. code-block:: c
+
+ /* Log only to stdout */
+ el_option(EL_OUT, EL_OUT_STDOUT);
+
+ /* Log to stderr, network and file simultaneously
+ * Note, this will disable previously set print to stdout! */
+ el_option(EL_OUT, EL_OUT_STDERR | EL_OUT_NET | EL_OUT_FILE);
+
+.. include:: /in/el_out.err
+
+--------------------------------------------------------------------------------
+
+EL_PRINT_NL
+^^^^^^^^^^^
+``EL_PRINT_NL (int nl)`` [default: **1**]
+
+When enabled, new line marker will be added to each print. If you
+disable it, you will be able to create very long lines with
+consecutive print calls.
+
+.. code-block:: c
+
+ el_option(EL_PRINT_NL, 1);
+ el_print(ELI, "one");
+ el_print(ELI, "two");
+ el_print(ELI, "three");
+ /* log output: */
+ /* i/one
+ * i/two
+ * i/three */
+
+ el_option(EL_PRINT_LEVEL, 0);
+ el_option(EL_PRINT_NL, 0);
+ el_print(ELI, "one");
+ el_print(ELI, "two");
+ el_print(ELI, "three");
+ /* log output: */
+ /* onetwothree */
+ /* If you didn't disable, EL_PRINT_LEVEL (which by default is enabled)
+ * you would get: i/onei/twoi/three
+
+--------------------------------------------------------------------------------
+
+EL_PREFIX
+^^^^^^^^^
+``EL_PREFIX (const char *prefix)`` [default: **none**]
+
+.. include:: /in/el_prefix.desc
+
+.. code-block:: c
+
+ el_option(EL_PREFIX, "my-prefix");
+ el_print(ELI, "some log");
+ /* log output */
+ /* i/my-prefix: some log */
+
+ el_option(EL_PREFIX, NULL); /* default */
+ el_print(ELI, "some log");
+ /* log output */
+ /* i/some log */
+
+--------------------------------------------------------------------------------
+
+EL_COLORS
+^^^^^^^^^
+``EL_COLORS (int colors)`` [default: **0**]
+
+.. include:: /in/el_colors.desc
+
+.. include:: /in/el_color.err
+
+--------------------------------------------------------------------------------
+
+EL_TS
+^^^^^
+``EL_TS (enum el_option_timestamp timestamp)`` [default: **EL_TS_OFF**]
+
+.. include:: /in/el_ts.desc
+
+.. code-block:: c
+
+ el_option(EL_TS, EL_TS_SHORT);
+ el_print(ELI, "some log");
+ /* log output */
+ /* [1709153777] i/some log */
+
+ el_option(EL_TS, EL_TS_LONG);
+ el_print(ELI, "some log");
+ /* log output */
+ /* [[2024-02-28 20:56:17]] i/some log */
+
+ERRORS
+ EINVAL
+ Input argument is invalid
+
+ ENOSYS
+ Timestamp support was not compiled in and setting this option
+ is disabled.
+
+--------------------------------------------------------------------------------
+
+EL_TS_TM
+^^^^^^^^
+``EL_TS_TM (enum el_option_timestamp_timer timer)`` [default: **EL_TS_TM_TIME**]
+
+.. include:: /in/el_ts_tm.desc
+
+.. code-block:: c
+
+ el_option(EL_TS_TM, EL_TS_TM_REALTIME);
+ el_option(EL_TS_TM, EL_TS_TM_TIME);
+
+ERRORS
+ EINVAL
+ Input argument is invalid
+
+ ENODEV
+ Specified timer source was not compiled in and is not available
+
+--------------------------------------------------------------------------------
+
+EL_TS_FRACT
+^^^^^^^^^^^
+``EL_TS_FRACT (enum el_option_timestamp_fraction fraction)`` [default: **EL_TS_FRACT_OFF**]
+
+.. include:: /in/el_ts_fract.desc
+
+.. code-block:: c
+
+ el_option(EL_TS_FRAC, EL_TS_FRACT_OFF);
+ el_option(EL_TS_FRAC, EL_TS_FRACT_MS);
+
+ERRORS
+ EINVAL
+ Input argument is invalid
+
+--------------------------------------------------------------------------------
+
+EL_PRINT_LEVEL
+^^^^^^^^^^^^^^
+``EL_PRINT_LEVEL (int print)`` [default: **1**]
+
+.. include:: /in/el_print_level.desc
+
+.. code-block:: none
+
+ el_option(EL_PRINT_LEVEL, 1);
+ c/this is critical message
+ n/this is just a notice
+ d/debug print
+
+If value is set to 0, level information will not be added, and above
+messages would like like this
+
+.. code-block:: none
+
+ el_option(EL_PRINT_LEVEL, 1);
+ this is critical message
+ this is just a notice
+ debug print
+
+ERRORS
+ EINVAL
+ Input argument is different than 1 or 0
+
+--------------------------------------------------------------------------------
+
+EL_PMEMORY_SPACE
+^^^^^^^^^^^^^^^^
+``EL_PMEMORY_SPACE (int spacing)`` [default: **0**]
+
+|el_pmemory| prints 16 bytes in a line. **EL_PMEMORY_SPACE** alows to add
+additional spacing in the middle between 8 bytes, to improve readability in
+some cases. Check |el_pmemory| how different spacing affects output.
+
+.. code-block:: c
+
+ el_option(EL_PMEMORY_SPACE, 2);
+
+ERRORS
+ EINVAL
+ *spacing* is not between 0 and 3.
+
+--------------------------------------------------------------------------------
+
+EL_FINFO
+^^^^^^^^
+``EL_FINFO (int finfo)`` [default: **0**]
+
+.. include:: /in/el_finfo.desc
+
+.. code-block:: c
+
+ el_option(EL_FINFO, 1);
+ el_print(ELI, "some log");
+ /* log output */
+ /* [some-file.c:68] i/some log */
+
+ERRORS
+ EINVAL
+ Input argument is different than 1 or 0
+
+--------------------------------------------------------------------------------
+
+EL_FUNCINFO
+^^^^^^^^^^^
+``EL_FUNCINFO (int funcinfo)`` [default: **0**]
+
+.. include:: /in/el_funcinfo.desc
+
+.. code-block:: c
+
+ el_option(EL_FUNCINFO, 1);
+ el_print(ELI, "some log");
+ /* log output */
+ /* [some_function()] i/some log */
+
+ERRORS
+ EINVAL
+ Input argument is different than 1 or 0
+
+--------------------------------------------------------------------------------
+
+EL_CUSTOM_PUT
+^^^^^^^^^^^^^
+``EL_CUSTOM_PUT (int (*el_custom_put)(const char *s, size_t slen, void *user), void *user)``
+
+.. include:: /in/el_custom_put.desc
+
+.. code-block:: c
+
+ int custom_logger(const char *s, size_t slen, void *user) {
+ FILE *f = user;
+ /* s will contain string "i/print log" */
+ fwrite(s, slen, 1, f);
+ return 0;
+ }
+
+ FILE *f = fopen(log_file, "w");
+ el_option(EL_CUSTOM_PUT, custom_logger, f);
+ el_option(EL_OUT, EL_OUT_CUSTOM);
+ el_print(ELI, "print log");
+
+
+--------------------------------------------------------------------------------
+
+EL_FPATH
+^^^^^^^^
+``EL_FPATH (const char *path)`` [default: **unset**]
+
+.. include:: /in/el_fpath.desc
+
+.. include:: /in/el_fpath.err
+
+--------------------------------------------------------------------------------
+
+EL_FROTATE_NUMBER
+^^^^^^^^^^^^^^^^^
+``EL_FROTATE_NUMBER (long number)`` [default: **0**]
+
+.. include:: /in/el_frotate_number.desc
+
+ERRORS
+ EINVAL
+ Input parameter is less than 0 or bigger than **USHRT_MAX**\ (65535).
+
+--------------------------------------------------------------------------------
+
+EL_FROTATE_SYMLINK
+^^^^^^^^^^^^^^^^^^
+``EL_FROTATE_SYMLINK (int enable)`` [default: **1**]
+
+When **EL_FROTATE_NUMBER** is bigger than 0, this option is enabled
+and program runs on UNIX, **embedlog** will create symlink file in
+the same directory as rest of the logs with base name of *path* that
+is passed to **EL_FPATH**. So if "/var/log/program/program.log" path
+is passed, after some time more or less this file structure will be
+generated
+
+.. code-block:: none
+
+ /var/log/program/program.log.0
+ /var/log/program/program.log.1
+ /var/log/program/program.log.2
+ /var/log/program/program.log.3
+ /var/log/program/program.log -> program.log.3
+
+Symlink will always point to file directly in the same directory.
+Symlink file will always point to most recent log file. This option
+is enabled by default.
+
+ERRORS
+ EINVAL
+ Input parameter is not 0 or 1
+
+--------------------------------------------------------------------------------
+
+EL_FROTATE_SIZE
+^^^^^^^^^^^^^^^
+``EL_FROTATE_SIZE (long size)`` [default: **0**]
+
+.. include:: /in/el_frotate_size.desc
+
+ERRORS
+ EINVAL
+ Value is less than 1
+
+EL_FROTATE_DATE
+^^^^^^^^^^^^^^^
+``EL_FROTATE_DATE (enum el_option_rotate timeslice)`` [default: **EL_ROT_OFF**]
+
+.. include:: /in/el_frotate_date.desc
+
+ERRORS
+ EINVAL
+ Invalid *timeslice* parameter
+
+--------------------------------------------------------------------------------
+
+EL_FSYNC_EVERY
+^^^^^^^^^^^^^^
+``EL_FSYNC_EVERY (long size)`` [default: 32768]
+
+.. include:: /in/el_fsync_every.desc
+
+ERRORS
+ EINVAL
+ Value is less than 0
+
+--------------------------------------------------------------------------------
+
+EL_FSYNC_LEVEL
+^^^^^^^^^^^^^^
+``EL_FSYNC_LEVEL (enum el_level level)`` [default: **EL_FATAL**]
+
+.. include:: /in/el_fsync_level.desc
+
+ERRORS
+ EINVAL
+ specified *level* is invalid (bigger than EL_DBG).
+
+--------------------------------------------------------------------------------
+
+EL_TTY_DEV
+^^^^^^^^^^
+``EL_TTY_DEV (const char *dev, speed_t speed)`` [default: **unset**]
+
+.. include:: /in/el_tty.desc
+
+.. include:: /in/el_tty.err
+
+--------------------------------------------------------------------------------
+
+EL_THREAD_SAFE
+^^^^^^^^^^^^^^
+``EL_THREAD_SAFE (int safe)`` [default: **0**]
+
+.. include:: /in/el_thread_safe.desc
+
+.. include:: /in/el_thread_safe.err
+
+RETURN VALUE
+------------
+On success 0 is returned. -1 is returned when any error occured.
+
+ERRORS
+------
+
+EINVAL
+ Passed *option* is invalid.
+
+ENOSYS
+ Passed *option* is not supported on this system (support was not
+ compiled)
+
+Also check for error description of specific option that failed for more
+informations
diff --git a/www/in/el_out.desc b/www/in/el_out.desc
new file mode 100644
index 0000000..584e2b8
--- /dev/null
+++ b/www/in/el_out.desc
@@ -0,0 +1,45 @@
+Set to what *outputs* logs will be printed with any of the printing
+function. User can enable as many outputs as he desires - it can be all
+inputs or even none (if one wants to surpress logging for some time). To
+enable multiple outputs join values with **or** operator ( **\|** ).
+
+Currently following *outputs* can be enabled.
+
+EL_OUT_STDERR
+ Messages will be printed to standard error output
+
+EL_OUT_STDOUT
+ Messages will be printed to standard output
+
+EL_OUT_SYSLOG
+ Messages will be sent to syslog facility. This requires system
+ with implemented POSIX.1-2001 and any syslog daemon
+
+EL_OUT_FILE
+ Messages will be printed to file. To work user should set output
+ file with **EL_FPATH**. Log rotation can be configured with
+ **EL_FROTATE_NUMBER** and **EL_FROTATE_SIZE** options.
+
+EL_OUT_NET
+ Messages shall be printed to external server. This requires BSD
+ Sockets to be enabled on the clients system, and listening server.
+ (TODO Not implemented yet)
+
+EL_OUT_TTY
+ Prints messages directly to configured serial console. Apart from
+ setting this, user should also configure device and speed with
+ **EL_TTY_DEV**.
+
+EL_OUT_ALL
+ Enables all supported outputs at once
+
+EL_OUT_NONE
+ Disables every output - logs won't be printed at all
+
+EL_OUT_CUSTOM
+ Enables custom function to be called on log print. Pointer to
+ custom function needs to be set with **EL_CUSTOM_PUTS** option.
+
+Many of the outputs can be configured for special needs, and some of
+them need mandatory configuration. For information about output
+configuration see proper option description
diff --git a/www/in/el_out.err b/www/in/el_out.err
new file mode 100644
index 0000000..3fd2381
--- /dev/null
+++ b/www/in/el_out.err
@@ -0,0 +1,7 @@
+ERRORS
+ EINVAL
+ Specified *output* is invalid
+
+ ENODEV
+ Specified *output* is not implemented on current system
+ (support was not compiled into library)
diff --git a/www/in/el_pbinary.in b/www/in/el_pbinary.in
new file mode 100644
index 0000000..989b267
--- /dev/null
+++ b/www/in/el_pbinary.in
@@ -0,0 +1,204 @@
+NAME
+----
+**el_pbinary** - print data and optional metadata in binary format
+
+SYNOPSIS
+--------
+.. code-block:: c
+
+ #include <embedlog.h>**
+
+ int el_putb(const void *memory, size_t mlen);
+ int el_pbinary(enum el_level level, const void *memory, size_t mlen);
+
+ int el_oputb(struct el *el, const void *memory, size_t mlen);
+ int el_opbinary(enum el_level level, struct el *el, const void *memory,
+ size_t mlen);
+
+DESCRIPTION
+-----------
+
+|el_putb| function dumps memory location into configured output
+That binary data will not be printed in ASCII like it is
+with |el_pmemory|. If *memory* contains **NULL** characters, they
+will be stored to file. If *memory* is for example ``char buf[] = {
+0xb0, 0xfc, 0x13, 0x37 }`` then exactly these bytes will be stored into
+file.
+
+|el_pbinary| is used to log binary data into block device. Both
+metadata and data itself are treated as binary data. Such files cannot
+be read with text tools like **less**, but rather need special program
+that will parse the file. This may be usefull when you need, for example
+to log every message on CAN bus. If there are a lot of messages, it may
+be better to store them in binary format as this may save *a lot* of
+space.
+
+|el_pbinary| uses specific format to store metadata to save as
+much space as possible. All numerical values in metadata are variadic in
+size. Order of fields are as follows:
+
+.. code-block:: none
+
+ +-------+------------+--------------+-------------+------+
+ | flags | ts_seconds | ts_fractions | data_length | data |
+ +-------+------------+--------------+-------------+------+
+
+The only mandatory fields are **flags**, **data_length** and **data**.
+**flags** determine what fields are present. **flags** field is always 1
+byte in size and its format is
+
+**ts_seconds** does not care if set timestamp is ``EL_TS_SHORT`` or
+``EL_TS_LONG``. As long as it's set, seconds will appear in the logs,
+and ``ts_seconds`` will be set to 1.
+
+.. code-block:: none
+
+ +------+-------+-----------------------------------------------------------+
+ | bits | value | description |
+ +======+=======+===========================================================+
+ | 0 | 0 | both ts_seconds and ts_fraction will not appear |
+ | +-------+-----------------------------------------------------------+
+ | | 1 | at least ts_seconds will appear, ts_fraction appearance |
+ | | | depends on 1..2 bits values |
+ +------+-------+-----------------------------------------------------------+
+ | 1..2 | 0 | ts_fractions will not appear |
+ | +-------+-----------------------------------------------------------+
+ | | 1 | ts_fractions will hold milliseconds value |
+ | +-------+-----------------------------------------------------------+
+ | | 2 | ts_fractions will hold microseconds value |
+ | +-------+-----------------------------------------------------------+
+ | | 3 | ts_fractions will hold nanoseconds value |
+ +------+-------+-----------------------------------------------------------+
+ | 3..5 | 0..7 | severity of the log, 0 is the highest and 7 is the lowest |
+ +------+-------+-----------------------------------------------------------+
+ | 6..7 | 0..3 | reserved |
+ +------+-------+-----------------------------------------------------------+
+
+**ts_seconds**, **ts_fractions** and **data_length** are numerical
+values with dynamic size. Each byte of a numerical value can hold number
+up to 127 and oldest bit is used as continuation bit, if that bit is
+set, program should treat next byte as next part of the same numerical
+value. Below is table with example decimal values and it's encoded
+counterpart.
+
+.. code-block:: none
+
+ +---------------+--------------------------+
+ | decimal value | encoded hex value |
+ +===============+==========================+
+ | 0 | 0x00 |
+ | 1 | 0x01 |
+ | 2 | 0x02 |
+ | 127 | 0x7f |
+ | 128 | 0x80 0x01 |
+ | 129 | 0x81 0x01 |
+ | 255 | 0xff 0x01 |
+ | 256 | 0x80 0x02 |
+ | 257 | 0x81 0x02 |
+ | 16383 | 0xff 0x7f |
+ | 16384 | 0x80 0x80 0x01 |
+ | 16385 | 0x81 0x80 0x01 |
+ | 438478374 | 0xa6 0xcc 0x8a 0xd1 0x01 |
+ | 2147483647 | 0xff 0xff 0xff 0xff 0x07 |
+ | 4294967295 | 0xff 0xff 0xff 0xff 0x0f |
+ +---------------+--------------------------+
+
+Encoded number are always **little-endian**, that is first byte is
+always the least significant byte.
+
+You can decode number with following code
+
+.. code-block:: c
+
+ static size_t decode_number
+ (
+ const void *number, /* number to decode */
+ unsigned long long *out /* decoded number */
+ )
+ {
+ const unsigned char *n; /* just a 'number' as unsigned char */
+ size_t i; /* temporary index */
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+ i = 0;
+ *out = 0;
+ n = number;
+ do
+ {
+ /* Take 7 bits, and append them to the out */
+ *out |= (n[i] & 0x7f) << (i * 7);
+
+ /* do this until number lacks of continuation bit */
+ }
+ while (n[i++] & 0x80);
+
+ /* return number of bytes processed from 'number' */
+
+ return i;
+ }
+
+**data** can be whatever you want of any size. |el_pbinary| uses
+only timestamp and log level, rest of the options in *el* are simply
+ignores.
+
+|el_pbinary| is filtered based on *level*. Log won't be stored
+unless it matches log level.
+
+Currently you can only output to file or custom routine function. If you
+try to print binary output to different output, it will be ignored.
+
+EXAMPLES
+--------
+Print few binary logs. In this example we print strings, because it's
+easier to show results, but you can use absolutely anything here. Just note
+that there is no processing. If you are on big endian machine, and you
+dump raw integers, when reading back log on little endian machine you
+will have to do endian swap!
+
+.. literalinclude:: /../examples/print-binary.c
+ :language: c
+
+You can then decode this file with ``decode-binary.c`` tool in examples.
+Output will be like this.
+
+.. code-block:: none
+
+ n/0x0000 6e 6f 74 20 73 6f 20 62 69 6e 61 72 79 not so binary
+ w/2024-02-28 19:14:34
+ w/0x0000 74 73 20 69 6e 2c 20 66 72 61 63 74 20 6f 75 74 ts in, fract out
+ f/2024-02-28 19:14:34.696323
+ f/0x0000 77 65 20 61 72 65 20 61 6c 6c 20 69 6e we are all in
+
+RETURN VALUE
+------------
+All functions return 0 when whole message has been successfuly printed
+to all configured outputs. If message couldn't be printed, it was
+printed only partially, or was not send to at least one configured
+output -1 is returned. Note that only one error is returned even if
+there was multiple errors.
+
+ERRORS
+------
+All functions may return one of these on error
+
+EINVAL
+ Any of the input parameters is invalid.
+
+EBADF
+ Loggig to file is enabled and filename was not set with **EL_FPATH**
+ option
+
+EBADF
+ Logging to file is enabled, file was opened sucessfuly, but log
+ cannot be stored into file. This usually happen that file was
+ unlinked from the file system and **embedlog** couldn't create new
+ file again (no access to directory or directory doesn't exist at
+ all). Log is lost, but **embedlog** will try to recreate log file
+ everytime |el_print| is called.
+
+ENODEV
+ All possible outputs are disabled
+
+When logging to file is enabled, all functions may also return errors
+from **fwrite**\ () and if file rotation is enabled also from
+**fopen**\ ()
diff --git a/www/in/el_pmemory.in b/www/in/el_pmemory.in
new file mode 100644
index 0000000..0bde972
--- /dev/null
+++ b/www/in/el_pmemory.in
@@ -0,0 +1,132 @@
+NAME
+-----
+**el_pmemory**, **el_pmemory_table** - dump data in
+wireshark-lik or hexdump format to configured outputs.
+
+SYNOPSIS
+========
+.. code-block:: c
+
+ #include <embedlog.h>
+
+ int el_pmemory(LEVEL, const void *memory, size_t mlen);
+ int el_pmemory_table(LEVEL, const void *memory, size_t mlen);
+
+ int el_opmemory(LEVEL, struct el *el, const void *memory, size_t mlen);
+ int el_opmemory_table(LEVEL, struct el *el, const void *memory, size_t mlen);
+
+DESCRIPTION
+===========
+
+(For information **LEVEL** argument, please refer to |el_print|)
+
+|el_pmemory| is designed to print memory location in a nice
+hex+ascii format. Function accepts pointer to *memory* and *mlen* number
+of bytes caller wants to print. If *mlen* is 0, function won't print
+anything and will return **EINVAL** error. Function doesn't care what is
+under passed address, memory block may contain strings with null
+characters '\0', integers, floats or even **struct** objects.
+
+Example output can look like this. We print all ascii table, to present
+printing of printable and non-printable values.
+
+.. code-block:: none
+
+ 0x0000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f ................
+ 0x0010 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f ................
+ 0x0020 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f !"#$%&'()*+,-./
+ 0x0030 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 0123456789:;<=>?
+ 0x0040 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f @ABCDEFGHIJKLMNO
+ 0x0050 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f PQRSTUVWXYZ[]^_
+ 0x0060 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f `abcdefghijklmno
+ 0x0070 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f pqrstuvwxyz{|}~.
+
+|el_pmemory_table| works just like |el_pmemory| but also
+prints table-like header and footer.
+
+.. code-block:: none
+
+ ------ ----------------------------------------------- ----------------
+ offset hex ascii
+ ------ ----------------------------------------------- ----------------
+ 0x0000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f ................
+ 0x0010 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f ................
+ 0x0020 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f !"#$%&'()*+,-./
+ 0x0030 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 0123456789:;<=>?
+ 0x0040 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f @ABCDEFGHIJKLMNO
+ 0x0050 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f PQRSTUVWXYZ[]^_
+ 0x0060 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f `abcdefghijklmno
+ 0x0070 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f pqrstuvwxyz{|}~.
+ ------ ----------------------------------------------- ----------------
+
+By setting **EL_PMEMORY_SPACE**, you can add padding after first 8 bytes
+printed. This could make log more readable for you. With that value set
+to 1, memory dump will look like this::
+
+ ------ ------------------------------------------------ -----------------
+ offset hex ascii
+ ------ ------------------------------------------------ -----------------
+ 0x0040 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f @ABCDEFG HIJKLMNO
+ 0x0050 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f PQRSTUVW XYZ[]^_
+ ------ ------------------------------------------------ -----------------
+
+This can be set to value up to 3::
+
+ ------ -------------------------------------------------- -------------------
+ offset hex ascii
+ ------ -------------------------------------------------- -------------------
+ 0x0040 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f @ABCDEFG HIJKLMNO
+ 0x0050 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f PQRSTUVW XYZ[]^_
+ ------ -------------------------------------------------- -------------------
+
+Padding applies to both table, and non-table version of memory print.
+
+All standard rules about printing file info, and log filtering are the same
+as with |el_print|.
+
+EXAMPLES
+--------
+
+.. literalinclude:: /../examples/print-memory.c
+ :language: c
+
+RETURN VALUE
+------------
+All functions return 0 when whole message has been successfuly printed
+to all configured outputs. If message couldn't be printed, it was
+printed only partially, or was not send to at least one configured
+output -1 is returned. Note that only one error is returned even if
+there was multiple errors.
+
+ERRORS
+------
+All functions may return one of these on error
+
+EINVAL
+ Any of the input parameters is invalid.
+
+EBADF
+ Loggig to file is enabled and filename was not set with **EL_FPATH**
+ option
+
+EBADF
+ Logging to file is enabled, file was opened sucessfuly, but log
+ cannot be stored into file. This usually happen that file was
+ unlinked from the file system and **embedlog** couldn't create new
+ file again (no access to directory or directory doesn't exist at
+ all). Log is lost, but **embedlog** will try to recreate log file
+ everytime |el_print| is called.
+
+ENODEV
+ All possible outputs are disabled
+
+ERANGE
+ Message will not be logged as message log level is lower than
+ configured one.
+
+ENOBUFS
+ Message is bigger than **EL_LOG_MAX** and will be truncated.
+
+When logging to file is enabled, all functions may also return errors
+from **fwrite** and if file rotation is enabled also from
+**fopen**
diff --git a/www/in/el_prefix.desc b/www/in/el_prefix.desc
new file mode 100644
index 0000000..e5c4b51
--- /dev/null
+++ b/www/in/el_prefix.desc
@@ -0,0 +1,7 @@
+You can configure logger to add *prefix* to every message you print.
+*prefix* will be printed between log level info "i/" and you message.
+No spaces are added. If you set your *prefix* to simple **PREFIX**,
+printed message will be **i/PREFIXmy log message**, so you might want
+to add space there. If *prefix* is bigger than **EL_PREFIX_LEN**
+prefix will be truncated. To disable prefixing, simply set *prefix*
+to **NULL**.
diff --git a/www/in/el_print.in b/www/in/el_print.in
new file mode 100644
index 0000000..513f84e
--- /dev/null
+++ b/www/in/el_print.in
@@ -0,0 +1,187 @@
+NAME
+----
+**el_print**, **el_vprint**, **el_puts**, **el_perror** - prints message
+to previously configured outputs.
+
+SYNOPSIS
+--------
+.. code-block:: c
+
+ #include <embedlog.h>
+
+ int el_puts(const char *string);
+ int el_print(LEVEL, const char *fmt, ...);
+ int el_vprint(LEVEL, const char *fmt, va_list ap);
+ int el_perror(LEVEL, const char *fmt, ...);
+
+ int el_oputs(struct el *el, const char *string);
+ int el_oprint(LEVEL, struct el *el, const char *fmt, ...);
+ int el_ovprint(LEVEL, struct el *el, const char *fmt, va_list ap);
+ int el_operror(LEVEL, struct el *el, const char *fmt, ...);
+
+ #define EL_DEBUG(...) el_print(ELD, __VA_ARGS__)
+
+DESCRIPTION
+-----------
+Functions print log into configured outputs.
+
+**LEVEL** is a macro that expands to:
+
+.. code-block:: c
+
+ __FILE__, __LINE__, __func__, LOG_LEVEL
+
+It's pointless to pass these values each time you wnat to print, so these
+are defined as macros, one for each level
+
+.. code-block:: none
+
+ ELF Fatal errors, usually precedes application crash
+ ELA Alert, vey major error that should be fixed as soon as possible
+ ELC Critical
+ ELE Error
+ ELW Warning
+ ELN Normal log, but of high importance
+ ELI Information message, shouldn't spam too much here
+ ELD Debug messages, can spam as much as you'd like
+
+|el_print| function behaves similar to standard **printf**\ ()
+function from the standard library, but it adds (if enabled) additional
+information, such as *file* name, *line* number or *func* name from
+where log has been printed, log *level*, and timestamp of the message.
+*fmt* and variadic variables *...* have the same role as it is described
+in **printf** manual page.
+
+.. code-block:: c
+
+ el_print(ELI, "Info message");
+ el_print(ELF, "Fatal message with additional argument %d", 42);
+ /* This will print: */
+ /* i/Info message
+ * f/Fatal message with additional argument 42 */
+
+|el_puts| function prints *message* that is simple string.
+*message* is not altered in anyway - that means no automatic log levels,
+location of the log nor timestamp is printed - even if they are enabled.
+Logs printed with this functions are not filtered by log level, and will
+always be printed. Prints can still be suppressed by disabling output.
+
+|el_vprint| function behaves just like |el_print| but it
+accepts argument pointer *ap* instead of variadic variables. Check
+**vprintf** for more information.
+
+|el_perror| works the same way as |el_print| but will also
+print information about current errno that was set. If *fmt* is
+**NULL**, only information about errno will be printed. It is similar to
+**perror** function, but **perror** does not accept format, while
+this function does. It is guaranteed that |el_perror| functions will
+not modify **errno** value.
+
+.. code-block:: c
+
+ errno = ENOENT;
+ el_perror(ELE, "Error writing to %s", some_file);
+ /* This will print: */
+ /* e/Error writing to /some/path
+ * e/errno num: 2, strerror: No such file or directory */
+
+|el_print|, |el_vprint|, |el_perror|, are filtered based on
+their *level*.
+
+All of above functions have their counterpart that also accepts custom
+*el* object. This is useful if we want for example, print logs into one
+file, and program queries into another. It can also be used to print
+every level into different file. It will also be usefull on RTOS with
+flat memory space.
+
+When user defines **EL_OPTIONS_OBJECT** macros with **OEL\*** can be
+used to save yourself the trouble to type ``&opt_obj`` each time. This
+macro should be defined to what normally would be passed to
+**el_oprint** functions familly. It usually is used with **extern**
+keyword like
+
+.. code-block:: c
+
+ /* one time declaration */
+ extern struct el log_foobar;
+ extern struct el log_query;
+ #define EL_OPTIONS_OBJECT &log_foobar
+
+ /* Print using custom log object, note that function is called
+ * el_oprint, not el_print, and LEVEL macro is also prefixed
+ * with an "O", so it's OELN and not ELN */
+ el_oprint(OELN, "Notice message");
+ /* Only one object can be declared to be used with OEL* macros,
+ * if you need to print to multiple loggers, you then need to
+ * manually specify object */
+ el_oprint(ELN, &g_log_query, "Query logged");
+
+If you define **NOFINFO** in your project, ``**__FILE__**,
+**__LINE__**, **EL_FUNC_NAME**`` will be unconditionally set to
+**NULL** and **0** and no file information will be printed - even if it
+was enabled with |el_option|.
+
+If user has access to **c99** compiler, one can use **EL_DEBUG** for
+debuging messages only. Later when application is compiled with NDEBUG,
+all side effects as well as strings used will be stripped out from final
+binary - so no vital information will be leaked in such way. This is not
+possible on **c89** compiller due to absence of variadic variables in
+preprocesor macros.
+
+**EL_FUNC_NAME** will work only on **c99** compilers, where
+``**__func__**`` is defined, on **c89** compilers function name won't be
+printed, and setting **EL_FUNCINFO** won't help it.
+
+EXAMPLES
+--------
+Simple printing using default object
+
+.. literalinclude:: /../examples/print-simple.c
+ :language: c
+
+Same code, but print to custom made embedlog object
+
+.. literalinclude:: /../examples/print-with-object.c
+ :language: c
+
+RETURN VALUE
+------------
+All functions return 0 when whole message has been successfuly printed
+to all configured outputs. If message couldn't be printed, it was
+printed only partially, or was not send to at least one configured
+output -1 is returned. Note that only one error is returned even if
+there was multiple errors.
+
+ERRORS
+------
+All functions may return one of these on error
+
+EINVAL
+ Any of the input parameters is invalid.
+
+EBADF
+ Logging to file is enabled and filename was not set with **EL_FPATH** option
+
+EBADF
+ Logging to file is enabled, file was opened sucessfuly, but log
+ cannot be stored into file. This usually happen that file was
+ unlinked from the file system and **embedlog** couldn't create new
+ file again (no access to directory or directory doesn't exist at
+ all). Log is lost, but **embedlog** will try to recreate log file
+ everytime |el_print| is called.
+
+ENODEV
+ All possible outputs are disabled
+
+|el_print|, |el_vprint|, |el_perror|, may also return:
+
+ERANGE
+ Message will not be logged as message log level is lower than
+ configured one.
+
+ENOBUFS
+ Message is bigger than **EL_LOG_MAX** and will be truncated.
+
+When logging to file is enabled, all functions may also return errors
+from **fwrite** and if file rotation is enabled also from
+**fopen**
diff --git a/www/in/el_print_extra_info.in b/www/in/el_print_extra_info.in
new file mode 100644
index 0000000..a3264b9
--- /dev/null
+++ b/www/in/el_print_extra_info.in
@@ -0,0 +1,43 @@
+NAME
+----
+**el_print_extra_info** - prepends usefull debugging info at beginning
+of log line.
+
+SYNOPSIS
+--------
+.. code-block:: c
+
+ #include <embedlog.h>
+
+ int el_print_extra_info(int print);
+
+ int el_oprint_extra_info(struct el *el, int print);
+
+DESCRIPTION
+-----------
+If set to 1, this will enable **EL_FINFO**, **EL_FUNCINFO** and
+**EL_PRINT_LEVEL**.
+
+.. include:: /in/el_finfo.desc
+
+.. include:: /in/el_funcinfo.desc
+
+.. include:: /in/el_print_level.desc
+
+EXAMPLES
+--------
+.. code-block:: c
+
+ el_print_extra_info(0);
+ el_print(ELI, "some lonely log");
+ /* log output */
+ /* some lonely log */
+
+ el_print_extra_info(1);
+ el_print(ELI, "some happy log");
+ /* log output */
+ /* [source-file.c:73:function()] i/some happy log
+
+RETURN VALUE
+------------
+0 on succes, or -1 and set **errno** on failure.
diff --git a/www/in/el_print_level.desc b/www/in/el_print_level.desc
new file mode 100644
index 0000000..9ed368b
--- /dev/null
+++ b/www/in/el_print_level.desc
@@ -0,0 +1,3 @@
+If EL_PRINT_LEVEL is set each log will have log level information prefix
+in format "l/" where 'l' is first character of level message is
+printed with.
diff --git a/www/in/el_set_custom_put.in b/www/in/el_set_custom_put.in
new file mode 100644
index 0000000..450d7a6
--- /dev/null
+++ b/www/in/el_set_custom_put.in
@@ -0,0 +1,41 @@
+NAME
+----
+**el_set_custom_put** - enables user to implement own printing device
+
+SYNOPSIS
+--------
+.. code-block:: c
+
+ #include <embedlog.h>
+
+ int el_set_custom_put(el_custom_put clbk, void *user);
+
+ int el_oset_custom_put(struct el *el, el_custom_put clbk, void *user);
+
+ typedef int (*el_custom_put)(const char *s, size_t slen, void *user);
+
+DESCRIPTION
+-----------
+.. include:: /in/el_custom_put.desc
+
+EXAMPLES
+--------
+.. code-block:: c
+
+ int custom_logger(const char *s, size_t slen, void *user) {
+ FILE *f = user;
+ /* s will contain string "i/print log" */
+ fwrite(s, slen, 1, f);
+ return 0;
+ }
+
+ FILE *f = fopen(log_file, "w");
+ el_set_custom_put(custom_logger, f);
+ el_print(ELI, "print log");
+
+RETURN VALUE
+------------
+0 on succes, or -1 and set **errno** on failure.
+
+ERRORS
+------
diff --git a/www/in/el_set_file_sync.in b/www/in/el_set_file_sync.in
new file mode 100644
index 0000000..21eef5b
--- /dev/null
+++ b/www/in/el_set_file_sync.in
@@ -0,0 +1,40 @@
+NAME
+----
+**el_set_file_sync** - configures condition on which logs should be
+force synced to disk.
+
+SYNOPSIS
+--------
+.. code-block:: c
+
+ #include <embedlog.h>
+
+ int el_set_file_sync(long sync_every, enum el_level level);
+
+ int el_oset_file_sync(struct el *el, long sync_every, enum el_level level);
+
+DESCRIPTION
+-----------
+This function sets both **EL_FSYNC_EVERY** and **EL_FSYNC_LEVEL** options.
+
+.. include:: /in/el_fsync_every.desc
+
+.. include:: /in/el_fsync_level.desc
+
+EXAMPLES
+--------
+.. code-block:: c
+
+ /* Sync logs once every 1024 bytes were written, or if log severity
+ * is higher than warning */
+ el_set_file_sync(1024, EL_WARN);
+
+ /* Sync all logs, with every print. In this case EL_WARN is useless */
+ el_set_file_sync(0, EL_WARN);
+
+RETURN VALUE
+------------
+0 on succes, or -1 and set **errno** on failure.
+
+ERRORS
+------
diff --git a/www/in/el_set_log_level.in b/www/in/el_set_log_level.in
new file mode 100644
index 0000000..e0ae8ee
--- /dev/null
+++ b/www/in/el_set_log_level.in
@@ -0,0 +1,37 @@
+NAME
+----
+**el_set_log_level** - set new log level
+
+SYNOPSIS
+--------
+
+.. code-block:: c
+
+ #include <embedlog.h>
+
+ int el_set_log_level(enum el_level level);
+
+ int el_oset_log_level(struct el *el, enum el_level level);
+
+DESCRIPTION
+-----------
+.. include:: /in/el_level.desc
+
+EXAMPLES
+--------
+.. code-block:: c
+
+ /* print only alert and fatal logs */
+ el_set_log_level(EL_ALERT);
+ /* print only error, critical, alert and fatal */
+ el_set_log_level(EL_ERROR);
+ /* print all, including debug logs */
+ el_set_log_level(EL_DBG);
+
+RETURN VALUE
+------------
+0 on succes, or -1 and set **errno** on failure.
+
+ERRORS
+------
+.. include:: /in/el_level.err
diff --git a/www/in/el_set_prefix.in b/www/in/el_set_prefix.in
new file mode 100644
index 0000000..a3afe6c
--- /dev/null
+++ b/www/in/el_set_prefix.in
@@ -0,0 +1,36 @@
+NAME
+----
+**el_set_prefix** - set custom prefix to add to every log
+
+SYNOPSIS
+--------
+.. code-block:: c
+
+ #include <embedlog.h>
+
+ int el_set_prefix(const char *prefix)
+
+ int el_oset_prefix(struct el *el, const char *prefix);
+
+DESCRIPTION
+-----------
+.. include:: /in/el_prefix.desc
+
+EXAMPLES
+--------
+.. code-block:: c
+
+ el_set_prefix("my-prefix");
+ el_print(ELI, "some log");
+ /* log output */
+ /* i/my-prefix: some log */
+
+ el_set_prefix(NULL);
+ el_print(ELI, "some log");
+ /* log output */
+ /* i/some log */
+
+
+RETURN VALUE
+------------
+0 on succes, or -1 and set **errno** on failure.
diff --git a/www/in/el_set_timestamp.in b/www/in/el_set_timestamp.in
new file mode 100644
index 0000000..aeea202
--- /dev/null
+++ b/www/in/el_set_timestamp.in
@@ -0,0 +1,67 @@
+NAME
+----
+|el_set_timestamp| - configure timestamp printing for each log
+
+SYNOPSIS
+--------
+.. code-block:: c
+
+ #include <embedlog.h>
+
+ int el_set_timestamp(enum el_option_timestamp timestamp,
+ enum el_option_timestamp_timer timer,
+ enum el_option_timestamp_fractions fraction);
+
+ int el_oset_timestamp(struct el *el, enum el_option_timestamp timestamp
+ enum el_option_timestamp_timer timer,
+ enum el_option_timestamp_fractions fraction);
+
+DESCRIPTION
+-----------
+Function sets **EL_TS**, **EL_TS_TM** and **EL_TS_FRACT** in one go.
+
+.. include:: /in/el_ts.desc
+
+.. include:: /in/el_ts_tm.desc
+
+.. include:: /in/el_ts_fract.desc
+
+EXAMPLES
+--------
+.. code-block:: c
+
+ /* Disable timestamps. This is default behaviour */
+ el_set_timestamp(EL_TS_OFF, 0, 0);
+ el_print(ELI, "no timestamp");
+ /* log output */
+ /* i/no timestamp */
+
+ /* Enable short timestamp without fraction seconds
+ * Measure time from system boot. */
+ el_set_timestamp(EL_TS_SHORT, EL_TS_TM_MONOTONIC, EL_TS_FRACT_OFF);
+ el_print(ELI, "short timestamp");
+ /* log output */
+ /* i/[3234] i/short timestamp */
+
+ /* Enable long timestamp with millisecond precision,
+ * Measure real, clock time */
+ el_set_timestamp(EL_TS_LONG, EL_TS_TM_REALTIME, EL_TS_FRACT_MS);
+ el_print(ELI, "long timestamp with ms");
+ /* log output */
+ /* i/[2024-02-29 10:23:47.361] i/long timestamp with ms */
+
+RETURN VALUE
+------------
+0 on succes, or -1 and set **errno** on failure.
+
+ERRORS
+------
+EINVAL
+ Input argument is invalid
+
+ENOSYS
+ Timestamp support was not compiled in and setting this option
+ is disabled.
+
+ENODEV
+ Specified timer source was not compiled in and is not available
diff --git a/www/in/el_set_tty_dev.in b/www/in/el_set_tty_dev.in
new file mode 100644
index 0000000..38c2e2b
--- /dev/null
+++ b/www/in/el_set_tty_dev.in
@@ -0,0 +1,33 @@
+NAME
+----
+**el_set_tty_dev** - sets and enables output to TTY device (like serial
+console).
+
+SYNOPSIS
+--------
+.. code-block:: c
+
+ #include <embedlog.h>
+
+ int el_set_tty_dev(const char *dev, unsigned speed);
+
+ int el_oset_tty_dev(struct el *el, const char *dev, unsigned speed);
+
+DESCRIPTION
+-----------
+.. include:: /in/el_tty.desc
+
+EXAMPLES
+--------
+.. code-block:: c
+
+ el_set_tty_dev("/dev/ttyS0", B115200);
+ el_print("this goes to /dev/ttyS0");
+
+RETURN VALUE
+------------
+0 on succes, or -1 and set **errno** on failure.
+
+ERRORS
+------
+.. include:: /in/el_tty.err
diff --git a/www/in/el_thread_safe.desc b/www/in/el_thread_safe.desc
new file mode 100644
index 0000000..d67f39a
--- /dev/null
+++ b/www/in/el_thread_safe.desc
@@ -0,0 +1,22 @@
+By default, **embedlog** is not thread safe. While it may be
+relatively safe to use it in multi-thread environment when you are
+logging to **stdio** or **stderr**, this surely isn't the case for
+more complex outputs like printing to file. Also, without
+**EL_THREAD_SAFE** calling **el_pmemory**\ (3) may result in
+interlacing prints.
+
+So, when using embedlog in multi-threaded environment, it is advised
+to enable **EL_THREAD_SAFE** by passing 1 as *safe* argument.
+**embedlog** will then **pthread_mutex_lock**\ () whenever threads
+access *el* object.
+
+**EL_THREAD_SAFE** call must be performed when no other threads are
+accessing *el* object, since at this point it is not possible to lock
+the mutex. Common usage is to enable thread safety at the beggining -
+right after **el_init**\ (3), and leave it to be destroyed by
+**el_cleanup**\ (3).
+
+It is safe to call this option multiple time with same argument.
+**embedlog** will not allow for multiple initialization nor
+destruction of mutex. When options is called for the second time with
+same argument (like 1), nothing will happen and funciton will return 0.
diff --git a/www/in/el_thread_safe.err b/www/in/el_thread_safe.err
new file mode 100644
index 0000000..e0dce57
--- /dev/null
+++ b/www/in/el_thread_safe.err
@@ -0,0 +1,6 @@
+ERRORS
+ Function can return errors from **pthread_mutex_init**\ (), and
+ **pthread_mutex_destroy**\ ().
+
+ EINVAL
+ *safe* is different than 1 or 0
diff --git a/www/in/el_ts.desc b/www/in/el_ts.desc
new file mode 100644
index 0000000..aaa77f2
--- /dev/null
+++ b/www/in/el_ts.desc
@@ -0,0 +1,13 @@
+**EL_TS** allows timestamp to be added to each log message. Possible values for
+*timestamp* are:
+
+EL_TS_OFF
+ Timestamp will not be added to messages
+
+EL_TS_SHORT
+ Short timestamp will be added to log in format
+ **[1503661223.537631]**
+
+EL_TS_LONG
+ Long timestamp will be added to log in format **[2017-08-25
+ 11:40:23.537651]**
diff --git a/www/in/el_ts_fract.desc b/www/in/el_ts_fract.desc
new file mode 100644
index 0000000..5ad4fe4
--- /dev/null
+++ b/www/in/el_ts_fract.desc
@@ -0,0 +1,16 @@
+**EL_TS_FRACT** option controls how to display fractions of seconds. If high
+resolution is not needed or not supported, it's best to set this to
+lowest resolution possible. Table will show exacly what this is
+about. Example uses long timestamp, interesting part is after date
+after dot '.'.
+
+.. code-block:: none
+
+ +-----------------+-------------------------------+
+ | value | resulting timestamp string |
+ +=================+===============================+
+ | EL_TS_FRACT_OFF | 2018-04-17 22:02:57 |
+ | EL_TS_FRACT_MS | 2018-04-17 22:02:57.070 |
+ | EL_TS_FRACT_US | 2018-04-17 22:02:57.070518 |
+ | EL_TS_FRACT_NS | 2018-04-17 22:02:57.070518782 |
+ +-----------------+-------------------------------+
diff --git a/www/in/el_ts_tm.desc b/www/in/el_ts_tm.desc
new file mode 100644
index 0000000..0357c30
--- /dev/null
+++ b/www/in/el_ts_tm.desc
@@ -0,0 +1,32 @@
+**EL_TS_TM** Sets the timer source for the timestamp print.
+
+EL_TS_TM_CLOCK
+ Library will use value from **clock**\ () function. With this
+ clock precission varies from 10^-3[s] to 10^-9[s]. On POSIX
+ systems, this clock has precision of 10^-6[s]. This timer has a
+ lot drawbacks, time value is unspecified at the beggining of the
+ program, timer is not incremented when thread is sleeping, timer
+ will overlap eventually (on 32bit systems with POSIX it takes
+ around 72 minutes for the clock to overlap). On the other hand
+ this is the most precise clock for pure c89 systems without POSIX.
+
+EL_TS_TM_TIME
+ Time is taken from **time**\ () function. This returns current
+ wall clock of the system, it's precision is very low (1[s]), but
+ it's pure c89 and it is good for logging low frequent messages.
+ This clock is susceptible to unexpected time change (from NTP or
+ by root itself).
+
+EL_TS_TM_REALTIME
+ Time is taken from **clock_gettime**\ () using **CLOCK_REALTIME**
+ clock. This required system with POSIX.1-2001. This time returns
+ current system wall clock, but it's precision is much higher than
+ **EL_TS_TM_TIME** clock (depending on system it can vary from
+ 10^-3[s] up to even 10^-9[s]). Just like it is with
+ **EL_TS_TM_TIME** this timestamp can jump forward of backward if
+ it is changed in the system.
+
+EL_TS_TM_MONOTONIC
+ This clock is similar to **EL_TS_TM_REALTIME** but it shows time
+ from unspecified time and is not affected by time change (it can
+ still be altered with **adjtime**\ () or NTP)
diff --git a/www/in/el_tty.desc b/www/in/el_tty.desc
new file mode 100644
index 0000000..bd76e6e
--- /dev/null
+++ b/www/in/el_tty.desc
@@ -0,0 +1,7 @@
+Tells *embedlog* to use *dev* serial device configured to *speed*.
+Serial device will also be configured to transmit in 8 bits of data,
+without parity and one stop bit (8N1). Logger uses only transmit pin
+(TX) and will translate all **LF** into **CR-LF**. If *speed* is
+configured to **B0,** serial port settings will not be altered,
+library will simply open port and will happily work on current serial
+settings.
diff --git a/www/in/el_tty.err b/www/in/el_tty.err
new file mode 100644
index 0000000..c307d8f
--- /dev/null
+++ b/www/in/el_tty.err
@@ -0,0 +1,3 @@
+ERRORS
+ Function can return errors from **open**, **tcgetattr**,
+ **cfsetispeed** and **tcsetattr**.
diff --git a/www/in/ref-list.in b/www/in/ref-list.in
new file mode 100644
index 0000000..b0ca3bb
--- /dev/null
+++ b/www/in/ref-list.in
@@ -0,0 +1,52 @@
+.. |el_cleanup| replace:: :ref:`el_cleanup(3) <manuals/base/el_cleanup.3:el_cleanup>`
+.. |el_destroy| replace:: :ref:`el_destroy(3) <manuals/base/el_destroy.3:el_destroy>`
+.. |el_flush| replace:: :ref:`el_flush(3) <manuals/base/el_flush.3:el_flush>`
+.. |el_init| replace:: :ref:`el_init(3) <manuals/base/el_init.3:el_init>`
+.. |el_new| replace:: :ref:`el_new(3) <manuals/base/el_new.3:el_new>`
+.. |el_ocleanup| replace:: :ref:`el_ocleanup(3) <manuals/el_o/el_ocleanup.3:el_ocleanup>`
+.. |el_odestroy| replace:: :ref:`el_odestroy(3) <manuals/el_o/el_odestroy.3:el_odestroy>`
+.. |el_odisable_output| replace:: :ref:`el_odisable_output(3) <manuals/el_o/el_odisable_output.3:el_odisable_output>`
+.. |el_oenable_colors| replace:: :ref:`el_oenable_colors(3) <manuals/el_o/el_oenable_colors.3:el_oenable_colors>`
+.. |el_oenable_file_log| replace:: :ref:`el_oenable_file_log(3) <manuals/el_o/el_oenable_file_log.3:el_oenable_file_log>`
+.. |el_oenable_output| replace:: :ref:`el_oenable_output(3) <manuals/el_o/el_oenable_output.3:el_oenable_output>`
+.. |el_oenable_thread_safe| replace:: :ref:`el_oenable_thread_safe(3) <manuals/el_o/el_oenable_thread_safe.3:el_oenable_thread_safe>`
+.. |el_oflush| replace:: :ref:`el_oflush(3) <manuals/el_o/el_oflush.3:el_oflush>`
+.. |el_oinit| replace:: :ref:`el_oinit(3) <manuals/el_o/el_oinit.3:el_oinit>`
+.. |el_ooption| replace:: :ref:`el_ooption(3) <manuals/el_o/el_ooption.3:el_ooption>`
+.. |el_opbinary| replace:: :ref:`el_opbinary(3) <manuals/el_o/el_opbinary.3:el_opbinary>`
+.. |el_operror| replace:: :ref:`el_operror(3) <manuals/el_o/el_operror.3:el_operror>`
+.. |el_opmemory| replace:: :ref:`el_opmemory(3) <manuals/el_o/el_opmemory.3:el_opmemory>`
+.. |el_opmemory_table| replace:: :ref:`el_opmemory_table(3) <manuals/el_o/el_opmemory_table.3:el_opmemory_table>`
+.. |el_oprint| replace:: :ref:`el_oprint(3) <manuals/el_o/el_oprint.3:el_oprint>`
+.. |el_oprint_extra_info| replace:: :ref:`el_oprint_extra_info(3) <manuals/el_o/el_oprint_extra_info.3:el_oprint_extra_info>`
+.. |el_oputb| replace:: :ref:`el_oputb(3) <manuals/el_o/el_oputb.3:el_oputb>`
+.. |el_oputs| replace:: :ref:`el_oputs(3) <manuals/el_o/el_oputs.3:el_oputs>`
+.. |el_oset_custom_put| replace:: :ref:`el_oset_custom_put(3) <manuals/el_o/el_oset_custom_put.3:el_oset_custom_put>`
+.. |el_oset_file_sync| replace:: :ref:`el_oset_file_sync(3) <manuals/el_o/el_oset_file_sync.3:el_oset_file_sync>`
+.. |el_oset_log_level| replace:: :ref:`el_oset_log_level(3) <manuals/el_o/el_oset_log_level.3:el_oset_log_level>`
+.. |el_oset_prefix| replace:: :ref:`el_oset_prefix(3) <manuals/el_o/el_oset_prefix.3:el_oset_prefix>`
+.. |el_oset_timestamp| replace:: :ref:`el_oset_timestamp(3) <manuals/el_o/el_oset_timestamp.3:el_oset_timestamp>`
+.. |el_oset_tty_dev| replace:: :ref:`el_oset_tty_dev(3) <manuals/el_o/el_oset_tty_dev.3:el_oset_tty_dev>`
+.. |el_ovprint| replace:: :ref:`el_ovprint(3) <manuals/el_o/el_ovprint.3:el_ovprint>`
+.. |el_disable_output| replace:: :ref:`el_disable_output(3) <manuals/options/el_disable_output.3:el_disable_output>`
+.. |el_enable_colors| replace:: :ref:`el_enable_colors(3) <manuals/options/el_enable_colors.3:el_enable_colors>`
+.. |el_enable_file_log| replace:: :ref:`el_enable_file_log(3) <manuals/options/el_enable_file_log.3:el_enable_file_log>`
+.. |el_enable_output| replace:: :ref:`el_enable_output(3) <manuals/options/el_enable_output.3:el_enable_output>`
+.. |el_enable_thread_safe| replace:: :ref:`el_enable_thread_safe(3) <manuals/options/el_enable_thread_safe.3:el_enable_thread_safe>`
+.. |el_option| replace:: :ref:`el_option(3) <manuals/options/el_option.3:el_option>`
+.. |el_print_extra_info| replace:: :ref:`el_print_extra_info(3) <manuals/options/el_print_extra_info.3:el_print_extra_info>`
+.. |el_set_custom_put| replace:: :ref:`el_set_custom_put(3) <manuals/options/el_set_custom_put.3:el_set_custom_put>`
+.. |el_set_file_sync| replace:: :ref:`el_set_file_sync(3) <manuals/options/el_set_file_sync.3:el_set_file_sync>`
+.. |el_set_log_level| replace:: :ref:`el_set_log_level(3) <manuals/options/el_set_log_level.3:el_set_log_level>`
+.. |el_set_prefix| replace:: :ref:`el_set_prefix(3) <manuals/options/el_set_prefix.3:el_set_prefix>`
+.. |el_set_timestamp| replace:: :ref:`el_set_timestamp(3) <manuals/options/el_set_timestamp.3:el_set_timestamp>`
+.. |el_set_tty_dev| replace:: :ref:`el_set_tty_dev(3) <manuals/options/el_set_tty_dev.3:el_set_tty_dev>`
+.. |el_pbinary| replace:: :ref:`el_pbinary(3) <manuals/print/el_pbinary.3:el_pbinary>`
+.. |el_perror| replace:: :ref:`el_perror(3) <manuals/print/el_perror.3:el_perror>`
+.. |el_pmemory| replace:: :ref:`el_pmemory(3) <manuals/print/el_pmemory.3:el_pmemory>`
+.. |el_pmemory_table| replace:: :ref:`el_pmemory_table(3) <manuals/print/el_pmemory_table.3:el_pmemory_table>`
+.. |el_print| replace:: :ref:`el_print(3) <manuals/print/el_print.3:el_print>`
+.. |el_putb| replace:: :ref:`el_putb(3) <manuals/print/el_putb.3:el_putb>`
+.. |el_puts| replace:: :ref:`el_puts(3) <manuals/print/el_puts.3:el_puts>`
+.. |el_vprint| replace:: :ref:`el_vprint(3) <manuals/print/el_vprint.3:el_vprint>`
+.. |el_overview| replace:: :ref:`el_overview(7) <el_overview.7:overview>`
diff --git a/www/index.in b/www/index.in
deleted file mode 100644
index f738bae..0000000
--- a/www/index.in
+++ /dev/null
@@ -1,7 +0,0 @@
-in_title="embedlog.bofc.pl - c/c++ logger with embedded devices in mind"
-in_description="Logger written in C89 targeting embedded systems. It's main goals are to be small and fast. Many features can be disabled during compilation to generate smaller binary."
-in_keywords="c, embedded, logger, file, rotate, network"
-in_author="Michał Łyszczek"
-in_lang="en"
-in_pygment=vim
-in_style=man
diff --git a/www/index.md b/www/index.md
deleted file mode 120000
index 15926e3..0000000
--- a/www/index.md
+++ /dev/null
@@ -1 +0,0 @@
-../readme.md \ No newline at end of file
diff --git a/www/index.rst b/www/index.rst
new file mode 100644
index 0000000..139e58b
--- /dev/null
+++ b/www/index.rst
@@ -0,0 +1,16 @@
+.. include:: readme.rst
+
+.. toctree::
+ :maxdepth: 3
+ :caption: Contents:
+
+ el_overview.7.rst
+ downloads.rst
+ manuals/index.rst
+
+Indices and tables
+------------------
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
diff --git a/www/manuals/base/el_cleanup.3.rst b/www/manuals/base/el_cleanup.3.rst
new file mode 100644
index 0000000..8289a35
--- /dev/null
+++ b/www/manuals/base/el_cleanup.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+==========
+el_cleanup
+==========
+.. include:: /in/el_cleanup.in
diff --git a/www/manuals/base/el_destroy.3.rst b/www/manuals/base/el_destroy.3.rst
new file mode 100644
index 0000000..1280e6e
--- /dev/null
+++ b/www/manuals/base/el_destroy.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+==========
+el_destroy
+==========
+.. include:: /in/el_cleanup.in
diff --git a/www/manuals/base/el_flush.3.rst b/www/manuals/base/el_flush.3.rst
new file mode 100644
index 0000000..bdc319b
--- /dev/null
+++ b/www/manuals/base/el_flush.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+========
+el_flush
+========
+.. include:: /in/el_flush.in
diff --git a/www/manuals/base/el_init.3.rst b/www/manuals/base/el_init.3.rst
new file mode 100644
index 0000000..db4e9d6
--- /dev/null
+++ b/www/manuals/base/el_init.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+=======
+el_init
+=======
+.. include:: /in/el_init.in
diff --git a/www/manuals/base/el_new.3.rst b/www/manuals/base/el_new.3.rst
new file mode 100644
index 0000000..d15f0ea
--- /dev/null
+++ b/www/manuals/base/el_new.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+======
+el_new
+======
+.. include:: /in/el_init.in
diff --git a/www/manuals/base/index.rst b/www/manuals/base/index.rst
new file mode 100644
index 0000000..6401de1
--- /dev/null
+++ b/www/manuals/base/index.rst
@@ -0,0 +1,12 @@
+base functions
+==============
+
+.. toctree::
+ :maxdepth: 2
+ :caption: Contents:
+
+ el_init.3.rst
+ el_new.3.rst
+ el_cleanup.3.rst
+ el_destroy.3.rst
+ el_flush.3.rst
diff --git a/www/manuals/el_o/el_ocleanup.3.rst b/www/manuals/el_o/el_ocleanup.3.rst
new file mode 100644
index 0000000..04d0081
--- /dev/null
+++ b/www/manuals/el_o/el_ocleanup.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+===========
+el_ocleanup
+===========
+.. include:: /in/el_cleanup.in
diff --git a/www/manuals/el_o/el_odestroy.3.rst b/www/manuals/el_o/el_odestroy.3.rst
new file mode 100644
index 0000000..0086241
--- /dev/null
+++ b/www/manuals/el_o/el_odestroy.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+===========
+el_odestroy
+===========
+.. include:: /in/el_cleanup.in
diff --git a/www/manuals/el_o/el_odisable_output.3.rst b/www/manuals/el_o/el_odisable_output.3.rst
new file mode 100644
index 0000000..fa3b1b2
--- /dev/null
+++ b/www/manuals/el_o/el_odisable_output.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+==================
+el_odisable_output
+==================
+.. include:: /in/el_enable_output.in
diff --git a/www/manuals/el_o/el_oenable_colors.3.rst b/www/manuals/el_o/el_oenable_colors.3.rst
new file mode 100644
index 0000000..6d48723
--- /dev/null
+++ b/www/manuals/el_o/el_oenable_colors.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+=================
+el_oenable_colors
+=================
+.. include:: /in/el_enable_colors.in
diff --git a/www/manuals/el_o/el_oenable_file_log.3.rst b/www/manuals/el_o/el_oenable_file_log.3.rst
new file mode 100644
index 0000000..45ad9cc
--- /dev/null
+++ b/www/manuals/el_o/el_oenable_file_log.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+===================
+el_oenable_file_log
+===================
+.. include:: /in/el_enable_file_log.in
diff --git a/www/manuals/el_o/el_oenable_output.3.rst b/www/manuals/el_o/el_oenable_output.3.rst
new file mode 100644
index 0000000..54801a5
--- /dev/null
+++ b/www/manuals/el_o/el_oenable_output.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+=================
+el_oenable_output
+=================
+.. include:: /in/el_enable_output.in
diff --git a/www/manuals/el_o/el_oenable_thread_safe.3.rst b/www/manuals/el_o/el_oenable_thread_safe.3.rst
new file mode 100644
index 0000000..547c66f
--- /dev/null
+++ b/www/manuals/el_o/el_oenable_thread_safe.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+======================
+el_oenable_thread_safe
+======================
+.. include:: /in/el_enable_thread_safe.in
diff --git a/www/manuals/el_o/el_oflush.3.rst b/www/manuals/el_o/el_oflush.3.rst
new file mode 100644
index 0000000..8e0a9f4
--- /dev/null
+++ b/www/manuals/el_o/el_oflush.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+=========
+el_oflush
+=========
+.. include:: /in/el_flush.in
diff --git a/www/manuals/el_o/el_oinit.3.rst b/www/manuals/el_o/el_oinit.3.rst
new file mode 100644
index 0000000..223e197
--- /dev/null
+++ b/www/manuals/el_o/el_oinit.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+========
+el_oinit
+========
+.. include:: /in/el_init.in
diff --git a/www/manuals/el_o/el_ooption.3.rst b/www/manuals/el_o/el_ooption.3.rst
new file mode 100644
index 0000000..9ea97e4
--- /dev/null
+++ b/www/manuals/el_o/el_ooption.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+==========
+el_ooption
+==========
+.. include:: /in/el_option.in
diff --git a/www/manuals/el_o/el_opbinary.3.rst b/www/manuals/el_o/el_opbinary.3.rst
new file mode 100644
index 0000000..fbef3fa
--- /dev/null
+++ b/www/manuals/el_o/el_opbinary.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+===========
+el_opbinary
+===========
+.. include:: /in/el_pbinary.in
diff --git a/www/manuals/el_o/el_operror.3.rst b/www/manuals/el_o/el_operror.3.rst
new file mode 100644
index 0000000..5e6c7ba
--- /dev/null
+++ b/www/manuals/el_o/el_operror.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+==========
+el_operror
+==========
+.. include:: /in/el_print.in
diff --git a/www/manuals/el_o/el_opmemory.3.rst b/www/manuals/el_o/el_opmemory.3.rst
new file mode 100644
index 0000000..774321b
--- /dev/null
+++ b/www/manuals/el_o/el_opmemory.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+===========
+el_opmemory
+===========
+.. include:: /in/el_pmemory.in
diff --git a/www/manuals/el_o/el_opmemory_table.3.rst b/www/manuals/el_o/el_opmemory_table.3.rst
new file mode 100644
index 0000000..4aa106a
--- /dev/null
+++ b/www/manuals/el_o/el_opmemory_table.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+=================
+el_opmemory_table
+=================
+.. include:: /in/el_pmemory.in
diff --git a/www/manuals/el_o/el_oprint.3.rst b/www/manuals/el_o/el_oprint.3.rst
new file mode 100644
index 0000000..633d0fb
--- /dev/null
+++ b/www/manuals/el_o/el_oprint.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+=========
+el_oprint
+=========
+.. include:: /in/el_print.in
diff --git a/www/manuals/el_o/el_oprint_extra_info.3.rst b/www/manuals/el_o/el_oprint_extra_info.3.rst
new file mode 100644
index 0000000..d9c0591
--- /dev/null
+++ b/www/manuals/el_o/el_oprint_extra_info.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+====================
+el_oprint_extra_info
+====================
+.. include:: /in/el_print_extra_info.in
diff --git a/www/manuals/el_o/el_oputb.3.rst b/www/manuals/el_o/el_oputb.3.rst
new file mode 100644
index 0000000..5192ee4
--- /dev/null
+++ b/www/manuals/el_o/el_oputb.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+========
+el_oputb
+========
+.. include:: /in/el_pbinary.in
diff --git a/www/manuals/el_o/el_oputs.3.rst b/www/manuals/el_o/el_oputs.3.rst
new file mode 100644
index 0000000..ef5f36e
--- /dev/null
+++ b/www/manuals/el_o/el_oputs.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+========
+el_oputs
+========
+.. include:: /in/el_print.in
diff --git a/www/manuals/el_o/el_oset_custom_put.3.rst b/www/manuals/el_o/el_oset_custom_put.3.rst
new file mode 100644
index 0000000..82daf72
--- /dev/null
+++ b/www/manuals/el_o/el_oset_custom_put.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+==================
+el_oset_custom_put
+==================
+.. include:: /in/el_set_custom_put.in
diff --git a/www/manuals/el_o/el_oset_file_sync.3.rst b/www/manuals/el_o/el_oset_file_sync.3.rst
new file mode 100644
index 0000000..4d35292
--- /dev/null
+++ b/www/manuals/el_o/el_oset_file_sync.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+=================
+el_oset_file_sync
+=================
+.. include:: /in/el_set_file_sync.in
diff --git a/www/manuals/el_o/el_oset_log_level.3.rst b/www/manuals/el_o/el_oset_log_level.3.rst
new file mode 100644
index 0000000..9cc2cde
--- /dev/null
+++ b/www/manuals/el_o/el_oset_log_level.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+=================
+el_oset_log_level
+=================
+.. include:: /in/el_set_log_level.in
diff --git a/www/manuals/el_o/el_oset_prefix.3.rst b/www/manuals/el_o/el_oset_prefix.3.rst
new file mode 100644
index 0000000..f0c5a30
--- /dev/null
+++ b/www/manuals/el_o/el_oset_prefix.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+==============
+el_oset_prefix
+==============
+.. include:: /in/el_set_prefix.in
diff --git a/www/manuals/el_o/el_oset_timestamp.3.rst b/www/manuals/el_o/el_oset_timestamp.3.rst
new file mode 100644
index 0000000..b315a79
--- /dev/null
+++ b/www/manuals/el_o/el_oset_timestamp.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+=================
+el_oset_timestamp
+=================
+.. include:: /in/el_set_timestamp.in
diff --git a/www/manuals/el_o/el_oset_tty_dev.3.rst b/www/manuals/el_o/el_oset_tty_dev.3.rst
new file mode 100644
index 0000000..5d25628
--- /dev/null
+++ b/www/manuals/el_o/el_oset_tty_dev.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+===============
+el_oset_tty_dev
+===============
+.. include:: /in/el_set_tty_dev.in
diff --git a/www/manuals/el_o/el_ovprint.3.rst b/www/manuals/el_o/el_ovprint.3.rst
new file mode 100644
index 0000000..232a7b2
--- /dev/null
+++ b/www/manuals/el_o/el_ovprint.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+==========
+el_ovprint
+==========
+.. include:: /in/el_print.in
diff --git a/www/manuals/el_o/index.rst b/www/manuals/el_o/index.rst
new file mode 100644
index 0000000..3acbc19
--- /dev/null
+++ b/www/manuals/el_o/index.rst
@@ -0,0 +1,37 @@
+===================
+el object functions
+===================
+
+List of functions that accept additional **el** object (el_o prefixed).
+These are the same documentation files as used for functions that do not
+take **el** object. They are here for reference and links to work.
+
+.. toctree::
+ :maxdepth: 2
+ :caption: Contents:
+
+ el_ocleanup.3.rst
+ el_odestroy.3.rst
+ el_odisable_output.3.rst
+ el_oenable_colors.3.rst
+ el_oenable_file_log.3.rst
+ el_oenable_output.3.rst
+ el_oenable_thread_safe.3.rst
+ el_oflush.3.rst
+ el_oinit.3.rst
+ el_ooption.3.rst
+ el_opbinary.3.rst
+ el_operror.3.rst
+ el_opmemory.3.rst
+ el_opmemory_table.3.rst
+ el_oprint.3.rst
+ el_oprint_extra_info.3.rst
+ el_oputb.3.rst
+ el_oputs.3.rst
+ el_oset_custom_put.3.rst
+ el_oset_file_sync.3.rst
+ el_oset_log_level.3.rst
+ el_oset_prefix.3.rst
+ el_oset_timestamp.3.rst
+ el_oset_tty_dev.3.rst
+ el_ovprint.3.rst
diff --git a/www/manuals/index.rst b/www/manuals/index.rst
new file mode 100644
index 0000000..bb83dab
--- /dev/null
+++ b/www/manuals/index.rst
@@ -0,0 +1,14 @@
+============
+manual pages
+============
+
+This sections contains manual pages for all embedlog functions
+
+.. toctree::
+ :maxdepth: 2
+ :caption: Contents:
+
+ base/index.rst
+ print/index.rst
+ options/index.rst
+ el_o/index.rst
diff --git a/www/manuals/options/el_disable_output.3.rst b/www/manuals/options/el_disable_output.3.rst
new file mode 100644
index 0000000..cf065de
--- /dev/null
+++ b/www/manuals/options/el_disable_output.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+=================
+el_disable_output
+=================
+.. include:: /in/el_enable_output.in
diff --git a/www/manuals/options/el_enable_colors.3.rst b/www/manuals/options/el_enable_colors.3.rst
new file mode 100644
index 0000000..89b61fb
--- /dev/null
+++ b/www/manuals/options/el_enable_colors.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+================
+el_enable_colors
+================
+.. include:: /in/el_enable_colors.in
diff --git a/www/manuals/options/el_enable_file_log.3.rst b/www/manuals/options/el_enable_file_log.3.rst
new file mode 100644
index 0000000..b39c711
--- /dev/null
+++ b/www/manuals/options/el_enable_file_log.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+==================
+el_enable_file_log
+==================
+.. include:: /in/el_enable_file_log.in
diff --git a/www/manuals/options/el_enable_output.3.rst b/www/manuals/options/el_enable_output.3.rst
new file mode 100644
index 0000000..35bc782
--- /dev/null
+++ b/www/manuals/options/el_enable_output.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+================
+el_enable_output
+================
+.. include:: /in/el_enable_output.in
diff --git a/www/manuals/options/el_enable_thread_safe.3.rst b/www/manuals/options/el_enable_thread_safe.3.rst
new file mode 100644
index 0000000..6361156
--- /dev/null
+++ b/www/manuals/options/el_enable_thread_safe.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+=====================
+el_enable_thread_safe
+=====================
+.. include:: /in/el_enable_thread_safe.in
diff --git a/www/manuals/options/el_option.3.rst b/www/manuals/options/el_option.3.rst
new file mode 100644
index 0000000..6f946d7
--- /dev/null
+++ b/www/manuals/options/el_option.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+=========
+el_option
+=========
+.. include:: /in/el_option.in
diff --git a/www/manuals/options/el_print_extra_info.3.rst b/www/manuals/options/el_print_extra_info.3.rst
new file mode 100644
index 0000000..c52ceaa
--- /dev/null
+++ b/www/manuals/options/el_print_extra_info.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+===================
+el_print_extra_info
+===================
+.. include:: /in/el_print_extra_info.in
diff --git a/www/manuals/options/el_set_custom_put.3.rst b/www/manuals/options/el_set_custom_put.3.rst
new file mode 100644
index 0000000..8d61574
--- /dev/null
+++ b/www/manuals/options/el_set_custom_put.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+=================
+el_set_custom_put
+=================
+.. include:: /in/el_set_custom_put.in
diff --git a/www/manuals/options/el_set_file_sync.3.rst b/www/manuals/options/el_set_file_sync.3.rst
new file mode 100644
index 0000000..b60304c
--- /dev/null
+++ b/www/manuals/options/el_set_file_sync.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+================
+el_set_file_sync
+================
+.. include:: /in/el_set_file_sync.in
diff --git a/www/manuals/options/el_set_log_level.3.rst b/www/manuals/options/el_set_log_level.3.rst
new file mode 100644
index 0000000..f371543
--- /dev/null
+++ b/www/manuals/options/el_set_log_level.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+================
+el_set_log_level
+================
+.. include:: /in/el_set_log_level.in
diff --git a/www/manuals/options/el_set_prefix.3.rst b/www/manuals/options/el_set_prefix.3.rst
new file mode 100644
index 0000000..65af2ff
--- /dev/null
+++ b/www/manuals/options/el_set_prefix.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+=============
+el_set_prefix
+=============
+.. include:: /in/el_set_prefix.in
diff --git a/www/manuals/options/el_set_timestamp.3.rst b/www/manuals/options/el_set_timestamp.3.rst
new file mode 100644
index 0000000..1cebec9
--- /dev/null
+++ b/www/manuals/options/el_set_timestamp.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+================
+el_set_timestamp
+================
+.. include:: /in/el_set_timestamp.in
diff --git a/www/manuals/options/el_set_tty_dev.3.rst b/www/manuals/options/el_set_tty_dev.3.rst
new file mode 100644
index 0000000..ff693b5
--- /dev/null
+++ b/www/manuals/options/el_set_tty_dev.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+==============
+el_set_tty_dev
+==============
+.. include:: /in/el_set_tty_dev.in
diff --git a/www/manuals/options/index.rst b/www/manuals/options/index.rst
new file mode 100644
index 0000000..afed8cd
--- /dev/null
+++ b/www/manuals/options/index.rst
@@ -0,0 +1,23 @@
+=================
+options functions
+=================
+
+These functions can be used to alter **embedlog** behaviour.
+
+.. toctree::
+ :maxdepth: 2
+ :caption: Contents:
+
+ el_enable_output.3.rst
+ el_enable_file_log.3.rst
+ el_set_timestamp.3.rst
+ el_print_extra_info.3.rst
+ el_set_file_sync.3.rst
+ el_enable_colors.3.rst
+ el_set_log_level.3.rst
+ el_set_prefix.3.rst
+ el_set_custom_put.3.rst
+ el_enable_thread_safe.3.rst
+ el_set_tty_dev.3.rst
+ el_disable_output.3.rst
+ el_option.3.rst
diff --git a/www/manuals/print/el_pbinary.3.rst b/www/manuals/print/el_pbinary.3.rst
new file mode 100644
index 0000000..5f446be
--- /dev/null
+++ b/www/manuals/print/el_pbinary.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+==========
+el_pbinary
+==========
+.. include:: /in/el_pbinary.in
diff --git a/www/manuals/print/el_perror.3.rst b/www/manuals/print/el_perror.3.rst
new file mode 100644
index 0000000..d53f80c
--- /dev/null
+++ b/www/manuals/print/el_perror.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+=========
+el_perror
+=========
+.. include:: /in/el_print.in
diff --git a/www/manuals/print/el_pmemory.3.rst b/www/manuals/print/el_pmemory.3.rst
new file mode 100644
index 0000000..d1c86b1
--- /dev/null
+++ b/www/manuals/print/el_pmemory.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+==========
+el_pmemory
+==========
+.. include:: /in/el_pmemory.in
diff --git a/www/manuals/print/el_pmemory_table.3.rst b/www/manuals/print/el_pmemory_table.3.rst
new file mode 100644
index 0000000..50ad662
--- /dev/null
+++ b/www/manuals/print/el_pmemory_table.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+================
+el_pmemory_table
+================
+.. include:: /in/el_pmemory.in
diff --git a/www/manuals/print/el_print.3.rst b/www/manuals/print/el_print.3.rst
new file mode 100644
index 0000000..99b85ad
--- /dev/null
+++ b/www/manuals/print/el_print.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+========
+el_print
+========
+.. include:: /in/el_print.in
diff --git a/www/manuals/print/el_putb.3.rst b/www/manuals/print/el_putb.3.rst
new file mode 100644
index 0000000..97f2912
--- /dev/null
+++ b/www/manuals/print/el_putb.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+=======
+el_putb
+=======
+.. include:: /in/el_pbinary.in
diff --git a/www/manuals/print/el_puts.3.rst b/www/manuals/print/el_puts.3.rst
new file mode 100644
index 0000000..d35e0ae
--- /dev/null
+++ b/www/manuals/print/el_puts.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+=======
+el_puts
+=======
+.. include:: /in/el_print.in
diff --git a/www/manuals/print/el_vprint.3.rst b/www/manuals/print/el_vprint.3.rst
new file mode 100644
index 0000000..c1b08dd
--- /dev/null
+++ b/www/manuals/print/el_vprint.3.rst
@@ -0,0 +1,6 @@
+.. include:: /in/ref-list.in
+
+=========
+el_vprint
+=========
+.. include:: /in/el_print.in
diff --git a/www/manuals/print/index.rst b/www/manuals/print/index.rst
new file mode 100644
index 0000000..e4223e5
--- /dev/null
+++ b/www/manuals/print/index.rst
@@ -0,0 +1,18 @@
+===============
+print functions
+===============
+
+Function used to log different data.
+
+.. toctree::
+ :maxdepth: 2
+ :caption: Contents:
+
+ el_print.3.rst
+ el_perror.3.rst
+ el_pmemory.3.rst
+ el_vprint.3.rst
+ el_pbinary.3.rst
+ el_pmemory_table.3.rst
+ el_puts.3.rst
+ el_putb.3.rst
diff --git a/www/post-process.sh b/www/post-process.sh
deleted file mode 100755
index ff643d6..0000000
--- a/www/post-process.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/sh
-
-# add single new line before about in index.html
-sed -i 's/<h1 id="about">/<h1 id="about" class="first">/' "out/index.html"
diff --git a/www/readme.rst b/www/readme.rst
new file mode 120000
index 0000000..1a5cade
--- /dev/null
+++ b/www/readme.rst
@@ -0,0 +1 @@
+../readme.rst \ No newline at end of file
diff --git a/www/static/custom.css b/www/static/custom.css
new file mode 100644
index 0000000..a73ef58
--- /dev/null
+++ b/www/static/custom.css
@@ -0,0 +1,10 @@
+* {
+ tab-size: 4;
+}
+
+a.reference:link, a.reference:visited {
+ font-weight: bold;
+ font-decoration: none;
+ color: black;
+ font-family: "JetBrains Mono"
+}