OSSP CVS Repository

ossp - Difference in ossp-pkg/cfg/cfg_node.c versions 1.16 and 1.17
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [History

ossp-pkg/cfg/cfg_node.c 1.16 -> 1.17

--- cfg_node.c   2002/11/18 09:51:29     1.16
+++ cfg_node.c   2002/11/22 14:34:32     1.17
@@ -39,68 +39,104 @@
 #include "cfg_node.h"
 #include "cfg_fmt.h"
 
-cfg_rc_t cfg_node_create(cfg_t *cfg, cfg_node_t **node)
+/* 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 **)&n)) != CFG_OK)
         return rc;
+
+    /* initialize node attributes */
     n->parent   = NULL;
-    n->lbroth   = NULL;
     n->rbroth   = NULL;
     n->child1   = NULL;
-    n->srcname  = NULL;
-    n->srcpos   = 0;
     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;
 }
 
-cfg_rc_t cfg_node_destroy(cfg_t *cfg, cfg_node_t *node)
+/* 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;
 }
 
-cfg_rc_t cfg_node_clone(cfg_t *cfg, cfg_node_t *node, cfg_node_t **node2)
+/* 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 **)&n)) != CFG_OK)
         return rc;
+
+    /* clone node attributes */
     n->parent   = node->parent;
-    n->lbroth   = node->lbroth;
     n->rbroth   = node->rbroth;
     n->child1   = node->child1;
-    n->srcname  = (node->srcname != NULL ? strdup(node->srcname) : NULL);
-    n->srcpos   = node->srcpos;
     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;
 }
 
-cfg_rc_t cfg_node_set(cfg_t *cfg, cfg_node_t *node, cfg_node_attr_t attr, ...)
+/* 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: {
@@ -108,7 +144,7 @@
             break;
         }
         case CFG_NODE_ATTR_LBROTH: {
-            return CFG_ERR_USE;
+            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 *);
@@ -119,28 +155,16 @@
             break;
         }
         case CFG_NODE_ATTR_CHILDL: {
-            return CFG_ERR_USE;
+            return CFG_ERR_USE; /* cannot be set, only get */
         }
         case CFG_NODE_ATTR_CHILDS: {
-            return CFG_ERR_USE;
+            return CFG_ERR_USE; /* cannot be set, only get */
         }
         case CFG_NODE_ATTR_NODES: {
-            return CFG_ERR_USE;
+            return CFG_ERR_USE; /* cannot be set, only get */
         }
         case CFG_NODE_ATTR_DEPTH: {
-            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;
+            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);
@@ -157,14 +181,30 @@
         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;
 }
 
-static int cfg_node_get_nodes(cfg_node_t *node)
+/* INTERNAL: calculate number of nodes */
+static int
+cfg_node_get_nodes(
+    cfg_node_t *node)
 {
     int n;
 
@@ -180,12 +220,20 @@
     return n;
 }
 
-cfg_rc_t cfg_node_get(cfg_t *cfg, cfg_node_t *node, cfg_node_attr_t attr, ...)
+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: {
@@ -267,20 +315,6 @@
                 (*k)++;
             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;
-        }
         case CFG_NODE_ATTR_TYPE: {
             cfg_node_type_t *type = (cfg_node_type_t *)va_arg(ap, void *);
             if (type == NULL)
@@ -302,21 +336,45 @@
             *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;
 }
 
-cfg_rc_t cfg_node_root(cfg_t *cfg, cfg_node_t **node)
+/* return root node */
+cfg_rc_t
+cfg_node_root(
+    cfg_t *cfg,
+    cfg_node_t **node)
 {
+    /* argument sanity checking */
     if (cfg == NULL || node == NULL)
         return CFG_ERR_ARG;
+
+    /* just return the root pointer */
     *node = cfg->root;
+
     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 *);
@@ -324,6 +382,7 @@
 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,
