OSSP CVS Repository

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

Check-in Number: 1933
Date: 2002-Mar-01 22:59:37 (local)
2002-Mar-01 21:59:37 (UTC)
User:rse
Branch:
Comment: Code Cleanup Phase III (too much details to describe)
Tickets:
Inspections:
Files:
ossp-pkg/var/var.c      1.71 -> 1.72     160 inserted, 100 deleted

ossp-pkg/var/var.c 1.71 -> 1.72

--- var.c        2002/03/01 20:28:33     1.71
+++ var.c        2002/03/01 21:59:37     1.72
@@ -148,6 +148,22 @@
     return;
 }
 
+static void tokenbuf_set(tokenbuf_t *buf, const char *begin, const char *end, size_t buffer_size)
+{
+    buf->begin = begin;
+    buf->end = end;
+    buf->buffer_size = buffer_size;
+    return;
+}
+
+static void tokenbuf_copy(tokenbuf_t *src, tokenbuf_t *dst)
+{
+    dst->begin = src->begin;
+    dst->end = src->end;
+    dst->buffer_size = src->buffer_size;
+    return;
+}
+
 static void tokenbuf_move(tokenbuf_t *src, tokenbuf_t *dst)
 {
     dst->begin = src->begin;
@@ -225,6 +241,11 @@
     return 1;
 }
 
+static int tokenbuf_merge(tokenbuf_t *output, tokenbuf_t *input)
+{
+    return tokenbuf_append(output, input->begin, input->end - input->begin);
+}
+
 static void tokenbuf_free(tokenbuf_t *buf)
 {
     if (buf->begin != NULL && buf->buffer_size > 0)
@@ -511,7 +532,7 @@
     return num;
 }
 
-/* parse number expression operand */
+/* parse numerical expression operand */
 static int 
 parse_num_exp_operand(
     var_t *var, var_parse_t *ctx,
@@ -599,18 +620,20 @@
     return (p - begin);
 }
 
+/* parse numerical expression */
 static int 
 parse_num_exp(
     var_t *var, var_parse_t *ctx,
     const char *begin, const char *end, 
     int *result, int *failed)
 {
-    const char *p = begin;
+    const char *p;
     char operator;
     int right;
     int rc;
 
-    if (begin == end)
+    p = begin;
+    if (p == end)
         return VAR_ERR_INCOMPLETE_INDEX_SPEC;
 
     rc = parse_num_exp_operand(var, ctx, p, end, result, failed);
@@ -666,7 +689,7 @@
     return p - begin;
 }
 
-/* callback wrapper function */
+/* lookup a variable value by callin the callback function */
 static int 
 lookup_value(
     var_t *var, var_parse_t *ctx,
@@ -681,7 +704,11 @@
                               var_ptr, var_len, var_idx, 
                               val_ptr, val_len, val_size);
 
-    /* convert undefined variable into empty variable */
+    /* convert undefined variable into empty variable if relative
+       lookups are counted. This is the case inside an active loop
+       construct if no limits are given. There the parse_input()
+       has to proceed until all variables have undefined values. 
+       This trick here allows it to determine this case. */
     if (ctx->rel_lookup_flag && rc == VAR_ERR_UNDEFINED_VARIABLE) {
         ctx->rel_lookup_cnt--;
         buf[0] = NUL;
@@ -1803,32 +1830,35 @@
     return rc;
 }
 
