aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/rin/diagnostic.h2
-rw-r--r--src/diagnostic/diagnostic.c158
-rw-r--r--src/diagnostic/diagnostic_private.h3
-rw-r--r--test/diagnostic.c54
-rw-r--r--test/meson.build4
5 files changed, 146 insertions, 75 deletions
diff --git a/include/rin/diagnostic.h b/include/rin/diagnostic.h
index ccec0b8..6fe9c3b 100644
--- a/include/rin/diagnostic.h
+++ b/include/rin/diagnostic.h
@@ -43,7 +43,7 @@ enum rin_diag_outstream {
};
void rin_diag_init(void);
-int rin_diag_flags(int flag, int action);
+int rin_diag_format(enum rin_diag_outstream, const char *format);
int rin_diag_set_outstream(enum rin_diag_outstream channel, FILE *stream);
void __rin_err(const char *func_name, const char *format, ...) FORMAT_STRING(2, 3);
diff --git a/src/diagnostic/diagnostic.c b/src/diagnostic/diagnostic.c
index 1258711..a5d7149 100644
--- a/src/diagnostic/diagnostic.c
+++ b/src/diagnostic/diagnostic.c
@@ -20,41 +20,109 @@
#include "diagnostic_private.h"
+#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "rin/diagnostic.h"
#include "rin/time.h"
#include "rin/definitions.h"
+static const char default_format[] = "C:F:mn";
+static const char valid_format[] = "CFtTn:m";
+
static struct iostate {
+ char pidconv[8];
struct timespec start;
FILE *err;
FILE *warn;
FILE *fixme;
FILE *info;
- unsigned int flags;
- char pidconv[8];
-} state = {{0, 0}, NULL, NULL, NULL, NULL, RIN_DIAG_PREFIX, "%08x:"};
+ char *err_format;
+ char *warn_format;
+ char *fixme_format;
+ char *info_format;
+} state = {"%08x:", {0, 0}, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
+
+void rin_diag_cleanup(void)
+{
+ char *tmp;
+
+ tmp = state.err_format;
+ state.err_format = NULL;
+ free(tmp);
+
+ tmp = state.warn_format;
+ state.warn_format = NULL;
+ free(tmp);
+
+ tmp = state.fixme_format;
+ state.fixme_format = NULL;
+ free(tmp);
+
+ tmp = state.info_format;
+ state.info_format = NULL;
+ free(tmp);
+}
void rin_diag_init(void)
{
static const char convstr[8] = "%04hx:";
+ clock_gettime(RIN_CLOCK_WALL_COUNTER, &state.start);
+
if (sizeof(pid_t) == 4) {
memcpy(state.pidconv, convstr, sizeof(convstr));
}
- clock_gettime(RIN_CLOCK_WALL_COUNTER, &state.start);
+ atexit(rin_diag_cleanup);
}
-int rin_diag_flags(int flag, int action)
+int rin_diag_format(enum rin_diag_outstream channel, const char *format)
{
- /* checking for non-existent flags */
- if (flag & ~(RIN_DIAG_ALLFLAGS)) {
- return EINVAL;
+ char *tmp;
+ size_t i, j;
+
+ if (!format) {
+ tmp = NULL;
+ } else {
+ for (i = 0; format[i]; ++i) {
+ int valid = 0;
+
+ for (j = 0; valid_format[j]; ++j) {
+ if (valid_format[j] == format [i]) {
+ valid = 1;
+ break;
+ }
+ }
+
+ if (!valid) {
+ return EINVAL;
+ }
+ }
+
+ tmp = strdup(format);
}
- state.flags = action ? (state.flags | flag) : (state.flags & ~(flag));
+ switch (channel) {
+ case rin_diag_err:
+ free(state.err_format);
+ state.err_format = tmp;
+ break;
+ case rin_diag_warn:
+ free(state.warn_format);
+ state.warn_format = tmp;
+ break;
+ case rin_diag_fixme:
+ free(state.fixme_format);
+ state.fixme_format = tmp;
+ break;
+ case rin_diag_info:
+ free(state.info_format);
+ state.info_format = tmp;
+ break;
+ default:
+ return EINVAL;
+ }
return 0;
}
@@ -86,7 +154,9 @@ void __rin_err(const char *func_name, const char *format, ...)
va_list args;
va_start(args, format);
- __rin_msg(state.err ? state.err : stderr, "error", func_name, format, args);
+ __rin_msg(state.err ? state.err : stderr, "error", func_name,
+ state.err_format ? state.err_format : default_format,
+ format, args);
}
void __rin_warn(const char *func_name, const char *format, ...)
@@ -94,7 +164,9 @@ void __rin_warn(const char *func_name, const char *format, ...)
va_list args;
va_start(args, format);
- __rin_msg(state.warn ? state.warn : stderr, "warning", func_name, format, args);
+ __rin_msg(state.warn ? state.warn : stderr, "warning", func_name,
+ state.warn_format ? state.warn_format : default_format,
+ format, args);
}
void __rin_fixme(const char *func_name, const char *format, ...)
@@ -102,7 +174,9 @@ void __rin_fixme(const char *func_name, const char *format, ...)
va_list args;
va_start(args, format);
- __rin_msg(state.fixme ? state.fixme : stderr, "fixme", func_name, format, args);
+ __rin_msg(state.fixme ? state.fixme : stderr, "fixme", func_name,
+ state.fixme_format ? state.fixme_format : default_format,
+ format, args);
}
void __rin_info(const char *func_name, const char *format, ...)
@@ -110,30 +184,46 @@ void __rin_info(const char *func_name, const char *format, ...)
va_list args;
va_start(args, format);
- __rin_msg(state.info ? state.info : stdout, "info", func_name, format, args);
+ __rin_msg(state.info ? state.info : stdout, "info", func_name,
+ state.info_format ? state.info_format : default_format,
+ format, args);
}
-static void __rin_msg(FILE *stream, const char *prefix, const char *func_name, const char *format, va_list args)
+static void __rin_msg(FILE *stream, const char *prefix, const char *func_name, const char *rin_format, const char *format, va_list args)
{
- if (state.flags & RIN_DIAG_PREFIX) {
- fprintf(stream, "%s:", prefix);
- }
-
- if (state.flags & RIN_DIAG_THREADNUM) {
- fprintf(stream, state.pidconv, gettid());
- }
-
- if (state.flags & RIN_DIAG_FUNC) {
- fprintf(stream, "%s:", func_name);
- }
-
- if (state.flags & RIN_DIAG_TIME) {
- struct timespec t;
- clock_gettime(RIN_CLOCK_WALL_COUNTER, &t);
- t = rin_time_sub(&t, &state.start);
- fprintf(stream, "%lu.%lu:", t.tv_sec, t.tv_nsec);
+ struct timespec t;
+ size_t i;
+ int gottime = 0;
+
+ for (i = 0; rin_format[i]; ++i) {
+ switch (rin_format[i]) {
+ case 'C':
+ fprintf(stream, "%s", prefix);
+ break;
+ case 'F':
+ fprintf(stream, "%s", func_name);
+ break;
+ case 't':
+ fprintf(stream, state.pidconv, gettid());
+ break;
+ case 'T':
+ if (!gottime) {
+ clock_gettime(RIN_CLOCK_WALL_COUNTER, &t);
+ t = rin_time_sub(&t, &state.start);
+ gottime = 1;
+ }
+
+ fprintf(stream, "%lus%06lu.%03luµs", t.tv_sec, t.tv_nsec / 1000, t.tv_nsec % 1000);
+ break;
+ case 'n':
+ fprintf(stream, "\n");
+ break;
+ case ':':
+ fprintf(stream, ":");
+ break;
+ case 'm':
+ vfprintf(stream, format, args);
+ break;
+ }
}
-
- vfprintf(stream, format, args);
- fputc('\n', stream);
}
diff --git a/src/diagnostic/diagnostic_private.h b/src/diagnostic/diagnostic_private.h
index 4f0033f..04778b5 100644
--- a/src/diagnostic/diagnostic_private.h
+++ b/src/diagnostic/diagnostic_private.h
@@ -28,6 +28,7 @@
#define RIN_NEED_GETTID
#include "rin/compat.h"
-static void __rin_msg(FILE *stream, const char *prefix, const char *func_name, const char *format, va_list args);
+static void __rin_msg(FILE *stream, const char *prefix, const char *func_name, const char *rin_format, const char *format, va_list args);
+static void rin_diag_cleanup(void);
#endif /* LIBRIN_DIAGNOSTIC_PRIVATE_INCLUDED */
diff --git a/test/diagnostic.c b/test/diagnostic.c
index 35866df..363743b 100644
--- a/test/diagnostic.c
+++ b/test/diagnostic.c
@@ -36,13 +36,11 @@ static int err_test(void);
static int warn_test(void);
static int fixme_test(void);
static int info_test(void);
-static int prefix_test(void);
-static int thread_test(void);
-static int clean_test(void);
+static int format_test(void);
static struct stdiocap capture_stdio_start(FILE *stream);
static void capture_stdio_stop(struct stdiocap *cap);
static char *visible_newlines(const char * const in);
-static int test_default_channels(const char * const in, const char * const expected, size_t i, int usearg, void (*func)(const char *, const char *, ...));
+static int test_default_channels(const char * const in, const char * const expected, size_t i, int usearg, const char *func_name, void (*func)(const char *, const char *, ...));
int diagnostic_test(char *testname)
{
@@ -51,9 +49,7 @@ int diagnostic_test(char *testname)
{"warn", warn_test},
{"fixme", fixme_test},
{"info", info_test},
- {"prefix", prefix_test},
- {"thread", thread_test},
- {"clean", clean_test} };
+ {"format", format_test}};
size_t i;
for (i = 0; i < arrlen(tests); ++i) {
@@ -72,11 +68,11 @@ static int err_test(void)
int ret;
static const char *in[] = {"", "test", "test number is %zu", "%zu tests ran"};
- static const char *expected[] = {"error:\n", "error:test\n", "error:test number is 3\n", "error:4 tests ran\n"};
+ static const char *expected[] = {"error:err_test:\n", "error:err_test:test\n", "error:err_test:test number is 3\n", "error:err_test:4 tests ran\n"};
for (i = 0; i < arrlen(in); ++i) {
usearg = i < (arrlen(in) / 2) ? 0 : 1;
- ret = test_default_channels(in[i], expected[i], i, usearg, __rin_err);
+ ret = test_default_channels(in[i], expected[i], i, usearg, __func__, __rin_err);
}
return ret;
@@ -89,11 +85,11 @@ static int warn_test(void)
int ret;
static const char *in[] = {"", "test", "test number is %zu", "%zu tests ran"};
- static const char *expected[] = {"warning:\n", "warning:test\n", "warning:test number is 3\n", "warning:4 tests ran\n"};
+ static const char *expected[] = {"warning:warn_test:\n", "warning:warn_test:test\n", "warning:warn_test:test number is 3\n", "warning:warn_test:4 tests ran\n"};
for (i = 0; i < arrlen(in); ++i) {
usearg = i < (arrlen(in) / 2) ? 0 : 1;
- ret = test_default_channels(in[i], expected[i], i, usearg, __rin_warn);
+ ret = test_default_channels(in[i], expected[i], i, usearg, __func__, __rin_warn);
}
return ret;
@@ -106,11 +102,11 @@ static int fixme_test(void)
int ret;
static const char *in[] = {"", "test", "test number is %zu", "%zu tests ran"};
- static const char *expected[] = {"fixme:\n", "fixme:test\n", "fixme:test number is 3\n", "fixme:4 tests ran\n"};
+ static const char *expected[] = {"fixme:fixme_test:\n", "fixme:fixme_test:test\n", "fixme:fixme_test:test number is 3\n", "fixme:fixme_test:4 tests ran\n"};
for (i = 0; i < arrlen(in); ++i) {
usearg = i < (arrlen(in) / 2) ? 0 : 1;
- ret = test_default_channels(in[i], expected[i], i, usearg, __rin_fixme);
+ ret = test_default_channels(in[i], expected[i], i, usearg, __func__, __rin_fixme);
}
return ret;
@@ -123,14 +119,14 @@ static int info_test(void)
int ret;
static const char *in[] = {"", "test", "test number is %zu", "%zu tests ran"};
- static const char *expected[] = {"info:\n", "info:test\n", "info:test number is 3\n", "info:4 tests ran\n"};
+ static const char *expected[] = {"info:info_test:\n", "info:info_test:test\n", "info:info_test:test number is 3\n", "info:info_test:4 tests ran\n"};
/* `ninja test` seems to be intercepting stdout, so we cannot test the default outstream */
rin_diag_set_outstream(rin_diag_info, stderr);
for (i = 0; i < arrlen(in); ++i) {
usearg = i < (arrlen(in) / 2) ? 0 : 1;
- ret = test_default_channels(in[i], expected[i], i, usearg, __rin_info);
+ ret = test_default_channels(in[i], expected[i], i, usearg, __func__, __rin_info);
}
/* restore the default, kind of */
@@ -139,17 +135,7 @@ static int info_test(void)
return ret;
}
-static int prefix_test(void)
-{
- return 77;
-}
-
-static int thread_test(void)
-{
- return 77;
-}
-
-static int clean_test(void)
+static int format_test(void)
{
return 77;
}
@@ -221,16 +207,12 @@ static char *visible_newlines(const char * const in)
return ret;
}
-static int test_default_channels(const char * const in, const char * const expected, size_t i, int usearg, void (*func)(const char *, const char *, ...))
+static int test_default_channels(const char * const in, const char * const expected, size_t i, int usearg, const char *func_name, void (*func)(const char *, const char *, ...))
{
- char buf[32] = {0};
+ char buf[64] = {0};
struct stdiocap cap;
- size_t len;
int ret = 0;
- len = strlen(expected);
- ++len;
-
cap = capture_stdio_start(stderr);
if (!cap.pipe) {
@@ -239,12 +221,12 @@ static int test_default_channels(const char * const in, const char * const expec
}
if (usearg) {
- func(NULL, in, i + 1);
+ func(func_name, in, i + 1);
} else {
- func(NULL, in);
+ func(func_name, in);
}
- if (!(fgets(buf, sizeof(buf) < len ? sizeof(buf) : len, cap.pipe))) {
+ if (!(fgets(buf, sizeof(buf), cap.pipe))) {
ret = 1;
goto fail;
}
@@ -257,7 +239,7 @@ fail:
} else {
char *tmp[2];
- ret = strncmp(buf, expected, sizeof(buf) < len ? sizeof(buf) : len);
+ ret = strncmp(buf, expected, sizeof(buf));
tmp[0] = visible_newlines(buf);
tmp[1] = visible_newlines(expected);
diff --git a/test/meson.build b/test/meson.build
index 7864166..3ca8a08 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -20,9 +20,7 @@ test('diagnostic err', test_e, args : ['diagnostic', 'err'])
test('diagnostic warn', test_e, args : ['diagnostic', 'warn'])
test('diagnostic fixme', test_e, args : ['diagnostic', 'fixme'])
test('diagnostic info', test_e, args : ['diagnostic', 'info'])
-test('diagnostic prefix', test_e, args : ['diagnostic', 'prefix'])
-test('diagnostic thread', test_e, args : ['diagnostic', 'thread'])
-test('diagnostic clean', test_e, args : ['diagnostic', 'clean'])
+test('diagnostic format', test_e, args : ['diagnostic', 'format'])
test('timespec add', test_e, args : ['time', 'timespec add'])
test('timespec subtract', test_e, args : ['time', 'timespec sub'])
test('timespec normalize', test_e, args : ['time', 'timespec normalize'])