@@ -336,30 +395,38 @@
 {
     cfg_rc_t rc;
 
-    fprintf(stderr, "step3: (1) cpSel=\"%s\", nSel=%d, nFilMin=%ld, nFilMax=%ld, nFound=%ld\n", cpSel, nSel, nFilMin, nFilMax, *nFound);
+    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: found node=0x%lx!!\n", (unsigned long)node);
+        (*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)
+            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;
+                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,
@@ -372,94 +439,108 @@
 {
     cfg_rc_t rc;
     char *token;
+    cfg_node_t *node2;
+    cfg_node_type_t type;
 
-    fprintf(stderr, "step2: (1) cpSel=\"%s\", nSel=%d, nFilMin=%ld, nFilMax=%ld, nFound=%ld\n", cpSel, nSel, nFilMin, nFilMax, *nFound);
+    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>/.."));
 
-    if (strncmp(cpSel, ".", nSel) == 0) {
+    rc = CFG_OK;
+    if (nSel == 1 && strncmp(cpSel, ".", nSel) == 0) {
         /* current node (no-op) */
-        return cfg_node_select_step3(cfg, node, result_vec, result_len, spec, cpSel, nSel, nFilMin, nFilMax, nFound);
+        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 (strncmp(cpSel, "..", nSel) == 0) {
+    else if (nSel == 2 && strncmp(cpSel, "..", nSel) == 0) {
         /* parent node */
-        if ((node = node->parent) == NULL)
-            return CFG_OK;
-        if (node->type == CFG_NODE_TYPE_DIR)
-            if ((node = node->parent) == NULL)
-                return CFG_OK;
-        return cfg_node_select_step3(cfg, node, result_vec, result_len, spec, cpSel, nSel, nFilMin, nFilMax, nFound);
+        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 (strncmp(cpSel, "....", nSel) == 0) {
+    else if (nSel == 4 && strncmp(cpSel, "....", nSel) == 0) {
         /* anchestor nodes */
-        while ((node = node->parent) != NULL) {
-            if (node->type == CFG_NODE_TYPE_DIR)
-                if ((node = node->parent) == NULL)
-                    break;
+        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)
-                return rc;
-        }
-        return CFG_OK;
+                break;
     }
-    else if (strncmp(cpSel, "-", nSel) == 0) {
+    else if (nSel == 1 && strncmp(cpSel, "-", nSel) == 0) {
         /* previous sibling node */
-        if ((rc = cfg_node_get(cfg, node, CFG_NODE_ATTR_LBROTH, &node)) != CFG_OK)
-            return CFG_OK;
-        return cfg_node_select_step3(cfg, node, result_vec, result_len, spec, cpSel, nSel, nFilMin, nFilMax, nFound);
+        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 (strncmp(cpSel, "--", nSel) == 0) {
+    else if (nSel == 2 && strncmp(cpSel, "--", nSel) == 0) {
         /* preceeding sibling nodes */
-        while ((rc = cfg_node_get(cfg, node, CFG_NODE_ATTR_LBROTH, &node)) == CFG_OK)
+        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)
-                return rc;
-        return CFG_OK;
+                break;
     }
-    else if (strncmp(cpSel, "+", nSel) == 0) {
+    else if (nSel == 1 && strncmp(cpSel, "+", nSel) == 0) {
         /* next sibling node */
-        if ((rc = cfg_node_get(cfg, node, CFG_NODE_ATTR_RBROTH, &node)) != CFG_OK)
-            return CFG_OK;
-        return cfg_node_select_step3(cfg, node, result_vec, result_len, spec, cpSel, nSel, nFilMin, nFilMax, nFound);
+        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 (strncmp(cpSel, "++", nSel) == 0) {
+    else if (nSel == 2 && strncmp(cpSel, "++", nSel) == 0) {
         /* following sibling nodes */
-        while ((rc = cfg_node_get(cfg, node, CFG_NODE_ATTR_RBROTH, &node)) == CFG_OK)
+        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)
-                return rc;
-        return CFG_OK;
+                break;
     }
-    else if (nSel == 0) {
+    else if (nSel == 0 /* "//" */) {
         /* descendant nodes */
-        if ((rc = cfg_node_get(cfg, node, CFG_NODE_ATTR_CHILD1, &node)) == CFG_OK)
-            while ((rc = cfg_node_get(cfg, node, CFG_NODE_ATTR_RBROTH, &node)) == CFG_OK)
+        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: child node 0x%lx\n", (unsigned long)node);
-        if ((node = node->child1) == NULL)
-            return CFG_OK;
-        if (node->type == CFG_NODE_TYPE_DIR)
-            if ((node = node->child1) == NULL)
-                return CFG_OK;
-        fprintf(stderr, "step2: child node 0x%lx\n", (unsigned long)node);
-        do {
-            if (node->token != NULL) {
-                size_t l;
-                token = node->token;
-                l = strlen(token);
-                fprintf(stderr, "step2: child node: \"%s\"\n", token);
-                if (   (l == 1 && l == nSel && 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;
+        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;
                 }
-            }
-        } while ((node = node->rbroth) != NULL);
+                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,
@@ -475,7 +556,7 @@
     cfg_rc_t rc;
     long nFound;
 
-    fprintf(stderr, "step1(spec=\"%s\")\n", spec);
+    fprintf(stderr, "  step1: (0) spec=\"%s\"\n", spec);
 
     /* stop processing if spec is empty */
     if (spec[0] == '\0')
@@ -512,41 +593,47 @@
         cp++;
     spec = cp;
 
-    fprintf(stderr, "    step1: (1) cpSel=\"%s\", nSel=%d, nFilMin=%ld, nFilMax=%ld\n", cpSel, nSel, nFilMin, nFilMax);
+    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) {
-        if (nFilMin == -1)
-            nFilMin = LONG_MAX;
-        if (nFilMax == -1)
-            nFilMax = LONG_MAX;
-        if (nFilMin < 0 || nFilMax < 0) {
-            nFound = 0;
-            if ((rc = cfg_node_select_step2(cfg, node, NULL, NULL, spec, cpSel, nSel, 1, LONG_MAX, &nFound)) != CFG_OK)
-                return rc;
-            if (nFilMin < 0) {
-                nFilMin = nFound + nFilMin;
-                if (nFilMin < 1)
-                    nFilMin = 1;
-            }
-            if (nFilMax < 0) {
-                nFilMax = nFound + nFilMax;
-                if (nFilMax < 1)
-                    nFilMax = 1;
-            }
+        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, nFilMin=%ld, nFilMax=%ld\n", cpSel, nSel, nFilMin, nFilMax);
+    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,
@@ -561,6 +648,7 @@
     char *cp;
     long result_len;
 
+    /* argument sanity checking */
     if (cfg == NULL || result_vec == NULL || fmt == NULL)
         return CFG_ERR_ARG;
 
@@ -570,15 +658,22 @@
     va_end(ap);
     if (spec == NULL)
         return CFG_ERR_FMT;
+    fprintf(stderr, "select: (1) spec=\"%s\"\n", spec);
 
-    /* special case for absolute (start from root-node) selection */
+    /* 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++;
     }
-    if (node == NULL)
+    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;
@@ -591,10 +686,12 @@
         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,
@@ -607,6 +704,7 @@
     return CFG_ERR_INT;
 }
 
+/* apply for each matching node (recursion) */
 cfg_rc_t
 cfg_node_apply(
     cfg_t *cfg,
@@ -618,6 +716,7 @@
 {
     cfg_rc_t rc;
 
+    /* argument sanity checking */
     if (cfg == NULL)
         return CFG_ERR_ARG;
     if (node != NULL) {
@@ -639,12 +738,14 @@
     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)
@@ -656,10 +757,17 @@
     return CFG_ERR_NDE;
 }
 
-cfg_rc_t cfg_node_link(cfg_t *cfg, cfg_node_t *node, cfg_node_attr_t attr, cfg_node_t *node2)
+/* 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) {
@@ -690,12 +798,18 @@
     return CFG_OK;
 }
 
-cfg_rc_t cfg_node_unlink(cfg_t *cfg, cfg_node_t *node)
+/* 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) {

CVSTrac 2.0.1