-/* expand the loop limits */
+/* parse loop construct limits ("[...]{b,s,e}") */
 static var_rc_t 
 parse_looplimits(
     var_t *var,
     var_parse_t *ctx,
     const char *begin, const char *end,
-    int *start, int *step, int *stop, 
-    int *open_end)
+    int *start, int *step, int *stop, int *open_stop)
 {
     const char *p;
     int rc;
     int failed;
 
+    /* initialization */
     p = begin;
-    if (begin == end)
+
+    /* we are happy if nothing is to left to parse */
+    if (p == end)
         return 0;
+
+    /* parse start delimiter */
     if (*p != var->syntax.delim_open)
         return 0;
-    else
-        p++;
+    p++;
 
-    /* Read start value for the loop. */
+    /* parse loop start value */
     failed = 0;
     rc = parse_num_exp(var, ctx, p, end, start, &failed);
     if (rc == VAR_ERR_INVALID_CHAR_IN_INDEX_SPEC)
-        *start = 0;          /* use default */
+        *start = 0; /* use default */
     else if (rc < 0)
         return rc;
     else
@@ -1836,107 +1866,120 @@
     if (failed)
         return VAR_ERR_UNDEFINED_VARIABLE;
 
+    /* parse separator */
     if (*p != ',')
         return VAR_ERR_INVALID_CHAR_IN_LOOP_LIMITS;
-    else
-        p++;
+    p++;
 
-    /* Read step value for the loop. */
+    /* parse loop step value */
     failed = 0;
     rc = parse_num_exp(var, ctx, p, end, step, &failed);
     if (rc == VAR_ERR_INVALID_CHAR_IN_INDEX_SPEC)
-        *step = 1;          /* use default */
+        *step = 1; /* use default */
     else if (rc < 0)
         return rc;
     else
         p += rc;
     if (failed)
         return VAR_ERR_UNDEFINED_VARIABLE;
+
+    /* parse separator */
     if (*p != ',') {
+        /* if not found, parse end delimiter */
         if (*p != var->syntax.delim_close)
             return VAR_ERR_INVALID_CHAR_IN_LOOP_LIMITS;
-        else {
-            p++;
-            *stop = *step;
-            *step = 1;
-            if (rc > 0)
-                *open_end = 0;
-            else
-                *open_end = 1;
-            return p - begin;
-        }
-    }
-    else
         p++;
 
-    /* Read stop value for the loop. */
+        /* shift step value to stop value */
+        *stop = *step;
+        *step = 1;
+
+        /* determine whether loop end is open */
+        if (rc > 0)
+            *open_stop = 0;
+        else
+            *open_stop = 1;
+        return (p - begin);
+    }
+    p++;
+
+    /* parse loop stop value */
     failed = 0;
     rc = parse_num_exp(var, ctx, p, end, stop, &failed);
     if (rc == VAR_ERR_INVALID_CHAR_IN_INDEX_SPEC) {
-        *stop = 0;  /* use default */
-        *open_end = 1;
+        *stop = 0; /* use default */
+        *open_stop = 1;
     }
     else if (rc < 0)
         return rc;
     else {
-        *open_end = 0;
+        *open_stop = 0;
         p += rc;
     }
     if (failed)
         return VAR_ERR_UNDEFINED_VARIABLE;
+
+    /* parse end delimiter */
     if (*p != var->syntax.delim_close)
         return VAR_ERR_INVALID_CHAR_IN_LOOP_LIMITS;
+    p++;
 
