%{ /* ** L2 - OSSP Logging Library ** Copyright (c) 2001 The OSSP Project (http://www.ossp.org/) ** Copyright (c) 2001 Cable & Wireless Deutschland (http://www.cw.com/de/) ** ** This file is part of OSSP L2, a flexible logging library which ** can be found at http://www.ossp.org/pkg/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_parse.y: GNU Bison (Yacc-style) parser specification ** ** ATTENTION: This requires GNU Bison 1.30 or newer! */ #include "l2.h" /* for l2_xxx() */ #include "l2_p.h" /* for l2_channel_t and l2_env_t internals */ #include "l2_spec.h" /* for l2_spec_ctx_t */ /* make sure yyparse() accepts a context pointer and passes through its inlined scanner context to yylex() */ #define CTX ((l2_spec_ctx_t *)ctx) #define YYPARSE_PARAM ctx #define YYLEX_PARAM CTX->yyscan /* provide an explicit prototype for the yylex() function */ extern int yylex(/*YYSTYPE*/ void *lvalp, /*YYLTYPE*/ void *llocp, l2_spec_ctx_t *ctx); /* generate verbose error messages and remember them inside the context */ #undef yyerror #define yyerror(msg) \ do { \ l2_env_errorinfo(CTX->env, L2_ERR_ARG, "%s", msg); \ CTX->rv = L2_ERR_ARG; \ } while (0) #define YYERROR_VERBOSE #define YYDEBUG 1 %} %pure_parser %locations %defines %union { char *cpValue; l2_channel_t *chChannel; unsigned int nLevels; } %type stream %type streams %type channel %type channel_spec %type channel_mask %type channel_levels %token T_ID %token T_STRING %token T_OP_ARROW %left T_OP_ARROW %% root : stream { CTX->ch = $1; } ; stream : channel { $$ = $1; } | channel T_OP_ARROW stream { $$ = $1; if ((CTX->rv = l2_channel_link($1, L2_LINK_CHILD, $3, NULL)) != L2_OK) { l2_env_errorinfo(CTX->env, CTX->rv, "unable to link parent '%s' with child '%s'", $1->handler.name, $3->handler.name); YYERROR; } } | channel T_OP_ARROW '{' streams '}' { $$ = $1; if ((CTX->rv = l2_channel_link($1, L2_LINK_CHILD, $4, NULL)) != L2_OK) { l2_env_errorinfo(CTX->env, CTX->rv, "unable to link parent '%s' with child list", $1->handler.name); YYERROR; } } ; streams : stream { $$ = $1; } | stream ';' streams { $$ = $1; l2_channel_link($1, L2_LINK_SIBLING, $3, NULL); } ; channel : channel_mask '/' channel_mask ':' channel_spec { $$ = $5; l2_channel_levels($5, $1, $3); } | channel_mask ':' channel_spec { $$ = $3; l2_channel_levels($3, $1, L2_LEVEL_NONE); } | channel_spec { $$ = $1; } ; channel_mask : T_ID { unsigned int levelmask; if ((CTX->rv = l2_util_s2l($1, strlen($1), ',', &levelmask)) != L2_OK) { l2_env_errorinfo(CTX->env, CTX->rv, "invalid level '%s'", $1); YYERROR; } $$ = L2_LEVEL_UPTO(levelmask); } | '(' channel_levels ')' { $$ = $2; } ; channel_levels : T_ID { unsigned int levelmask; if ((CTX->rv = l2_util_s2l($1, strlen($1), ',', &levelmask)) != L2_OK) { l2_env_errorinfo(CTX->env, CTX->rv, "invalid level '%s'", $1); YYERROR; } $$ = levelmask; } | T_ID '|' channel_levels { unsigned int levelmask; if ((CTX->rv = l2_util_s2l($1, strlen($1), ',', &levelmask)) != L2_OK) { l2_env_errorinfo(CTX->env, CTX->rv, "invalid level '%s'", $1); YYERROR; } $$ = levelmask | $3; } ; channel_spec : T_ID { l2_channel_t *ch; if ((CTX->rv = l2_channel_create(&ch, CTX->env, $1)) != L2_OK) { l2_env_errorinfo(CTX->env, CTX->rv, "failed to create channel '%s'", $1); YYERROR; } $$ = ch; /* provide channel to channel_param rule below because it does not know where on the token stack our $$ is because it is a sub-rule of the recursive channel_param_list rule and hence cannot use "$-n". */ CTX->chTmp = ch; } channel_params { $$ = $2; CTX->chTmp = NULL; } ; channel_params : /* empty */ | '(' channel_param_list ')' ; channel_param_list : /* empty */ | channel_param | channel_param ',' channel_param_list ; channel_param : T_ID '=' T_STRING { if ((CTX->rv = l2_channel_configure(CTX->chTmp, "%s=\"%s\"", $1, $3)) != L2_OK) { l2_env_errorinfo(CTX->env, CTX->rv, "failed to configure channel with '%s=\"%s\"'", $1, $3); YYERROR; } } ; %%