OSSP CVS Repository

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

Check-in Number: 2317
Date: 2002-Jul-18 17:34:55 (local)
2002-Jul-18 15:34:55 (UTC)
User:rse
Branch:
Comment: flush work of today: first cut for real cfg_node_select()
Tickets:
Inspections:
Files:
ossp-pkg/cfg/00TODO      1.8->removed
ossp-pkg/cfg/cfg.h      1.10 -> 1.11     1 inserted, 1 deleted
ossp-pkg/cfg/cfg.pod      1.3 -> 1.4     44 inserted, 4 deleted
ossp-pkg/cfg/cfg_node.c      1.12 -> 1.13     265 inserted, 20 deleted
ossp-pkg/cfg/cfg_syn.c      1.12 -> 1.13     16 inserted, 6 deleted
ossp-pkg/cfg/cfg_test.c      1.6 -> 1.7     28 inserted, 3 deleted

ossp-pkg/cfg/00TODO 1.8 -> 1.9

--- 00TODO       2002/07/17 18:47:52     1.8
+++ 00TODO       2002/07/18 15:34:55     1.9
@@ -1,4 +1,5 @@
 
+- destroy haengt in Endlosschleife
 - in scanner: use an combination of dynamic buffer and atomic symbol/token sub-library 
   to allow first tokens of mostly arbitrary size and then to store the tokens
   redundancy-free.


ossp-pkg/cfg/cfg.h 1.10 -> 1.11

--- cfg.h        2002/07/17 15:04:08     1.10
+++ cfg.h        2002/07/18 15:34:55     1.11
@@ -135,7 +135,7 @@
 
 /* node traversing/locating */
 cfg_rc_t   cfg_node_root   (cfg_t  *cfg, cfg_node_t **node);
-cfg_rc_t   cfg_node_select (cfg_t  *cfg, cfg_node_t  *node, cfg_node_t **node2, const char *spec, ...);
+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);
 cfg_rc_t   cfg_node_cmp    (cfg_t  *cfg, cfg_node_t  *node, void *token);


ossp-pkg/cfg/cfg.pod 1.3 -> 1.4

--- cfg.pod      2002/07/12 19:59:33     1.3
+++ cfg.pod      2002/07/18 15:34:55     1.4
@@ -175,13 +175,53 @@
 
  virtualhost[2].directory
 
+=head1 NODE SELECTION SPECIFICATION
+
+The B<cfg_node_select> function takes a I<node selection specification>
+string B<select> for locating the intended nodes. This specification is
+defined as:
+
+B<select>           ::= I<empty>
+                   | B<select-step> B<select>
+
+B<select-step>      ::= B<select-direction> 
+                     B<select-pattern> 
+                     B<select-filter>
+
+B<select-direction> ::= "./"        # current node
+                   | "../"       # parent node
+                   | "..../"     # anchestor nodes
+                   | "-/"        # previous sibling node
+                   | "--/"       # preceeding sibling nodes
+                   | "+/"        # next sibling node
+                   | "++/"       # following sibling nodes
+                   | "/"         # child nodes
+                   | "//"        # descendant nodes
+
+B<select-pattern>   ::= /</ B<regex> />/
+                   | B<token> 
+
+B<select-filter>    ::= I<empty>
+                   | /\[/ B<filter-range> /\]/
+
+B<filter-range>     ::= B<num>           # short for: num,num
+                   | B<num> /,/          # short for: num,-1
+                   | /,/ B<num>          # short for: 1,num
+                   | B<num> /,/ B<num>
+                   
+B<num>              ::= /^[+-]?[0-9]+/
+
+B<regex>            ::= "Regular Expression (PCRE-based)"
+
+B<token>            ::= "Plain-Text Token String"
+
 =head1 HISTORY
 
 B<OSSP cfg> was implemented in lots of small steps over a very
-long time. The first ideas date back to the year 1995 when Ralf S.
-Engelschall attended his first compiler construction lessons at
-university. But it was first time finished in 2002 by him for use in the
-B<OSSP> project.
+long time. The first ideas date back to the year 1995 when
+Ralf S. Engelschall attended his first compiler construction lessons at
+university. But it was first time finished in summer 2002 by him for use
+in the B<OSSP> project.
 
 =head1 AUTHOR
 


ossp-pkg/cfg/cfg_node.c 1.12 -> 1.13

