OSSP CVS Repository

ossp - Check-in [4864]
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [Patchset]  [Tagging/Branching

Check-in Number: 4864
Date: 2004-Nov-20 15:52:56 (local)
2004-Nov-20 14:52:56 (UTC)
User:rse
Branch:
Comment: Change cfg_node_root() API function to be able to both set and/or get the root node.
Tickets:
Inspections:
Files:
ossp-pkg/cfg/ChangeLog      1.19 -> 1.20     4 inserted, 0 deleted
ossp-pkg/cfg/cfg.h      1.14 -> 1.15     1 inserted, 1 deleted
ossp-pkg/cfg/cfg_node.c      added-> 1.21
ossp-pkg/cfg/cfg_syn.c      1.19 -> 1.20     1 inserted, 1 deleted
ossp-pkg/cfg/perl/cfg.xs      1.5 -> 1.6     5 inserted, 4 deleted

ossp-pkg/cfg/ChangeLog 1.19 -> 1.20

--- ChangeLog    2004/11/20 12:54:07     1.19
+++ ChangeLog    2004/11/20 14:52:56     1.20
@@ -10,6 +10,10 @@
 
  Changes between 0.9.4 and 0.9.5 (31-Oct-2004 to xx-Nov-2004):
 
+   *) Change cfg_node_root() API function to be able to both
+      set and/or get the root node.
+      [Ralf S. Engelschall <rse@engelschall.com>]
+
    *) Fixed cfg_test program by correctly passing the used number of
       bytes in the buffer instead of the size of the buffer.
       [Ralf S. Engelschall <rse@engelschall.com>]


ossp-pkg/cfg/cfg.h 1.14 -> 1.15

--- cfg.h        2004/07/17 07:37:55     1.14
+++ cfg.h        2004/11/20 14:52:56     1.15
@@ -135,7 +135,7 @@
 cfg_rc_t   cfg_node_get    (cfg_t  *cfg, cfg_node_t  *node, cfg_node_attr_t attr, ...);
 
 /* node traversing/locating */
-cfg_rc_t   cfg_node_root   (cfg_t  *cfg, cfg_node_t **node);
+cfg_rc_t   cfg_node_root   (cfg_t  *cfg, cfg_node_t  *node, cfg_node_t **node_old);
 cfg_rc_t   cfg_node_select (cfg_t  *cfg, cfg_node_t  *node, cfg_node_t ***result, const char *spec, ...);
 cfg_rc_t   cfg_node_find   (cfg_t  *cfg, cfg_node_t  *node, cfg_rc_t (*cb_fct_cmp)(cfg_t *, cfg_node_t *, void *), void *cb_ctx_cmp, cfg_node_t **cont);
 cfg_rc_t   cfg_node_apply  (cfg_t  *cfg, cfg_node_t  *node, cfg_rc_t (*cb_fct_cmp)(cfg_t *, cfg_node_t *, void *), void *cb_ctx_cmp, cfg_rc_t (*cb_fct_cb)(cfg_t *, cfg_node_t *, void *), void *cb_ctx_cb);


ossp-pkg/cfg/cfg_node.c -> 1.21

