From: Olivier Matz Date: Fri, 28 Oct 2016 14:51:27 +0000 (+0200) Subject: log framework X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=047b9599fed749e245c735c98c6840ad4fe8d422;p=protos%2Flibecoli.git log framework --- diff --git a/lib/Makefile b/lib/Makefile index 9aeeae2..08a1b40 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -36,7 +36,7 @@ CFLAGS += -I. srcs := ecoli_tk.c ecoli_tk_str.c ecoli_tk_seq.c srcs += ecoli_tk_space.c ecoli_tk_or.c ecoli_test.c srcs += ecoli_tk_empty.c ecoli_tk_int.c -srcs += ecoli_malloc.c +srcs += ecoli_malloc.c ecoli_log.c shlib-y-$(O)libecoli.so := $(srcs) exe-y-$(O)test = $(srcs) main.c diff --git a/lib/build/test b/lib/build/test index 34b89ac..2913edb 100755 Binary files a/lib/build/test and b/lib/build/test differ diff --git a/lib/ecoli_log.c b/lib/ecoli_log.c new file mode 100644 index 0000000..53c3acb --- /dev/null +++ b/lib/ecoli_log.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2016, Olivier MATZ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the University of California, Berkeley nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define _GNU_SOURCE /* for vasprintf */ +#include +#include +#include +#include + +#include + +static ec_log_t ec_log_fct = ec_log_default; +static void *ec_log_opaque; + +int ec_log_default(unsigned int level, void *opaque, const char *str) +{ + (void)opaque; + (void)level; + + return printf("%s", str); +} + +int ec_log_register(ec_log_t usr_log, void *opaque) +{ + if (usr_log == NULL) + return -1; + + ec_log_fct = usr_log; + ec_log_opaque = opaque; + + return 0; +} + +void ec_log_unregister(void) +{ + ec_log_fct = NULL; +} + +int ec_vlog(unsigned int level, const char *format, va_list ap) +{ + char *s; + int ret; + + if (ec_log_fct == NULL) { + errno = ENODEV; + return -1; + } + + ret = vasprintf(&s, format, ap); + if (ret < 0) + return ret; + + ret = ec_log_fct(level, ec_log_opaque, s); + free(s); + + return ret; +} + +int ec_log(unsigned int level, const char *format, ...) +{ + va_list ap; + int ret; + + va_start(ap, format); + ret = ec_vlog(level, format, ap); + va_end(ap); + + return ret; +} diff --git a/lib/ecoli_log.h b/lib/ecoli_log.h new file mode 100644 index 0000000..f46f6f2 --- /dev/null +++ b/lib/ecoli_log.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2016, Olivier MATZ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the University of California, Berkeley nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ECOLI_LOG_ +#define ECOLI_LOG_ + +#define EC_LOG_EMERG 0 /* system is unusable */ +#define EC_LOG_ALERT 1 /* action must be taken immediately */ +#define EC_LOG_CRIT 2 /* critical conditions */ +#define EC_LOG_ERR 3 /* error conditions */ +#define EC_LOG_WARNING 4 /* warning conditions */ +#define EC_LOG_NOTICE 5 /* normal but significant condition */ +#define EC_LOG_INFO 6 /* informational */ +#define EC_LOG_DEBUG 7 /* debug-level messages */ + +#include + +/* return -1 on error, len(s) on success */ +typedef int (*ec_log_t)(unsigned int level, void *opaque, const char *str); + +int ec_log_register(ec_log_t usr_log, void *opaque); +void ec_log_unregister(void); + +/* same api than printf */ +int ec_log(unsigned int level, const char *format, ...); +int ec_vlog(unsigned int level, const char *format, va_list ap); + +/* default log handler for the library, use printf */ +int ec_log_default(unsigned int level, void *opaque, const char *str); + +#endif diff --git a/lib/ecoli_test.c b/lib/ecoli_test.c index e3942c6..3f1c4fd 100644 --- a/lib/ecoli_test.c +++ b/lib/ecoli_test.c @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -57,9 +58,9 @@ int ec_test_check_tk_parse(const struct ec_tk *tk, const char *input, ret = 0; if (expected == NULL && ret != 0) - printf("tk should not match but matches <%s>\n", s); + ec_log(EC_LOG_ERR, "tk should not match but matches <%s>\n", s); if (expected != NULL && ret != 0) - printf("tk should match <%s> but matches <%s>\n", + ec_log(EC_LOG_ERR, "tk should match <%s> but matches <%s>\n", expected, s); ec_parsed_tk_free(p); @@ -83,9 +84,11 @@ int ec_test_check_tk_complete(const struct ec_tk *tk, const char *input, ret = 0; if (expected == NULL && ret != 0) - printf("tk should not complete but completes with <%s>\n", s); + ec_log(EC_LOG_ERR, + "tk should not complete but completes with <%s>\n", s); if (expected != NULL && ret != 0) - printf("tk should complete with <%s> but completes with <%s>\n", + ec_log(EC_LOG_ERR, + "tk should complete with <%s> but completes with <%s>\n", expected, s); ec_completed_tk_free(p); @@ -123,7 +126,8 @@ static void *debug_malloc(size_t size, const char *file, unsigned int line) ret = hdr + 1; } - printf("%s:%d: info: malloc(%zd) -> %p\n", file, line, size, ret); + ec_log(EC_LOG_INFO, "%s:%d: info: malloc(%zd) -> %p\n", + file, line, size, ret); return ret; } @@ -135,14 +139,14 @@ static void debug_free(void *ptr, const char *file, unsigned int line) (void)file; (void)line; - printf("%s:%d: info: free(%p)\n", file, line, ptr); + ec_log(EC_LOG_INFO, "%s:%d: info: free(%p)\n", file, line, ptr); if (ptr == NULL) return; hdr = (ptr - sizeof(*hdr)); if (hdr->cookie != 0x12345678) { - printf("%s:%d: error: free(%p): bad start cookie\n", + ec_log(EC_LOG_ERR, "%s:%d: error: free(%p): bad start cookie\n", file, line, ptr); abort(); } @@ -153,7 +157,7 @@ static void debug_free(void *ptr, const char *file, unsigned int line) } if (h == NULL) { - printf("%s:%d: error: free(%p): bad ptr\n", + ec_log(EC_LOG_ERR, "%s:%d: error: free(%p): bad ptr\n", file, line, ptr); abort(); } @@ -171,7 +175,7 @@ void *debug_realloc(void *ptr, size_t size, const char *file, unsigned int line) if (ptr != NULL) { if (hdr->cookie != 0x12345678) { - printf("%s:%d: error: realloc(%p): bad start cookie\n", + ec_log(EC_LOG_ERR, "%s:%d: error: realloc(%p): bad start cookie\n", file, line, ptr); abort(); } @@ -182,7 +186,7 @@ void *debug_realloc(void *ptr, size_t size, const char *file, unsigned int line) } if (h == NULL) { - printf("%s:%d: error: realloc(%p): bad ptr\n", + ec_log(EC_LOG_ERR, "%s:%d: error: realloc(%p): bad ptr\n", file, line, ptr); abort(); } @@ -211,7 +215,7 @@ void *debug_realloc(void *ptr, size_t size, const char *file, unsigned int line) TAILQ_INSERT_TAIL(&debug_alloc_hdr_list, hdr, next); } - printf("%s:%d: info: realloc(%p, %zd) -> %p\n", + ec_log(EC_LOG_INFO, "%s:%d: info: realloc(%p, %zd) -> %p\n", file, line, ptr, size, ret); return ret; @@ -222,11 +226,12 @@ void debug_alloc_dump(void) struct debug_alloc_hdr *hdr; TAILQ_FOREACH(hdr, &debug_alloc_hdr_list, next) { - printf("%s:%d: error: memory leak size=%zd ptr=%p\n", + ec_log(EC_LOG_ERR, "%s:%d: error: memory leak size=%zd ptr=%p\n", hdr->file, hdr->line, hdr->size, hdr + 1); } } +/* XXX todo */ /* int ec_test_check_tk_complete_list(const struct ec_tk *tk, */ /* const char *input, ...) */ @@ -239,15 +244,17 @@ int ec_test_all(void) /* register a new malloc to trac memleaks */ if (ec_malloc_register(debug_malloc, debug_free, debug_realloc) < 0) { - printf("cannot register new malloc\n"); + ec_log(EC_LOG_ERR, "cannot register new malloc\n"); return -1; } TAILQ_FOREACH(test, &test_list, next) { if (test->test() == 0) { - printf("== test %-20s success\n", test->name); + ec_log(EC_LOG_INFO, "== test %-20s success\n", + test->name); } else { - printf("== test %-20s failed\n", test->name); + ec_log(EC_LOG_INFO, "== test %-20s failed\n", + test->name); ret = -1; } } diff --git a/lib/ecoli_tk.c b/lib/ecoli_tk.c index 6683af7..e814b68 100644 --- a/lib/ecoli_tk.c +++ b/lib/ecoli_tk.c @@ -113,7 +113,7 @@ void ec_parsed_tk_free(struct ec_parsed_tk *parsed_tk) ec_free(parsed_tk); } -static void __ec_parsed_tk_dump(const struct ec_parsed_tk *parsed_tk, +static void __ec_parsed_tk_dump(FILE *out, const struct ec_parsed_tk *parsed_tk, size_t indent) { struct ec_parsed_tk *child; @@ -122,22 +122,22 @@ static void __ec_parsed_tk_dump(const struct ec_parsed_tk *parsed_tk, /* XXX enhance */ for (i = 0; i < indent; i++) - printf(" "); + fprintf(out, " "); s = ec_parsed_tk_to_string(parsed_tk); - printf("id=%s, s=<%s>\n", parsed_tk->tk->id, s); + fprintf(out, "id=%s, s=<%s>\n", parsed_tk->tk->id, s); TAILQ_FOREACH(child, &parsed_tk->children, next) - __ec_parsed_tk_dump(child, indent + 2); + __ec_parsed_tk_dump(out, child, indent + 2); } -void ec_parsed_tk_dump(const struct ec_parsed_tk *parsed_tk) +void ec_parsed_tk_dump(FILE *out, const struct ec_parsed_tk *parsed_tk) { if (parsed_tk == NULL) { - printf("no match\n"); + fprintf(out, "no match\n"); return; } - __ec_parsed_tk_dump(parsed_tk, 0); + __ec_parsed_tk_dump(out, parsed_tk, 0); } void ec_parsed_tk_add_child(struct ec_parsed_tk *parsed_tk, @@ -293,20 +293,20 @@ void ec_completed_tk_free(struct ec_completed_tk *completed_tk) ec_free(completed_tk); } -void ec_completed_tk_dump(const struct ec_completed_tk *completed_tk) +void ec_completed_tk_dump(FILE *out, const struct ec_completed_tk *completed_tk) { struct ec_completed_tk_elt *elt; if (completed_tk == NULL || completed_tk->count == 0) { - printf("no completion\n"); + fprintf(out, "no completion\n"); return; } - printf("completion: count=%u smallest_start=<%s>\n", + fprintf(out, "completion: count=%u smallest_start=<%s>\n", completed_tk->count, completed_tk->smallest_start); TAILQ_FOREACH(elt, &completed_tk->elts, next) - printf("add=<%s> full=<%s>\n", elt->add, elt->full); + fprintf(out, "add=<%s> full=<%s>\n", elt->add, elt->full); } const char *ec_completed_tk_smallest_start( diff --git a/lib/ecoli_tk.h b/lib/ecoli_tk.h index 167a528..490c5e1 100644 --- a/lib/ecoli_tk.h +++ b/lib/ecoli_tk.h @@ -31,6 +31,8 @@ #include #include +#include + #define EC_TK_ENDLIST ((void *)1) struct ec_tk; @@ -71,7 +73,7 @@ struct ec_parsed_tk *ec_parsed_tk_new(const struct ec_tk *tk); struct ec_parsed_tk *ec_tk_parse(const struct ec_tk *token, const char *str); void ec_parsed_tk_add_child(struct ec_parsed_tk *parsed_tk, struct ec_parsed_tk *child); -void ec_parsed_tk_dump(const struct ec_parsed_tk *parsed_tk); +void ec_parsed_tk_dump(FILE *out, const struct ec_parsed_tk *parsed_tk); void ec_parsed_tk_free(struct ec_parsed_tk *parsed_tk); struct ec_parsed_tk *ec_parsed_tk_find_first(struct ec_parsed_tk *parsed_tk, @@ -112,7 +114,8 @@ struct ec_completed_tk *ec_completed_tk_merge( struct ec_completed_tk *completed_tk1, struct ec_completed_tk *completed_tk2); void ec_completed_tk_free(struct ec_completed_tk *completed_tk); -void ec_completed_tk_dump(const struct ec_completed_tk *completed_tk); +void ec_completed_tk_dump(FILE *out, + const struct ec_completed_tk *completed_tk); const char *ec_completed_tk_smallest_start( const struct ec_completed_tk *completed_tk); diff --git a/lib/ecoli_tk_int.c b/lib/ecoli_tk_int.c index 41ed54a..6296b8b 100644 --- a/lib/ecoli_tk_int.c +++ b/lib/ecoli_tk_int.c @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -123,7 +124,7 @@ static int testcase(void) tk = ec_tk_int_new(NULL, 0, 256, 0); if (tk == NULL) { - printf("cannot create tk\n"); + ec_log(EC_LOG_ERR, "cannot create tk\n"); return -1; } ret |= EC_TEST_CHECK_TK_PARSE(tk, "0", "0"); @@ -156,7 +157,7 @@ static int testcase(void) tk = ec_tk_int_new(NULL, -1, LLONG_MAX, 16); if (tk == NULL) { - printf("cannot create tk\n"); + ec_log(EC_LOG_ERR, "cannot create tk\n"); return -1; } ret |= EC_TEST_CHECK_TK_PARSE(tk, "0", "0"); @@ -180,7 +181,7 @@ static int testcase(void) tk = ec_tk_int_new(NULL, LLONG_MIN, 0, 10); if (tk == NULL) { - printf("cannot create tk\n"); + ec_log(EC_LOG_ERR, "cannot create tk\n"); return -1; } ret |= EC_TEST_CHECK_TK_PARSE(tk, "0", "0"); @@ -194,7 +195,7 @@ static int testcase(void) /* /\* test completion *\/ */ /* tk = ec_tk_int_new(NULL, "foo"); */ /* if (tk == NULL) { */ - /* printf("cannot create tk\n"); */ + /* ec_log(EC_LOG_ERR, "cannot create tk\n"); */ /* return -1; */ /* } */ /* ret |= EC_TEST_CHECK_TK_COMPLETE(tk, "", "foo"); */ diff --git a/lib/ecoli_tk_or.c b/lib/ecoli_tk_or.c index 9276c70..b498dcb 100644 --- a/lib/ecoli_tk_or.c +++ b/lib/ecoli_tk_or.c @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -179,7 +180,7 @@ static int testcase(void) ec_tk_str_new(NULL, "bar"), EC_TK_ENDLIST); if (tk == NULL) { - printf("cannot create tk\n"); + ec_log(EC_LOG_ERR, "cannot create tk\n"); return -1; } ret |= EC_TEST_CHECK_TK_PARSE(tk, "foo", "foo"); @@ -197,7 +198,7 @@ static int testcase(void) ec_tk_str_new(NULL, "titi"), EC_TK_ENDLIST); if (tk == NULL) { - printf("cannot create tk\n"); + ec_log(EC_LOG_ERR, "cannot create tk\n"); return -1; } ret |= EC_TEST_CHECK_TK_COMPLETE(tk, "", ""); diff --git a/lib/ecoli_tk_str.c b/lib/ecoli_tk_str.c index 41f99db..f7b18fb 100644 --- a/lib/ecoli_tk_str.c +++ b/lib/ecoli_tk_str.c @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -129,7 +130,7 @@ static int testcase(void) /* all inputs starting with foo should match */ tk = ec_tk_str_new(NULL, "foo"); if (tk == NULL) { - printf("cannot create tk\n"); + ec_log(EC_LOG_ERR, "cannot create tk\n"); return -1; } ret |= EC_TEST_CHECK_TK_PARSE(tk, "foo", "foo"); @@ -142,7 +143,7 @@ static int testcase(void) /* all inputs starting with foo should match */ tk = ec_tk_str_new(NULL, "Здравствуйте"); if (tk == NULL) { - printf("cannot create tk\n"); + ec_log(EC_LOG_ERR, "cannot create tk\n"); return -1; } ret |= EC_TEST_CHECK_TK_PARSE(tk, "Здравствуйте", "Здравствуйте"); @@ -154,7 +155,7 @@ static int testcase(void) /* an empty token string always matches */ tk = ec_tk_str_new(NULL, ""); if (tk == NULL) { - printf("cannot create tk\n"); + ec_log(EC_LOG_ERR, "cannot create tk\n"); return -1; } ret |= EC_TEST_CHECK_TK_PARSE(tk, "", ""); @@ -164,7 +165,7 @@ static int testcase(void) /* test completion */ tk = ec_tk_str_new(NULL, "foo"); if (tk == NULL) { - printf("cannot create tk\n"); + ec_log(EC_LOG_ERR, "cannot create tk\n"); return -1; } ret |= EC_TEST_CHECK_TK_COMPLETE(tk, "", "foo"); diff --git a/lib/main.c b/lib/main.c index 059515b..601508a 100644 --- a/lib/main.c +++ b/lib/main.c @@ -56,14 +56,14 @@ static void test(void) /* ok */ p = ec_tk_parse(seq, "hello mike"); - ec_parsed_tk_dump(p); + ec_parsed_tk_dump(stdout, p); name = ec_parsed_tk_to_string(ec_parsed_tk_find_first(p, "name")); printf("parsed with name=%s\n", name); ec_parsed_tk_free(p); /* ko */ p = ec_tk_parse(seq, "hello robert"); - ec_parsed_tk_dump(p); + ec_parsed_tk_dump(stdout, p); name = ec_parsed_tk_to_string(ec_parsed_tk_find_first(p, "name")); printf("parsed with name=%s\n", name); ec_parsed_tk_free(p);