Index: ossp-pkg/cfg/ChangeLog RCS File: /v/ossp/cvs/ossp-pkg/cfg/ChangeLog,v rcsdiff -q -kk '-r1.27' '-r1.28' -u '/v/ossp/cvs/ossp-pkg/cfg/ChangeLog,v' 2>/dev/null --- ChangeLog 2004/11/29 07:09:33 1.27 +++ ChangeLog 2004/12/04 12:48:40 1.28 @@ -10,6 +10,12 @@ Changes between 0.9.5 and 0.9.6 (27-Nov-2004 to xx-Dec-2004): + *) Plug remaining memory leaks by introducing the usual + LOAN/GIFT/COPY argument passing semantics to cfg_node_{set,get} + and using this to directly pass the allocated tokens from the + scanner through the parser into the node tree. + [Ralf S. Engelschall ] + *) Fix optional DMalloc build support. [Ralf S. Engelschall ] Index: ossp-pkg/cfg/cfg.h RCS File: /v/ossp/cvs/ossp-pkg/cfg/cfg.h,v rcsdiff -q -kk '-r1.15' '-r1.16' -u '/v/ossp/cvs/ossp-pkg/cfg/cfg.h,v' 2>/dev/null --- cfg.h 2004/11/20 14:52:56 1.15 +++ cfg.h 2004/12/04 12:48:40 1.16 @@ -63,21 +63,27 @@ } cfg_node_type_t; /* list of node attributes */ -typedef enum { - CFG_NODE_ATTR_PARENT, /* RW: (cfg_node_t *) pointer to parent node */ - CFG_NODE_ATTR_LBROTH, /* RW: (cfg_node_t *) pointer to left brother node */ - CFG_NODE_ATTR_RBROTH, /* RW: (cfg_node_t *) pointer to right brother node */ - CFG_NODE_ATTR_CHILD1, /* RW: (cfg_node_t *) pointer to first child node */ - CFG_NODE_ATTR_CHILDL, /* RO: (cfg_node_t *) pointer to last child */ - CFG_NODE_ATTR_CHILDS, /* RO: (int) number of child nodes */ - CFG_NODE_ATTR_NODES, /* RO: (int) number of total nodes (recursive) */ - CFG_NODE_ATTR_DEPTH, /* RO: (int) number of nodes back to root node */ - CFG_NODE_ATTR_SRCNAME, /* RW: (char *) pointer to the source name */ - CFG_NODE_ATTR_SRCPOS, /* RW: (int) position offset into source */ - CFG_NODE_ATTR_TYPE, /* RW: (cfg_node_type_t) type of node */ - CFG_NODE_ATTR_TOKEN, /* RW: (char *) pointer to the node token string */ - CFG_NODE_ATTR_DATA /* RW: (cfg_data_t *) pointer to the node annotation data */ -} cfg_node_attr_t; +typedef int cfg_node_attr_t; +enum { + /* attribute selection */ + CFG_NODE_ATTR_PARENT = (1 << 0), /* RW: (cfg_node_t *) pointer to parent node */ + CFG_NODE_ATTR_LBROTH = (1 << 1), /* RW: (cfg_node_t *) pointer to left brother node */ + CFG_NODE_ATTR_RBROTH = (1 << 2), /* RW: (cfg_node_t *) pointer to right brother node */ + CFG_NODE_ATTR_CHILD1 = (1 << 3), /* RW: (cfg_node_t *) pointer to first child node */ + CFG_NODE_ATTR_CHILDL = (1 << 4), /* RO: (cfg_node_t *) pointer to last child */ + CFG_NODE_ATTR_CHILDS = (1 << 5), /* RO: (int) number of child nodes */ + CFG_NODE_ATTR_NODES = (1 << 6), /* RO: (int) number of total nodes (recursive) */ + CFG_NODE_ATTR_DEPTH = (1 << 7), /* RO: (int) number of nodes back to root node */ + CFG_NODE_ATTR_SRCNAME = (1 << 8), /* RW: (char *) pointer to the source name */ + CFG_NODE_ATTR_SRCPOS = (1 << 9), /* RW: (int) position offset into source */ + CFG_NODE_ATTR_TYPE = (1 << 10), /* RW: (cfg_node_type_t) type of node */ + CFG_NODE_ATTR_TOKEN = (1 << 11), /* RW: (char *) pointer to the node token string */ + CFG_NODE_ATTR_DATA = (1 << 12), /* RW: (cfg_data_t *) pointer to the node annotation data */ + /* attribute passing semantics */ + CFG_ATTR_LOAN = (1 << 13), /* loan attribute on set/get: source still owns orginal data */ + CFG_ATTR_GIFT = (1 << 14), /* gift attribute on set/get: target then owns orginal data */ + CFG_ATTR_COPY = (1 << 15) /* copy attribute on set/get: target then owns copied data */ +}; /* list of data types */ typedef enum { Index: ossp-pkg/cfg/cfg_main.c RCS File: /v/ossp/cvs/ossp-pkg/cfg/cfg_main.c,v rcsdiff -q -kk '-r1.13' '-r1.14' -u '/v/ossp/cvs/ossp-pkg/cfg/cfg_main.c,v' 2>/dev/null --- cfg_main.c 2004/11/29 07:09:33 1.13 +++ cfg_main.c 2004/12/04 12:48:40 1.14 @@ -73,11 +73,18 @@ return CFG_OK; } +static cfg_rc_t cfg_destroy_node(cfg_t *cfg, cfg_node_t *node, void *ctx) +{ + cfg_node_destroy(cfg, node); + return CFG_OK; +} + cfg_rc_t cfg_destroy(cfg_t *cfg) { if (cfg == NULL) return CFG_ERR_ARG; - /* FIXME: on each node, free token string first */ + if (cfg->root != NULL) + cfg_node_apply(cfg, cfg->root, NULL, NULL, cfg_destroy_node, NULL); cfg_grid_destroy(cfg->grid_nodes); cfg_grid_destroy(cfg->grid_tokens); free(cfg); Index: ossp-pkg/cfg/cfg_node.c RCS File: /v/ossp/cvs/ossp-pkg/cfg/cfg_node.c,v rcsdiff -q -kk '-r1.22' '-r1.23' -u '/v/ossp/cvs/ossp-pkg/cfg/cfg_node.c,v' 2>/dev/null --- cfg_node.c 2004/11/29 07:09:33 1.22 +++ cfg_node.c 2004/12/04 12:48:40 1.23 @@ -57,6 +57,7 @@ return rc; /* initialize node attributes */ + n->owner = 0; n->parent = NULL; n->rbroth = NULL; n->child1 = NULL; @@ -81,10 +82,11 @@ return CFG_ERR_ARG; /* destroy memory */ - if (node->token != NULL) + if ((node->owner & CFG_NODE_ATTR_TOKEN) && node->token != NULL) free(node->token); - if (node->srcname != NULL) + if ((node->owner & CFG_NODE_ATTR_SRCNAME) && node->srcname != NULL) free(node->srcname); + cfg_data_kill(&node->data); cfg_grid_free(cfg->grid_nodes, node); return CFG_OK; @@ -109,14 +111,23 @@ return rc; /* clone node attributes */ + n->owner = node->owner; n->parent = node->parent; n->rbroth = node->rbroth; n->child1 = node->child1; n->type = node->type; - n->token = (node->token != NULL ? strdup(node->token) : NULL); - cfg_data_copy(&node->data, &n->data); - n->srcname = (node->srcname != NULL ? strdup(node->srcname) : NULL); n->srcpos = node->srcpos; + if (node->owner & CFG_NODE_ATTR_TOKEN) + n->token = (node->token != NULL ? strdup(node->token) : NULL); + else + n->token = node->token; + if (node->owner & CFG_NODE_ATTR_SRCNAME) + n->srcname = (node->srcname != NULL ? strdup(node->srcname) : NULL); + else + n->srcname = node->srcname; + cfg_data_copy(&node->data, &n->data); + + /* store result */ *node2 = n; return CFG_OK; @@ -138,7 +149,7 @@ /* dispatch into individual attribute handling */ va_start(ap, attr); - switch (attr) { + switch (attr & ~(CFG_ATTR_LOAN|CFG_ATTR_GIFT|CFG_ATTR_COPY)) { case CFG_NODE_ATTR_PARENT: { node->parent = (cfg_node_t *)va_arg(ap, cfg_node_t *); break; @@ -171,22 +182,28 @@ break; } case CFG_NODE_ATTR_TOKEN: { - if (node->token != NULL) + char *value = (char *)va_arg(ap, char *); + if (attr & CFG_ATTR_COPY) + value = strdup(value); + if (node->owner & CFG_NODE_ATTR_TOKEN && node->token != NULL) free(node->token); - node->token = (char *)va_arg(ap, char *); - if (node->token != NULL) - node->token = strdup(node->token); + node->token = value; + if (attr & (CFG_ATTR_COPY|CFG_ATTR_GIFT)) + node->owner |= CFG_NODE_ATTR_TOKEN; break; } case CFG_NODE_ATTR_DATA: { return CFG_ERR_USE; } case CFG_NODE_ATTR_SRCNAME: { - if (node->srcname != NULL) + char *value = (char *)va_arg(ap, char *); + if (attr & CFG_ATTR_COPY) + value = strdup(value); + if (node->owner & CFG_NODE_ATTR_SRCNAME && node->srcname != NULL) free(node->srcname); - node->srcname = (char *)va_arg(ap, char *); - if (node->srcname != NULL) - node->srcname = strdup(node->srcname); + node->srcname = value; + if (attr & (CFG_ATTR_COPY|CFG_ATTR_GIFT)) + node->owner |= CFG_NODE_ATTR_SRCNAME; break; } case CFG_NODE_ATTR_SRCPOS: { @@ -220,6 +237,7 @@ return n; } +/* get a node attribute */ cfg_rc_t cfg_node_get( cfg_t *cfg, @@ -327,6 +345,10 @@ if (token == NULL) return CFG_ERR_ARG; *token = node->token; + if (attr & CFG_ATTR_COPY) + *token = strdup(*token); + if (attr & CFG_ATTR_GIFT) + node->token = NULL; break; } case CFG_NODE_ATTR_DATA: { @@ -341,6 +363,10 @@ if (name == NULL) return CFG_ERR_ARG; *name = node->srcname; + if (attr & CFG_ATTR_COPY) + *name = strdup(*name); + if (attr & CFG_ATTR_GIFT) + node->srcname = NULL; break; } case CFG_NODE_ATTR_SRCPOS: { @@ -721,26 +747,45 @@ void *cb_ctx_cb) { cfg_rc_t rc; + cfg_node_t *child1; + cfg_node_t *rbroth; /* argument sanity checking */ if (cfg == NULL) return CFG_ERR_ARG; - if (node != NULL) { - if ((rc = cb_fct_cmp(cfg, node, cb_ctx_cmp)) == CFG_OK) - cb_fct_cb(cfg, node, cb_ctx_cb); - if (rc != CFG_ERR_NDE) + + /* short-circuit processing */ + if (node == NULL) + return CFG_OK; + + /* remember traversing informations from child and brother + (important in case the callbacks destroy it) */ + child1 = node->child1; + rbroth = node->rbroth; + + /* check whether the node matches */ + if (cb_fct_cmp != NULL) + rc = cb_fct_cmp(cfg, node, cb_ctx_cmp); + else + rc = CFG_OK; + + /* if node matched, apply optional callback on node */ + if (rc == CFG_OK && cb_fct_cb != NULL) + if ((rc = cb_fct_cb(cfg, node, cb_ctx_cb)) != CFG_OK) return rc; - if (node->child1 != NULL) - if ((rc = cfg_node_apply(cfg, node->child1, - cb_fct_cmp, cb_ctx_cmp, - cb_fct_cb, cb_ctx_cb)) != CFG_OK) - return rc; - if (node->rbroth != NULL) - if ((rc = cfg_node_apply(cfg, node->rbroth, - cb_fct_cmp, cb_ctx_cmp, - cb_fct_cb, cb_ctx_cb)) != CFG_OK) - return rc; - } + + /* recursively apply on child and brother nodes */ + if (child1 != NULL) + if ((rc = cfg_node_apply(cfg, child1, + cb_fct_cmp, cb_ctx_cmp, + cb_fct_cb, cb_ctx_cb)) != CFG_OK) + return rc; + if (rbroth != NULL) + if ((rc = cfg_node_apply(cfg, rbroth, + cb_fct_cmp, cb_ctx_cmp, + cb_fct_cb, cb_ctx_cb)) != CFG_OK) + return rc; + return CFG_OK; } @@ -804,7 +849,7 @@ return CFG_OK; } -/* unlink a nodes from others */ +/* unlink a node from others */ cfg_rc_t cfg_node_unlink( cfg_t *cfg, Index: ossp-pkg/cfg/cfg_node.h RCS File: /v/ossp/cvs/ossp-pkg/cfg/cfg_node.h,v co -q -kk -p'1.11' '/v/ossp/cvs/ossp-pkg/cfg/cfg_node.h,v' | diff -u /dev/null - -L'ossp-pkg/cfg/cfg_node.h' 2>/dev/null --- ossp-pkg/cfg/cfg_node.h +++ - 2024-05-16 06:24:42.284322670 +0200 @@ -0,0 +1,59 @@ +/* +** OSSP cfg - Configuration Parsing +** Copyright (c) 2002-2004 Ralf S. Engelschall +** Copyright (c) 2002-2004 The OSSP Project (http://www.ossp.org/) +** Copyright (c) 2002-2004 Cable & Wireless (http://www.cw.com/) +** +** This file is part of OSSP cfg, a configuration parsing +** library which can be found at http://www.ossp.org/pkg/lib/cfg/. +** +** 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. +** +** cfg_node.h: configuration nodes (internals) +*/ + +#ifndef __CFG_NODE_H__ +#define __CFG_NODE_H__ + +#include "cfg.h" +#include "cfg_data.h" + +struct cfg_node_st { + /* attribute ownership */ + unsigned long owner; /* attribute ownership bit field */ + + /* node linkage */ + cfg_node_t *parent; /* pointer to parent node */ + cfg_node_t *rbroth; /* pointer to right brother node */ + cfg_node_t *child1; /* pointer to first child node */ + + /* node contents */ + cfg_node_type_t type; /* type of node */ + char *token; /* pointer to corresponding token string */ + + /* node annotation */ + cfg_data_t data; /* annotational data */ + + /* node source location */ + char *srcname; /* name of original source configuration */ + int srcpos; /* offset into original source configuration */ +}; + +#endif /* __CFG_NODE_H__ */ + Index: ossp-pkg/cfg/cfg_syn_parse.y RCS File: /v/ossp/cvs/ossp-pkg/cfg/cfg_syn_parse.y,v co -q -kk -p'1.11' '/v/ossp/cvs/ossp-pkg/cfg/cfg_syn_parse.y,v' | diff -u /dev/null - -L'ossp-pkg/cfg/cfg_syn_parse.y' 2>/dev/null --- ossp-pkg/cfg/cfg_syn_parse.y +++ - 2024-05-16 06:24:42.287018605 +0200 @@ -0,0 +1,170 @@ +%{ +/* +** OSSP cfg - Configuration Parsing +** Copyright (c) 2002-2004 Ralf S. Engelschall +** Copyright (c) 2002-2004 The OSSP Project (http://www.ossp.org/) +** Copyright (c) 2002-2004 Cable & Wireless (http://www.cw.com/) +** +** This file is part of OSSP cfg, a configuration parsing +** library which can be found at http://www.ossp.org/pkg/lib/cfg/. +** +** 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. +** +** cfg_syn_parse.y: context free grammar specification for GNU Bison +** +** ATTENTION: This requires GNU Bison 1.875 or newer! +*/ + +#include +#include + +#include "cfg.h" +#include "cfg_global.h" +#include "cfg_syn.h" + +/* make sure yyparse() accepts a context pointer and + passes through its inlined scanner context to yylex() */ +#define CTX ((cfg_syn_ctx_t *)ctx) +#define YYPARSE_PARAM ctx +#define YYLEX_PARAM CTX->yyscan + +/* provide an explicit prototype for the yylex() function but use + "void *" instead of correct type because at this point in the + generation process we have the types still not available */ +extern int yylex(/*YYSTYPE*/ void *lvalp, + /*YYLTYPE*/ void *llocp, cfg_syn_ctx_t *ctx); + +/* generate verbose error messages and remember them inside the context */ +#undef yyerror +#define yyerror(msg) \ + cfg_syn_error(CTX, CFG_ERR_SYN, &yylloc, "%s", msg) + +/* scanner state transition */ +extern void cfg_syn_scan_push(cfg_syn_ctx_t *, const char *state); +extern void cfg_syn_scan_pop (cfg_syn_ctx_t *); + +%} + +/* parser options */ +%error-verbose +%pure_parser +%locations +%defines + +/* the YYSTYPE: parser token value */ +%union { + char *cpString; + cfg_node_t *npNode; +} + +/* assign YYSTYPE elements to parser rules */ +%type sequence +%type directives +%type directive +%type tokens +%type token +%type string + +/* list of scanner tokens */ +%token T_SEP +%token T_OPEN +%token T_CLOSE +%token T_STRING + +/* operator association */ +%right T_SEP +%right T_OPEN +%right T_CLOSE + +/* grammar start rule + (technically redundant but explicit to be sure) */ +%start configuration + +%% + +configuration + : sequence { + CTX->node = $1; + } + ; + +sequence + : directives { + cfg_node_t *n; + cfg_node_create(CTX->cfg, &n); + cfg_node_set(CTX->cfg, n, CFG_NODE_ATTR_TYPE, CFG_NODE_TYPE_SEQ); + cfg_node_set(CTX->cfg, n, CFG_NODE_ATTR_CHILD1, $1); + $$ = n; + } + ; + +directives + : /* empty */ { + $$ = NULL; + } + | directive { + $$ = $1; + } + | directive T_SEP directives { + cfg_node_set(CTX->cfg, $1, CFG_NODE_ATTR_RBROTH, $3); + $$ = $1; + } + ; + +directive + : tokens { + cfg_node_t *n; + cfg_node_create(CTX->cfg, &n); + cfg_node_set(CTX->cfg, n, CFG_NODE_ATTR_TYPE, CFG_NODE_TYPE_DIR); + cfg_node_set(CTX->cfg, n, CFG_NODE_ATTR_CHILD1, $1); + $$ = n; + } + ; + +tokens + : token { + $$ = $1; + } + | token tokens { + cfg_node_set(CTX->cfg, $1, CFG_NODE_ATTR_RBROTH, $2); + $$ = $1; + } + ; + +token + : T_OPEN sequence T_CLOSE { + $$ = $2; + } + | string { + $$ = $1; + } + ; + +string + : T_STRING { + cfg_node_t *n; + cfg_node_create(CTX->cfg, &n); + cfg_node_set(CTX->cfg, n, CFG_NODE_ATTR_TYPE, CFG_NODE_TYPE_ARG); + cfg_node_set(CTX->cfg, n, CFG_NODE_ATTR_TOKEN|CFG_ATTR_GIFT, $1); + $$ = n; + } + ; + +%% + Index: ossp-pkg/cfg/perl/cfg.xs RCS File: /v/ossp/cvs/ossp-pkg/cfg/perl/cfg.xs,v rcsdiff -q -kk '-r1.6' '-r1.7' -u '/v/ossp/cvs/ossp-pkg/cfg/perl/cfg.xs,v' 2>/dev/null --- cfg.xs 2004/11/20 14:52:57 1.6 +++ cfg.xs 2004/12/04 12:48:42 1.7 @@ -283,7 +283,7 @@ cfg_node_attr_t attr char *va_arg1 CODE: - RETVAL = cfg_node_set(cfg, node, attr, va_arg1); + RETVAL = cfg_node_set(cfg, node, attr|CFG_ATTR_COPY, va_arg1); OUTPUT: RETVAL CASE: ((cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_TYPE) @@ -357,7 +357,7 @@ cfg_node_attr_t attr char *&va_arg1 = NO_INIT CODE: - RETVAL = cfg_node_get(cfg, node, attr, &va_arg1); + RETVAL = cfg_node_get(cfg, node, attr|CFG_ATTR_COPY, &va_arg1); OUTPUT: va_arg1 RETVAL