head 1.12;
access;
symbols
L2_0_9_13:1.12
FSL_1_7_0:1.12
L2_0_9_12:1.12
LMTP2NNTP_1_4_1:1.12
LMTP2NNTP_1_4_0:1.12
FSL_1_6_1:1.12
L2_0_9_11:1.12
FSL_1_6_0:1.11
FSL_1_6b2:1.11
L2_0_9_10:1.11
FSL_1_6b1:1.11
L2_0_9_9:1.11
LMTP2NNTP_1_3_0:1.10
LMTP2NNTP_1_3b2:1.10
LMTP2NNTP_1_3b1:1.10
LMTP2NNTP_1_3a3:1.10
FSL_1_5_0:1.10
LMTP2NNTP_1_3a2:1.10
FSL_1_5a3:1.10
LMTP2NNTP_1_3a1:1.10
FSL_1_5a2:1.10
L2_0_9_8:1.10
FSL_1_5a1:1.10
L2_0_9_7:1.10
L2_0_9_6:1.10
FSL_1_4_0:1.10
FSL_1_4b1:1.10
L2_0_9_5:1.10
FSL_1_4a1:1.10
FSL_1_3_0:1.10
FSL_1_3b1:1.10
L2_0_9_4:1.10
FSL_1_2_1:1.10
L2_0_9_3:1.10
FSL_1_2_0:1.10
L2_0_9_2:1.10
FSL_1_1_0:1.10
FSL_1_1b1:1.10
WORKOFF:1.10.0.2
WORKOFF_BP:1.10
FSL_1_0_8:1.10
LMTP2NNTP_1_2_0:1.10
LMTP2NNTP_1_2b4:1.10
LMTP2NNTP_1_2b3:1.10
LMTP2NNTP_1_2b2:1.10
LMTP2NNTP_1_2b1:1.10
LMTP2NNTP_1_2a8:1.10
LMTP2NNTP_1_2a7:1.10
FSL_1_0_7:1.10
FSL_1_0_6:1.9
FSL_1_0_5:1.9
FSL_1_0_4:1.9
L2_0_9_1:1.9
FSL_1_0_3:1.9
LMTP2NNTP_1_2a6:1.9
FSL_1_0_2:1.9
FSL_1_0_1:1.9
FSL_1_0_0:1.9
FSL_0_9_0:1.9
L2_0_9_0:1.9
FSL_0_1_12:1.8
FSL_0_1_11:1.8
FSL_0_1_10:1.8
FSL_0_1_9:1.8
FSL_0_1_8:1.8
FSL_0_1_7:1.8
FSL_0_1_6:1.8
FSL_0_1_5:1.8
FSL_0_1_1:1.8
LMTP2NNTP_1_2a5:1.8
LMTP2NNTP_1_2a4:1.8
LMTP2NNTP_1_2a3:1.8
LMTP2NNTP_1_2a1:1.4;
locks; strict;
comment @ * @;
1.12
date 2005.10.03.08.08.11; author rse; state Exp;
branches;
next 1.11;
1.11
date 2005.01.24.15.03.17; author rse; state Exp;
branches;
next 1.10;
1.10
date 2003.01.06.11.41.52; author rse; state Exp;
branches;
next 1.9;
1.9
date 2002.07.30.19.08.25; author rse; state Exp;
branches;
next 1.8;
1.8
date 2002.01.02.17.07.38; author rse; state Exp;
branches;
next 1.7;
1.7
date 2001.12.22.22.18.34; author rse; state Exp;
branches;
next 1.6;
1.6
date 2001.12.22.22.04.18; author rse; state Exp;
branches;
next 1.5;
1.5
date 2001.12.14.12.42.07; author rse; state Exp;
branches;
next 1.4;
1.4
date 2001.11.30.09.44.47; author rse; state Exp;
branches;
next 1.3;
1.3
date 2001.11.07.16.43.07; author rse; state Exp;
branches;
next 1.2;
1.2
date 2001.11.07.16.35.18; author rse; state Exp;
branches;
next 1.1;
1.1
date 2001.11.07.16.17.09; author rse; state Exp;
branches;
next ;
desc
@@
1.12
log
@Adjust copyright messages for new year 2005.
@
text
@/*
** OSSP l2 - Flexible Logging
** Copyright (c) 2001-2005 Cable & Wireless
** Copyright (c) 2001-2005 The OSSP Project
** Copyright (c) 2001-2005 Ralf S. Engelschall
**
** This file is part of OSSP l2, a flexible logging library which
** can be found at http://www.ossp.org/pkg/lib/l2/.
**
** Permission to use, copy, modify, and distribute this software for
** any purpose with or without fee is hereby granted, provided that
** the above copyright notice and this permission notice appear in all
** copies.
**
** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 AUTHORS AND COPYRIGHT HOLDERS AND THEIR
** 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.
**
** l2_spec.c: channel tree specification support
*/
#include "l2.h"
#include "l2_p.h"
#include "l2_spec.h"
/* prototypes for Flex-generated scanner */
extern int l2_spec_lex_init(void *);
extern int l2_spec_lex_destroy(void *);
extern void l2_spec_set_extra(void *, void *);
/* prototypes for Bison-generated parser */
extern int l2_spec_parse(void *);
/* build a channel tree according to a textual specification */
l2_result_t l2_spec(l2_channel_t **ch, l2_env_t *env, const char *spec, ...)
{
va_list ap;
l2_result_t rv;
/* pass-through to va_list-based variant */
va_start(ap, spec);
rv = l2_vspec(ch, env, spec, ap);
va_end(ap);
return rv;
}
/* build a channel tree according to a textual specification (va_list variant) */
l2_result_t l2_vspec(l2_channel_t **ch, l2_env_t *env, const char *spec, va_list ap)
{
l2_spec_ctx_t ctx;
void *yyscan;
char *specstr;
/* on-the-fly create or take over specification string */
if ((specstr = l2_util_vasprintf(spec, ap)) == NULL)
return L2_ERR_ARG;
/* initialize scanner */
l2_spec_lex_init(&yyscan);
l2_spec_set_extra(&ctx, yyscan);
/* establish our own context which is passed
through the parser and scanner */
ctx.yyscan = yyscan;
ctx.inputptr = specstr;
ctx.inputbuf = specstr;
ctx.inputlen = strlen(specstr);
ctx.env = env;
ctx.ch = NULL;
ctx.chTmp = NULL;
ctx.rv = L2_OK;
/* start the parser loop */
if (l2_spec_parse(&ctx))
ctx.rv = (ctx.rv == L2_OK ? L2_ERR_INT : ctx.rv);
/* destroy scanner */
l2_spec_lex_destroy(yyscan);
/* destroy specification string */
free(specstr);
/* provide root/top-level channel as result */
*ch = ctx.ch;
return ctx.rv;
}
/* remember a specification parsing error (used internally) */
void l2_spec_error(l2_spec_ctx_t *ctx, l2_result_t rv, YYLTYPE *loc, const char *fmt, ...)
{
va_list ap;
const char *cpF, *cpL;
const char *cpP, *cpE;
int line, column;
char *cpBuf;
char *cp;
int n;
/* determine first and last positions of token */
cpF = ctx->inputbuf+loc->first;
cpL = ctx->inputbuf+loc->last;
/* determine epilog and prolog of token */
cpP = cpF-4;
if (cpP < ctx->inputbuf)
cpP = ctx->inputbuf;
cpE = cpL+4;
if (cpE > ctx->inputbuf+ctx->inputlen)
cpE = ctx->inputbuf+ctx->inputlen;
/* calculate line and column of token */
line = 1;
column = 1;
for (cp = (char *)ctx->inputbuf; cp < (ctx->inputbuf+ctx->inputlen) && cp != cpF; cp++) {
column++;
if (*cp == '\n') {
column = 1;
line++;
}
}
/* extract token context with mark token borders */
if ((cpBuf = malloc((cpE-cpP)+2+1)) == NULL)
return;
cp = cpBuf;
n = cpF-cpP;
memcpy(cp, cpP, n); cp += n;
*cp++ = '<';
n = cpL-cpF;
memcpy(cp, cpF, n); cp += n;
*cp++ = '>';
n = cpE-cpL;
memcpy(cp, cpL, n); cp += n;
*cp++ = '\0';
/* remember error */
va_start(ap, fmt);
if ((cp = l2_util_vasprintf(fmt, ap)) != NULL) {
l2_env_errorinfo(ctx->env, rv, "line %d, column %d: `%s'; %s",
line, column, cpBuf, cp);
free(cp);
}
else
l2_env_errorinfo(ctx->env, rv, "line %d, column %d: `%s'; N.A.",
line, column, cpBuf);
va_end(ap);
ctx->rv = rv;
/* cleanup */
free(cpBuf);
return;
}
@
1.11
log
@Adjust copyright messages for new year 2005.
@
text
@d3 3
a5 3
** Copyright (c) 2001-2004 Cable & Wireless
** Copyright (c) 2001-2004 The OSSP Project
** Copyright (c) 2001-2004 Ralf S. Engelschall
@
1.10
log
@- remove trailing whitespaces
- adjust copyright messages
- consistently use "OSSP l2"
- consistently talk about "Flexible Logging"
- use standard OSSP ASCII-art
@
text
@d3 3
a5 3
** Copyright (c) 2001-2003 Cable & Wireless Deutschland GmbH
** Copyright (c) 2001-2003 The OSSP Project (http://www.ossp.org/)
** Copyright (c) 2001-2003 Ralf S. Engelschall
@
1.9
log
@polish for release
@
text
@d2 4
a5 3
** OSSP l2 - Logging Library
** Copyright (c) 2001-2002 The OSSP Project (http://www.ossp.org/)
** Copyright (c) 2001-2002 Cable & Wireless Deutschland (http://www.cw.com/de/)
d7 1
a7 1
** This file is part of OSSP L2, a flexible logging library which
d72 1
a72 1
/* establish our own context which is passed
@
1.8
log
@bump copyright year
@
text
@d2 1
a2 1
** L2 - OSSP Logging Library
d7 1
a7 1
** can be found at http://www.ossp.org/pkg/l2/.
@
1.7
log
@Fix l2_spec_error function and remove again the not
really needed l2_env_verrorinfo function.
@
text
@d3 2
a4 2
** Copyright (c) 2001 The OSSP Project (http://www.ossp.org/)
** Copyright (c) 2001 Cable & Wireless Deutschland (http://www.cw.com/de/)
@
1.6
log
@remove warning
@
text
@d101 1
d147 10
a156 2
l2_env_errorinfo(ctx->env, rv, "line %d, column %d: `%s'; %s",
line, column, cpBuf, fmt);
@
1.5
log
@Whoohooo! Add support for location tracking. This way the reported
errors contain line, column, context and found/expected information.
Now the specification parser is full featured...
@
text
@d123 1
a123 1
for (cp = ctx->inputbuf; cp < (ctx->inputbuf+ctx->inputlen) && cp != cpF; cp++) {
@
1.4
log
@Allow a channel tree specification to be a printf-style string to make
the API more powerful and to remove the burden from the application to
pre-format the specification in an own buffer.
@
text
@d98 58
@
1.3
log
@reduce includes
@
text
@d43 15
a57 1
l2_result_t l2_spec(l2_channel_t **ch, l2_env_t *env, const char *spec)
d61 5
d74 3
a76 3
ctx.inputptr = spec;
ctx.inputbuf = spec;
ctx.inputlen = strlen(spec);
d88 3
@
1.2
log
@cleanup and documentation
@
text
@a32 1
#include "l2_spec_parse.h"
@
1.1
log
@HEADS UP, guys:
Here comes the first cut for the long-awaited channel tree specification
parser and channel tree builder. This certainly makes L2 finally _THE_ killer
library in the logging field. Woohooo... and the crowd goes wild!
It allows one to build an arbitrary complex logging channel tree
out of a single textual specification. An example follows:
noop -> {
prefix(prefix="[%d-%m-%Y/%H:%M:%S] %L test[%P]: ", timezone="local")
-> filter(regex="hecking", negate="0")
-> buffer(size="800")
-> file(path="l2_test.log",append="1",perm="420");
error: syslog(ident="L2-Test", facility="user",
remotehost="en1", logpid="1", target="remote");
panic: smtp(rcpt="rse@@engelschall.com", host="en1", port="25"
}
This allows one to log nice timestamp-prefixed messages containing the
word "hecking" to a buffered file. Additionally if the message has a
level higher or equal to "error" it also logs it remotely via UDP to the
syslogd on en1. And additionally if the message is a panic message, it
is also sent out as an Email via SMTP to the MTA on en1.
Ever thought a C library has to be dull and simple? ;)
PS: This stuff certainly needs more polishing and cleanup and also
a few things I'll enhance in the future (for instance to remove the
restriction that parameter values have to be in quotation marks, etc.).
@
text
@d1 28
a28 2
#include
d35 1
a38 5
extern int l2_spec_debug;
void dump(int level, l2_channel_t *ch)
{
l2_channel_t *chD;
d40 2
a41 6
fprintf(stderr, "%*s%s (0x%lx)\n", level*4, "", ch->handler.name, ch);
chD = NULL;
while ((l2_channel_downstream(ch, &chD)) == L2_OK)
dump(level+1, chD);
return;
}
d43 1
d49 1
d53 2
d64 1
a64 3
#if 0
l2_spec_debug = 1;
#endif
d68 4
a72 4
dump(0, ctx.ch);
l2_spec_lex_destroy(yyscan);
@