Gitweb links:
...log
http://git.netsurf-browser.org/libnslog.git/shortlog/0d8bf0efca755ba4446a213d500975de65098dd0
...commit
http://git.netsurf-browser.org/libnslog.git/commit/0d8bf0efca755ba4446a213d500975de65098dd0
...tree
http://git.netsurf-browser.org/libnslog.git/tree/0d8bf0efca755ba4446a213d500975de65098dd0
The branch, master has been created
at 0d8bf0efca755ba4446a213d500975de65098dd0 (commit)
- Log -----------------------------------------------------------------
commitdiff
http://git.netsurf-browser.org/libnslog.git/commit/?id=0d8bf0efca755ba4446a213d500975de65098dd0
commit 0d8bf0efca755ba4446a213d500975de65098dd0
Author: Daniel Silverstone <[email protected]>
Commit: Daniel Silverstone <[email protected]>
Remove redundant parse test
diff --git a/test/Makefile b/test/Makefile
index 5ebac01..36d5092 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -1,3 +1,3 @@
-DIR_TEST_ITEMS := testrunner:testmain.c;basictests.c parse:parse.c
+DIR_TEST_ITEMS := testrunner:testmain.c;basictests.c
include $(NSBUILD)/Makefile.subdir
diff --git a/test/parse.c b/test/parse.c
deleted file mode 100644
index 9fca97b..0000000
--- a/test/parse.c
+++ /dev/null
@@ -1,25 +0,0 @@
-#include "nslog/nslog.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-
-int main(int argc, char **argv)
-{
- if (argc != 2) {
- fprintf(stderr, "usage: parse 'filtertext'\n");
- return 1;
- }
- nslog_filter_t *filt;
- nslog_error err;
-
- err = nslog_filter_from_text(argv[1], &filt);
- if (err != NSLOG_NO_ERROR) {
- fprintf(stderr, "Unable to parse.\n");
- return 2;
- }
- char *ct = nslog_filter_sprintf(filt);
- filt = nslog_filter_unref(filt);
- printf("%s\n", ct);
- free(ct);
- return 0;
-}
commitdiff
http://git.netsurf-browser.org/libnslog.git/commit/?id=768988d88470ffc1c64c35d6f9d3c37a9a6f75da
commit 768988d88470ffc1c64c35d6f9d3c37a9a6f75da
Author: Daniel Silverstone <[email protected]>
Commit: Daniel Silverstone <[email protected]>
Simple parser for filter syntax
diff --git a/include/nslog/nslog.h b/include/nslog/nslog.h
index fc3ead4..10b90a8 100644
--- a/include/nslog/nslog.h
+++ b/include/nslog/nslog.h
@@ -30,6 +30,7 @@ typedef enum {
const char *nslog_level_name(nslog_level level);
#define NSLOG_LEVEL_DD NSLOG_LEVEL_DEEPDEBUG
+#define NSLOG_LEVEL_DBG NSLOG_LEVEL_DEBUG
#define NSLOG_LEVEL_CHAT NSLOG_LEVEL_VERBOSE
#define NSLOG_LEVEL_WARN NSLOG_LEVEL_WARNING
#define NSLOG_LEVEL_ERR NSLOG_LEVEL_ERROR
@@ -105,6 +106,7 @@ typedef enum {
NSLOG_NO_ERROR = 0,
NSLOG_NO_MEMORY = 1,
NSLOG_UNCORKED = 2,
+ NSLOG_PARSE_ERROR = 3,
} nslog_error;
typedef void (*nslog_callback)(void *context, nslog_entry_context_t *ctx,
@@ -145,4 +147,9 @@ nslog_filter_t *nslog_filter_unref(nslog_filter_t *filter);
nslog_error nslog_filter_set_active(nslog_filter_t *filter,
nslog_filter_t **prev);
+char *nslog_filter_sprintf(nslog_filter_t *filter);
+
+nslog_error nslog_filter_from_text(const char *input,
+ nslog_filter_t **output);
+
#endif /* NSLOG_NSLOG_H_ */
diff --git a/src/Makefile b/src/Makefile
index 7fbad1c..3ca70cd 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,3 +1,37 @@
DIR_SOURCES := core.c filter.c
+CFLAGS := $(CFLAGS) -I$(BUILDDIR) -Isrc/
+
+SOURCES := $(SOURCES) $(BUILDDIR)/filter-parser.c $(BUILDDIR)/filter-lexer.c
+
+$(BUILDDIR)/%-lexer.c $(BUILDDIR)/%-lexer.h: src/%-lexer.l
+ $(VQ)$(ECHO) " FLEX: $<"
+ $(Q)$(FLEX) --outfile=$(BUILDDIR)/$(*F)-lexer.c
--header-file=$(BUILDDIR)/$(*F)-lexer.h $<
+
+$(BUILDDIR)/%-lexer.c: $(BUILDDIR)/%-parser.h
+
+# Bison 3.0 and later require api.prefix in curly braces
+# Bison 2.6 and later require api.prefix
+# Bison 2.5 and earlier require name-prefix switch
+bisonvsn := $(word 4,$(shell $(BISON) --version))
+bisonmaj := $(word 1,$(subst ., ,$(bisonvsn)))
+bisonmin := $(word 2,$(subst ., ,$(bisonvsn)))
+ifeq ($(bisonmaj),1)
+ BISON_DEFINES = --name-prefix=$(*F)_
+else
+ ifeq ($(bisonmaj),2)
+ ifneq ($(findstring $(bisonmin),"0 1 2 3 4 5"),)
+ BISON_DEFINES = --name-prefix=$(*F)_
+ else
+ BISON_DEFINES = --define=api.prefix=$(*F)_
+ endif
+ else
+ BISON_DEFINES = --define=api.prefix={$(*F)_}
+ endif
+endif
+
+$(BUILDDIR)/%-parser.c $(BUILDDIR)/%-parser.h: src/%-parser.y
+ $(VQ)$(ECHO) " BISON: $<"
+ $(Q)$(BISON) -d -t $(BISON_DEFINES) --report=all
--output=$(BUILDDIR)/$(*F)-parser.c --defines=$(BUILDDIR)/$(*F)-parser.h $<
+
include $(NSBUILD)/Makefile.subdir
diff --git a/src/filter-lexer.l b/src/filter-lexer.l
new file mode 100644
index 0000000..5f75d29
--- /dev/null
+++ b/src/filter-lexer.l
@@ -0,0 +1,84 @@
+%{
+
+/* This is a lexer for libnslog filter syntax
+ *
+ * This file is part of libnslog.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2017 Daniel Silverstone <[email protected]>
+ *
+ */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "nslog/nslog.h"
+
+#include "filter-parser.h"
+
+/* Ensure compatability with bison 2.6 and later */
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED && defined
FILTER_STYPE_IS_DECLARED
+#define YYSTYPE FILTER_STYPE
+#endif
+
+#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED && defined
FILTER_LTYPE_IS_DECLARED
+#define YYLTYPE FILTER_LTYPE
+#endif
+
+%}
+
+
+/* lexer options */
+%option never-interactive
+%option bison-bridge
+%option bison-locations
+%option warn
+%option prefix="filter_"
+%option nounput
+%option noinput
+%option noyywrap
+
+whitespace [ \t]+
+
+pattern [^ \t]+
+
+%x st_patt
+
+%%
+
+{whitespace} { /* nothing */ }
+
+level: { return T_LEVEL_SPECIFIER; }
+lvl: { return T_LEVEL_SPECIFIER; }
+
+cat: { BEGIN(st_patt); return T_CATEGORY_SPECIFIER; }
+category: { BEGIN(st_patt); return T_CATEGORY_SPECIFIER; }
+file: { BEGIN(st_patt); return T_FILENAME_SPECIFIER; }
+filename: { BEGIN(st_patt); return T_FILENAME_SPECIFIER; }
+dir: { BEGIN(st_patt); return T_DIRNAME_SPECIFIER; }
+dirname: { BEGIN(st_patt); return T_DIRNAME_SPECIFIER; }
+func: { BEGIN(st_patt); return T_FUNCNAME_SPECIFIER; }
+funcname: { BEGIN(st_patt); return T_FUNCNAME_SPECIFIER; }
+
+"&&" { return T_OP_AND; }
+"||" { return T_OP_OR; }
+
+DEEPDEBUG { yylval->level = NSLOG_LEVEL_DEEPDEBUG; return T_LEVEL; }
+DDEBUG { yylval->level = NSLOG_LEVEL_DEEPDEBUG; return T_LEVEL; }
+DD { yylval->level = NSLOG_LEVEL_DEEPDEBUG; return T_LEVEL; }
+DEBUG { yylval->level = NSLOG_LEVEL_DEBUG; return T_LEVEL; }
+DBG { yylval->level = NSLOG_LEVEL_DEBUG; return T_LEVEL; }
+VERBOSE { yylval->level = NSLOG_LEVEL_VERBOSE; return T_LEVEL; }
+CHAT { yylval->level = NSLOG_LEVEL_VERBOSE; return T_LEVEL; }
+INFO { yylval->level = NSLOG_LEVEL_INFO; return T_LEVEL; }
+WARNING { yylval->level = NSLOG_LEVEL_WARNING; return T_LEVEL; }
+WARN { yylval->level = NSLOG_LEVEL_WARNING; return T_LEVEL; }
+ERROR { yylval->level = NSLOG_LEVEL_ERROR; return T_LEVEL; }
+ERR { yylval->level = NSLOG_LEVEL_ERROR; return T_LEVEL; }
+CRITICAL { yylval->level = NSLOG_LEVEL_CRITICAL; return T_LEVEL; }
+CRIT { yylval->level = NSLOG_LEVEL_CRITICAL; return T_LEVEL; }
+
+<st_patt>{pattern} { yylval->patt = yytext; BEGIN(INITIAL); return
T_PATTERN; }
+
+. { return (int) yytext[0]; }
diff --git a/src/filter-parser.y b/src/filter-parser.y
new file mode 100644
index 0000000..bb225b6
--- /dev/null
+++ b/src/filter-parser.y
@@ -0,0 +1,197 @@
+%{
+/* This is a bison parser for libnslog's filter syntax
+ *
+ * This file is part of libnslog.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2017 Daniel Silverstone <[email protected]>
+ *
+ */
+
+#include "nslog/nslog.h"
+#include <assert.h>
+
+#include "filter-parser.h"
+#include "filter-lexer.h"
+
+static void filter_error(FILTER_LTYPE *loc, nslog_filter_t **output, const
char *msg)
+{
+ (void)loc;
+ (void)output;
+ (void)msg;
+}
+
+%}
+
+%locations
+%pure-parser
+%parse-param { nslog_filter_t **output }
+
+%union {
+ char *patt;
+ nslog_level level;
+ nslog_filter_t *filter;
+}
+
+%token <patt> T_PATTERN
+%token <level> T_LEVEL
+
+%token T_CATEGORY_SPECIFIER
+%token T_FILENAME_SPECIFIER
+%token T_LEVEL_SPECIFIER
+%token T_DIRNAME_SPECIFIER
+%token T_FUNCNAME_SPECIFIER
+
+%token T_OP_AND
+%token T_OP_OR
+
+%type <filter> level_filter
+%type <filter> category_filter
+%type <filter> filename_filter
+%type <filter> dirname_filter
+%type <filter> funcname_filter
+%type <filter> basic_filter
+
+%type <filter> and_filter
+%type <filter> or_filter
+%type <filter> xor_filter
+%type <filter> binary_filter
+%type <filter> not_filter
+
+%type <filter> filter
+%type <filter> toplevel
+
+%start toplevel
+
+%%
+
+ /*
+ part ::= [^: \t\n]+
+level-name ::= 'DEEPDEBUG' | 'DD' | 'DEBUG' | 'VERBOSE' | 'CHAT' |
+ 'WARNING' | 'WARN' | 'ERROR' | 'ERR' | 'CRITICAL' | 'CRIT'
+
+category-filter ::= 'cat:' part
+level-filter ::= 'level:' level-name
+file-filter ::= 'file:' part
+dir-filter ::= 'dir:' dir
+
+factor ::= category-filter | level-filter | file-filter | dir-filter |
+ '(' expression ')'
+
+op ::= '&&' | '||' | '^' | 'and' | 'or' | 'xor' | 'eor'
+
+term ::= factor {op factor}
+
+expression ::= term | '!' term
+ */
+
+level_filter:
+ T_LEVEL_SPECIFIER T_LEVEL
+ {
+ assert(nslog_filter_level_new($2, &$$) == NSLOG_NO_ERROR);
+ }
+ ;
+
+category_filter:
+ T_CATEGORY_SPECIFIER T_PATTERN
+ {
+ assert(nslog_filter_category_new($2, &$$) == NSLOG_NO_ERROR);
+ }
+ ;
+
+filename_filter:
+ T_FILENAME_SPECIFIER T_PATTERN
+ {
+ assert(nslog_filter_filename_new($2, &$$) == NSLOG_NO_ERROR);
+ }
+ ;
+
+dirname_filter:
+ T_DIRNAME_SPECIFIER T_PATTERN
+ {
+ assert(nslog_filter_dirname_new($2, &$$) == NSLOG_NO_ERROR);
+ }
+ ;
+
+funcname_filter:
+ T_FUNCNAME_SPECIFIER T_PATTERN
+ {
+ assert(nslog_filter_funcname_new($2, &$$) == NSLOG_NO_ERROR);
+ }
+ ;
+
+basic_filter:
+ level_filter
+ |
+ category_filter
+ |
+ filename_filter
+ |
+ dirname_filter
+ |
+ funcname_filter
+ ;
+
+and_filter:
+ '(' filter T_OP_AND filter ')'
+ {
+ assert(nslog_filter_and_new($2, $4, &$$) == NSLOG_NO_ERROR);
+ nslog_filter_unref($2);
+ nslog_filter_unref($4);
+ }
+ ;
+
+or_filter:
+ '(' filter T_OP_OR filter ')'
+ {
+ assert(nslog_filter_or_new($2, $4, &$$) == NSLOG_NO_ERROR);
+ nslog_filter_unref($2);
+ nslog_filter_unref($4);
+ }
+ ;
+
+xor_filter:
+ '(' filter '^' filter ')'
+ {
+ assert(nslog_filter_xor_new($2, $4, &$$) == NSLOG_NO_ERROR);
+ nslog_filter_unref($2);
+ nslog_filter_unref($4);
+ }
+ ;
+
+binary_filter:
+ and_filter
+ |
+ or_filter
+ |
+ xor_filter
+ ;
+
+not_filter:
+ '!' filter
+ {
+ assert(nslog_filter_not_new($2, &$$) == NSLOG_NO_ERROR);
+ nslog_filter_unref($2);
+ }
+ ;
+
+filter:
+ not_filter
+ |
+ binary_filter
+ |
+ basic_filter
+ ;
+
+toplevel:
+ filter
+ {
+ $$ = *output = $1;
+ }
+ |
+ error
+ {
+ (void)yylloc;
+ YYABORT ;
+ }
+ ;
diff --git a/src/filter.c b/src/filter.c
index 1dc4e81..0a478b1 100644
--- a/src/filter.c
+++ b/src/filter.c
@@ -14,6 +14,19 @@
#include "nslog_internal.h"
+#include "filter-parser.h"
+
+/* Ensure compatability with bison 2.6 and later */
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED && defined
FILTER_STYPE_IS_DECLARED
+#define YYSTYPE FILTER_STYPE
+#endif
+
+#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED && defined
FILTER_LTYPE_IS_DECLARED
+#define YYLTYPE FILTER_LTYPE
+#endif
+
+#include "filter-lexer.h"
+
typedef enum {
/* Fundamentals */
NSLFK_CATEGORY = 0,
@@ -308,3 +321,74 @@ bool nslog__filter_matches(nslog_entry_context_t *ctx)
return true;
return _nslog__filter_matches(ctx, nslog__active_filter);
}
+
+char *nslog_filter_sprintf(nslog_filter_t *filter)
+{
+ char *ret = NULL;
+ switch (filter->kind) {
+ case NSLFK_CATEGORY:
+ ret = calloc(filter->params.str.len + 5, 1);
+ sprintf(ret, "cat:%s", filter->params.str.ptr);
+ break;
+ case NSLFK_LEVEL: {
+ const char *lvl = nslog_level_name(filter->params.level);
+ ret = calloc(strlen(lvl) + 5, 1);
+ sprintf(ret, "lvl:%s", lvl);
+ break;
+ }
+ case NSLFK_FILENAME:
+ ret = calloc(filter->params.str.len + 6, 1);
+ sprintf(ret, "file:%s", filter->params.str.ptr);
+ break;
+ case NSLFK_DIRNAME:
+ ret = calloc(filter->params.str.len + 5, 1);
+ sprintf(ret, "dir:%s", filter->params.str.ptr);
+ break;
+ case NSLFK_FUNCNAME:
+ ret = calloc(filter->params.str.len + 6, 1);
+ sprintf(ret, "func:%s", filter->params.str.ptr);
+ break;
+ case NSLFK_AND:
+ case NSLFK_OR:
+ case NSLFK_XOR: {
+ char *left = nslog_filter_sprintf(filter->params.binary.input1);
+ char *right =
nslog_filter_sprintf(filter->params.binary.input2);
+ const char *op =
+ (filter->kind == NSLFK_AND) ? "&&" :
+ (filter->kind == NSLFK_OR) ? "||" : "^";
+ ret = calloc(strlen(left) + strlen(right) + 7, 1);
+ sprintf(ret, "(%s %s %s)", left, op, right);
+ free(left);
+ free(right);
+ break;
+ }
+ case NSLFK_NOT: {
+ char *input = nslog_filter_sprintf(filter->params.unary_input);
+ ret = calloc(strlen(input) + 2, 1);
+ sprintf(ret, "!%s", input);
+ free(input);
+ break;
+ }
+ default:
+ assert("Unexpected kind" == NULL);
+ return strdup("***ERROR***");
+ }
+ return ret;
+}
+
+nslog_error nslog_filter_from_text(const char *input,
+ nslog_filter_t **output)
+{
+ int ret;
+ YY_BUFFER_STATE buffer = filter__scan_string((char *)input);
+ filter_push_buffer_state(buffer);
+ ret = filter_parse(output);
+ filter_lex_destroy();
+ switch (ret) {
+ case 0:
+ return NSLOG_NO_ERROR;
+ case 2:
+ return NSLOG_NO_MEMORY;
+ }
+ return NSLOG_PARSE_ERROR;
+}
diff --git a/test/Makefile b/test/Makefile
index 36d5092..5ebac01 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -1,3 +1,3 @@
-DIR_TEST_ITEMS := testrunner:testmain.c;basictests.c
+DIR_TEST_ITEMS := testrunner:testmain.c;basictests.c parse:parse.c
include $(NSBUILD)/Makefile.subdir
diff --git a/test/basictests.c b/test/basictests.c
index b83ed9f..d74df87 100644
--- a/test/basictests.c
+++ b/test/basictests.c
@@ -171,7 +171,7 @@ START_TEST (test_nslog_simple_filter_corked_message)
"Captured message wasn't correct filename");
fail_unless(strcmp(captured_context.funcname,
"test_nslog_simple_filter_corked_message") == 0,
"Captured message wasn't correct function name");
-
+
}
END_TEST
@@ -198,7 +198,34 @@ START_TEST (test_nslog_simple_filter_uncorked_message)
"Captured message wasn't correct filename");
fail_unless(strcmp(captured_context.funcname,
"test_nslog_simple_filter_uncorked_message") == 0,
"Captured message wasn't correct function name");
-
+
+}
+END_TEST
+
+START_TEST (test_nslog_basic_filter_sprintf)
+{
+ char *ct = nslog_filter_sprintf(cat_test);
+ fail_unless(ct != NULL, "Unable to sprintf");
+ fail_unless(strcmp(ct, "cat:test") == 0,
+ "Printed category test is wrong");
+ free(ct);
+ ct = nslog_filter_sprintf(cat_another);
+ fail_unless(ct != NULL, "Unable to sprintf");
+ fail_unless(strcmp(ct, "cat:another") == 0,
+ "Printed category another is wrong");
+ free(ct);
+}
+END_TEST
+
+START_TEST (test_nslog_parse_and_sprintf)
+{
+ nslog_filter_t *filt;
+ fail_unless(nslog_filter_from_text("cat:test", &filt) == NSLOG_NO_ERROR,
+ "Unable to parse cat:test");
+ char *ct = nslog_filter_sprintf(filt);
+ nslog_filter_unref(filt);
+ fail_unless(strcmp(ct, "cat:test") == 0,
+ "Printed parsed cat:test not right");
}
END_TEST
@@ -209,22 +236,24 @@ nslog_basic_suite(SRunner *sr)
{
Suite *s = suite_create("libnslog: Basic tests");
TCase *tc_basic = NULL;
-
+
tc_basic = tcase_create("Simple log checks, no filters");
-
+
tcase_add_checked_fixture(tc_basic, with_simple_context_setup,
with_simple_context_teardown);
tcase_add_test(tc_basic, test_nslog_trivial_corked_message);
tcase_add_test(tc_basic, test_nslog_trivial_uncorked_message);
suite_add_tcase(s, tc_basic);
-
+
tc_basic = tcase_create("Simple filter checks");
-
+
tcase_add_checked_fixture(tc_basic, with_simple_filter_context_setup,
with_simple_filter_context_teardown);
tcase_add_test(tc_basic, test_nslog_simple_filter_corked_message);
tcase_add_test(tc_basic, test_nslog_simple_filter_uncorked_message);
+ tcase_add_test(tc_basic, test_nslog_basic_filter_sprintf);
+ tcase_add_test(tc_basic, test_nslog_parse_and_sprintf);
suite_add_tcase(s, tc_basic);
-
+
srunner_add_suite(sr, s);
}
diff --git a/test/parse.c b/test/parse.c
new file mode 100644
index 0000000..9fca97b
--- /dev/null
+++ b/test/parse.c
@@ -0,0 +1,25 @@
+#include "nslog/nslog.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(int argc, char **argv)
+{
+ if (argc != 2) {
+ fprintf(stderr, "usage: parse 'filtertext'\n");
+ return 1;
+ }
+ nslog_filter_t *filt;
+ nslog_error err;
+
+ err = nslog_filter_from_text(argv[1], &filt);
+ if (err != NSLOG_NO_ERROR) {
+ fprintf(stderr, "Unable to parse.\n");
+ return 2;
+ }
+ char *ct = nslog_filter_sprintf(filt);
+ filt = nslog_filter_unref(filt);
+ printf("%s\n", ct);
+ free(ct);
+ return 0;
+}
commitdiff
http://git.netsurf-browser.org/libnslog.git/commit/?id=602a6b133f83e2349a4b233536fdca90446638cd
commit 602a6b133f83e2349a4b233536fdca90446638cd
Author: Daniel Silverstone <[email protected]>
Commit: Daniel Silverstone <[email protected]>
Remove assert stuff, we don't need it, add more test
diff --git a/test/basictests.c b/test/basictests.c
index 4d94059..b83ed9f 100644
--- a/test/basictests.c
+++ b/test/basictests.c
@@ -18,12 +18,6 @@
#define UNUSED(x) (void)(x)
#endif
-#ifndef NDEBUG
-
-/* Tests go here which need assert() to be checked */
-
-#endif
-
NSLOG_DEFINE_CATEGORY(test, "Top level test category");
static void *captured_render_context = NULL;
@@ -181,25 +175,42 @@ START_TEST (test_nslog_simple_filter_corked_message)
}
END_TEST
+START_TEST (test_nslog_simple_filter_uncorked_message)
+{
+ fail_unless(nslog_filter_set_active(cat_test, NULL) == NSLOG_NO_ERROR,
+ "Unable to set active filter to cat:test");
+ fail_unless(nslog_uncork() == NSLOG_NO_ERROR,
+ "Unable to uncork");
+ NSLOG(test, INFO, "Hello world");
+ fail_unless(captured_message_count == 1,
+ "Captured message count was wrong");
+ fail_unless(captured_render_context == anchor_context_2,
+ "Captured context wasn't passed through");
+ fail_unless(strcmp(captured_context.category->name, "test") == 0,
+ "Captured context category wasn't normalised");
+ fail_unless(captured_context.category == &__nslog_category_test,
+ "Captured context category wasn't the one we wanted");
+ fail_unless(captured_rendered_message_length == 11,
+ "Captured message wasn't correct length");
+ fail_unless(strcmp(captured_rendered_message, "Hello world") == 0,
+ "Captured message wasn't correct");
+ fail_unless(strcmp(captured_context.filename, "test/basictests.c") == 0,
+ "Captured message wasn't correct filename");
+ fail_unless(strcmp(captured_context.funcname,
"test_nslog_simple_filter_uncorked_message") == 0,
+ "Captured message wasn't correct function name");
+
+}
+END_TEST
+
/**** And the suites are set up here ****/
void
nslog_basic_suite(SRunner *sr)
{
Suite *s = suite_create("libnslog: Basic tests");
- TCase *tc_basic = tcase_create("Abort checking");
-
-#ifndef NDEBUG
- /*
- tcase_add_test_raise_signal(tc_basic,
- test_lwc_string_hash_value_aborts,
- SIGABRT);
- */
-#endif
-
- suite_add_tcase(s, tc_basic);
-
- tc_basic = tcase_create("Simple log checks, no filters");
+ TCase *tc_basic = NULL;
+
+ tc_basic = tcase_create("Simple log checks, no filters");
tcase_add_checked_fixture(tc_basic, with_simple_context_setup,
with_simple_context_teardown);
@@ -212,6 +223,7 @@ nslog_basic_suite(SRunner *sr)
tcase_add_checked_fixture(tc_basic, with_simple_filter_context_setup,
with_simple_filter_context_teardown);
tcase_add_test(tc_basic, test_nslog_simple_filter_corked_message);
+ tcase_add_test(tc_basic, test_nslog_simple_filter_uncorked_message);
suite_add_tcase(s, tc_basic);
srunner_add_suite(sr, s);
diff --git a/test/testmain.c b/test/testmain.c
index 9a6b257..38a4ace 100644
--- a/test/testmain.c
+++ b/test/testmain.c
@@ -15,18 +15,6 @@
#define UNUSED(x) ((x) = (x))
#endif
-/* This means that assertion failures are silent in tests */
-#ifndef NDEBUG
-void __assert_fail(const char *__assertion, const char *__file,
- unsigned int __line, const char *__function) {
- (void)__assertion;
- (void)__file;
- (void)__line;
- (void)__function;
- abort();
-}
-#endif
-
int
main(int argc, char **argv)
{
@@ -35,16 +23,16 @@ main(int argc, char **argv)
UNUSED(argc);
UNUSED(argv);
-
+
sr = srunner_create(suite_create("Test suite for libnslog"));
-
+
nslog_basic_suite(sr);
-
+
srunner_set_fork_status(sr, CK_FORK);
srunner_run_all(sr, CK_ENV);
number_failed = srunner_ntests_failed(sr);
-
+
srunner_free(sr);
-
+
return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}
commitdiff
http://git.netsurf-browser.org/libnslog.git/commit/?id=43f7f54dadecb1d11b4fd9cd2af4889043865490
commit 43f7f54dadecb1d11b4fd9cd2af4889043865490
Author: Daniel Silverstone <[email protected]>
Commit: Daniel Silverstone <[email protected]>
Switch to a check based test suite, start fixing bugs
diff --git a/Makefile b/Makefile
index 184f9d4..26cf49f 100644
--- a/Makefile
+++ b/Makefile
@@ -17,7 +17,7 @@ NSSHARED ?= $(PREFIX)/share/netsurf-buildsystem
include $(NSSHARED)/makefiles/Makefile.tools
# Reevaluate when used, as BUILDDIR won't be defined yet
-TESTRUNNER = test/runtest.sh $(BUILDDIR) $(EXEEXT)
+TESTRUNNER = $(BUILDDIR)/test_testrunner$(EXEEXT)
# Toolchain flags
WARNFLAGS := -Wall -W -Wundef -Wpointer-arith -Wcast-align \
@@ -48,6 +48,15 @@ TESTLDFLAGS := -lm -l$(COMPONENT) $(TESTLDFLAGS)
include $(NSBUILD)/Makefile.top
+ifeq ($(WANT_TEST),yes)
+ ifneq ($(PKGCONFIG),)
+ TESTCFLAGS := $(TESTCFLAGS) $(shell $(PKGCONFIG) --cflags check)
+ TESTLDFLAGS := $(TESTLDFLAGS) $(shell $(PKGCONFIG) --libs check)
+ else
+ TESTLDFLAGS := $(TESTLDFLAGS) -lcheck
+ endif
+endif
+
# Extra installation rules
I := /$(INCLUDEDIR)/nslog
INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):include/nslog/nslog.h
diff --git a/include/nslog/nslog.h b/include/nslog/nslog.h
index 550bffb..fc3ead4 100644
--- a/include/nslog/nslog.h
+++ b/include/nslog/nslog.h
@@ -104,6 +104,7 @@ void nslog__log(nslog_entry_context_t *ctx,
typedef enum {
NSLOG_NO_ERROR = 0,
NSLOG_NO_MEMORY = 1,
+ NSLOG_UNCORKED = 2,
} nslog_error;
typedef void (*nslog_callback)(void *context, nslog_entry_context_t *ctx,
diff --git a/src/core.c b/src/core.c
index 978f169..95d06c2 100644
--- a/src/core.c
+++ b/src/core.c
@@ -73,7 +73,7 @@ static void nslog__log_corked(nslog_entry_context_t *ctx,
va_list args)
{
/* If corked, we need to store a copy */
- struct nslog_cork_chain *newcork = malloc(sizeof(*newcork) +
measured_len + 1);
+ struct nslog_cork_chain *newcork = calloc(sizeof(struct
nslog_cork_chain) + measured_len + 1, 1);
if (newcork == NULL) {
/* Wow, something went wrong */
return;
@@ -157,6 +157,8 @@ nslog_error nslog_uncork()
free(ent);
}
nslog__corked = false;
+ return NSLOG_NO_ERROR;
+ } else {
+ return NSLOG_UNCORKED;
}
- return NSLOG_NO_ERROR;
}
diff --git a/test/Makefile b/test/Makefile
index 033033f..36d5092 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -1,3 +1,3 @@
-DIR_TEST_ITEMS := basic:basic.c explicitfilter:explicitfilter.c
+DIR_TEST_ITEMS := testrunner:testmain.c;basictests.c
include $(NSBUILD)/Makefile.subdir
diff --git a/test/basic.c b/test/basic.c
deleted file mode 100644
index d514814..0000000
--- a/test/basic.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2017 Daniel Silverstone <[email protected]>
- *
- * This file is part of libnslog.
- *
- * Licensed under the MIT License,
- * http://www.opensource.org/licenses/mit-license.php
- */
-
-#include "nslog/nslog.h"
-
-#include <stdio.h>
-
-NSLOG_DEFINE_CATEGORY(test, "Test category");
-
-static void test_render_function(
- void *_ctx, nslog_entry_context_t *ctx,
- const char *fmt, va_list args)
-{
- (void)ctx;
- fprintf(stderr, "%s %s:%d [%s] %s() ",
- nslog_level_name(ctx->level),
- ctx->filename, ctx->lineno,
- ctx->category->name,
- ctx->funcname);
- vfprintf(stderr, fmt, args);
- fprintf(stderr, "\n");
-}
-
-int main(int argc, char **argv)
-{
- nslog_set_render_callback(test_render_function, NULL);
- NSLOG(test, INFO, "Pre-uncorking");
- fprintf(stderr, "About to nslog_uncork()\n");
- nslog_uncork();
- fprintf(stderr, "Uncorked now\n");
- NSLOG(test, WARN, "argc=%d", argc);
- for (int i = 0; i < argc; ++i)
- NSLOG(test, WARN, "argv[%d] = %s", i, argv[i]);
- return 0;
-}
diff --git a/test/basictests.c b/test/basictests.c
new file mode 100644
index 0000000..4d94059
--- /dev/null
+++ b/test/basictests.c
@@ -0,0 +1,218 @@
+/* test/basictests.c
+ *
+ * Basic tests for the test suite for libnslog
+ *
+ * Copyright 2009,2017 The NetSurf Browser Project
+ * Daniel Silverstone <[email protected]>
+ */
+
+#include <check.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "tests.h"
+
+#ifndef UNUSED
+#define UNUSED(x) (void)(x)
+#endif
+
+#ifndef NDEBUG
+
+/* Tests go here which need assert() to be checked */
+
+#endif
+
+NSLOG_DEFINE_CATEGORY(test, "Top level test category");
+
+static void *captured_render_context = NULL;
+static nslog_entry_context_t captured_context = { 0 };
+static char captured_rendered_message[4096] = { 0 };
+static int captured_rendered_message_length = 0;
+static int captured_message_count = 0;
+
+static const char* anchor_context_1 = "1";
+
+static void
+nslog__test__render_function(void *_ctx, nslog_entry_context_t *ctx,
+ const char *fmt, va_list args)
+{
+ captured_context = *ctx;
+ captured_render_context = _ctx;
+ captured_rendered_message_length =
+ vsnprintf(captured_rendered_message,
+ sizeof(captured_rendered_message),
+ fmt, args);
+ captured_message_count++;
+}
+
+/**** The next set of tests need a fixture set ****/
+
+static void
+with_simple_context_setup(void)
+{
+ captured_render_context = NULL;
+ memset(&captured_context, 0, sizeof(captured_context));
+ memset(captured_rendered_message, 0, sizeof(captured_rendered_message));
+ captured_rendered_message_length = 0;
+ captured_message_count = 0;
+ fail_unless(nslog_set_render_callback(
+ nslog__test__render_function,
+ (void *)anchor_context_1) == NSLOG_NO_ERROR,
+ "Unable to set up render callback");
+}
+
+static void
+with_simple_context_teardown(void)
+{
+ /* Nothing to do to tear down */
+}
+
+START_TEST (test_nslog_trivial_corked_message)
+{
+ NSLOG(test, INFO, "Hello %s", "world");
+ fail_unless(nslog_uncork() == NSLOG_NO_ERROR,
+ "Unable to uncork");
+ fail_unless(captured_message_count == 1,
+ "Captured message count was wrong");
+ fail_unless(captured_render_context == anchor_context_1,
+ "Captured context wasn't passed through");
+ fail_unless(strcmp(captured_context.category->name, "test") == 0,
+ "Captured context category wasn't normalised");
+ fail_unless(captured_context.category == &__nslog_category_test,
+ "Captured context category wasn't the one we wanted");
+ fail_unless(captured_rendered_message_length == 11,
+ "Captured message wasn't correct length");
+ fail_unless(strcmp(captured_rendered_message, "Hello world") == 0,
+ "Captured message wasn't correct");
+ fail_unless(strcmp(captured_context.filename, "test/basictests.c") == 0,
+ "Captured message wasn't correct filename");
+ fail_unless(strcmp(captured_context.funcname,
"test_nslog_trivial_corked_message") == 0,
+ "Captured message wasn't correct function name");
+}
+END_TEST
+
+START_TEST (test_nslog_trivial_uncorked_message)
+{
+ fail_unless(nslog_uncork() == NSLOG_NO_ERROR,
+ "Unable to uncork");
+ fail_unless(captured_message_count == 0,
+ "Unusual, we had messages from before uncorking");
+ NSLOG(test, INFO, "Hello %s", "world");
+ fail_unless(captured_message_count == 1,
+ "Captured message count was wrong");
+ fail_unless(captured_render_context == anchor_context_1,
+ "Captured context wasn't passed through");
+ fail_unless(strcmp(captured_context.category->name, "test") == 0,
+ "Captured context category wasn't normalised");
+ fail_unless(captured_context.category == &__nslog_category_test,
+ "Captured context category wasn't the one we wanted");
+ fail_unless(captured_rendered_message_length == 11,
+ "Captured message wasn't correct length");
+ fail_unless(strcmp(captured_rendered_message, "Hello world") == 0,
+ "Captured message wasn't correct");
+ fail_unless(strcmp(captured_context.filename, "test/basictests.c") == 0,
+ "Captured message wasn't correct filename");
+ fail_unless(strcmp(captured_context.funcname,
"test_nslog_trivial_uncorked_message") == 0,
+ "Captured message wasn't correct function name");
+}
+END_TEST
+
+/**** The next set of tests need a fixture set for filters ****/
+
+static nslog_filter_t *cat_test = NULL;
+static nslog_filter_t *cat_another = NULL;
+
+static const char *anchor_context_2 = "2";
+
+static void
+with_simple_filter_context_setup(void)
+{
+ captured_render_context = NULL;
+ memset(&captured_context, 0, sizeof(captured_context));
+ memset(captured_rendered_message, 0, sizeof(captured_rendered_message));
+ captured_rendered_message_length = 0;
+ captured_message_count = 0;
+ fail_unless(nslog_set_render_callback(
+ nslog__test__render_function,
+ (void *)anchor_context_2) == NSLOG_NO_ERROR,
+ "Unable to set up render callback");
+ fail_unless(nslog_filter_category_new("test", &cat_test) ==
NSLOG_NO_ERROR,
+ "Unable to create a category filter for 'test'");
+ fail_unless(nslog_filter_category_new("another", &cat_another) ==
NSLOG_NO_ERROR,
+ "Unable to create a category filter for 'another'");
+}
+
+static void
+with_simple_filter_context_teardown(void)
+{
+ /* Nothing to do to tear down */
+ fail_unless(nslog_filter_set_active(NULL, NULL) == NSLOG_NO_ERROR,
+ "Unable to clear active filter");
+ cat_test = nslog_filter_unref(cat_test);
+ cat_another = nslog_filter_unref(cat_another);
+}
+
+START_TEST (test_nslog_simple_filter_corked_message)
+{
+ NSLOG(test, INFO, "Hello world");
+ fail_unless(nslog_filter_set_active(cat_test, NULL) == NSLOG_NO_ERROR,
+ "Unable to set active filter to cat:test");
+ fail_unless(nslog_uncork() == NSLOG_NO_ERROR,
+ "Unable to uncork");
+ fail_unless(captured_message_count == 1,
+ "Captured message count was wrong");
+ fail_unless(captured_render_context == anchor_context_2,
+ "Captured context wasn't passed through");
+ fail_unless(strcmp(captured_context.category->name, "test") == 0,
+ "Captured context category wasn't normalised");
+ fail_unless(captured_context.category == &__nslog_category_test,
+ "Captured context category wasn't the one we wanted");
+ fail_unless(captured_rendered_message_length == 11,
+ "Captured message wasn't correct length");
+ fail_unless(strcmp(captured_rendered_message, "Hello world") == 0,
+ "Captured message wasn't correct");
+ fail_unless(strcmp(captured_context.filename, "test/basictests.c") == 0,
+ "Captured message wasn't correct filename");
+ fail_unless(strcmp(captured_context.funcname,
"test_nslog_simple_filter_corked_message") == 0,
+ "Captured message wasn't correct function name");
+
+}
+END_TEST
+
+/**** And the suites are set up here ****/
+
+void
+nslog_basic_suite(SRunner *sr)
+{
+ Suite *s = suite_create("libnslog: Basic tests");
+ TCase *tc_basic = tcase_create("Abort checking");
+
+#ifndef NDEBUG
+ /*
+ tcase_add_test_raise_signal(tc_basic,
+ test_lwc_string_hash_value_aborts,
+ SIGABRT);
+ */
+#endif
+
+ suite_add_tcase(s, tc_basic);
+
+ tc_basic = tcase_create("Simple log checks, no filters");
+
+ tcase_add_checked_fixture(tc_basic, with_simple_context_setup,
+ with_simple_context_teardown);
+ tcase_add_test(tc_basic, test_nslog_trivial_corked_message);
+ tcase_add_test(tc_basic, test_nslog_trivial_uncorked_message);
+ suite_add_tcase(s, tc_basic);
+
+ tc_basic = tcase_create("Simple filter checks");
+
+ tcase_add_checked_fixture(tc_basic, with_simple_filter_context_setup,
+ with_simple_filter_context_teardown);
+ tcase_add_test(tc_basic, test_nslog_simple_filter_corked_message);
+ suite_add_tcase(s, tc_basic);
+
+ srunner_add_suite(sr, s);
+}
diff --git a/test/explicitfilter.c b/test/explicitfilter.c
deleted file mode 100644
index c7aca8a..0000000
--- a/test/explicitfilter.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2017 Daniel Silverstone <[email protected]>
- *
- * This file is part of libnslog.
- *
- * Licensed under the MIT License,
- * http://www.opensource.org/licenses/mit-license.php
- */
-
-#include "nslog/nslog.h"
-
-#include <stdio.h>
-#include <assert.h>
-
-NSLOG_DEFINE_CATEGORY(test, "Test category");
-
-static void test_render_function(
- void *_ctx, nslog_entry_context_t *ctx,
- const char *fmt, va_list args)
-{
- (void)ctx;
- fprintf(stderr, "%s %s:%d [%s] %s() ",
- nslog_level_name(ctx->level),
- ctx->filename, ctx->lineno,
- ctx->category->name,
- ctx->funcname);
- vfprintf(stderr, fmt, args);
- fprintf(stderr, "\n");
-}
-
-int main(int argc, char **argv)
-{
- nslog_set_render_callback(test_render_function, NULL);
- nslog_uncork();
-
- nslog_filter_t *cat_test, *cat_another;
-
- assert(nslog_filter_category_new("test", &cat_test) == NSLOG_NO_ERROR);
- assert(nslog_filter_category_new("another", &cat_another) ==
NSLOG_NO_ERROR);
-
- NSLOG(test, INFO, "Hurrah, a message!");
- assert(nslog_filter_set_active(cat_test, NULL) == NSLOG_NO_ERROR);
- NSLOG(test, INFO, "You should see me.");
- assert(nslog_filter_set_active(cat_another, NULL) == NSLOG_NO_ERROR);
- NSLOG(test, INFO, "You should not see me!");
- assert(nslog_filter_set_active(NULL, NULL) == NSLOG_NO_ERROR);
- NSLOG(test, INFO, "You should see this one though.");
-
- return 0;
-}
diff --git a/test/testmain.c b/test/testmain.c
new file mode 100644
index 0000000..9a6b257
--- /dev/null
+++ b/test/testmain.c
@@ -0,0 +1,50 @@
+/* test/testmain.c
+ *
+ * Core of the test suite for libnslog
+ *
+ * Copyright 2009, 2017 The NetSurf Browser Project
+ * Daniel Silverstone <[email protected]>
+ */
+
+#include <check.h>
+#include <stdlib.h>
+
+#include "tests.h"
+
+#ifndef UNUSED
+#define UNUSED(x) ((x) = (x))
+#endif
+
+/* This means that assertion failures are silent in tests */
+#ifndef NDEBUG
+void __assert_fail(const char *__assertion, const char *__file,
+ unsigned int __line, const char *__function) {
+ (void)__assertion;
+ (void)__file;
+ (void)__line;
+ (void)__function;
+ abort();
+}
+#endif
+
+int
+main(int argc, char **argv)
+{
+ int number_failed = 0;
+ SRunner *sr;
+
+ UNUSED(argc);
+ UNUSED(argv);
+
+ sr = srunner_create(suite_create("Test suite for libnslog"));
+
+ nslog_basic_suite(sr);
+
+ srunner_set_fork_status(sr, CK_FORK);
+ srunner_run_all(sr, CK_ENV);
+ number_failed = srunner_ntests_failed(sr);
+
+ srunner_free(sr);
+
+ return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/test/tests.h b/test/tests.h
new file mode 100644
index 0000000..37cdd8d
--- /dev/null
+++ b/test/tests.h
@@ -0,0 +1,21 @@
+/* test/tests.h
+ *
+ * Set of test suites for libnslog
+ *
+ * Copyright 2009,2017 The NetSurf Browser Project
+ * Daniel Silverstone <[email protected]>
+ */
+
+#ifndef nslog_tests_h_
+#define nslog_tests_h_
+
+#include <assert.h>
+#include <signal.h>
+
+#include <check.h>
+
+#include "nslog/nslog.h"
+
+extern void nslog_basic_suite(SRunner *);
+
+#endif /* nslog_tests_h_ */
commitdiff
http://git.netsurf-browser.org/libnslog.git/commit/?id=8b4ce0ba86d0396bde2546dd248c863876da4106
commit 8b4ce0ba86d0396bde2546dd248c863876da4106
Author: Daniel Silverstone <[email protected]>
Commit: Daniel Silverstone <[email protected]>
Another step toward filters working
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..f24cd50
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,19 @@
+# This is an EditorConfig file
+# Learn more at http://editorconfig.org
+
+root = true
+
+# All files are UNIX-style and UTF-8
+[*]
+end_of_line = lf
+insert_final_newline = true
+charset = utf-8
+trim_trailing_whitespace = true
+
+# Makefiles use tabs
+[Makefile]
+indent_style = tab
+
+# C code uses tabs
+[*.{c,h}]
+indent_style = tab
diff --git a/include/nslog/nslog.h b/include/nslog/nslog.h
index ffa87bd..550bffb 100644
--- a/include/nslog/nslog.h
+++ b/include/nslog/nslog.h
@@ -4,7 +4,7 @@
* This file is part of libnslog.
*
* Licensed under the MIT License,
- * http://www.opensource.org/licenses/mit-license.php
+ * http://www.opensource.org/licenses/mit-license.php
*/
/**
@@ -18,41 +18,44 @@
#include <stdarg.h>
typedef enum {
- NSLOG_LEVEL_DEEPDEBUG = 0,
- NSLOG_LEVEL_DEBUG = 1,
- NSLOG_LEVEL_VERBOSE = 2,
- NSLOG_LEVEL_INFO = 3,
- NSLOG_LEVEL_WARNING = 4,
- NSLOG_LEVEL_ERROR = 5,
- NSLOG_LEVEL_CRITICAL = 6,
+ NSLOG_LEVEL_DEEPDEBUG = 0,
+ NSLOG_LEVEL_DEBUG = 1,
+ NSLOG_LEVEL_VERBOSE = 2,
+ NSLOG_LEVEL_INFO = 3,
+ NSLOG_LEVEL_WARNING = 4,
+ NSLOG_LEVEL_ERROR = 5,
+ NSLOG_LEVEL_CRITICAL = 6,
} nslog_level;
const char *nslog_level_name(nslog_level level);
-#define NSLOG_LEVEL_DD NSLOG_LEVEL_DEEPDEBUG
-#define NSLOG_LEVEL_CHAT NSLOG_LEVEL_VERBOSE
-#define NSLOG_LEVEL_WARN NSLOG_LEVEL_WARNING
-#define NSLOG_LEVEL_ERR NSLOG_LEVEL_ERROR
-#define NSLOG_LEVEL_CRIT NSLOG_LEVEL_CRITICAL
+#define NSLOG_LEVEL_DD NSLOG_LEVEL_DEEPDEBUG
+#define NSLOG_LEVEL_CHAT NSLOG_LEVEL_VERBOSE
+#define NSLOG_LEVEL_WARN NSLOG_LEVEL_WARNING
+#define NSLOG_LEVEL_ERR NSLOG_LEVEL_ERROR
+#define NSLOG_LEVEL_CRIT NSLOG_LEVEL_CRITICAL
#ifndef NSLOG_COMPILED_MIN_LEVEL
#define NSLOG_COMPILED_MIN_LEVEL NSLOG_LEVEL_DEBUG
#endif
typedef struct nslog_category_s {
- const char *cat_name;
- const char *description;
- struct nslog_category_s *parent;
- char *name;
- struct nslog_category_s *next;
+ const char *cat_name;
+ const char *description;
+ struct nslog_category_s *parent;
+ char *name;
+ int namelen;
+ struct nslog_category_s *next;
} nslog_category_t;
typedef struct nslog_entry_context_s {
- nslog_category_t *category;
- nslog_level level;
- const char *filename;
+ nslog_category_t *category;
+ nslog_level level;
+ const char *filename;
+ int filenamelen;
const char *funcname;
- int lineno;
+ int funcnamelen;
+ int lineno;
} nslog_entry_context_t;
#define NSLOG_DECLARE_CATEGORY(catname) \
@@ -64,6 +67,7 @@ typedef struct nslog_entry_context_s {
description, \
NULL, \
NULL, \
+ 0, \
NULL, \
}
@@ -73,6 +77,7 @@ typedef struct nslog_entry_context_s {
description, \
&__nslog_category_##parentcatname, \
NULL, \
+ 0, \
NULL, \
}
@@ -83,7 +88,9 @@ typedef struct nslog_entry_context_s {
&__nslog_category_##catname, \
NSLOG_LEVEL_##level, \
__FILE__, \
+ sizeof(__FILE__) - 1, \
__PRETTY_FUNCTION__, \
+ sizeof(__PRETTY_FUNCTION__) - 1, \
__LINE__, \
}; \
nslog__log(&ctx, logmsg, ##args); \
@@ -106,4 +113,35 @@ nslog_error nslog_set_render_callback(nslog_callback cb,
void *context);
nslog_error nslog_uncork(void);
+typedef struct nslog_filter_s nslog_filter_t;
+
+nslog_error nslog_filter_category_new(const char *catname,
+ nslog_filter_t **filter);
+nslog_error nslog_filter_level_new(nslog_level level,
+ nslog_filter_t **filter);
+nslog_error nslog_filter_filename_new(const char *filename,
+ nslog_filter_t **filter);
+nslog_error nslog_filter_dirname_new(const char *dirname,
+ nslog_filter_t **filter);
+nslog_error nslog_filter_funcname_new(const char *funcname,
+ nslog_filter_t **filter);
+
+nslog_error nslog_filter_and_new(nslog_filter_t *left,
+ nslog_filter_t *right,
+ nslog_filter_t **filter);
+nslog_error nslog_filter_or_new(nslog_filter_t *left,
+ nslog_filter_t *right,
+ nslog_filter_t **filter);
+nslog_error nslog_filter_xor_new(nslog_filter_t *left,
+ nslog_filter_t *right,
+ nslog_filter_t **filter);
+nslog_error nslog_filter_not_new(nslog_filter_t *input,
+ nslog_filter_t **filter);
+
+nslog_filter_t *nslog_filter_ref(nslog_filter_t *filter);
+nslog_filter_t *nslog_filter_unref(nslog_filter_t *filter);
+
+nslog_error nslog_filter_set_active(nslog_filter_t *filter,
+ nslog_filter_t **prev);
+
#endif /* NSLOG_NSLOG_H_ */
diff --git a/src/Makefile b/src/Makefile
index 45ecb90..7fbad1c 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,3 +1,3 @@
-DIR_SOURCES := core.c
+DIR_SOURCES := core.c filter.c
include $(NSBUILD)/Makefile.subdir
diff --git a/src/core.c b/src/core.c
index ee5f2bc..978f169 100644
--- a/src/core.c
+++ b/src/core.c
@@ -4,7 +4,7 @@
* This file is part of libnslog.
*
* Licensed under the MIT License,
- * http://www.opensource.org/licenses/mit-license.php
+ * http://www.opensource.org/licenses/mit-license.php
*/
/**
@@ -12,21 +12,14 @@
* NetSurf Logging Core
*/
-#include "nslog/nslog.h"
-
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-
+#include "nslog_internal.h"
static bool nslog__corked = true;
static struct nslog_cork_chain {
struct nslog_cork_chain *next;
nslog_entry_context_t context;
- char message[0]; /* NUL terminated */
+ char message[0]; /* NUL terminated */
} *nslog__cork_chain = NULL, *nslog__cork_chain_last = NULL;
static nslog_callback nslog__cb = NULL;
@@ -52,7 +45,7 @@ const char *nslog_level_name(nslog_level level)
case NSLOG_LEVEL_CRITICAL:
return "CRITICAL";
};
-
+
return "**UNKNOWN**";
}
@@ -61,6 +54,7 @@ static void nslog__normalise_category(nslog_category_t *cat)
{
if (cat->parent == NULL) {
cat->name = strdup(cat->cat_name);
+ cat->namelen = strlen(cat->name);
} else {
nslog__normalise_category(cat->parent);
cat->name = malloc(strlen(cat->parent->name) +
strlen(cat->cat_name) + 2);
@@ -68,6 +62,7 @@ static void nslog__normalise_category(nslog_category_t *cat)
strcat(cat->name, "/");
strcat(cat->name, cat->cat_name);
cat->next = nslog__all_categories;
+ cat->namelen = strlen(cat->name);
nslog__all_categories = cat;
}
}
@@ -102,7 +97,8 @@ static void nslog__log_uncorked(nslog_entry_context_t *ctx,
if (ctx->category->name == NULL) {
nslog__normalise_category(ctx->category);
}
- (*nslog__cb)(nslog__cb_ctx, ctx, fmt, args);
+ if (nslog__filter_matches(ctx))
+ (*nslog__cb)(nslog__cb_ctx, ctx, fmt, args);
}
}
@@ -129,7 +125,7 @@ nslog_error nslog_set_render_callback(nslog_callback cb,
void *context)
{
nslog__cb = cb;
nslog__cb_ctx = context;
-
+
return NSLOG_NO_ERROR;
}
@@ -155,12 +151,12 @@ nslog_error nslog_uncork()
if (ent->context.category->name == NULL) {
nslog__normalise_category(ent->context.category);
}
- __nslog__deliver_corked_entry(&ent->context,
- "%s", ent->message);
+ if (nslog__filter_matches(&ent->context))
+ __nslog__deliver_corked_entry(&ent->context,
+ "%s",
ent->message);
free(ent);
}
nslog__corked = false;
}
return NSLOG_NO_ERROR;
}
-
diff --git a/src/filter.c b/src/filter.c
new file mode 100644
index 0000000..1dc4e81
--- /dev/null
+++ b/src/filter.c
@@ -0,0 +1,310 @@
+/*
+ * Copyright 2017 Daniel Silverstone <[email protected]>
+ *
+ * This file is part of libnslog.
+ *
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+
+/**
+ * \file
+ * NetSurf Logging Filters
+ */
+
+#include "nslog_internal.h"
+
+typedef enum {
+ /* Fundamentals */
+ NSLFK_CATEGORY = 0,
+ NSLFK_LEVEL,
+ NSLFK_FILENAME,
+ NSLFK_DIRNAME,
+ NSLFK_FUNCNAME,
+ /* logical operations */
+ NSLFK_AND,
+ NSLFK_OR,
+ NSLFK_XOR,
+ NSLFK_NOT,
+} nslog_filter_kind;
+
+struct nslog_filter_s {
+ nslog_filter_kind kind;
+ int refcount;
+ union {
+ struct {
+ char *ptr;
+ int len;
+ } str;
+ nslog_level level;
+ nslog_filter_t *unary_input;
+ struct {
+ nslog_filter_t *input1;
+ nslog_filter_t *input2;
+ } binary;
+ } params;
+};
+
+static nslog_filter_t *nslog__active_filter = NULL;
+
+nslog_error nslog_filter_category_new(const char *catname,
+ nslog_filter_t **filter)
+{
+ nslog_filter_t *ret = calloc(sizeof(*ret), 1);
+ if (ret == NULL)
+ return NSLOG_NO_MEMORY;
+ ret->kind = NSLFK_CATEGORY;
+ ret->refcount = 1;
+ ret->params.str.ptr = strdup(catname);
+ ret->params.str.len = strlen(catname);
+ if (ret->params.str.ptr == NULL) {
+ free(ret);
+ return NSLOG_NO_MEMORY;
+ }
+ *filter = ret;
+ return NSLOG_NO_ERROR;
+}
+
+nslog_error nslog_filter_level_new(nslog_level level,
+ nslog_filter_t **filter)
+{
+ nslog_filter_t *ret = calloc(sizeof(*ret), 1);
+ if (ret == NULL)
+ return NSLOG_NO_MEMORY;
+ ret->kind = NSLFK_LEVEL;
+ ret->refcount = 1;
+ ret->params.level = level;
+ *filter = ret;
+ return NSLOG_NO_ERROR;
+}
+
+nslog_error nslog_filter_filename_new(const char *filename,
+ nslog_filter_t **filter)
+{
+ nslog_filter_t *ret = calloc(sizeof(*ret), 1);
+ if (ret == NULL)
+ return NSLOG_NO_MEMORY;
+ ret->kind = NSLFK_FILENAME;
+ ret->refcount = 1;
+ ret->params.str.ptr = strdup(filename);
+ ret->params.str.len = strlen(filename);
+ if (ret->params.str.ptr == NULL) {
+ free(ret);
+ return NSLOG_NO_MEMORY;
+ }
+ *filter = ret;
+ return NSLOG_NO_ERROR;
+}
+
+nslog_error nslog_filter_dirname_new(const char *dirname,
+ nslog_filter_t **filter)
+{
+ nslog_filter_t *ret = calloc(sizeof(*ret), 1);
+ if (ret == NULL)
+ return NSLOG_NO_MEMORY;
+ ret->kind = NSLFK_DIRNAME;
+ ret->refcount = 1;
+ ret->params.str.ptr = strdup(dirname);
+ ret->params.str.len = strlen(dirname);
+ if (ret->params.str.ptr == NULL) {
+ free(ret);
+ return NSLOG_NO_MEMORY;
+ }
+ *filter = ret;
+ return NSLOG_NO_ERROR;
+}
+
+nslog_error nslog_filter_funcname_new(const char *funcname,
+ nslog_filter_t **filter)
+{
+ nslog_filter_t *ret = calloc(sizeof(*ret), 1);
+ if (ret == NULL)
+ return NSLOG_NO_MEMORY;
+ ret->kind = NSLFK_FUNCNAME;
+ ret->refcount = 1;
+ ret->params.str.ptr = strdup(funcname);
+ ret->params.str.len = strlen(funcname);
+ if (ret->params.str.ptr == NULL) {
+ free(ret);
+ return NSLOG_NO_MEMORY;
+ }
+ *filter = ret;
+ return NSLOG_NO_ERROR;
+}
+
+
+nslog_error nslog_filter_and_new(nslog_filter_t *left,
+ nslog_filter_t *right,
+ nslog_filter_t **filter)
+{
+ nslog_filter_t *ret = calloc(sizeof(*ret), 1);
+ if (ret == NULL)
+ return NSLOG_NO_MEMORY;
+ ret->kind = NSLFK_AND;
+ ret->refcount = 1;
+ ret->params.binary.input1 = nslog_filter_ref(left);
+ ret->params.binary.input2 = nslog_filter_ref(right);
+ *filter = ret;
+ return NSLOG_NO_ERROR;
+}
+
+nslog_error nslog_filter_or_new(nslog_filter_t *left,
+ nslog_filter_t *right,
+ nslog_filter_t **filter)
+{
+ nslog_filter_t *ret = calloc(sizeof(*ret), 1);
+ if (ret == NULL)
+ return NSLOG_NO_MEMORY;
+ ret->kind = NSLFK_OR;
+ ret->refcount = 1;
+ ret->params.binary.input1 = nslog_filter_ref(left);
+ ret->params.binary.input2 = nslog_filter_ref(right);
+ *filter = ret;
+ return NSLOG_NO_ERROR;
+}
+
+nslog_error nslog_filter_xor_new(nslog_filter_t *left,
+ nslog_filter_t *right,
+ nslog_filter_t **filter)
+{
+ nslog_filter_t *ret = calloc(sizeof(*ret), 1);
+ if (ret == NULL)
+ return NSLOG_NO_MEMORY;
+ ret->kind = NSLFK_XOR;
+ ret->refcount = 1;
+ ret->params.binary.input1 = nslog_filter_ref(left);
+ ret->params.binary.input2 = nslog_filter_ref(right);
+ *filter = ret;
+ return NSLOG_NO_ERROR;
+}
+
+nslog_error nslog_filter_not_new(nslog_filter_t *input,
+ nslog_filter_t **filter)
+{
+ nslog_filter_t *ret = calloc(sizeof(*ret), 1);
+ if (ret == NULL)
+ return NSLOG_NO_MEMORY;
+ ret->kind = NSLFK_NOT;
+ ret->refcount = 1;
+ ret->params.unary_input = nslog_filter_ref(input);
+ *filter = ret;
+ return NSLOG_NO_ERROR;
+}
+
+
+nslog_filter_t *nslog_filter_ref(nslog_filter_t *filter)
+{
+ if (filter != NULL)
+ filter->refcount++;
+
+ return filter;
+}
+
+nslog_filter_t *nslog_filter_unref(nslog_filter_t *filter)
+{
+ if (filter != NULL && filter->refcount-- == 1) {
+ switch(filter->kind) {
+ case NSLFK_CATEGORY:
+ case NSLFK_FILENAME:
+ case NSLFK_DIRNAME:
+ case NSLFK_FUNCNAME:
+ free(filter->params.str.ptr);
+ break;
+ case NSLFK_AND:
+ case NSLFK_OR:
+ case NSLFK_XOR:
+ nslog_filter_unref(filter->params.binary.input1);
+ nslog_filter_unref(filter->params.binary.input2);
+ break;
+ case NSLFK_NOT:
+ nslog_filter_unref(filter->params.unary_input);
+ break;
+ default:
+ /* Nothing to do for the other kind(s) */
+ break;
+ }
+ free(filter);
+ }
+
+ return NULL;
+}
+
+nslog_error nslog_filter_set_active(nslog_filter_t *filter,
+ nslog_filter_t **prev)
+{
+ if (prev != NULL)
+ *prev = nslog__active_filter;
+ else
+ nslog_filter_unref(nslog__active_filter);
+
+ nslog__active_filter = nslog_filter_ref(filter);
+
+ return NSLOG_NO_ERROR;
+}
+
+static bool _nslog__filter_matches(nslog_entry_context_t *ctx,
+ nslog_filter_t *filter)
+{
+ switch (filter->kind) {
+ case NSLFK_CATEGORY:
+ if (filter->params.str.len > ctx->category->namelen)
+ return false;
+ if (ctx->category->name[filter->params.str.len] != '\0' &&
+ ctx->category->name[filter->params.str.len] != '/')
+ return false;
+ return (strncmp(filter->params.str.ptr,
+ ctx->category->name,
+ filter->params.str.len) == 0);
+
+ case NSLFK_LEVEL:
+ return (ctx->level >= filter->params.level);
+ case NSLFK_FILENAME:
+ if (filter->params.str.len > ctx->filenamelen)
+ return false;
+ if ((filter->params.str.len == ctx->filenamelen) &&
+ (strcmp(filter->params.str.ptr, ctx->filename) == 0))
+ return true;
+ if ((ctx->filename[ctx->filenamelen - filter->params.str.len -
1] == '/')
+ && (strcmp(filter->params.str.ptr,
+ ctx->filename + ctx->filenamelen -
filter->params.str.len) == 0))
+ return true;
+ return false;
+ case NSLFK_DIRNAME:
+ if (filter->params.str.len >= ctx->filenamelen)
+ return false;
+ if ((ctx->filename[filter->params.str.len] == '/')
+ && (strncmp(filter->params.str.ptr,
+ ctx->filename,
+ filter->params.str.len) == 0))
+ return true;
+ return false;
+ case NSLFK_FUNCNAME:
+ return (filter->params.str.len == ctx->funcnamelen &&
+ strcmp(ctx->funcname, filter->params.str.ptr) == 0);
+ case NSLFK_AND:
+ return (_nslog__filter_matches(ctx,
filter->params.binary.input1)
+ &&
+ _nslog__filter_matches(ctx,
filter->params.binary.input2));
+ case NSLFK_OR:
+ return (_nslog__filter_matches(ctx,
filter->params.binary.input1)
+ ||
+ _nslog__filter_matches(ctx,
filter->params.binary.input2));
+ case NSLFK_XOR:
+ return (_nslog__filter_matches(ctx,
filter->params.binary.input1)
+ ^
+ _nslog__filter_matches(ctx,
filter->params.binary.input2));
+ case NSLFK_NOT:
+ return !_nslog__filter_matches(ctx, filter->params.unary_input);
+ default:
+ /* unknown */
+ assert("Unknown filter kind" == NULL);
+ return false;
+ }
+}
+
+bool nslog__filter_matches(nslog_entry_context_t *ctx)
+{
+ if (nslog__active_filter == NULL)
+ return true;
+ return _nslog__filter_matches(ctx, nslog__active_filter);
+}
diff --git a/src/nslog_internal.h b/src/nslog_internal.h
new file mode 100644
index 0000000..d5519e7
--- /dev/null
+++ b/src/nslog_internal.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2017 Daniel Silverstone <[email protected]>
+ *
+ * This file is part of libnslog.
+ *
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+
+/**
+ * \file
+ * NetSurf Logging
+ */
+
+#ifndef NSLOG_INTERNAL_H_
+#define NSLOG_INTERNAL_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdarg.h>
+#include <assert.h>
+
+#include "nslog/nslog.h"
+
+bool nslog__filter_matches(nslog_entry_context_t *ctx);
+
+#endif /* NSLOG_INTERNAL_H_ */
diff --git a/test/Makefile b/test/Makefile
index 0cebdaa..033033f 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -1,3 +1,3 @@
-DIR_TEST_ITEMS := basic:basic.c
+DIR_TEST_ITEMS := basic:basic.c explicitfilter:explicitfilter.c
include $(NSBUILD)/Makefile.subdir
diff --git a/test/basic.c b/test/basic.c
index 7626dd8..d514814 100644
--- a/test/basic.c
+++ b/test/basic.c
@@ -4,7 +4,7 @@
* This file is part of libnslog.
*
* Licensed under the MIT License,
- * http://www.opensource.org/licenses/mit-license.php
+ * http://www.opensource.org/licenses/mit-license.php
*/
#include "nslog/nslog.h"
@@ -18,10 +18,10 @@ static void test_render_function(
const char *fmt, va_list args)
{
(void)ctx;
- fprintf(stderr, "%s %s:%d [%s] %s() ",
- nslog_level_name(ctx->level),
- ctx->filename, ctx->lineno,
- ctx->category->name,
+ fprintf(stderr, "%s %s:%d [%s] %s() ",
+ nslog_level_name(ctx->level),
+ ctx->filename, ctx->lineno,
+ ctx->category->name,
ctx->funcname);
vfprintf(stderr, fmt, args);
fprintf(stderr, "\n");
diff --git a/test/explicitfilter.c b/test/explicitfilter.c
new file mode 100644
index 0000000..c7aca8a
--- /dev/null
+++ b/test/explicitfilter.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2017 Daniel Silverstone <[email protected]>
+ *
+ * This file is part of libnslog.
+ *
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+
+#include "nslog/nslog.h"
+
+#include <stdio.h>
+#include <assert.h>
+
+NSLOG_DEFINE_CATEGORY(test, "Test category");
+
+static void test_render_function(
+ void *_ctx, nslog_entry_context_t *ctx,
+ const char *fmt, va_list args)
+{
+ (void)ctx;
+ fprintf(stderr, "%s %s:%d [%s] %s() ",
+ nslog_level_name(ctx->level),
+ ctx->filename, ctx->lineno,
+ ctx->category->name,
+ ctx->funcname);
+ vfprintf(stderr, fmt, args);
+ fprintf(stderr, "\n");
+}
+
+int main(int argc, char **argv)
+{
+ nslog_set_render_callback(test_render_function, NULL);
+ nslog_uncork();
+
+ nslog_filter_t *cat_test, *cat_another;
+
+ assert(nslog_filter_category_new("test", &cat_test) == NSLOG_NO_ERROR);
+ assert(nslog_filter_category_new("another", &cat_another) ==
NSLOG_NO_ERROR);
+
+ NSLOG(test, INFO, "Hurrah, a message!");
+ assert(nslog_filter_set_active(cat_test, NULL) == NSLOG_NO_ERROR);
+ NSLOG(test, INFO, "You should see me.");
+ assert(nslog_filter_set_active(cat_another, NULL) == NSLOG_NO_ERROR);
+ NSLOG(test, INFO, "You should not see me!");
+ assert(nslog_filter_set_active(NULL, NULL) == NSLOG_NO_ERROR);
+ NSLOG(test, INFO, "You should see this one though.");
+
+ return 0;
+}
diff --git a/test/runtest.sh b/test/runtest.sh
index 1b67a97..3bf903e 100755
--- a/test/runtest.sh
+++ b/test/runtest.sh
@@ -5,7 +5,7 @@ set -e
TEST_PATH=$1
TEST_PFX=$4
-for TEST in basic; do
+for TEST in basic explicitfilter; do
${TEST_PATH}/${TEST_PFX}${TEST}
done
commitdiff
http://git.netsurf-browser.org/libnslog.git/commit/?id=8052642eadfb95b244f978b10889dff51f9133f5
commit 8052642eadfb95b244f978b10889dff51f9133f5
Author: Daniel Silverstone <[email protected]>
Commit: Daniel Silverstone <[email protected]>
Rework to only allocate one thing in the corked state and nothing in the
uncorked state
diff --git a/include/nslog/nslog.h b/include/nslog/nslog.h
index fff31a7..ffa87bd 100644
--- a/include/nslog/nslog.h
+++ b/include/nslog/nslog.h
@@ -15,6 +15,8 @@
#ifndef NSLOG_NSLOG_H_
#define NSLOG_NSLOG_H_
+#include <stdarg.h>
+
typedef enum {
NSLOG_LEVEL_DEEPDEBUG = 0,
NSLOG_LEVEL_DEBUG = 1,
@@ -45,16 +47,15 @@ typedef struct nslog_category_s {
struct nslog_category_s *next;
} nslog_category_t;
-typedef struct nslog_entry_s {
+typedef struct nslog_entry_context_s {
nslog_category_t *category;
nslog_level level;
const char *filename;
const char *funcname;
int lineno;
- char message[0]; /* NUL terminated */
-} nslog_entry_t;
+} nslog_entry_context_t;
-#define NSLOG_DECLARE_CATEGORY(catname) \
+#define NSLOG_DECLARE_CATEGORY(catname) \
extern nslog_category_t __nslog_category_##catname
#define NSLOG_DEFINE_CATEGORY(catname, description) \
@@ -75,31 +76,31 @@ typedef struct nslog_entry_s {
NULL, \
}
-#define NSLOG(catname, level, logmsg, args...) \
- if (NSLOG_LEVEL_##level >= NSLOG_COMPILED_MIN_LEVEL) { \
- nslog__log(&__nslog_category_##catname, \
- NSLOG_LEVEL_##level, \
- __FILE__, \
- __LINE__, \
- __PRETTY_FUNCTION__, \
- logmsg, \
- ##args); \
- }
-
-void nslog__log(nslog_category_t *category,
- nslog_level level,
- const char *filename,
- int lineno,
- const char *funcname,
+#define NSLOG(catname, level, logmsg, args...) \
+ do { \
+ if (NSLOG_LEVEL_##level >= NSLOG_COMPILED_MIN_LEVEL) { \
+ nslog_entry_context_t ctx = { \
+ &__nslog_category_##catname, \
+ NSLOG_LEVEL_##level, \
+ __FILE__, \
+ __PRETTY_FUNCTION__, \
+ __LINE__, \
+ }; \
+ nslog__log(&ctx, logmsg, ##args); \
+ } \
+ } while(0)
+
+void nslog__log(nslog_entry_context_t *ctx,
const char *pattern,
- ...) __attribute__ ((format (printf, 6, 7)));
+ ...) __attribute__ ((format (printf, 2, 3)));
typedef enum {
NSLOG_NO_ERROR = 0,
NSLOG_NO_MEMORY = 1,
} nslog_error;
-typedef void (*nslog_callback)(void *context, nslog_entry_t *msg);
+typedef void (*nslog_callback)(void *context, nslog_entry_context_t *ctx,
+ const char *fmt, va_list args);
nslog_error nslog_set_render_callback(nslog_callback cb, void *context);
diff --git a/src/core.c b/src/core.c
index 0665195..ee5f2bc 100644
--- a/src/core.c
+++ b/src/core.c
@@ -20,12 +20,14 @@
#include <stdlib.h>
#include <string.h>
+
static bool nslog__corked = true;
static struct nslog_cork_chain {
struct nslog_cork_chain *next;
- nslog_entry_t *entry;
-} *nslog__cork_chain = NULL;
+ nslog_entry_context_t context;
+ char message[0]; /* NUL terminated */
+} *nslog__cork_chain = NULL, *nslog__cork_chain_last = NULL;
static nslog_callback nslog__cb = NULL;
static void *nslog__cb_ctx = NULL;
@@ -70,58 +72,56 @@ static void nslog__normalise_category(nslog_category_t *cat)
}
}
-static void nslog__deliver(nslog_entry_t *entry)
+static void nslog__log_corked(nslog_entry_context_t *ctx,
+ int measured_len,
+ const char *fmt,
+ va_list args)
+{
+ /* If corked, we need to store a copy */
+ struct nslog_cork_chain *newcork = malloc(sizeof(*newcork) +
measured_len + 1);
+ if (newcork == NULL) {
+ /* Wow, something went wrong */
+ return;
+ }
+ newcork->context = *ctx;
+ vsprintf(newcork->message, fmt, args);
+ if (nslog__cork_chain == NULL) {
+ nslog__cork_chain = nslog__cork_chain_last = newcork;
+ } else {
+ nslog__cork_chain_last->next = newcork;
+ nslog__cork_chain_last = newcork;
+ }
+}
+
+static void nslog__log_uncorked(nslog_entry_context_t *ctx,
+ const char *fmt,
+ va_list args)
{
/* TODO: Add filtering here */
if (nslog__cb != NULL) {
- if (entry->category->name == NULL) {
- nslog__normalise_category(entry->category);
+ if (ctx->category->name == NULL) {
+ nslog__normalise_category(ctx->category);
}
- (*nslog__cb)(nslog__cb_ctx, entry);
+ (*nslog__cb)(nslog__cb_ctx, ctx, fmt, args);
}
}
-void nslog__log(nslog_category_t *category,
- nslog_level level,
- const char *filename,
- int lineno,
- const char *funcname,
+void nslog__log(nslog_entry_context_t *ctx,
const char *pattern,
...)
{
va_list ap;
va_start(ap, pattern);
- va_list ap2;
- va_copy(ap2, ap);
- int slen = vsnprintf(NULL, 0, pattern, ap);
- va_end(ap);
- nslog_entry_t *entry = malloc(sizeof(nslog_entry_t) + slen + 1);
- if (entry == NULL) {
- /* We're at ENOMEM! log entry is lost */
- va_end(ap2);
- return;
- }
- entry->category = category;
- entry->level = level;
- entry->filename = filename;
- entry->funcname = funcname;
- entry->lineno = lineno;
- vsprintf(entry->message, pattern, ap2);
- va_end(ap2);
if (nslog__corked) {
- struct nslog_cork_chain *chained = malloc(sizeof(struct
nslog_cork_chain));
- if (chained == NULL) {
- /* ENOMEM during corked operation! wow */
- free(entry);
- return;
- }
- chained->next = nslog__cork_chain;
- chained->entry = entry;
- nslog__cork_chain = chained;
+ va_list ap2;
+ va_copy(ap2, ap);
+ int slen = vsnprintf(NULL, 0, pattern, ap);
+ va_end(ap);
+ nslog__log_corked(ctx, slen, pattern, ap2);
+ va_end(ap2);
} else {
- /* Not corked */
- nslog__deliver(entry);
- free(entry);
+ nslog__log_uncorked(ctx, pattern, ap);
+ va_end(ap);
}
}
@@ -133,14 +133,30 @@ nslog_error nslog_set_render_callback(nslog_callback cb,
void *context)
return NSLOG_NO_ERROR;
}
+
+static void __nslog__deliver_corked_entry(nslog_entry_context_t *ctx,
+ const char *fmt,
+ ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ if (nslog__cb != NULL) {
+ (*nslog__cb)(nslog__cb_ctx, ctx, fmt, args);
+ }
+ va_end(args);
+}
+
nslog_error nslog_uncork()
{
if (nslog__corked) {
while (nslog__cork_chain != NULL) {
struct nslog_cork_chain *ent = nslog__cork_chain;
nslog__cork_chain = ent->next;
- nslog__deliver(ent->entry);
- free(ent->entry);
+ if (ent->context.category->name == NULL) {
+
nslog__normalise_category(ent->context.category);
+ }
+ __nslog__deliver_corked_entry(&ent->context,
+ "%s", ent->message);
free(ent);
}
nslog__corked = false;
diff --git a/test/basic.c b/test/basic.c
index fd40633..7626dd8 100644
--- a/test/basic.c
+++ b/test/basic.c
@@ -13,21 +13,29 @@
NSLOG_DEFINE_CATEGORY(test, "Test category");
-static void test_render_function(void *ctx, nslog_entry_t *log)
+static void test_render_function(
+ void *_ctx, nslog_entry_context_t *ctx,
+ const char *fmt, va_list args)
{
(void)ctx;
- fprintf(stderr, "%s %s:%d [%s] %s() %s\n",
- nslog_level_name(log->level),
- log->filename, log->lineno,
- log->category->name,
- log->funcname,
- log->message);
+ fprintf(stderr, "%s %s:%d [%s] %s() ",
+ nslog_level_name(ctx->level),
+ ctx->filename, ctx->lineno,
+ ctx->category->name,
+ ctx->funcname);
+ vfprintf(stderr, fmt, args);
+ fprintf(stderr, "\n");
}
int main(int argc, char **argv)
{
nslog_set_render_callback(test_render_function, NULL);
+ NSLOG(test, INFO, "Pre-uncorking");
+ fprintf(stderr, "About to nslog_uncork()\n");
nslog_uncork();
+ fprintf(stderr, "Uncorked now\n");
NSLOG(test, WARN, "argc=%d", argc);
+ for (int i = 0; i < argc; ++i)
+ NSLOG(test, WARN, "argv[%d] = %s", i, argv[i]);
return 0;
}
commitdiff
http://git.netsurf-browser.org/libnslog.git/commit/?id=551cf378a93588d42732983ec30716e14afef945
commit 551cf378a93588d42732983ec30716e14afef945
Author: Daniel Silverstone <[email protected]>
Commit: Daniel Silverstone <[email protected]>
Initial version
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..8039af5
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+*~
+build-*
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..0bedd97
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,19 @@
+Copyright 2014 Vincent Sanders <[email protected]>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+ * The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..184f9d4
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,55 @@
+#!/bin/make
+#
+# Makefile for libnslog
+#
+# Copyright 2014-1015 Vincent Sanders <[email protected]>
+# Copyright 2017 Daniel Silverstone <[email protected]>
+
+# Component settings
+COMPONENT := nslog
+COMPONENT_VERSION := 0.0.0
+# Default to a static library
+COMPONENT_TYPE ?= lib-static
+
+# Setup the tooling
+PREFIX ?= /opt/netsurf
+NSSHARED ?= $(PREFIX)/share/netsurf-buildsystem
+include $(NSSHARED)/makefiles/Makefile.tools
+
+# Reevaluate when used, as BUILDDIR won't be defined yet
+TESTRUNNER = test/runtest.sh $(BUILDDIR) $(EXEEXT)
+
+# Toolchain flags
+WARNFLAGS := -Wall -W -Wundef -Wpointer-arith -Wcast-align \
+ -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes \
+ -Wmissing-declarations -Wnested-externs
+
+CFLAGS := -D_GNU_SOURCE -D_DEFAULT_SOURCE \
+ -I$(CURDIR)/include/ -I$(CURDIR)/src $(WARNFLAGS) $(CFLAGS)
+ifneq ($(GCCVER),2)
+ CFLAGS := $(CFLAGS) -std=c99
+else
+ # __inline__ is a GCCism
+ CFLAGS := $(CFLAGS) -Dinline="__inline__"
+endif
+CFLAGS := $(CFLAGS) -D_POSIX_C_SOURCE=200809L
+
+REQUIRED_LIBS := nslog
+
+# Strictly the requirement for rt is dependant on both the clib and if
+# the build is using rt features like clock_gettime() but this check
+# will suffice
+ifeq ($(HOST),x86_64-linux-gnu)
+ REQUIRED_LIBS := $(REQUIRED_LIBS) rt
+endif
+
+TESTCFLAGS := -g -O2
+TESTLDFLAGS := -lm -l$(COMPONENT) $(TESTLDFLAGS)
+
+include $(NSBUILD)/Makefile.top
+
+# Extra installation rules
+I := /$(INCLUDEDIR)/nslog
+INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):include/nslog/nslog.h
+INSTALL_ITEMS := $(INSTALL_ITEMS) /$(LIBDIR)/pkgconfig:lib$(COMPONENT).pc.in
+INSTALL_ITEMS := $(INSTALL_ITEMS) /$(LIBDIR):$(OUTPUT)
diff --git a/README b/README
new file mode 100644
index 0000000..45e0a12
--- /dev/null
+++ b/README
@@ -0,0 +1,40 @@
+Libnsutils - NetSurf utility functions
+======================================
+
+Overview
+--------
+
+ Libnsutils provides a small number of useful utility routines which
+ require platform-specific implementations.
+
+Requirements
+------------
+
+ Libnsutils requires the following tools:
+
+ + A C99 capable C compiler
+ + GNU make or compatible
+ + Pkg-config
+
+Compilation
+-----------
+
+ If necessary, modify the toolchain settings in the Makefile.
+ Invoke make:
+ $ make
+
+Verification
+------------
+
+ To verify that the library is working, it is necessary to specify a
+ different makefile target than that used for normal compilation, thus:
+
+ $ make test
+
+API documentation
+-----------------
+
+ Currently, there is none. However, the code is well commented and the
+ public API may be found in the "include" directory. The testcase sources
+ may also be of use in working out how to use it.
+
diff --git a/include/nslog/nslog.h b/include/nslog/nslog.h
new file mode 100644
index 0000000..fff31a7
--- /dev/null
+++ b/include/nslog/nslog.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2017 Daniel Silverstone <[email protected]>
+ *
+ * This file is part of libnslog.
+ *
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+
+/**
+ * \file
+ * NetSurf Logging
+ */
+
+#ifndef NSLOG_NSLOG_H_
+#define NSLOG_NSLOG_H_
+
+typedef enum {
+ NSLOG_LEVEL_DEEPDEBUG = 0,
+ NSLOG_LEVEL_DEBUG = 1,
+ NSLOG_LEVEL_VERBOSE = 2,
+ NSLOG_LEVEL_INFO = 3,
+ NSLOG_LEVEL_WARNING = 4,
+ NSLOG_LEVEL_ERROR = 5,
+ NSLOG_LEVEL_CRITICAL = 6,
+} nslog_level;
+
+const char *nslog_level_name(nslog_level level);
+
+#define NSLOG_LEVEL_DD NSLOG_LEVEL_DEEPDEBUG
+#define NSLOG_LEVEL_CHAT NSLOG_LEVEL_VERBOSE
+#define NSLOG_LEVEL_WARN NSLOG_LEVEL_WARNING
+#define NSLOG_LEVEL_ERR NSLOG_LEVEL_ERROR
+#define NSLOG_LEVEL_CRIT NSLOG_LEVEL_CRITICAL
+
+#ifndef NSLOG_COMPILED_MIN_LEVEL
+#define NSLOG_COMPILED_MIN_LEVEL NSLOG_LEVEL_DEBUG
+#endif
+
+typedef struct nslog_category_s {
+ const char *cat_name;
+ const char *description;
+ struct nslog_category_s *parent;
+ char *name;
+ struct nslog_category_s *next;
+} nslog_category_t;
+
+typedef struct nslog_entry_s {
+ nslog_category_t *category;
+ nslog_level level;
+ const char *filename;
+ const char *funcname;
+ int lineno;
+ char message[0]; /* NUL terminated */
+} nslog_entry_t;
+
+#define NSLOG_DECLARE_CATEGORY(catname) \
+ extern nslog_category_t __nslog_category_##catname
+
+#define NSLOG_DEFINE_CATEGORY(catname, description) \
+ nslog_category_t __nslog_category_##catname = { \
+ #catname, \
+ description, \
+ NULL, \
+ NULL, \
+ NULL, \
+ }
+
+#define NSLOG_DEFINE_SUBCATEGORY(parentcatname, catname, description) \
+ nslog_category_t __nslog_category_##catname = { \
+ #catname, \
+ description, \
+ &__nslog_category_##parentcatname, \
+ NULL, \
+ NULL, \
+ }
+
+#define NSLOG(catname, level, logmsg, args...) \
+ if (NSLOG_LEVEL_##level >= NSLOG_COMPILED_MIN_LEVEL) { \
+ nslog__log(&__nslog_category_##catname, \
+ NSLOG_LEVEL_##level, \
+ __FILE__, \
+ __LINE__, \
+ __PRETTY_FUNCTION__, \
+ logmsg, \
+ ##args); \
+ }
+
+void nslog__log(nslog_category_t *category,
+ nslog_level level,
+ const char *filename,
+ int lineno,
+ const char *funcname,
+ const char *pattern,
+ ...) __attribute__ ((format (printf, 6, 7)));
+
+typedef enum {
+ NSLOG_NO_ERROR = 0,
+ NSLOG_NO_MEMORY = 1,
+} nslog_error;
+
+typedef void (*nslog_callback)(void *context, nslog_entry_t *msg);
+
+nslog_error nslog_set_render_callback(nslog_callback cb, void *context);
+
+nslog_error nslog_uncork(void);
+
+#endif /* NSLOG_NSLOG_H_ */
diff --git a/libnslog.pc.in b/libnslog.pc.in
new file mode 100644
index 0000000..d382216
--- /dev/null
+++ b/libnslog.pc.in
@@ -0,0 +1,10 @@
+prefix=PREFIX
+exec_prefix=${prefix}
+libdir=${exec_prefix}/LIBDIR
+includedir=${prefix}/INCLUDEDIR
+
+Name: libnslog
+Description: NetSurf Logging sublayer
+Version: VERSION
+Libs: -L${libdir} LIBRARIES
+Cflags: -I${includedir}
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000..45ecb90
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,3 @@
+DIR_SOURCES := core.c
+
+include $(NSBUILD)/Makefile.subdir
diff --git a/src/core.c b/src/core.c
new file mode 100644
index 0000000..0665195
--- /dev/null
+++ b/src/core.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2017 Daniel Silverstone <[email protected]>
+ *
+ * This file is part of libnslog.
+ *
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+
+/**
+ * \file
+ * NetSurf Logging Core
+ */
+
+#include "nslog/nslog.h"
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+static bool nslog__corked = true;
+
+static struct nslog_cork_chain {
+ struct nslog_cork_chain *next;
+ nslog_entry_t *entry;
+} *nslog__cork_chain = NULL;
+
+static nslog_callback nslog__cb = NULL;
+static void *nslog__cb_ctx = NULL;
+
+static nslog_category_t *nslog__all_categories = NULL;
+
+const char *nslog_level_name(nslog_level level)
+{
+ switch (level) {
+ case NSLOG_LEVEL_DEEPDEBUG:
+ return "DEEPDEBUG";
+ case NSLOG_LEVEL_DEBUG:
+ return "DEBUG";
+ case NSLOG_LEVEL_VERBOSE:
+ return "VERBOSE";
+ case NSLOG_LEVEL_INFO:
+ return "INFO";
+ case NSLOG_LEVEL_WARNING:
+ return "WARNING";
+ case NSLOG_LEVEL_ERROR:
+ return "ERROR";
+ case NSLOG_LEVEL_CRITICAL:
+ return "CRITICAL";
+ };
+
+ return "**UNKNOWN**";
+}
+
+
+static void nslog__normalise_category(nslog_category_t *cat)
+{
+ if (cat->parent == NULL) {
+ cat->name = strdup(cat->cat_name);
+ } else {
+ nslog__normalise_category(cat->parent);
+ cat->name = malloc(strlen(cat->parent->name) +
strlen(cat->cat_name) + 2);
+ strcpy(cat->name, cat->parent->name);
+ strcat(cat->name, "/");
+ strcat(cat->name, cat->cat_name);
+ cat->next = nslog__all_categories;
+ nslog__all_categories = cat;
+ }
+}
+
+static void nslog__deliver(nslog_entry_t *entry)
+{
+ /* TODO: Add filtering here */
+ if (nslog__cb != NULL) {
+ if (entry->category->name == NULL) {
+ nslog__normalise_category(entry->category);
+ }
+ (*nslog__cb)(nslog__cb_ctx, entry);
+ }
+}
+
+void nslog__log(nslog_category_t *category,
+ nslog_level level,
+ const char *filename,
+ int lineno,
+ const char *funcname,
+ const char *pattern,
+ ...)
+{
+ va_list ap;
+ va_start(ap, pattern);
+ va_list ap2;
+ va_copy(ap2, ap);
+ int slen = vsnprintf(NULL, 0, pattern, ap);
+ va_end(ap);
+ nslog_entry_t *entry = malloc(sizeof(nslog_entry_t) + slen + 1);
+ if (entry == NULL) {
+ /* We're at ENOMEM! log entry is lost */
+ va_end(ap2);
+ return;
+ }
+ entry->category = category;
+ entry->level = level;
+ entry->filename = filename;
+ entry->funcname = funcname;
+ entry->lineno = lineno;
+ vsprintf(entry->message, pattern, ap2);
+ va_end(ap2);
+ if (nslog__corked) {
+ struct nslog_cork_chain *chained = malloc(sizeof(struct
nslog_cork_chain));
+ if (chained == NULL) {
+ /* ENOMEM during corked operation! wow */
+ free(entry);
+ return;
+ }
+ chained->next = nslog__cork_chain;
+ chained->entry = entry;
+ nslog__cork_chain = chained;
+ } else {
+ /* Not corked */
+ nslog__deliver(entry);
+ free(entry);
+ }
+}
+
+nslog_error nslog_set_render_callback(nslog_callback cb, void *context)
+{
+ nslog__cb = cb;
+ nslog__cb_ctx = context;
+
+ return NSLOG_NO_ERROR;
+}
+
+nslog_error nslog_uncork()
+{
+ if (nslog__corked) {
+ while (nslog__cork_chain != NULL) {
+ struct nslog_cork_chain *ent = nslog__cork_chain;
+ nslog__cork_chain = ent->next;
+ nslog__deliver(ent->entry);
+ free(ent->entry);
+ free(ent);
+ }
+ nslog__corked = false;
+ }
+ return NSLOG_NO_ERROR;
+}
+
diff --git a/test/Makefile b/test/Makefile
new file mode 100644
index 0000000..0cebdaa
--- /dev/null
+++ b/test/Makefile
@@ -0,0 +1,3 @@
+DIR_TEST_ITEMS := basic:basic.c
+
+include $(NSBUILD)/Makefile.subdir
diff --git a/test/basic.c b/test/basic.c
new file mode 100644
index 0000000..fd40633
--- /dev/null
+++ b/test/basic.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2017 Daniel Silverstone <[email protected]>
+ *
+ * This file is part of libnslog.
+ *
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+
+#include "nslog/nslog.h"
+
+#include <stdio.h>
+
+NSLOG_DEFINE_CATEGORY(test, "Test category");
+
+static void test_render_function(void *ctx, nslog_entry_t *log)
+{
+ (void)ctx;
+ fprintf(stderr, "%s %s:%d [%s] %s() %s\n",
+ nslog_level_name(log->level),
+ log->filename, log->lineno,
+ log->category->name,
+ log->funcname,
+ log->message);
+}
+
+int main(int argc, char **argv)
+{
+ nslog_set_render_callback(test_render_function, NULL);
+ nslog_uncork();
+ NSLOG(test, WARN, "argc=%d", argc);
+ return 0;
+}
diff --git a/test/runtest.sh b/test/runtest.sh
new file mode 100755
index 0000000..1b67a97
--- /dev/null
+++ b/test/runtest.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+set -e
+
+TEST_PATH=$1
+TEST_PFX=$4
+
+for TEST in basic; do
+ ${TEST_PATH}/${TEST_PFX}${TEST}
+done
+
+exit 0
-----------------------------------------------------------------------
--
NetSurf Parametric Logging Library
_______________________________________________
netsurf-commits mailing list
[email protected]
http://listmaster.pepperfish.net/cgi-bin/mailman/listinfo/netsurf-commits-netsurf-browser.org