*** /dev/null    Tue Apr 30 13:52:06 2024
--- -    Tue Apr 30 13:52:10 2024
***************
*** 0 ****
--- 1,834 ----
+ /*
+ **  OSSP cfg - Configuration Parsing
+ **  Copyright (c) 2002-2004 Ralf S. Engelschall <rse@engelschall.com>
+ **  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.c: configuration nodes
+ */
+ 
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <stdarg.h>
+ #include <unistd.h>
+ #include <limits.h>
+ 
+ #include "cfg_global.h"
+ #include "cfg_main.h"
+ #include "cfg_node.h"
+ #include "cfg_fmt.h"
+ 
+ /* create a configuration node */
+ cfg_rc_t
+ cfg_node_create(
+     cfg_t *cfg,
+     cfg_node_t **node)
+ {
+     cfg_node_t *n;
+     cfg_rc_t rc;
+ 
+     /* argument sanity checking */
+     if (node == NULL)
+         return CFG_ERR_ARG;
+ 
+     /* allocate memory */
+     if ((rc = cfg_grid_alloc(cfg->grid_nodes, (void **)(void *)&n)) != CFG_OK)
+         return rc;
+ 
+     /* initialize node attributes */
+     n->parent   = NULL;
+     n->rbroth   = NULL;
+     n->child1   = NULL;
+     n->type     = CFG_NODE_TYPE_ARG;
+     n->token    = NULL;
+     cfg_data_init(&n->data);
+     n->srcname  = NULL;
+     n->srcpos   = 0;
+     *node = n;
+ 
+     return CFG_OK;
+ }
+ 
+ /* destroy a configuration node */
+ cfg_rc_t
+ cfg_node_destroy(
+     cfg_t *cfg,
+     cfg_node_t *node)
+ {
+     /* argument sanity checking */
+     if (node == NULL)
+         return CFG_ERR_ARG;
+ 
+     /* destroy memory */
+     if (node->token != NULL)
+         free(node->token);
+     if (node->srcname != NULL)
+         free(node->srcname);
+     cfg_grid_free(cfg->grid_nodes, node);
+ 
+     return CFG_OK;
+ }
+ 
+ /* clone a node */
+ cfg_rc_t
+ cfg_node_clone(
+     cfg_t *cfg,
+     cfg_node_t *node,
+     cfg_node_t **node2)
+ {
+     cfg_node_t *n;
+     cfg_rc_t rc;
+ 
+     /* argument sanity checking */
+     if (node == NULL || node2 == NULL)
+         return CFG_ERR_ARG;
+ 
+     /* allocate memory for new node */
+     if ((rc = cfg_grid_alloc(cfg->grid_nodes, (void **)(void *)&n)) != CFG_OK)
+         return rc;
+ 
+     /* clone node attributes */
+     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;
+     *node2 = n;
+ 
+     return CFG_OK;
+ }
+ 
+ /* set a node attribute */
+ cfg_rc_t
+ cfg_node_set(
+     cfg_t *cfg,
+     cfg_node_t *node,
+     cfg_node_attr_t attr,
+     ...)
+ {
+     va_list ap;
+ 
+     /* argument sanity checking */
+     if (node == NULL)
+         return CFG_ERR_ARG;
+ 
+     /* dispatch into individual attribute handling */
+     va_start(ap, attr);
+     switch (attr) {
+         case CFG_NODE_ATTR_PARENT: {
+             node->parent = (cfg_node_t *)va_arg(ap, cfg_node_t *);
+             break;
+         }
+         case CFG_NODE_ATTR_LBROTH: {
+             return CFG_ERR_USE; /* cannot be set, only get */
+         }
+         case CFG_NODE_ATTR_RBROTH: {
+             node->rbroth = (cfg_node_t *)va_arg(ap, cfg_node_t *);
+             break;
+         }
+         case CFG_NODE_ATTR_CHILD1: {
+             node->child1 = (cfg_node_t *)va_arg(ap, cfg_node_t *);
+             break;
+         }
+         case CFG_NODE_ATTR_CHILDL: {
+             return CFG_ERR_USE; /* cannot be set, only get */
+         }
+         case CFG_NODE_ATTR_CHILDS: {
+             return CFG_ERR_USE; /* cannot be set, only get */
+         }
+         case CFG_NODE_ATTR_NODES: {
+             return CFG_ERR_USE; /* cannot be set, only get */
+         }
+         case CFG_NODE_ATTR_DEPTH: {
+             return CFG_ERR_USE; /* cannot be set, only get */
+         }
+         case CFG_NODE_ATTR_TYPE: {
+             node->type = (cfg_node_type_t)va_arg(ap, cfg_node_type_t);
+             break;
+         }
+         case CFG_NODE_ATTR_TOKEN: {
+             if (node->token != NULL)
+                 free(node->token);
+             node->token = (char *)va_arg(ap, char *);
+             if (node->token != NULL)
+                 node->token = strdup(node->token);
+             break;
+         }
+         case CFG_NODE_ATTR_DATA: {
+             return CFG_ERR_USE;
+         }
+         case CFG_NODE_ATTR_SRCNAME: {
+             if (node->srcname != NULL)
+                 free(node->srcname);
+             node->srcname = (char *)va_arg(ap, char *);
+             if (node->srcname != NULL)
+                 node->srcname = strdup(node->srcname);
+             break;
+         }
+         case CFG_NODE_ATTR_SRCPOS: {
+             node->srcpos = (int)va_arg(ap, int);
+             break;
+         }
+         default:
+             return CFG_ERR_ARG;
+     }
+     va_end(ap);
+ 
+     return CFG_OK;
+ }
+ 
+ /* INTERNAL: calculate number of nodes */
+ static int
+ cfg_node_get_nodes(
+     cfg_node_t *node)
+ {
+     int n;
+ 
+     n = 0;
+     if (node != NULL) {
+         n++;
+         if ((node = node->child1) != NULL) {
+             n += cfg_node_get_nodes(node);
+             if ((node = node->rbroth) != NULL)
+                 n += cfg_node_get_nodes(node);
+         }
+     }
+     return n;
+ }
+ 
+ cfg_rc_t
+ cfg_node_get(
+     cfg_t *cfg,
+     cfg_node_t *node,
+     cfg_node_attr_t attr,
+     ...)
+ {
+     va_list ap;
+ 
+     /* argument sanity checking */
+     if (node == NULL)
+         return CFG_ERR_ARG;
+ 
+     /* dispatch into individual attribute handling */
+     va_start(ap, attr);
+     switch (attr) {
+         case CFG_NODE_ATTR_PARENT: {
+             cfg_node_t **n = (cfg_node_t **)va_arg(ap, void *);
+             if (n == NULL)
+                 return CFG_ERR_ARG;
+             *n = node->parent;
+             break;
+         }
+         case CFG_NODE_ATTR_LBROTH: {
+             cfg_node_t **np = (cfg_node_t **)va_arg(ap, void *);
+             cfg_node_t *n;
+             if (np == NULL)
+                 return CFG_ERR_ARG;
+             *np = NULL;
+             if ((n = node->parent) != NULL) {
+                 if ((n = n->child1) != NULL) {
+                     while (n->rbroth != node && n->rbroth != NULL)
+                         n = n->rbroth;
+                     if (n->rbroth == node)
+                         *np = n;
+                 }
+             }
+             break;
+         }
+         case CFG_NODE_ATTR_RBROTH: {
+             cfg_node_t **n = (cfg_node_t **)va_arg(ap, void *);
+             if (n == NULL)
+                 return CFG_ERR_ARG;
+             *n = node->rbroth;
+             break;
+         }
+         case CFG_NODE_ATTR_CHILD1: {
+             cfg_node_t **n = (cfg_node_t **)va_arg(ap, void *);
+             if (n == NULL)
+                 return CFG_ERR_ARG;
+             *n = node->child1;
+             break;
+         }
+         case CFG_NODE_ATTR_CHILDL: {
+             cfg_node_t **n = (cfg_node_t **)va_arg(ap, void *);
+             if (n == NULL)
+                 return CFG_ERR_ARG;
+             if ((*n = node->child1) != NULL)
+                 while ((*n)->rbroth != NULL)
+                     *n = (*n)->rbroth;
+             break;
+         }
+         case CFG_NODE_ATTR_CHILDS: {
+             int *c = (int *)va_arg(ap, int *);
+             cfg_node_t *n;
+             if (c == NULL)
+                 return CFG_ERR_ARG;
+             *c = 0;
+             if ((n = node->child1) != NULL) {
+                 (*c)++;
+                 while (n->rbroth != NULL) {
+                     n = n->rbroth;
+                     (*c)++;
+                 }
+             }
+             break;
+         }
+         case CFG_NODE_ATTR_NODES: {
+             int *k = (int *)va_arg(ap, int *);
+             if (k == NULL)
+                 return CFG_ERR_ARG;
+             *k = cfg_node_get_nodes(node);
+             break;
+         }
+         case CFG_NODE_ATTR_DEPTH: {
+             int *k = (int *)va_arg(ap, int *);
+             cfg_node_t *n;
+             if (k == NULL)
+                 return CFG_ERR_ARG;
+             *k = 0;
+             n = node;
+             while ((n = n->parent) != NULL)
+                 (*k)++;
+             break;
+         }
+         case CFG_NODE_ATTR_TYPE: {
+             cfg_node_type_t *type = (cfg_node_type_t *)va_arg(ap, void *);
+             if (type == NULL)
+                 return CFG_ERR_ARG;
+             *type = node->type;
+             break;
+         }
+         case CFG_NODE_ATTR_TOKEN: {
+             char **token = (char **)va_arg(ap, char **);
+             if (token == NULL)
+                 return CFG_ERR_ARG;
+             *token = node->token;
+             break;
+         }
+         case CFG_NODE_ATTR_DATA: {
+             cfg_data_t **data = (cfg_data_t **)va_arg(ap, void *);
+             if (data == NULL)
+                 return CFG_ERR_ARG;
+             *data = &(node->data);
+             break;
+         }
+         case CFG_NODE_ATTR_SRCNAME: {
+             char **name = (char **)va_arg(ap, char **);
+             if (name == NULL)
+                 return CFG_ERR_ARG;
+             *name = node->srcname;
+             break;
+         }
+         case CFG_NODE_ATTR_SRCPOS: {
+             int *pos = (int *)va_arg(ap, int *);
+             if (pos == NULL)
+                 return CFG_ERR_ARG;
+             *pos = node->srcpos;
+             break;
+         }
+         default:
+             return CFG_ERR_ARG;
+     }
+     va_end(ap);
+ 
+     return CFG_OK;
+ }
+ 
+ /* get and/or set root node */
+ cfg_rc_t
+ cfg_node_root(
+     cfg_t *cfg,
+     cfg_node_t  *node,
+     cfg_node_t **node_old)
+ {
+     /* argument sanity checking */
+     if (cfg == NULL || (node == NULL && node_old == NULL))
+         return CFG_ERR_ARG;
+ 
+     /* optionally get old root node pointer */
+     if (node_old != NULL)
+         *node_old = cfg->root;
+ 
+     /* optionally set new root node pointer */
+     if (node != NULL)
+         cfg->root = node;
+ 
+     return CFG_OK;
+ }
+ 
+ /* forward declarations for internal stepping functions */
+ static cfg_rc_t
+ cfg_node_select_step1(
+     cfg_t *, cfg_node_t *, cfg_node_t ***, long *, const char *);
+ static cfg_rc_t
+ cfg_node_select_step2(
+     cfg_t *, cfg_node_t *, cfg_node_t ***, long *, const char *, const char *, size_t, long, long, long *);
+ 
+ /* INTERNAL: selection stepping function (part 3, matching node processing) */
+ static cfg_rc_t
+ cfg_node_select_step3(
+     cfg_t *cfg,
+     cfg_node_t *node,
+     cfg_node_t ***result_vec, long *result_len,
+     const char *spec,
+     const char *cpSel, size_t nSel,
+     long nFilMin, long nFilMax,
+     long *nFound)
+ {
+     cfg_rc_t rc;
+ 
+     fprintf(stderr, "      step3: (1) cpSel=\"%s\", nSel=%d, spec=\"%s\", nFilMin=%ld, nFilMax=%ld, nFound=%ld\n",
+             cpSel, nSel, spec, nFilMin, nFilMax, *nFound);
+ 
+     if (spec[0] == '\0') {
+         /* end of selection, node found */
+         (*nFound)++;
+         fprintf(stderr, "      step3: (2) found node!!\n");
+         fprintf(stderr, "      step3:     current node=0x%lx type=%s token=\"%s\"\n",
+                 (unsigned long)node,
+                 (node != NULL ? (node->type == CFG_NODE_TYPE_SEQ ? "SEQ" : (node->type == CFG_NODE_TYPE_DIR ? "DIR" : "ARG")) : "<NULL>/.."),
+                 (node != NULL ? (node->token != NULL ? node->token : "<NULL>") : "<NULL>/.."));
+         if (nFilMin <= *nFound && *nFound <= nFilMax) {
+             if (result_len != NULL) {
+                 (*result_len)++;
+                 if (result_vec != NULL) {
+                     if ((*result_vec = (cfg_node_t **)realloc(*result_vec, sizeof(cfg_node_t *)*((*result_len)+1))) == NULL)
+                         return CFG_ERR_SYS;
+                     (*result_vec)[(*result_len)-1] = node;
+                     (*result_vec)[(*result_len)] = NULL;
+                 }
+             }
+         }
+         rc = CFG_OK;
+     }
+     else {
+         /* start over with next step */
+         rc = cfg_node_select_step1(cfg, node, result_vec, result_len, spec);
+     }
+     return rc;
+ }
+ 
+ /* INTERNAL: selection stepping function (part 2, node matching) */
+ static cfg_rc_t
+ cfg_node_select_step2(
+     cfg_t *cfg,
+     cfg_node_t *node,
+     cfg_node_t ***result_vec, long *result_len,
+     const char *spec,
+     const char *cpSel, size_t nSel,
+     long nFilMin, long nFilMax,
+     long *nFound)
+ {
+     cfg_rc_t rc;
+     char *token;
+     cfg_node_t *node2;
+     cfg_node_type_t type;
+ 
+     fprintf(stderr, "    step2: (1) cpSel=\"%.*s\", nSel=%d, spec=\"%s\", nFilMin=%ld, nFilMax=%ld, nFound=%ld\n",
+             nSel, cpSel, nSel, spec, nFilMin, nFilMax, *nFound);
+     fprintf(stderr, "    step2:     current node=0x%lx type=%s token=\"%s\"\n",
+             (unsigned long)node,
+             (node != NULL ? (node->type == CFG_NODE_TYPE_SEQ ? "SEQ" : (node->type == CFG_NODE_TYPE_DIR ? "DIR" : "ARG")) : "<NULL>/.."),
+             (node != NULL ? (node->token != NULL ? node->token : "<NULL>") : "<NULL>/.."));
+ 
+     rc = CFG_OK;
+     if (nSel == 1 && strncmp(cpSel, ".", nSel) == 0) {
+         /* current node (no-op) */
+         fprintf(stderr, "    step2: search current node, starting at node 0x%lx\n", (unsigned long)node);
+         rc = cfg_node_select_step3(cfg, node, result_vec, result_len, spec, cpSel, nSel, nFilMin, nFilMax, nFound);
+     }
+     else if (nSel == 2 && strncmp(cpSel, "..", nSel) == 0) {
+         /* parent node */
+         fprintf(stderr, "    step2: search parent node, starting at node 0x%lx\n", (unsigned long)node);
+         if (cfg_node_get(cfg, node, CFG_NODE_ATTR_PARENT, &node) == CFG_OK && node != NULL)
+             rc = cfg_node_select_step3(cfg, node, result_vec, result_len, spec, cpSel, nSel, nFilMin, nFilMax, nFound);
+     }
+     else if (nSel == 4 && strncmp(cpSel, "....", nSel) == 0) {
+         /* anchestor nodes */
+         fprintf(stderr, "    step2: search ancestor nodes, starting at node 0x%lx\n", (unsigned long)node);
+         while (cfg_node_get(cfg, node, CFG_NODE_ATTR_PARENT, &node) == CFG_OK && node != NULL)
+             if ((rc = cfg_node_select_step3(cfg, node, result_vec, result_len, spec, cpSel, nSel, nFilMin, nFilMax, nFound)) != CFG_OK)
+                 break;
+     }
+     else if (nSel == 1 && strncmp(cpSel, "-", nSel) == 0) {
+         /* previous sibling node */
+         fprintf(stderr, "    step2: search previous sibling node, starting at node 0x%lx\n", (unsigned long)node);
+         if ((rc = cfg_node_get(cfg, node, CFG_NODE_ATTR_LBROTH, &node)) == CFG_OK && node != NULL)
+             rc = cfg_node_select_step3(cfg, node, result_vec, result_len, spec, cpSel, nSel, nFilMin, nFilMax, nFound);
+     }
+     else if (nSel == 2 && strncmp(cpSel, "--", nSel) == 0) {
+         /* preceeding sibling nodes */
+         fprintf(stderr, "    step2: search preceeding sibling nodes, starting at node 0x%lx\n", (unsigned long)node);
+         while (cfg_node_get(cfg, node, CFG_NODE_ATTR_LBROTH, &node) == CFG_OK && node != NULL)
+             if ((rc = cfg_node_select_step3(cfg, node, result_vec, result_len, spec, cpSel, nSel, nFilMin, nFilMax, nFound)) != CFG_OK)
+                 break;
+     }
+     else if (nSel == 1 && strncmp(cpSel, "+", nSel) == 0) {
+         /* next sibling node */
+         fprintf(stderr, "    step2: search next sibling node, starting at node 0x%lx\n", (unsigned long)node);
+         if ((rc = cfg_node_get(cfg, node, CFG_NODE_ATTR_RBROTH, &node)) == CFG_OK && node != NULL)
+             rc = cfg_node_select_step3(cfg, node, result_vec, result_len, spec, cpSel, nSel, nFilMin, nFilMax, nFound);
+     }
+     else if (nSel == 2 && strncmp(cpSel, "++", nSel) == 0) {
+         /* following sibling nodes */
+         fprintf(stderr, "    step2: search following sibling nodes, starting at node 0x%lx\n", (unsigned long)node);
+         while (cfg_node_get(cfg, node, CFG_NODE_ATTR_RBROTH, &node) == CFG_OK && node != NULL)
+             if ((rc = cfg_node_select_step3(cfg, node, result_vec, result_len, spec, cpSel, nSel, nFilMin, nFilMax, nFound)) != CFG_OK)
+                 break;
+     }
+     else if (nSel == 0 /* "//" */) {
+         /* descendant nodes */
+         fprintf(stderr, "    step2: search descendant nodes, starting at node 0x%lx\n", (unsigned long)node);
+ #if 0 /* FIXME */
+         if ((rc = cfg_node_apply(cfg, node, NULL, NULL, cfg_node_select_step2_descendant, &descendant_ctx)
+             cfg_rc_t cfg_node_select_step2_descendant(cfg_t *cfg, cfg_node_t *node, void *_ctx));
+ #endif
+         if ((rc = cfg_node_get(cfg, node, CFG_NODE_ATTR_CHILD1, &node)) == CFG_OK && node != NULL) {
+             do {
+                 if ((rc = cfg_node_select_step3(cfg, node, result_vec, result_len, spec, cpSel, nSel, nFilMin, nFilMax, nFound)) != CFG_OK)
+                     return rc;
+                 if ((rc = cfg_node_select_step2(cfg, node, result_vec, result_len, spec, cpSel, nSel, nFilMin, nFilMax, nFound)) != CFG_OK)
+                     return rc;
+             } while ((rc = cfg_node_get(cfg, node, CFG_NODE_ATTR_RBROTH, &node)) == CFG_OK && node != NULL);
+         }
+         return CFG_OK;
+     }
+     else {
+         /* child node */
+         fprintf(stderr, "    step2: search child nodes, starting at node 0x%lx\n", (unsigned long)node);
+         if ((rc = cfg_node_get(cfg, node, CFG_NODE_ATTR_CHILD1, &node)) == CFG_OK && node != NULL) {
+             do {
+                 if ((rc = cfg_node_get(cfg, node, CFG_NODE_ATTR_TOKEN, &token)) != CFG_OK)
+                     continue;
+                 if ((rc = cfg_node_get(cfg, node, CFG_NODE_ATTR_TYPE, &type)) == CFG_OK && type == CFG_NODE_TYPE_DIR) {
+                     if ((rc = cfg_node_get(cfg, node, CFG_NODE_ATTR_CHILD1, &node2)) != CFG_OK || node2 == NULL)
+                         continue;
+                     if ((rc = cfg_node_get(cfg, node2, CFG_NODE_ATTR_TOKEN, &token)) != CFG_OK)
+                         continue;
+                 }
+                 if (token != NULL) {
+                     size_t l = strlen(token);
+                     fprintf(stderr, "    step2: compare child node: token \"%s\"\n", token);
+                     if (   (l == 1 && nSel == 1 && token[0] == '*')
+                         || (l == nSel && strncmp(token, cpSel, nSel) == 0)) {
+                         if ((rc = cfg_node_select_step3(cfg, node, result_vec, result_len, spec, cpSel, nSel, nFilMin, nFilMax, nFound)) != CFG_OK)
+                             return rc;
+                     }
+                 }
+             } while ((rc = cfg_node_get(cfg, node, CFG_NODE_ATTR_RBROTH, &node)) == CFG_OK && node != NULL);
+         }
+         return CFG_OK;
+     }
+     return rc;
+ }
+ 
+ /* INTERNAL: selection stepping function (part 1, selection parsing) */
+ static cfg_rc_t
+ cfg_node_select_step1(
+     cfg_t *cfg,
+     cfg_node_t *node,
+     cfg_node_t ***result_vec, long *result_len,
+     const char *spec)
+ {
+     const char *cpSel; size_t nSel;
+     long nFilMin, nFilMax;
+     long n;
+     const char *cp;
+     char *cp2;
+     cfg_rc_t rc;
+     long nFound;
+ 
+     fprintf(stderr, "  step1: (0) spec=\"%s\"\n", spec);
+ 
+     /* stop processing if spec is empty */
+     if (spec[0] == '\0')
+         return CFG_OK;
+ 
+     /* determine selection step information */
+     cpSel = spec;
+     nSel = strcspn(cpSel, "[/");
+     cp = cpSel+nSel;
+     nFilMin = 1;
+     nFilMax = LONG_MAX;
+     if (*cp == '[') {
+         cp++;
+         n = strtol(cp, &cp2, 10);
+         if (cp2 > cp && n != 0)
+             nFilMin = n;
+         cp = cp2;
+         if (*cp == ',') {
+             cp++;
+             n = strtol(cp, &cp2, 10);
+             if (cp2 > cp && n != 0)
+                 nFilMax = n;
+             cp = cp2;
+         }
+         else
+             nFilMax = nFilMin;
+         if (*cp != ']') {
+             cfg_error_info(cfg, CFG_ERR_ARG, "invalid selection specification filter range");
+             return CFG_ERR_ARG;
+         }
+         cp++;
+     }
+     if (*cp == '/')
+         cp++;
+     spec = cp;
+ 
+     fprintf(stderr, "  step1: (1) cpSel=\"%s\", nSel=%d, spec=\"%s\", nFilMin=%ld, nFilMax=%ld\n",
+             cpSel, nSel, spec, nFilMin, nFilMax);
+ 
+     /* perform pre-selection if filter range is relative to last element */
+     if (nFilMin < 0 || nFilMax < 0) {
+         nFound = 0;
+         fprintf(stderr, "  step1: pre-selection start\n");
+         if ((rc = cfg_node_select_step2(cfg, node, NULL, NULL, spec, cpSel, nSel, 1, LONG_MAX, &nFound)) != CFG_OK)
+             return rc;
+         fprintf(stderr, "  step1: (1b) cpSel=\"%s\", nSel=%d, spec=\"%s\", nFilMin=%ld, nFilMax=%ld nFound=%ld\n", 
+                 cpSel, nSel, spec, nFilMin, nFilMax, nFound);
+         fprintf(stderr, "  step1: pre-selection end\n");
+         if (nFound == 0)
+             return CFG_OK;
+         if (nFilMin < 0) {
+             nFilMin = nFound + (nFilMin+1);
+             if (nFilMin < 1)
+                 nFilMin = 1;
+         }
+         if (nFilMax < 0) {
+             nFilMax = nFound + (nFilMax+1);
+             if (nFilMax < 1)
+                 nFilMax = 1;
+         }
+     }
+ 
+     fprintf(stderr, "  step1: (2) cpSel=\"%s\", nSel=%d, spec=\"%s\", nFilMin=%ld, nFilMax=%ld\n",
+             cpSel, nSel, spec, nFilMin, nFilMax);
+ 
+     /* perform real selection */
+     nFound = 0;
+     if ((rc = cfg_node_select_step2(cfg, node, result_vec, result_len, spec, cpSel, nSel, nFilMin, nFilMax, &nFound)) != CFG_OK)
+         return rc;
+ 
+     fprintf(stderr, "  step1: (3) cpSel=\"%s\", nSel=%d, spec=\"%s\", nFilMin=%ld, nFilMax=%ld nFound=%ld\n",
+             cpSel, nSel, spec, nFilMin, nFilMax, nFound);
+ 
+     return CFG_OK;
+ }
+ 
+ /* select a node */
+ cfg_rc_t
+ cfg_node_select(
+     cfg_t *cfg,
+     cfg_node_t *node,
+     cfg_node_t ***result_vec,
+     const char *fmt,
+     ...)
+ {
+     cfg_rc_t rc;
+     va_list ap;
+     char *spec;
+     char *cp;
+     long result_len;
+ 
+     /* argument sanity checking */
+     if (cfg == NULL || result_vec == NULL || fmt == NULL)
+         return CFG_ERR_ARG;
+ 
+     /* on-the-fly create or just take over specification string */
+     va_start(ap, fmt);
+     spec = cfg_fmt_vasprintf(fmt, ap);
+     va_end(ap);
+     if (spec == NULL)
+         return CFG_ERR_FMT;
+     fprintf(stderr, "select: (1) spec=\"%s\"\n", spec);
+ 
+     /* special cases for absolute (start from root-node) selection */
+     cp = spec;
+     if (cp[0] == '/') {
+         /* <any,"/x"> is same as <root,"x"> */
+         if (node != NULL)
+             return CFG_ERR_USE;
+         node = cfg->root;
+         cp++;
+     }
+     else if (node == NULL) {
+         /* <NULL, "..."> is same as <root, "..."> */
+         node = cfg->root;
+     }
+     fprintf(stderr, "select: (2) spec=\"%s\"\n", cp);
+ 
+     /* initialize result node array */
+     result_len = 0;
+     if ((*result_vec = (cfg_node_t **)malloc(sizeof(cfg_node_t *)*(result_len+1))) == NULL)
+         return CFG_ERR_SYS;
+     (*result_vec)[result_len] = NULL;
+ 
+     /* perform the selection stepping */
+     if ((rc = cfg_node_select_step1(cfg, node, result_vec, &result_len, cp)) != CFG_OK) {
+         free(*result_vec);
+         return rc;
+     }
+     fprintf(stderr, "select: (3) result_len=%ld\n", result_len);
+ 
+     return CFG_OK;
+ }
+ 
+ /* return next matching node (iteration) */
+ cfg_rc_t
+ cfg_node_find(
+     cfg_t *cfg,
+     cfg_node_t *node,
+     cfg_rc_t (*cb_fct_cmp)(cfg_t *, cfg_node_t *, void *),
+     void *cb_ctx_cmp,
+     cfg_node_t **cont)
+ {
+     /* FIXME */
+     return CFG_ERR_INT;
+ }
+ 
+ /* apply for each matching node (recursion) */
+ cfg_rc_t
+ cfg_node_apply(
+     cfg_t *cfg,
+     cfg_node_t *node,
+     cfg_rc_t (*cb_fct_cmp)(cfg_t *, cfg_node_t *, void *),
+     void *cb_ctx_cmp,
+     cfg_rc_t (*cb_fct_cb)(cfg_t *, cfg_node_t *, void *),
+     void *cb_ctx_cb)
+ {
+     cfg_rc_t rc;
+ 
+     /* 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)
+             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;
+     }
+     return CFG_OK;
+ }
+ 
+ /* compare two nodes */
+ cfg_rc_t
+ cfg_node_cmp(
+     cfg_t *cfg,
+     cfg_node_t *node,
+     void *token)
+ {
+     /* argument sanity checking */
+     if (cfg == NULL || node == NULL || token == NULL)
+         return CFG_ERR_NDE;
+     if (node->token == NULL && token == NULL)
+         return CFG_OK;
+     if (node->token == NULL || token == NULL)
+         return CFG_ERR_NDE;
+     if (strcmp(node->token, (char *)token) == 0)
+         return CFG_OK;
+     return CFG_ERR_NDE;
+ }
+ 
+ /* link to nodes together */
+ cfg_rc_t
+ cfg_node_link(
+     cfg_t *cfg,
+     cfg_node_t *node,
+     cfg_node_attr_t attr,
+     cfg_node_t *node2)
+ {
+     cfg_node_t *n;
+ 
+     /* argument sanity checking */
+     if (node == NULL || node2 == NULL)
+         return CFG_ERR_ARG;
+     if (attr == CFG_NODE_ATTR_RBROTH) {
+         /* make node a rbroth */
+         n = node2;
+         n->parent = node->parent;
+         while (n->rbroth != NULL) {
+             n->parent = node->parent;
+             n = n->rbroth;
+         }
+         n->rbroth = node->rbroth;
+         node->rbroth = node2;
+     }
+     else if (attr == CFG_NODE_ATTR_CHILD1) {
+         /* make node a child1 */
+         n = node2;
+         n->parent = node;
+         while (n->rbroth != NULL) {
+             n->parent = node;
+             n = n->rbroth;
+         }
+         n->rbroth = node->child1;
+         node->child1 = node2;
+     }
+     /* FIXME more linkage possibilities */
+     else
+         return CFG_ERR_ARG;
+     return CFG_OK;
+ }
+ 
+ /* unlink a nodes from others */
+ cfg_rc_t
+ cfg_node_unlink(
+     cfg_t *cfg,
+     cfg_node_t *node)
+ {
+     cfg_node_t *n;
+ 
+     /* argument sanity checking */
+     if (node == NULL)
+         return CFG_ERR_ARG;
+ 
+     if (node->parent == NULL)
+         return CFG_OK;
+     if (node->parent->child1 == node) {
+         /* node was a child1 */
+         node->parent->child1 = node->rbroth;
+     }
+     else {
+         /* node was a rbroth */
+         n = node->parent->child1;
+         while (n->rbroth != node)
+             n = n->rbroth;
+         n->rbroth = node->rbroth;
+     }
+     return CFG_OK;
+ }
+ 


ossp-pkg/cfg/cfg_syn.c 1.19 -> 1.20

--- cfg_syn.c    2004/11/20 12:54:07     1.19
+++ cfg_syn.c    2004/11/20 14:52:56     1.20
@@ -335,7 +335,7 @@
     ctx.buf    = buf;
     ctx.indent = 0;
 
-    if ((rc = cfg_node_root(cfg, &root)) != CFG_OK)
+    if ((rc = cfg_node_root(cfg, NULL, &root)) != CFG_OK)
         return rc;
     if (node == root) {
         /* if we dump the whole configuration, treat the first SEQ node special


ossp-pkg/cfg/perl/cfg.xs 1.5 -> 1.6

--- cfg.xs       2004/11/19 21:37:06     1.5
+++ cfg.xs       2004/11/20 14:52:57     1.6
@@ -396,16 +396,17 @@
             RETVAL
 
 cfg_rc_t
-cfg_node_root(cfg,node)
+cfg_node_root(cfg,node,node_old)
     PROTOTYPE:
         $$
     INPUT:
         cfg_t *cfg
-        cfg_node_t *&node = NO_INIT
+        cfg_node_t *node
+        cfg_node_t *&node_old = NO_INIT
     CODE:
-        RETVAL = cfg_node_root(cfg, &node);
+        RETVAL = cfg_node_root(cfg, node, &node_old);
     OUTPUT:
-        node
+        node_old
         RETVAL
 
 cfg_rc_t

CVSTrac 2.0.1