-    return ++p - begin;
+    /* return amount of parsed input */
+    return (p - begin);
 }
 
 /* expand input in general */
 static var_rc_t 
 parse_input(
-    var_t *var,
-    var_parse_t *ctx,
+    var_t *var, var_parse_t *ctx,
     const char *begin, const char *end,
-    tokenbuf_t *output, 
-    int recursion_level)
+    tokenbuf_t *output, int recursion_level)
 {
-    const char *p = begin;
+    const char *p;
     int rc, rc2;
     tokenbuf_t result;
-    int start, step, stop, open_end;
+    int start, step, stop, open_stop;
     int i;
-    int output_backup;
+    tokenbuf_t output_backup;
     int rel_lookup_cnt;
     int loop_limit_length;
     var_parse_t myctx;
 
-    tokenbuf_init(&result);
+    /* initialization */
+    p = begin;
 
     do {
         /* try to parse a loop construct */
-        if (   begin != end 
+        if (   p != end 
             && var->syntax.index_open != NUL 
-            && *begin == var->syntax.index_open) {
+            && *p == var->syntax.index_open) {
+            p++;
 
+            /* loop preparation */
             loop_limit_length = -1;
-            begin++;
+            rel_lookup_cnt = ctx->rel_lookup_cnt;
+            open_stop = 1;
+            rc = 0;
             start = 0;
             step  = 1;
             stop  = 0;
-            open_end = 1;
-            rc = 0;
-            output_backup = 0;
-            rel_lookup_cnt = ctx->rel_lookup_cnt;
+            tokenbuf_copy(output, &output_backup);
 
+            /* iterate over loop construct, either as long as there is
+               (still) nothing known about the limit, or there is an open
+               (=unknown) limit stop and there are still defined variables
+               or there is a stop limit known and it is still not reached */
             re_loop:
             for (i = start;
-                 (   (  open_end 
+                 (   (   open_stop 
                       && (   loop_limit_length < 0 
                           || rel_lookup_cnt > ctx->rel_lookup_cnt)) 
-                  || (   !open_end 
-                      && i <= stop)                                            );
+                  || (   !open_stop 
+                      && i <= stop)                                );
                  i += step) {
-                /* remember current state for backing off */
-                output_backup = output->end - output->begin;
+
+                /* remember current output end for restoring */
+                tokenbuf_copy(output, &output_backup);
 
                 /* open temporary context for recursion */ 
                 ctx = var_parse_push(ctx, &myctx);
@@ -1944,84 +1987,106 @@
                 ctx->rel_lookup_flag = 1;
                 ctx->index_this      = i;
 
-                rc = parse_input(var, ctx, begin, end, 
+                /* recursive parse input through ourself */
+                rc = parse_input(var, ctx, p, end, 
                                  output, recursion_level+1);
 
                 /* retrieve info and close temporary context */
                 rel_lookup_cnt = ctx->rel_lookup_cnt;
                 ctx = var_parse_pop(ctx);
 
+                /* error handling */
                 if (rc < 0)
                     goto error_return;
-                if (begin[rc] != var->syntax.index_close) {
+
+                /* make sure the loop construct is closed */
+                if (p[rc] != var->syntax.index_close) {
                     rc = VAR_ERR_UNTERMINATED_LOOP_CONSTRUCT;
                     goto error_return;
                 }
+
+                /* try to parse loop construct limit specification */
                 if (loop_limit_length < 0) {
-                    rc2 = parse_looplimits(var, ctx, begin + rc + 1, end, 
-                                            &start, &step,
-                                            &stop, &open_end);
+                    rc2 = parse_looplimits(var, ctx, p+rc+1, end, 
+                                           &start, &step, &stop, &open_stop);
                     if (rc2 < 0)
                         goto error_return;
                     else if (rc2 == 0)
                         loop_limit_length = 0;
                     else if (rc2 > 0) {
                         loop_limit_length = rc2;
-                        output->end = output->begin + output_backup;
+                        /* restart loop from scratch */
+                        tokenbuf_copy(&output_backup, output);
                         goto re_loop;
                     }
                 }
             }
-            if (open_end)
-                output->end = output->begin + output_backup;
-            else
-                rel_lookup_cnt = ctx->rel_lookup_cnt;
-            begin += rc;
-            begin++;
-            begin += loop_limit_length;
+
+            /* if stop value is open, restore to the output end
+               because the last iteration was just to determine the loop
+               termination and its result has to be discarded */
+            if (open_stop)
+                tokenbuf_copy(&output_backup, output);
+
+            /* skip parsed loop construct */
+            p += rc;
+            p++;
+            p += loop_limit_length;
+
             continue;
         }
 
         /* try to parse plain text */
-        rc = parse_text(var, ctx, begin, end);
+        rc = parse_text(var, ctx, p, end);
         if (rc > 0) {
-            if (!tokenbuf_append(output, begin, rc)) {
+            if (!tokenbuf_append(output, p, rc)) {
                 rc = VAR_ERR_OUT_OF_MEMORY;
                 goto error_return;
             }
-            begin += rc;
+            p += rc;
             continue;
         } else if (rc < 0)
             goto error_return;
 
         /* try to parse a variable construct */
-        rc = parse_variable(var, ctx, begin, end, &result);
+        tokenbuf_init(&result);
+        rc = parse_variable(var, ctx, p, end, &result);
         if (rc > 0) {
-            if (!tokenbuf_append(output, result.begin, result.end - result.begin)) {
+            if (!tokenbuf_merge(output, &result)) {
+                tokenbuf_free(&result);
                 rc = VAR_ERR_OUT_OF_MEMORY;
                 goto error_return;
             }
-            begin += rc;
+            tokenbuf_free(&result);
+            p += rc;
             continue;
-        }
+        }    
+        tokenbuf_free(&result);
         if (rc < 0)
             goto error_return;
 
-    } while (begin != end && rc > 0);
+    } while (p != end && rc > 0);
 
-    if (recursion_level == 0 && begin != end) {
+    /* We do not know whether this really could happen, but because we
+       are paranoid, report an error at the outer most parsing level if
+       there is still any input. Because this would mean that we are no
+       longer able to parse the remaining input as a loop construct, a
+       text or a variable construct. This would be very strange, but
+       could perhaps happen in case of configuration errors!?... */
+    if (recursion_level == 0 && p != end) {
         rc = VAR_ERR_INPUT_ISNT_TEXT_NOR_VARIABLE;
         goto error_return;
     }
 
-    return begin - p;
+    /* return amount of parsed text */
+    return (p - begin);
 
-  error_return:
+    /* return with an error where as a special case the output begin is
+       set to the input begin and the output end to the last input parsing
+       position. */
+    error_return:
     tokenbuf_free(output);
-    tokenbuf_free(&result);
-    output->begin = p;
-    output->end = begin;
-    output->buffer_size = 0;
+    tokenbuf_set(output, begin, p, 0);
     return rc;
 }
 
@@ -2185,42 +2250,37 @@
         return VAR_RC(VAR_ERR_INVALID_ARGUMENT);
 
     /* prepare internal expansion context */
-    ctx.lower = NULL;
-    ctx.force_expand = force_expand;
+    ctx.lower           = NULL;
+    ctx.force_expand    = force_expand;
     ctx.rel_lookup_flag = 0;
-    ctx.rel_lookup_cnt = 0;
-    ctx.index_this = 0;
+    ctx.rel_lookup_cnt  = 0;
+    ctx.index_this      = 0;
 
-    /* set the dst_ptr pointer to the src_ptr so that it is correctly
-       initialized in case we fail with an error later. */
-    *dst_ptr = (char *)src_ptr;
-
-    /* call the parsing */
+    /* start the parsing */
     tokenbuf_init(&output);
-    rc = parse_input(var, &ctx, src_ptr, src_ptr + src_len, &output, 0);
+    rc = parse_input(var, &ctx, src_ptr, src_ptr+src_len, &output, 0);
 
-    /* post-process output */
+    /* post-processing */
     if (rc >= 0) {
-        /* always NUL-terminate output for convinience reasons */
+        /* always NUL-terminate output for convinience reasons 
+           but do not count the NUL-terminator in the length */
         if (!tokenbuf_append(&output, "\0", 1)) {
             tokenbuf_free(&output);
             return VAR_RC(VAR_ERR_OUT_OF_MEMORY);
         }
         output.end--;
 
-        /* provide dst_ptrs */
+        /* provide result */
         *dst_ptr = (char *)output.begin;
         if (dst_len != NULL)
-            *dst_len = output.end - output.begin;
-
-        /* canonify all positive answers */
+            *dst_len = (output.end - output.begin);
         rc = VAR_OK;
     }
     else {
-        /* provide error dst_ptr */
+        /* provide result */
         *dst_ptr = (char *)src_ptr;
         if (dst_len != NULL)
-            *dst_len = output.end - output.begin;
+            *dst_len = (output.end - output.begin);
     }
 
     return VAR_RC(rc);

CVSTrac 2.0.1