--- var.c 2001/12/08 16:27:57 1.42
+++ var.c 2001/12/12 16:51:20 1.43
@@ -98,7 +98,8 @@
"index specification of array variable contains an invalid character", /* VAR_ERR_INVALID_CHAR_IN_INDEX_SPEC = -38 */
"index specification of array variable is incomplete", /* VAR_ERR_INCOMPLETE_INDEX_SPEC = -39 */
"bracket expression in array variable's index is not closed", /* VAR_ERR_UNCLOSED_BRACKET_IN_INDEX = -40 */
- "division by zero error in index specification" /* VAR_ERR_DIVISION_BY_ZERO_IN_INDEX = -41 */
+ "division by zero error in index specification", /* VAR_ERR_DIVISION_BY_ZERO_IN_INDEX = -41 */
+ "unterterminated loop construct" /* VAR_ERR_UNTERMINATED_LOOP_CONSTRUCT = -42 */
};
rc = 0 - rc;
@@ -429,28 +430,36 @@
/* The recursive-descent parser for variable expressions. */
static int variable(const char *, const char *, const var_config_t *,
- const char_class_t, var_cb_t, void *, int, tokenbuf_t *);
+ const char_class_t, var_cb_t, void *, int, tokenbuf_t *, int);
static int command(const char *, const char *, const var_config_t *,
- const char_class_t, var_cb_t, void *, int, tokenbuf_t *);
+ const char_class_t, var_cb_t, void *, int, tokenbuf_t *, int);
static int num_exp(const char *begin, const char *end, int current_index,
int* result, int* failed, const var_config_t *config,
const char_class_t nameclass,
var_cb_t lookup, void* lookup_context);
static int text(const char *begin, const char *end, char varinit,
- char escape)
-{
+ char startindex, char endindex, char escape)
+ {
const char *p;
- for (p = begin; p != end && *p != varinit; ++p) {
- if (*p == escape) {
- if (p + 1 == end)
+ for (p = begin; p != end; ++p)
+ {
+ if (*p == escape)
+ {
+ if (++p == end)
return VAR_ERR_INCOMPLETE_QUOTED_PAIR;
- else
- ++p;
+ }
+ else if (*p == varinit)
+ {
+ break;
+ }
+ else if (startindex && (*p == startindex || *p == endindex))
+ {
+ break;
+ }
}
- }
return p - begin;
-}
+ }
static int varname(const char *begin, const char *end,
const char_class_t nameclass)
@@ -540,11 +549,11 @@
}
else if (*p == config->varinit)
{
- rc = variable(p, end, config, nameclass, lookup, lookup_context, 1, &tmp);
+ rc = variable(p, end, config, nameclass, lookup, lookup_context, 1, &tmp, current_index);
if (rc == VAR_ERR_UNDEFINED_VARIABLE)
{
*failed = 1;
- rc = variable(p, end, config, nameclass, lookup, lookup_context, 0, &tmp);
+ rc = variable(p, end, config, nameclass, lookup, lookup_context, 0, &tmp, current_index);
if (rc < 0)
return rc;
p += rc;
@@ -689,14 +698,14 @@
const var_config_t *config,
const char_class_t nameclass, var_cb_t lookup,
void *lookup_context, int force_expand,
- tokenbuf_t *result)
+ tokenbuf_t *result, int current_index)
{
const char *p = begin;
const char *data;
size_t len, buffer_size;
int failed = 0;
int rc;
- int index = 0;
+ int index = current_index;
tokenbuf_t name;
tokenbuf_t tmp;
@@ -733,7 +742,7 @@
}
rc = variable(p, end, config, nameclass, lookup, lookup_context,
- force_expand, &tmp);
+ force_expand, &tmp, current_index);
if (rc < 0)
goto error_return;
if (rc > 0)
@@ -762,7 +771,7 @@
if (config->startindex && *p == config->startindex)
{
printf("Found START-INDEX: %s\n", p);
- rc = num_exp(++p, end, 0, &index, &failed, config, nameclass, lookup, lookup_context);
+ rc = num_exp(++p, end, current_index, &index, &failed, config, nameclass, lookup, lookup_context);
if (rc < 0)
goto error_return;
if (rc == 0)
@@ -853,10 +862,10 @@
++p;
if (!failed)
rc = command(p, end, config, nameclass, lookup,
- lookup_context, force_expand, result);
+ lookup_context, force_expand, result, current_index);
else
rc = command(p, end, config, nameclass, lookup,
- lookup_context, force_expand, &tmp);
+ lookup_context, force_expand, &tmp, current_index);
if (rc < 0)
goto error_return;
p += rc;
@@ -892,7 +901,7 @@
static int variable(const char *begin, const char *end,
const var_config_t *config, const char_class_t nameclass,
var_cb_t lookup, void *lookup_context,
- int force_expand, tokenbuf_t *result)
+ int force_expand, tokenbuf_t *result, int current_index)
{
const char *p = begin;
const char *data;
@@ -939,7 +948,7 @@
/* OK, we're dealing with a complex expression here. */
rc = expression(p, end, config, nameclass, lookup, lookup_context,
- force_expand, result);
+ force_expand, result, current_index);
if (rc > 0)
++rc;
return rc;
@@ -949,7 +958,7 @@
const var_config_t *config,
const char_class_t nameclass, var_cb_t lookup,
void *lookup_context, int force_expand,
- tokenbuf_t *result)
+ tokenbuf_t *result, int current_index)
{
const char *p = begin;
tokenbuf_t tmp;
@@ -974,7 +983,7 @@
}
rc = variable(p, end, config, nameclass, lookup, lookup_context,
- force_expand, &tmp);
+ force_expand, &tmp, current_index);
if (rc < 0)
goto error_return;
if (rc > 0) {
@@ -1001,7 +1010,7 @@
const var_config_t *config,
const char_class_t nameclass, var_cb_t lookup,
void *lookup_context, int force_expand,
- tokenbuf_t *result)
+ tokenbuf_t *result, int current_index)
{
const char *p = begin;
tokenbuf_t tmp;
@@ -1026,7 +1035,7 @@
}
rc = variable(p, end, config, nameclass, lookup, lookup_context,
- force_expand, &tmp);
+ force_expand, &tmp, current_index);
if (rc < 0)
goto error_return;
if (rc > 0) {
@@ -1472,7 +1481,7 @@
static int command(const char *begin, const char *end,
const var_config_t *config, const char_class_t nameclass,
var_cb_t lookup, void *lookup_context, int force_expand,
- tokenbuf_t *data)
+ tokenbuf_t *data, int current_index)
{
const char *p = begin;
tokenbuf_t tmptokbuf;
@@ -1578,7 +1587,7 @@
case '-': /* Substitute parameter if data is empty. */
++p;
rc = exptext_or_variable(p, end, config, nameclass, lookup,
- lookup_context, force_expand, &tmptokbuf);
+ lookup_context, force_expand, &tmptokbuf, current_index);
if (rc < 0)
goto error_return;
if (rc == 0) {
@@ -1595,7 +1604,7 @@
case '*': /* Return "" if data is not empty, parameter otherwise. */
++p;
rc = exptext_or_variable(p, end, config, nameclass, lookup,
- lookup_context, force_expand, &tmptokbuf);
+ lookup_context, force_expand, &tmptokbuf, current_index);
if (rc < 0)
goto error_return;
if (rc == 0) {
@@ -1618,7 +1627,7 @@
case '+': /* Substitute parameter if data is not empty. */
++p;
rc = exptext_or_variable(p, end, config, nameclass, lookup,
- lookup_context, force_expand, &tmptokbuf);
+ lookup_context, force_expand, &tmptokbuf, current_index);
if (rc < 0)
goto error_return;
if (rc == 0) {
@@ -1640,7 +1649,7 @@
++p;
rc = substext_or_variable(p, end, config, nameclass, lookup,
- lookup_context, force_expand, &search);
+ lookup_context, force_expand, &search, current_index);
if (rc < 0)
goto error_return;
p += rc;
@@ -1652,7 +1661,7 @@
++p;
rc = substext_or_variable(p, end, config, nameclass, lookup,
- lookup_context, force_expand, &replace);
+ lookup_context, force_expand, &replace, current_index);
if (rc < 0)
goto error_return;
p += rc;
@@ -1686,7 +1695,7 @@
++p;
rc = substext_or_variable(p, end, config, nameclass, lookup,
- lookup_context, force_expand, &search);
+ lookup_context, force_expand, &search, current_index);
if (rc < 0)
goto error_return;
p += rc;
@@ -1698,7 +1707,7 @@
++p;
rc = substext_or_variable(p, end, config, nameclass, lookup,
- lookup_context, force_expand, &replace);
+ lookup_context, force_expand, &replace, current_index);
if (rc < 0)
goto error_return;
p += rc;
@@ -1741,7 +1750,7 @@
++p;
rc = substext_or_variable(p, end, config, nameclass, lookup,
- lookup_context, force_expand, &replace);
+ lookup_context, force_expand, &replace, current_index);
if (rc < 0)
goto error_return;
p += rc;
@@ -1790,31 +1799,101 @@
return rc;
}
+struct wrapper_context
+ {
+ var_cb_t lookup;
+ void* context;
+ int* found_variables;
+ };
+
+static int lookup_wrapper(void *context,
+ const char *varname, size_t name_len, int index,
+ const char **data, size_t *data_len,
+ size_t *buffer_size)
+ {
+ static char buf[1];
+ struct wrapper_context* wcon = context;
+ int rc;
+
+ printf("Looking up '");
+ fwrite(varname, name_len, 1, stdout);
+ printf("[%d]' ... rc = ", index);
+
+ rc = (*wcon->lookup)(wcon->context, varname, name_len, index, data, data_len, buffer_size);
+ printf("%d\n", rc);
+ if (rc == 0)
+ {
+ *data = buf;
+ *data_len = 0;
+ *buffer_size = 0;
+ return 1;
+ }
+ else
+ {
+ *(wcon->found_variables) += 1;
+ return rc;
+ }
+ }
+
static var_rc_t input(const char *begin, const char *end,
const var_config_t *config,
const char_class_t nameclass, var_cb_t lookup,
void *lookup_context, int force_expand,
- tokenbuf_t *output)
+ tokenbuf_t *output, int current_index, size_t recursion_level)
{
const char* p = begin;
int rc;
tokenbuf_t result;
-
+ int found_variables;
+ int i;
+ int output_backup;
+ struct wrapper_context wcon;
tokenbuf_init(&result);
do {
- rc = text(begin, end, config->varinit, config->escape);
+ printf("input(): Parsing string '%s'.\n", begin);
+
+ if (begin != end && *begin == config->startindex)
+ {
+ printf("Found loop construct.\n");
+ wcon.lookup = lookup;
+ wcon.context = lookup_context;
+ wcon.found_variables = &found_variables;
+ ++begin;
+ for (i = 0; i == 0 || found_variables; ++i)
+ {
+ output_backup = output->end - output->begin;
+ found_variables = 0;
+ printf("Recursing with default index %d.\n", i);
+ rc = input(begin, end, config, nameclass, &lookup_wrapper, &wcon, 1, output, i, recursion_level+1);
+ printf("input() recursion returned %d.\n", rc);
+ if (rc < 0)
+ goto error_return;
+ if (begin[rc] != config->endindex)
+ {
+ rc = VAR_ERR_UNTERMINATED_LOOP_CONSTRUCT;
+ goto error_return;
+ }
+ }
+ output->end = output->begin + output_backup;
+ begin += rc;
+ ++begin;
+ continue;
+ }
+
+ rc = text(begin, end, config->varinit, config->startindex, config->endindex, config->escape);
if (rc > 0) {
if (!tokenbuf_append(output, begin, rc)) {
rc = VAR_ERR_OUT_OF_MEMORY;
goto error_return;
}
begin += rc;
+ continue;
} else if (rc < 0)
goto error_return;
rc = variable(begin, end, config, nameclass, lookup,
- lookup_context, force_expand, &result);
+ lookup_context, force_expand, &result, current_index);
if (rc > 0) {
if (!tokenbuf_append
(output, result.begin, result.end - result.begin)) {
@@ -1822,18 +1901,19 @@
goto error_return;
}
begin += rc;
+ continue;
}
if (rc < 0)
goto error_return;
}
- while (rc > 0);
+ while (begin != end && rc > 0);
- if (begin != end) {
+ if (recursion_level == 0 && begin != end) {
rc = VAR_ERR_INPUT_ISNT_TEXT_NOR_VARIABLE;
goto error_return;
}
- return VAR_OK;
+ return begin - p;
error_return:
tokenbuf_free(output);
@@ -1882,8 +1962,8 @@
/* Call the parser. */
tokenbuf_init(&output);
rc = input(input_buf, input_buf + input_len, config, nameclass,
- lookup, lookup_context, force_expand, &output);
+ lookup, lookup_context, force_expand, &output, 0, 0);
*result = (char *)output.begin;
*result_len = output.end - output.begin;
- return rc;
+ return (rc >= 0) ? VAR_OK : rc;
}
|