--- cfg_node.c   2002/07/17 15:04:08     1.12
+++ cfg_node.c   2002/07/18 15:34:55     1.13
@@ -32,9 +32,11 @@
 #include <stdlib.h>
 #include <stdarg.h>
 #include <unistd.h>
+#include <limits.h>
 
 #include "cfg_main.h"
 #include "cfg_node.h"
+#include "cfg_fmt.h"
 
 cfg_rc_t cfg_node_create(cfg_t *cfg, cfg_node_t **node)
 {
@@ -314,37 +316,280 @@
     return CFG_OK;
 }
 
-cfg_rc_t cfg_node_select(cfg_t *cfg, cfg_node_t *node, cfg_node_t **node2, const char *fmt, ...)
+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 *);
+
+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)
 {
-#if 0
-    cfg_node_t *n;
+    cfg_rc_t rc;
+
+    fprintf(stderr, "step3: (1) cpSel=\"%s\", nSel=%d, nFilMin=%ld, nFilMax=%ld, nFound=%ld\n", cpSel, nSel, nFilMin, nFilMax, *nFound);
+
+    if (spec[0] == '\0') {
+        /* end of selection, node found */
+        *nFound++;
+        fprintf(stderr, "step3: found node=0x%lx!!\n", (unsigned long)node);
+        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 {
+        rc = cfg_node_select_step1(cfg, node, result_vec, result_len, spec);
+    }
+    return rc;
+}
+
+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;
+
+    fprintf(stderr, "step2: (1) cpSel=\"%s\", nSel=%d, nFilMin=%ld, nFilMax=%ld, nFound=%ld\n", cpSel, nSel, nFilMin, nFilMax, *nFound);
+
+    if (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);
+    }
+    else if (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);
+    }
+    else if (strncmp(cpSel, "....", nSel) == 0) {
+        /* anchestor nodes */
+        while ((node = node->parent) != NULL) {
+            if (node->type == CFG_NODE_TYPE_DIR)
+                if ((node = node->parent) == NULL)
+                    break;
+            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;
+    }
+    else if (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);
+    }
+    else if (strncmp(cpSel, "--", nSel) == 0) {
+        /* preceeding sibling nodes */
+        while ((rc = cfg_node_get(cfg, node, CFG_NODE_ATTR_LBROTH, &node)) == CFG_OK)
+            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;
+    }
+    else if (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);
+    }
+    else if (strncmp(cpSel, "++", nSel) == 0) {
+        /* following sibling nodes */
+        while ((rc = cfg_node_get(cfg, node, CFG_NODE_ATTR_RBROTH, &node)) == CFG_OK)
+            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;
+    }
+    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)
+                if ((rc = cfg_node_select_step2(cfg, node, result_vec, result_len, spec, cpSel, nSel, nFilMin, nFilMax, nFound)) != CFG_OK)
+                    return rc;
+        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) {
+                token = node->token;
+                size_t 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;
+                }
+            }
+        } while ((node = node->rbroth) != NULL);
+        return CFG_OK;
+    }
+    return rc;
+}
+
+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(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, nFilMin=%ld, nFilMax=%ld\n", cpSel, nSel, 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;
+            }
+        }
+    }
+
+    fprintf(stderr, "    step1: (2) cpSel=\"%s\", nSel=%d, nFilMin=%ld, nFilMax=%ld\n", cpSel, nSel, 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;
+
+    return CFG_OK;
+}
+
+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 *cpB;
-    char *cpE;
     char *spec;
+    char *cp;
+    long result_len;
 
-    if (cfg == NULL || node == NULL || node2 == NULL || spec == NULL)
+    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 = l2_util_vasprintf(fmt, ap);
+    spec = cfg_fmt_vasprintf(fmt, ap);
     va_end(ap);
+    if (spec == NULL)
+        return CFG_ERR_FMT;
+
+    /* special case for absolute (start from root-node) selection */
+    cp = spec;
+    if (cp[0] == '/') {
+        node = cfg->root;
+        cp++;
+    }
+    if (node == NULL)
+        node = cfg->root;
 
-    /* enter the parsing loop */
-    cpE = spec;
-    while (*cpE != '\0') {
-        /* determine begin of parameter name */
-        cpB = cpE;
-        if ((n = strspn(cpB, " \t\r\n")) > 0)
-            cpB += n;
-
-        /* determine end of parameter name */
-        cpE = cpB;
-        if ((n = strspn(cpB, " \t\r\n")) > 0)
-            cpB += n;
+    /* 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;
     }
-#endif
+
     return CFG_OK;
 }
 


ossp-pkg/cfg/cfg_syn.c 1.12 -> 1.13

--- cfg_syn.c    2002/07/10 14:46:28     1.12
+++ cfg_syn.c    2002/07/18 15:34:55     1.13
@@ -270,7 +270,8 @@
     cfg_rc_t rc;
     char *token;
 
-    rc = cfg_node_get(ctx->cfg, node, CFG_NODE_ATTR_TYPE, &type);
+    if ((rc = cfg_node_get(ctx->cfg, node, CFG_NODE_ATTR_TYPE, &type)) != CFG_OK)
+        return;
     if (type == CFG_NODE_TYPE_SEQ) {
         export_format(ctx, "{\n");
         export_indent(ctx, 1);
@@ -313,6 +314,7 @@
     cfg_buf_t *buf;
     cfg_rc_t rc;
     export_t ctx;
+    cfg_node_t *root;
 
     if (node == NULL || output == NULL)
         return CFG_ERR_ARG;
@@ -323,12 +325,20 @@
     ctx.buf    = buf;
     ctx.indent = 0;
 
-    /* first SEQ node is special, so expand it manually instead
-       of just calling once export_node(&ctx, node); */
-    cfg_node_get(cfg, node, CFG_NODE_ATTR_CHILD1, &node);
-    while (node != NULL) {
+    if ((rc = cfg_node_root(cfg, &root)) != CFG_OK)
+        return rc;
+    if (node == root) {
+        /* if we dump the whole configuration, treat the first SEQ node special
+           because of the implicit braces around it. So expand it manually instead
+           of just calling once export_node(&ctx, node); */
+        cfg_node_get(cfg, node, CFG_NODE_ATTR_CHILD1, &node);
+        while (node != NULL) {
+            export_node(&ctx, node);
+            cfg_node_get(cfg, node, CFG_NODE_ATTR_RBROTH, &node);
+        }
+    }
+    else {
         export_node(&ctx, node);
-        cfg_node_get(cfg, node, CFG_NODE_ATTR_RBROTH, &node);
     }
 
     cfg_buf_content(buf, output, NULL, NULL);


ossp-pkg/cfg/cfg_test.c 1.6 -> 1.7

--- cfg_test.c   2002/07/11 09:19:13     1.6
+++ cfg_test.c   2002/07/18 15:34:55     1.7
@@ -14,9 +14,12 @@
     char *ex_ptr;
     char *error;
     cfg_t *cfg;
+    cfg_node_t **vec;
+    cfg_node_t *n;
+    int i;
 
-    if (argc != 2) {
-        fprintf(stderr, "USAGE: %s <file>\n", argv[0]);
+    if (argc < 2 || argc > 3) {
+        fprintf(stderr, "USAGE: %s <file> [<select>]\n", argv[0]);
         exit(1);
     }
 
@@ -40,7 +43,6 @@
         exit(1);
     }
 
-
     if ((rc = cfg_export(cfg, NULL, CFG_FMT_CFG, &ex_ptr, 0)) != CFG_OK) {
         cfg_error(cfg, rc, &error);
         fprintf(stderr, "ERROR: cfg_export: %s\n", error);
@@ -50,6 +52,29 @@
     }
 
     fprintf(stdout, "%s", ex_ptr);
+    fflush(stdout);
+
+    if (argc == 3) {
+        if ((rc = cfg_node_select(cfg, NULL, &vec, "%s", argv[2])) != CFG_OK) {
+            cfg_error(cfg, rc, &error);
+            fprintf(stderr, "ERROR: cfg_node_select: %s\n", error);
+            free(im_ptr);
+            //cfg_destroy(cfg);
+            exit(1);
+        }
+        for (i = 1; vec[i] != NULL; i++) {
+            fprintf(stdout, "---- selection #%d ----\n", i);
+            if ((rc = cfg_export(cfg, vec[i], CFG_FMT_CFG, &ex_ptr, 0)) != CFG_OK) {
+                cfg_error(cfg, rc, &error);
+                fprintf(stderr, "ERROR: cfg_export: %s\n", error);
+                free(im_ptr);
+                //cfg_destroy(cfg);
+                exit(1);
+            }
+            fprintf(stdout, "%s", ex_ptr);
+            fprintf(stdout, "---- selection #%d ----\n", i);
+        }
+    }
 
 #if 0
     cfg_syn_destroy(cfg, node);

CVSTrac 2.0.1